Skip to content

Commit ed8adac

Browse files
committed
[GR-40267] [GR-40268] More HPy fast-paths: HPy_Is, HPy_Type for boxed handles, HPy_Get/SetItem_s JNI upcall.
PullRequest: graalpython/2385
2 parents c9190d8 + cbfd1bf commit ed8adac

File tree

13 files changed

+357
-66
lines changed

13 files changed

+357
-66
lines changed

graalpython/com.oracle.graal.python.jni/src/hpy_jni.c

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ static JNIEnv* jniEnv;
8787
UPCALL(ListCheck, SIG_HPY, SIG_INT) \
8888
UPCALL(UnicodeFromWideChar, SIG_PTR SIG_SIZE_T, SIG_HPY) \
8989
UPCALL(UnicodeFromJCharArray, SIG_JCHARARRAY, SIG_HPY) \
90+
UPCALL(SetItems, SIG_HPY SIG_STRING SIG_HPY, SIG_INT) \
91+
UPCALL(GetItems, SIG_HPY SIG_STRING, SIG_HPY) \
9092
UPCALL(DictNew, , SIG_HPY) \
9193
UPCALL(ListNew, SIG_SIZE_T, SIG_HPY) \
9294
UPCALL(TupleFromArray, SIG_JLONGARRAY SIG_BOOL, SIG_HPY) \
@@ -218,6 +220,42 @@ static void ctx_Field_Store_jni(HPyContext *ctx, HPy owner, HPyField *field, HPy
218220
field->_i = DO_UPCALL_SIZE_T(CONTEXT_INSTANCE(ctx), FieldStore, HPY_UP(owner), field->_i, HPY_UP(value));
219221
}
220222

223+
static const char* getBoxedPrimitiveName(uint64_t bits) {
224+
assert(!isBoxedHandle(bits));
225+
if (isBoxedInt(bits)) {
226+
return "int";
227+
}
228+
assert(isBoxedDouble(bits));
229+
return "float";
230+
}
231+
232+
int ctx_SetItem_s_jni(HPyContext *ctx, HPy target, const char *name, HPy value) {
233+
uint64_t bits = toBits(target);
234+
if (!isBoxedHandle(bits)) {
235+
const size_t buffer_size = 128;
236+
char message[buffer_size];
237+
snprintf(message, buffer_size,
238+
"'%s' object does not support item assignment", getBoxedPrimitiveName(bits));
239+
HPyErr_SetString(ctx, ctx->h_TypeError, message);
240+
return -1;
241+
}
242+
jstring jname = (*jniEnv)->NewStringUTF(jniEnv, name);
243+
return DO_UPCALL_INT(CONTEXT_INSTANCE(ctx), SetItems, target, jname, value);
244+
}
245+
246+
HPy ctx_GetItem_s_jni(HPyContext *ctx, HPy target, const char *name) {
247+
uint64_t bits = toBits(target);
248+
if (!isBoxedHandle(bits)) {
249+
const size_t buffer_size = 128;
250+
char message[buffer_size];
251+
snprintf(message, buffer_size,
252+
"'%s' object is not subscriptable", getBoxedPrimitiveName(bits));
253+
return HPyErr_SetString(ctx, ctx->h_TypeError, message);
254+
}
255+
jstring jname = (*jniEnv)->NewStringUTF(jniEnv, name);
256+
return DO_UPCALL_HPY(CONTEXT_INSTANCE(ctx), GetItems, target, jname);
257+
}
258+
221259
//*************************
222260
// BOXING
223261

@@ -258,14 +296,29 @@ static HPy (*original_Global_Load)(HPyContext *ctx, HPyGlobal global);
258296
static void (*original_Field_Store)(HPyContext *ctx, HPy target_object, HPyField *target_field, HPy h);
259297
static HPy (*original_Field_Load)(HPyContext *ctx, HPy source_object, HPyField source_field);
260298
static int (*original_Is)(HPyContext *ctx, HPy a, HPy b);
299+
static HPy (*original_Type)(HPyContext *, HPy);
261300

262301
static int augment_Is(HPyContext *ctx, HPy a, HPy b) {
263302
long bitsA = toBits(a);
264303
long bitsB = toBits(b);
265304
if (bitsA == bitsB) {
266305
return 1;
267306
} else if (isBoxedHandle(bitsA) && isBoxedHandle(bitsB)) {
268-
return original_Is(ctx, a, b);
307+
// This code assumes that objects pointed by a handle <= SINGLETON_HANDLES_MAX
308+
// always get that same handle
309+
long unboxedA = unboxHandle(bitsA);
310+
long unboxedB = unboxHandle(bitsB);
311+
if (unboxedA <= SINGLETON_HANDLES_MAX) {
312+
return 0;
313+
} else if (unboxedB <= SINGLETON_HANDLES_MAX) {
314+
return 0;
315+
}
316+
// This code assumes that space[x] != NULL <=> objects pointed by x has native struct
317+
void** space = (void**)ctx->_private;
318+
if (space[unboxedA] == NULL && space[unboxedB] == NULL) {
319+
return original_Is(ctx, a, b);
320+
}
321+
return space[unboxedA] == space[unboxedB];
269322
} else {
270323
return 0;
271324
}
@@ -504,7 +557,7 @@ _HPy_HIDDEN void upcallBulkClose(HPyContext *ctx, HPy *items, HPy_ssize_t nitems
504557
}
505558

506559
HPy augment_Global_Load(HPyContext *ctx, HPyGlobal global) {
507-
long bits = toBits(global);
560+
uint64_t bits = toBits(global);
508561
if (bits && isBoxedHandle(bits)) {
509562
return original_Global_Load(ctx, global);
510563
} else {
@@ -513,7 +566,7 @@ HPy augment_Global_Load(HPyContext *ctx, HPyGlobal global) {
513566
}
514567

515568
void augment_Global_Store(HPyContext *ctx, HPyGlobal *global, HPy h) {
516-
long bits = toBits(h);
569+
uint64_t bits = toBits(h);
517570
if (bits && isBoxedHandle(bits)) {
518571
original_Global_Store(ctx, global, h);
519572
} else {
@@ -522,7 +575,7 @@ void augment_Global_Store(HPyContext *ctx, HPyGlobal *global, HPy h) {
522575
}
523576

524577
HPy augment_Field_Load(HPyContext *ctx, HPy source_object, HPyField source_field) {
525-
long bits = toBits(source_field);
578+
uint64_t bits = toBits(source_field);
526579
if (bits && isBoxedHandle(bits)) {
527580
return original_Field_Load(ctx, source_object, source_field);
528581
} else {
@@ -531,14 +584,25 @@ HPy augment_Field_Load(HPyContext *ctx, HPy source_object, HPyField source_field
531584
}
532585

533586
void augment_Field_Store(HPyContext *ctx, HPy target_object, HPyField *target_field, HPy h) {
534-
long bits = toBits(h);
587+
uint64_t bits = toBits(h);
535588
if (bits && isBoxedHandle(bits)) {
536589
original_Field_Store(ctx, target_object, target_field, h);
537590
} else {
538591
target_field->_i = h._i;
539592
}
540593
}
541594

595+
HPy augment_Type(HPyContext *ctx, HPy h) {
596+
uint64_t bits = toBits(h);
597+
if (isBoxedInt(bits)) {
598+
return ctx->h_LongType;
599+
} else if (isBoxedDouble(bits)) {
600+
return ctx->h_FloatType;
601+
} else {
602+
return original_Type(ctx, h);
603+
}
604+
}
605+
542606
void initDirectFastPaths(HPyContext *context) {
543607
LOG("%p", context);
544608
context->name = "HPy Universal ABI (GraalVM backend, JNI)";
@@ -595,6 +659,8 @@ void initDirectFastPaths(HPyContext *context) {
595659

596660
AUGMENT(Is);
597661

662+
AUGMENT(Type);
663+
598664
#undef AUGMENT
599665
}
600666

@@ -656,6 +722,9 @@ JNIEXPORT jint JNICALL Java_com_oracle_graal_python_builtins_objects_cext_hpy_Gr
656722
context->ctx_Field_Load = ctx_Field_Load_jni;
657723
context->ctx_Field_Store = ctx_Field_Store_jni;
658724

725+
context->ctx_SetItem_s = ctx_SetItem_s_jni;
726+
context->ctx_GetItem_s = ctx_GetItem_s_jni;
727+
659728
graal_hpy_context_get_native_context(context)->jni_context = (void *) (*env)->NewGlobalRef(env, ctx);
660729
assert(clazz != NULL);
661730

@@ -672,6 +741,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_graal_python_builtins_objects_cext_hpy_Gr
672741
#define SIG_TRACKER "J"
673742
#define SIG_JCHARARRAY "[C"
674743
#define SIG_JLONGARRAY "[J"
744+
#define SIG_STRING "Ljava/lang/String;"
675745

676746
#define UPCALL(name, jniSigArgs, jniSigRet) \
677747
jniMethod_ ## name = (*env)->GetMethodID(env, clazz, "ctx" #name, "(" jniSigArgs ")" jniSigRet); \

graalpython/com.oracle.graal.python.jni/src/hpy_jni.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@
6262
#define NAN_BOXING_MAX_HANDLE (0x000000007FFFFFFFllu)
6363
#define IMMUTABLE_HANDLES (0x0000000000000100llu)
6464

65+
// Some singleton Python objects are guaranteed to be always represented by
66+
// those handles, so that we do not have to upcall to unambiguously check if
67+
// a handle represents one of those
68+
#define SINGLETON_HANDLES_MAX (3)
69+
6570
#define isBoxedDouble(value) ((value) >= NAN_BOXING_BASE)
6671
#define isBoxedHandle(value) ((value) <= NAN_BOXING_MAX_HANDLE)
6772
#define isBoxedInt(value) (((value) & NAN_BOXING_MASK) == NAN_BOXING_INT)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@
5252
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___SET__;
5353
import static com.oracle.graal.python.nodes.StringLiterals.T_DATE;
5454
import static com.oracle.graal.python.nodes.StringLiterals.T_DATETIME;
55+
import static com.oracle.graal.python.nodes.StringLiterals.T_LBRACKET;
5556
import static com.oracle.graal.python.nodes.StringLiterals.T_STRUCT_TIME;
5657
import static com.oracle.graal.python.nodes.StringLiterals.T_TIME;
5758
import static com.oracle.graal.python.nodes.truffle.TruffleStringMigrationPythonTypes.isJavaString;
58-
import static com.oracle.graal.python.nodes.StringLiterals.T_LBRACKET;
5959
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
6060
import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached;
6161
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
@@ -1346,7 +1346,7 @@ static Object doIt(Object object, Object attrName,
13461346
@GenerateUncached
13471347
public abstract static class PInteropSubscriptAssignNode extends Node {
13481348

1349-
public abstract void execute(Object primary, Object key, Object value) throws UnsupportedMessageException;
1349+
public abstract void execute(PythonAbstractObject primary, Object key, Object value) throws UnsupportedMessageException;
13501350

13511351
@Specialization
13521352
static void doSpecialObject(PythonAbstractObject primary, Object key, Object value,

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
public class GraalHPyBoxing {
4444

45-
// see the corresponding implementation in hpy_native.c
45+
// see the corresponding implementation in hpy_jni.c
4646

4747
/*-
4848
* This NaN boxing mechanism puts all non-double values into the range
@@ -67,6 +67,10 @@ public class GraalHPyBoxing {
6767
private static final long NAN_BOXING_INT_MASK = 0x00000000FFFFFFFFL;
6868
private static final long NAN_BOXING_MAX_HANDLE = Integer.MAX_VALUE;
6969

70+
// First N constants in the HPyContext are guaranteed to always get the same handle assigned.
71+
// Note that 0 is HPy_NULL, so in this case we are counting from 1.
72+
public static final int SINGLETON_HANDLE_MAX = 3;
73+
7074
public static boolean isBoxedDouble(long value) {
7175
return Long.compareUnsigned(value, NAN_BOXING_BASE) >= 0;
7276
}

0 commit comments

Comments
 (0)