Skip to content

Commit ba41b40

Browse files
committed
[GR-38597] Add native impl for HPyTupleBuilder and improve HPyTuple_FromArray.
PullRequest: graalpython/2247
2 parents 072fa95 + c988fe1 commit ba41b40

File tree

8 files changed

+262
-18
lines changed

8 files changed

+262
-18
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
42+
/*
43+
* Native implementation of HPyTupleBuilder.
44+
* This is written in a way that we could also use the internal functions
45+
* 'builder_*' to implement HPyListBuilder.
46+
*/
47+
48+
49+
#include "hpy_jni.h"
50+
51+
typedef struct {
52+
HPy_ssize_t capacity; // allocated handles
53+
HPy handles[0];
54+
} _HPyBuilder_s;
55+
56+
static inline _HPyBuilder_s *_ht2hb(HPyTupleBuilder ht) {
57+
return (_HPyBuilder_s *) (ht)._tup;
58+
}
59+
60+
static inline HPyTupleBuilder _hb2ht(_HPyBuilder_s *hp) {
61+
return (HPyTupleBuilder) {(HPy_ssize_t) (hp)};
62+
}
63+
64+
static inline _HPyBuilder_s *builder_new(HPy_ssize_t size) {
65+
_HPyBuilder_s *hb = calloc(1, sizeof(_HPyBuilder_s) + size * sizeof(HPy));
66+
if (hb == NULL) {
67+
/* delay the MemoryError */
68+
/* note: it's done this way so that the caller doesn't need to
69+
check if HPyTupleBuilder_New() or every HPyTupleBuilder_Set()
70+
raised. If there is a rare error like a MemoryError somewhere,
71+
further calls to the HPyTupleBuilder are ignored. The final
72+
HPyTupleBuilder_Build() will re-raise the MemoryError and so
73+
it's enough for the caller to check at that point. */
74+
} else {
75+
hb->capacity = size;
76+
}
77+
return hb;
78+
}
79+
static inline void builder_set(HPyContext *ctx, _HPyBuilder_s *hb, HPy_ssize_t index, HPy h_item)
80+
{
81+
if (hb != NULL) {
82+
assert(index >= 0 && index < hb->capacity);
83+
assert(HPy_IsNull(hb->handles[index]));
84+
hb->handles[index] = HPy_Dup(ctx, h_item);
85+
}
86+
}
87+
88+
static inline void builder_cancel(HPyContext *ctx, _HPyBuilder_s *hb)
89+
{
90+
if (hb == NULL) {
91+
// we don't report the memory error here: the builder
92+
// is being cancelled (so the result of the builder is not being used)
93+
// and likely it's being cancelled during the handling of another error
94+
return;
95+
}
96+
for (HPy_ssize_t i = 0; i < hb->capacity; i++) {
97+
HPy_Close(ctx, hb->handles[i]);
98+
}
99+
free(hb);
100+
}
101+
102+
_HPy_HIDDEN HPyTupleBuilder
103+
ctx_TupleBuilder_New(HPyContext *ctx, HPy_ssize_t size)
104+
{
105+
return _hb2ht(builder_new(size));
106+
}
107+
108+
_HPy_HIDDEN void
109+
ctx_TupleBuilder_Set(HPyContext *ctx, HPyTupleBuilder builder,
110+
HPy_ssize_t index, HPy h_item)
111+
{
112+
builder_set(ctx, _ht2hb(builder), index, h_item);
113+
}
114+
115+
_HPy_HIDDEN HPy
116+
ctx_TupleBuilder_Build(HPyContext *ctx, HPyTupleBuilder builder)
117+
{
118+
_HPyBuilder_s *hb = _ht2hb(builder);
119+
if (hb == NULL) {
120+
HPyErr_NoMemory(ctx);
121+
return HPy_NULL;
122+
}
123+
HPy res = upcallTupleFromArray(ctx, hb->handles, hb->capacity, JNI_TRUE);
124+
free(hb);
125+
return res;
126+
}
127+
128+
_HPy_HIDDEN void
129+
ctx_TupleBuilder_Cancel(HPyContext *ctx, HPyTupleBuilder builder)
130+
{
131+
builder_cancel(ctx, _ht2hb(builder));
132+
}

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
* SOFTWARE.
4040
*/
4141

42-
#include <hpy.h>
42+
#include "hpy_jni.h"
43+
4344
#include <wchar.h>
4445
#include <assert.h>
4546
#include <stdio.h>
@@ -59,7 +60,6 @@
5960

6061
#include "com_oracle_graal_python_builtins_objects_cext_hpy_GraalHPyContext.h"
6162
#include "hpynative.h"
62-
#include <jni.h>
6363

6464
/* definitions for HPyTracker */
6565
#include "hpy/runtime/ctx_funcs.h"
@@ -88,6 +88,7 @@ static JNIEnv* jniEnv;
8888
UPCALL(UnicodeFromJCharArray, SIG_JCHARARRAY, SIG_HPY) \
8989
UPCALL(DictNew, , SIG_HPY) \
9090
UPCALL(ListNew, SIG_SIZE_T, SIG_HPY) \
91+
UPCALL(TupleFromArray, SIG_JLONGARRAY SIG_BOOL, SIG_HPY) \
9192

9293
#define UPCALL(name, jniSigArgs, jniSigRet) static jmethodID jniMethod_ ## name;
9394
ALL_UPCALLS
@@ -267,6 +268,7 @@ static int (*original_NumberCheck)(HPyContext *ctx, HPy h);
267268
static int (*original_TypeCheck)(HPyContext *ctx, HPy h, HPy type);
268269
static void (*original_Close)(HPyContext *ctx, HPy h);
269270
static HPy (*original_UnicodeFromWideChar)(HPyContext *ctx, const wchar_t *arr, HPy_ssize_t size);
271+
static HPy (*original_TupleFromArray)(HPyContext *ctx, HPy *items, HPy_ssize_t nitems);
270272

271273
static void *augment_AsStruct(HPyContext *ctx, HPy h) {
272274
uint64_t bits = toBits(h);
@@ -428,6 +430,17 @@ static HPy augment_UnicodeFromWideChar(HPyContext *ctx, const wchar_t *u, HPy_ss
428430
}
429431
}
430432

433+
_HPy_HIDDEN HPy upcallTupleFromArray(HPyContext *ctx, HPy *items, HPy_ssize_t nitems, jboolean steal) {
434+
jarray jLongArray = (*jniEnv)->NewLongArray(jniEnv, (jsize) nitems);
435+
(*jniEnv)->SetLongArrayRegion(jniEnv, jLongArray, 0, (jsize) nitems, (const jlong *)items);
436+
return DO_UPCALL_HPY(CONTEXT_INSTANCE(ctx), TupleFromArray, jLongArray, steal);
437+
}
438+
439+
static HPy augment_TupleFromArray(HPyContext *ctx, HPy *items, HPy_ssize_t nitems) {
440+
return upcallTupleFromArray(ctx, items, nitems, JNI_FALSE);
441+
}
442+
443+
431444
void initDirectFastPaths(HPyContext *context) {
432445
LOG("%p", context);
433446
context->name = "HPy Universal ABI (GraalVM backend, JNI)";
@@ -437,10 +450,10 @@ void initDirectFastPaths(HPyContext *context) {
437450

438451
original_FloatAsDouble = context->ctx_Float_AsDouble;
439452
context->ctx_Float_AsDouble = augment_FloatAsDouble;
440-
453+
441454
original_LongAsLong = context->ctx_Long_AsLong;
442455
context->ctx_Long_AsLong = augment_LongAsLong;
443-
456+
444457
original_LongAsDouble = context->ctx_Long_AsDouble;
445458
context->ctx_Long_AsDouble = augment_LongAsDouble;
446459

@@ -467,6 +480,9 @@ void initDirectFastPaths(HPyContext *context) {
467480

468481
original_UnicodeFromWideChar = context->ctx_Unicode_FromWideChar;
469482
context->ctx_Unicode_FromWideChar = augment_UnicodeFromWideChar;
483+
484+
original_TupleFromArray = context->ctx_Tuple_FromArray;
485+
context->ctx_Tuple_FromArray = augment_TupleFromArray;
470486
}
471487

472488
void setHPyContextNativeSpace(HPyContext *context, void** nativeSpace) {
@@ -517,18 +533,25 @@ JNIEXPORT jint JNICALL Java_com_oracle_graal_python_builtins_objects_cext_hpy_Gr
517533
context->ctx_Tracker_ForgetAll = ctx_Tracker_ForgetAll;
518534
context->ctx_Tracker_Close = ctx_Tracker_Close;
519535

536+
context->ctx_TupleBuilder_New = ctx_TupleBuilder_New;
537+
context->ctx_TupleBuilder_Set = ctx_TupleBuilder_Set;
538+
context->ctx_TupleBuilder_Build = ctx_TupleBuilder_Build;
539+
context->ctx_TupleBuilder_Cancel = ctx_TupleBuilder_Cancel;
540+
520541
graal_hpy_context_get_native_context(context)->jni_context = (void *) (*env)->NewGlobalRef(env, ctx);
521542
assert(clazz != NULL);
522543

523544
#define SIG_HPY "J"
524545
#define SIG_SIZE_T "J"
525546
#define SIG_PTR "J"
526547
#define SIG_VOID "V"
548+
#define SIG_BOOL "Z"
527549
#define SIG_INT "I"
528550
#define SIG_LONG "J"
529551
#define SIG_DOUBLE "D"
530552
#define SIG_TRACKER "J"
531553
#define SIG_JCHARARRAY "[C"
554+
#define SIG_JLONGARRAY "[J"
532555

533556
#define UPCALL(name, jniSigArgs, jniSigRet) \
534557
jniMethod_ ## name = (*env)->GetMethodID(env, clazz, "ctx" #name, "(" jniSigArgs ")" jniSigRet); \
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
42+
/*
43+
* Native implementation of HPyTupleBuilder.
44+
* This is written in a way that we could also use the internal functions
45+
* 'builder_*' to implement HPyListBuilder.
46+
*/
47+
48+
#include <hpy.h>
49+
#include <jni.h>
50+
51+
_HPy_HIDDEN HPy upcallTupleFromArray(HPyContext *ctx, HPy *items, HPy_ssize_t nitems, jboolean steal);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/buffer/BufferAcquireGenerateUncachedNode.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -51,7 +51,6 @@
5151
import com.oracle.truffle.api.Truffle;
5252
import com.oracle.truffle.api.frame.VirtualFrame;
5353
import com.oracle.truffle.api.nodes.NodeCost;
54-
import com.oracle.truffle.api.utilities.NeverValidAssumption;
5554

5655
/**
5756
* Helper node for using {@link PythonBufferAcquireLibrary} and {@link PythonBufferAccessLibrary} in
@@ -205,12 +204,12 @@ public PythonBufferAccessLibrary getAccessLib() {
205204

206205
@Override
207206
public Assumption needNotPassFrameAssumption() {
208-
return NeverValidAssumption.INSTANCE;
207+
return Assumption.NEVER_VALID;
209208
}
210209

211210
@Override
212211
public Assumption needNotPassExceptionAssumption() {
213-
return NeverValidAssumption.INSTANCE;
212+
return Assumption.NEVER_VALID;
214213
}
215214

216215
@Override

0 commit comments

Comments
 (0)