bind: do not generate unused Seq objects

Updates golang/go#12619

Change-Id: Ie851795580c82ade3ee70bdb3945b23ca72f57e0
Reviewed-on: https://go-review.googlesource.com/17866
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
David Crawshaw
2016-01-11 18:08:22 +00:00
parent f85352c0f7
commit ab6091a309
3 changed files with 51 additions and 26 deletions
+20 -6
View File
@@ -77,6 +77,9 @@ static mem *mem_ensure(mem *m, uint32_t size) {
}
static mem *mem_get(JNIEnv *env, jobject obj) {
if (obj == NULL) {
return NULL;
}
// Storage space for pointer is always 64-bits, even on 32-bit
// machines. Cast to uintptr_t to avoid -Wint-to-pointer-cast.
return (mem*)(uintptr_t)(*env)->GetLongField(env, obj, memptr_id);
@@ -400,13 +403,20 @@ Java_go_Seq_destroyRef(JNIEnv *env, jclass clazz, jint refnum) {
JNIEXPORT void JNICALL
Java_go_Seq_send(JNIEnv *env, jclass clazz, jstring descriptor, jint code, jobject src_obj, jobject dst_obj) {
uint8_t* req = NULL;
size_t reqlen = 0;
mem *src = mem_get(env, src_obj);
if (src == NULL) {
LOG_FATAL("send src is NULL");
if (src != NULL) {
req = src->buf;
reqlen = src->len;
}
uint8_t** res = NULL;
size_t* reslen = NULL;
mem *dst = mem_get(env, dst_obj);
if (dst == NULL) {
LOG_FATAL("send dst is NULL");
if (dst != NULL) {
res = &dst->buf;
reslen = &dst->len;
}
GoString desc;
@@ -415,9 +425,13 @@ Java_go_Seq_send(JNIEnv *env, jclass clazz, jstring descriptor, jint code, jobje
LOG_FATAL("send GetStringUTFChars failed");
}
desc.n = (*env)->GetStringUTFLength(env, descriptor);
Send(desc, (GoInt)code, src->buf, src->len, &dst->buf, &dst->len);
Send(desc, (GoInt)code, req, reqlen, res, reslen);
(*env)->ReleaseStringUTFChars(env, descriptor, desc.p);
unpin_arrays(env, src); // assume 'src' is no longer needed.
if (src != NULL) {
unpin_arrays(env, src); // assume 'src' is no longer needed.
}
}
JNIEXPORT void JNICALL
+19 -11
View File
@@ -31,18 +31,26 @@ func Send(descriptor string, code int, req *C.uint8_t, reqlen C.size_t, res **C.
if fn == nil {
panic(fmt.Sprintf("invalid descriptor(%s) and code(0x%x)", descriptor, code))
}
in := new(seq.Buffer)
if reqlen > 0 {
in.Data = (*[maxSliceLen]byte)(unsafe.Pointer(req))[:reqlen]
}
out := new(seq.Buffer)
fn(out, in)
// BUG(hyangah): the function returning a go byte slice (so fn writes a pointer into 'out') is unsafe.
// After fn is complete here, Go runtime is free to collect or move the pointed byte slice
// contents. (Explicitly calling runtime.GC here will surface the problem?)
// Without pinning support from Go side, it will be hard to fix it without extra copying.
seqToBuf(res, reslen, out)
var in, out *seq.Buffer
if req != nil && reqlen > 0 {
in = &seq.Buffer{
Data: (*[maxSliceLen]byte)(unsafe.Pointer(req))[:reqlen],
}
}
if res != nil {
out = new(seq.Buffer)
}
fn(out, in)
if res != nil {
// BUG(hyangah): the function returning a go byte slice (so fn writes a pointer into 'out') is unsafe.
// After fn is complete here, Go runtime is free to collect or move the pointed byte slice
// contents. (Explicitly calling runtime.GC here will surface the problem?)
// Without pinning support from Go side, it will be hard to fix it without extra copying.
seqToBuf(res, reslen, out)
}
}
// DestroyRef is called by Java to inform Go it is done with a reference.