Skip to content

Commit 6f4235c

Browse files
committed
HPy: JNI fast-paths for GetItem_s/SetItem_s
1 parent 02ccb71 commit 6f4235c

File tree

5 files changed

+106
-1
lines changed

5 files changed

+106
-1
lines changed

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

Lines changed: 42 additions & 0 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) \
@@ -539,6 +541,42 @@ void augment_Field_Store(HPyContext *ctx, HPy target_object, HPyField *target_fi
539541
}
540542
}
541543

544+
static const char* getBoxedPrimitiveName(uint64_t bits) {
545+
assert(!isBoxedHandle(bits));
546+
if (isBoxedInt(bits)) {
547+
return "int";
548+
}
549+
assert(isBoxedDouble(bits));
550+
return "float";
551+
}
552+
553+
int augment_SetItem_s(HPyContext *ctx, HPy target, const char *name, HPy value) {
554+
uint64_t bits = toBits(target);
555+
if (!isBoxedHandle(bits)) {
556+
const size_t buffer_size = 128;
557+
char message[buffer_size];
558+
snprintf(message, buffer_size,
559+
"'%s' object does not support item assignment", getBoxedPrimitiveName(bits));
560+
HPyErr_SetString(ctx, ctx->h_TypeError, message);
561+
return -1;
562+
}
563+
jstring jname = (*jniEnv)->NewStringUTF(jniEnv, name);
564+
return DO_UPCALL_INT(CONTEXT_INSTANCE(ctx), SetItems, target, jname, value);
565+
}
566+
567+
HPy augment_GetItem_s(HPyContext *ctx, HPy target, const char *name) {
568+
uint64_t bits = toBits(target);
569+
if (!isBoxedHandle(bits)) {
570+
const size_t buffer_size = 128;
571+
char message[buffer_size];
572+
snprintf(message, buffer_size,
573+
"'%s' object is not subscriptable", getBoxedPrimitiveName(bits));
574+
return HPyErr_SetString(ctx, ctx->h_TypeError, message);
575+
}
576+
jstring jname = (*jniEnv)->NewStringUTF(jniEnv, name);
577+
return DO_UPCALL_HPY(CONTEXT_INSTANCE(ctx), GetItems, target, jname);
578+
}
579+
542580
void initDirectFastPaths(HPyContext *context) {
543581
LOG("%p", context);
544582
context->name = "HPy Universal ABI (GraalVM backend, JNI)";
@@ -596,6 +634,9 @@ void initDirectFastPaths(HPyContext *context) {
596634
AUGMENT(Is);
597635

598636
#undef AUGMENT
637+
638+
context->ctx_SetItem_s = augment_SetItem_s;
639+
context->ctx_GetItem_s = augment_GetItem_s;
599640
}
600641

601642
void setHPyContextNativeSpace(HPyContext *context, void** nativeSpace) {
@@ -672,6 +713,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_graal_python_builtins_objects_cext_hpy_Gr
672713
#define SIG_TRACKER "J"
673714
#define SIG_JCHARARRAY "[C"
674715
#define SIG_JLONGARRAY "[J"
716+
#define SIG_STRING "Ljava/lang/String;"
675717

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

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

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
// skip GIL
4242
package com.oracle.graal.python.builtins.objects.cext.hpy;
4343

44+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError;
4445
import static com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContext.HPyContextSignatureType.DataPtr;
4546
import static com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContext.HPyContextSignatureType.DataPtrPtr;
4647
import static com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContext.HPyContextSignatureType.Double;
@@ -82,6 +83,11 @@
8283

8384
import com.oracle.graal.python.builtins.objects.common.EconomicMapStorage;
8485
import com.oracle.truffle.api.strings.TruffleString;
86+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodes.HPyRaiseNode;
87+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodes.HPyTransformExceptionToNativeNode;
88+
import com.oracle.graal.python.lib.PyObjectGetItem;
89+
import com.oracle.graal.python.lib.PyObjectSetItem;
90+
import com.oracle.graal.python.runtime.GilNode.UncachedAcquire;
8591
import org.graalvm.nativeimage.ImageInfo;
8692

8793
import com.oracle.graal.python.PythonLanguage;
@@ -1650,6 +1656,8 @@ public enum Counter {
16501656
UpcallDictNew,
16511657
UpcallListNew,
16521658
UpcallTupleFromArray,
1659+
UpcallGetItemS,
1660+
UpcallSetItemS,
16531661
UpcallFieldLoad,
16541662
UpcallFieldStore,
16551663
UpcallGlobalLoad,
@@ -1736,6 +1744,48 @@ public long ctxAsStruct(long handle) {
17361744
return (long) HPyGetNativeSpacePointerNodeGen.getUncached().execute(receiver);
17371745
}
17381746

1747+
1748+
// Note: assumes that receiverHandle is not a boxed primitive value
1749+
@SuppressWarnings("try")
1750+
public final int ctxSetItems(long receiverHandle, String name, long valueHandle) {
1751+
increment(Counter.UpcallSetItemS);
1752+
Object receiver = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(receiverHandle));
1753+
Object value;
1754+
if (GraalHPyBoxing.isBoxedHandle(valueHandle)) {
1755+
value = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(valueHandle));
1756+
} else if (GraalHPyBoxing.isBoxedInt(valueHandle)) {
1757+
value = GraalHPyBoxing.unboxInt(valueHandle);
1758+
} else if (GraalHPyBoxing.isBoxedDouble(valueHandle)) {
1759+
value = GraalHPyBoxing.unboxDouble(valueHandle);
1760+
} else {
1761+
HPyRaiseNode.raiseIntUncached(this, -1, SystemError, ErrorMessages.HPY_UNEXPECTED_HPY_NULL);
1762+
return -1;
1763+
}
1764+
try (UncachedAcquire gil = GilNode.uncachedAcquire()) {
1765+
PyObjectSetItem.getUncached().execute(null, receiver, name, value);
1766+
return 0;
1767+
} catch (PException e) {
1768+
HPyTransformExceptionToNativeNode.executeUncached(this, e);
1769+
return -1;
1770+
}
1771+
}
1772+
1773+
// Note: assumes that receiverHandle is not a boxed primitive value
1774+
@SuppressWarnings("try")
1775+
public final long ctxGetItems(long receiverHandle, String name) {
1776+
increment(Counter.UpcallGetItemS);
1777+
Object receiver = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(receiverHandle));
1778+
TruffleString tsName = toTruffleStringUncached(name);
1779+
Object result;
1780+
try (UncachedAcquire gil = GilNode.uncachedAcquire()) {
1781+
result = PyObjectGetItem.getUncached().execute(null, receiver, tsName);
1782+
} catch (PException e) {
1783+
HPyTransformExceptionToNativeNode.executeUncached(this, e);
1784+
return 0;
1785+
}
1786+
return GraalHPyBoxing.boxHandle(getHPyHandleForObject(result));
1787+
}
1788+
17391789
public long ctxNew(long typeHandle, long dataOutVar) {
17401790
increment(Counter.UpcallNew);
17411791

@@ -2352,7 +2402,7 @@ private static Object[] createMembers(PythonContext context, TruffleString name,
23522402
createTypeConstant(members, HPyContextMember.H_INDENTATIONERROR, context, PythonBuiltinClassType.IndentationError);
23532403
createTypeConstant(members, HPyContextMember.H_TABERROR, context, PythonBuiltinClassType.TabError);
23542404
createTypeConstant(members, HPyContextMember.H_REFERENCEERROR, context, PythonBuiltinClassType.ReferenceError);
2355-
createTypeConstant(members, HPyContextMember.H_SYSTEMERROR, context, PythonBuiltinClassType.SystemError);
2405+
createTypeConstant(members, HPyContextMember.H_SYSTEMERROR, context, SystemError);
23562406
createTypeConstant(members, HPyContextMember.H_SYSTEMEXIT, context, PythonBuiltinClassType.SystemExit);
23572407
createTypeConstant(members, HPyContextMember.H_TYPEERROR, context, PythonBuiltinClassType.TypeError);
23582408
createTypeConstant(members, HPyContextMember.H_UNBOUNDLOCALERROR, context, PythonBuiltinClassType.UnboundLocalError);

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,11 @@
9696
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyAttachNFIFunctionTypeNodeGen;
9797
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyGetSetSetterHandleCloseNodeGen;
9898
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyKeywordsHandleCloseNodeGen;
99+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyRaiseNodeGen;
99100
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyRichcmptFuncArgsCloseNodeGen;
100101
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPySSizeObjArgProcCloseNodeGen;
101102
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPySelfHandleCloseNodeGen;
103+
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyTransformExceptionToNativeNodeGen;
102104
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNodesFactory.HPyVarargsHandleCloseNodeGen;
103105
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyObjectBuiltins.HPyObjectNewNode;
104106
import com.oracle.graal.python.builtins.objects.cext.hpy.HPyArrayWrappers.HPyArrayWrapper;
@@ -228,6 +230,10 @@ public final void execute(GraalHPyContext nativeContext, PException e) {
228230
execute(null, nativeContext, e);
229231
}
230232

233+
public static void executeUncached(GraalHPyContext nativeContext, PException e) {
234+
HPyTransformExceptionToNativeNodeGen.getUncached().execute(nativeContext, e);
235+
}
236+
231237
@Specialization
232238
static void setCurrentException(Frame frame, GraalHPyContext nativeContext, PException e,
233239
@Cached GetCurrentFrameRef getCurrentFrameRef,
@@ -257,6 +263,10 @@ public final Object raiseWithoutFrame(GraalHPyContext nativeContext, Object erro
257263
return execute(null, nativeContext, errorValue, errType, format, arguments);
258264
}
259265

266+
public static int raiseIntUncached(GraalHPyContext nativeContext, int errorValue, PythonBuiltinClassType errType, TruffleString format, Object... arguments) {
267+
return HPyRaiseNodeGen.getUncached().raiseIntWithoutFrame(nativeContext, errorValue, errType, format, arguments);
268+
}
269+
260270
public abstract Object execute(Frame frame, GraalHPyContext nativeContext, Object errorValue, PythonBuiltinClassType errType, TruffleString format, Object[] arguments);
261271

262272
public abstract int executeInt(Frame frame, GraalHPyContext nativeContext, int errorValue, PythonBuiltinClassType errType, TruffleString format, Object[] arguments);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,4 +1441,5 @@ public abstract class ErrorMessages {
14411441
public static final TruffleString MSG_NOT_SET = tsLiteral("<message not set>");
14421442

14431443
public static final TruffleString HPY_DEBUG_MODE_NOT_AVAILABLE = tsLiteral("HPy debug mode is not available");
1444+
public static final TruffleString HPY_UNEXPECTED_HPY_NULL = tsLiteral("unexpected HPy_NULL");
14441445
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/resources/jni-config.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
{"name":"ctxUnicodeFromWideChar","parameterTypes":["long","long"] },
2626
{"name":"ctxUnicodeFromJCharArray","parameterTypes":["char[]"] },
2727
{"name":"ctxTupleFromArray","parameterTypes":["long[]", "boolean"] },
28+
{"name":"ctxSetItems","parameterTypes":["long", "java.lang.String", "long"] },
29+
{"name":"ctxGetItems","parameterTypes":["long", "java.lang.String"] },
2830
{"name":"ctxGlobalLoad","parameterTypes":["long"] },
2931
{"name":"ctxGlobalStore","parameterTypes":["long","long"] },
3032
{"name":"ctxFieldLoad","parameterTypes":["long","long"] },

0 commit comments

Comments
 (0)