bind/java: ensure there is enough capacity for writing seq
The new testLongString triggers the bug without this change. Fixes golang/go#9251. Change-Id: I463e2897b5b08f53801f151c7311d591546c0719 Reviewed-on: https://go-review.googlesource.com/1373 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
parent
96c0ef1480
commit
6cf9d880ce
|
@ -16,6 +16,28 @@ public class SeqTest extends TestCase {
|
||||||
assertEquals("Unexpected arithmetic failure", 7, res);
|
assertEquals("Unexpected arithmetic failure", 7, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testShortString() {
|
||||||
|
String want = "a short string";
|
||||||
|
String got = Testpkg.StrDup(want);
|
||||||
|
assertEquals("Strings should match", want, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLongString() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
for (int i = 0; i < 128*1024; i++) {
|
||||||
|
b.append("0123456789");
|
||||||
|
}
|
||||||
|
String want = b.toString();
|
||||||
|
String got = Testpkg.StrDup(want);
|
||||||
|
assertEquals("Strings should match", want, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUnicode() {
|
||||||
|
String want = "Hello, 世界";
|
||||||
|
String got = Testpkg.StrDup(want);
|
||||||
|
assertEquals("Strings should match", want, got);
|
||||||
|
}
|
||||||
|
|
||||||
public void testGoRefGC() {
|
public void testGoRefGC() {
|
||||||
Testpkg.S s = Testpkg.New();
|
Testpkg.S s = Testpkg.New();
|
||||||
runGC();
|
runGC();
|
||||||
|
|
|
@ -30,21 +30,27 @@ typedef struct mem {
|
||||||
uint32_t cap;
|
uint32_t cap;
|
||||||
} mem;
|
} mem;
|
||||||
|
|
||||||
static mem *mem_resize(mem *m, uint32_t size) {
|
// mem_ensure ensures that m has at least size bytes free.
|
||||||
|
// If m is NULL, it is created.
|
||||||
|
static mem *mem_ensure(mem *m, uint32_t size) {
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
m = (mem*)malloc(sizeof(mem));
|
m = (mem*)malloc(sizeof(mem));
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
LOG_FATAL("mem_resize malloc failed");
|
LOG_FATAL("mem_ensure malloc failed");
|
||||||
}
|
}
|
||||||
|
m->cap = 0;
|
||||||
m->off = 0;
|
m->off = 0;
|
||||||
m->len = 0;
|
m->len = 0;
|
||||||
m->buf = NULL;
|
m->buf = NULL;
|
||||||
}
|
}
|
||||||
m->buf = (uint8_t*)realloc((void*)m->buf, size);
|
if (m->cap > m->off+size) {
|
||||||
if (m->buf == NULL) {
|
return m;
|
||||||
LOG_FATAL("mem_resize realloc failed, size=%d", size);
|
|
||||||
}
|
}
|
||||||
m->cap = size;
|
m->buf = (uint8_t*)realloc((void*)m->buf, m->off+size);
|
||||||
|
if (m->buf == NULL) {
|
||||||
|
LOG_FATAL("mem_ensure realloc failed, off=%d, size=%d", m->off, size);
|
||||||
|
}
|
||||||
|
m->cap = m->off+size;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,9 +84,11 @@ uint8_t *mem_write(JNIEnv *env, jobject obj, uint32_t size) {
|
||||||
if (m->off != m->len) {
|
if (m->off != m->len) {
|
||||||
LOG_FATAL("write can only append to seq, size: (off=%d, len=%d, size=%d", m->off, m->len, size);
|
LOG_FATAL("write can only append to seq, size: (off=%d, len=%d, size=%d", m->off, m->len, size);
|
||||||
}
|
}
|
||||||
if (m->off+size > m->cap) {
|
uint32_t cap = m->cap;
|
||||||
m = mem_resize(m, 2*m->cap);
|
while (m->off+size > cap) {
|
||||||
|
cap *= 2;
|
||||||
}
|
}
|
||||||
|
m = mem_ensure(m, cap);
|
||||||
uint8_t *res = m->buf+m->off;
|
uint8_t *res = m->buf+m->off;
|
||||||
m->off += size;
|
m->off += size;
|
||||||
m->len += size;
|
m->len += size;
|
||||||
|
@ -130,8 +138,8 @@ void init_seq(void *javavm) {
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_go_Seq_ensure(JNIEnv *env, jobject obj, jint size) {
|
Java_go_Seq_ensure(JNIEnv *env, jobject obj, jint size) {
|
||||||
mem *m = mem_get(env, obj);
|
mem *m = mem_get(env, obj);
|
||||||
if (m == NULL || size > m->cap - m->off) {
|
if (m == NULL || m->off+size > m->cap) {
|
||||||
m = mem_resize(m, size);
|
m = mem_ensure(m, size);
|
||||||
(*env)->SetLongField(env, obj, memptr_id, (jlong)(uintptr_t)m);
|
(*env)->SetLongField(env, obj, memptr_id, (jlong)(uintptr_t)m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ public abstract class Testpkg {
|
||||||
public static void Call(I i) {
|
public static void Call(I i) {
|
||||||
go.Seq _in = new go.Seq();
|
go.Seq _in = new go.Seq();
|
||||||
go.Seq _out = new go.Seq();
|
go.Seq _out = new go.Seq();
|
||||||
System.out.println("Call!");
|
|
||||||
_in.writeRef(i.ref());
|
_in.writeRef(i.ref());
|
||||||
Seq.send(DESCRIPTOR, CALL_Call, _in, _out);
|
Seq.send(DESCRIPTOR, CALL_Call, _in, _out);
|
||||||
}
|
}
|
||||||
|
@ -150,11 +149,22 @@ public abstract class Testpkg {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String StrDup(String s) {
|
||||||
|
go.Seq _in = new go.Seq();
|
||||||
|
go.Seq _out = new go.Seq();
|
||||||
|
String _result;
|
||||||
|
_in.writeUTF16(s);
|
||||||
|
Seq.send(DESCRIPTOR, CALL_StrDup, _in, _out);
|
||||||
|
_result = _out.readUTF16();
|
||||||
|
return _result;
|
||||||
|
}
|
||||||
|
|
||||||
private static final int CALL_Add = 1;
|
private static final int CALL_Add = 1;
|
||||||
private static final int CALL_Call = 2;
|
private static final int CALL_Call = 2;
|
||||||
private static final int CALL_GC = 3;
|
private static final int CALL_GC = 3;
|
||||||
private static final int CALL_Keep = 4;
|
private static final int CALL_Keep = 4;
|
||||||
private static final int CALL_New = 5;
|
private static final int CALL_New = 5;
|
||||||
private static final int CALL_NumSCollected = 6;
|
private static final int CALL_NumSCollected = 6;
|
||||||
|
private static final int CALL_StrDup = 7;
|
||||||
private static final String DESCRIPTOR = "testpkg";
|
private static final String DESCRIPTOR = "testpkg";
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,12 @@ func init() {
|
||||||
seq.Register(proxySDescriptor, proxySFCode, proxySF)
|
seq.Register(proxySDescriptor, proxySFCode, proxySF)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func proxy_StrDup(out, in *seq.Buffer) {
|
||||||
|
param_s := in.ReadUTF16()
|
||||||
|
res := testpkg.StrDup(param_s)
|
||||||
|
out.WriteUTF16(res)
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
seq.Register("testpkg", 1, proxy_Add)
|
seq.Register("testpkg", 1, proxy_Add)
|
||||||
seq.Register("testpkg", 2, proxy_Call)
|
seq.Register("testpkg", 2, proxy_Call)
|
||||||
|
@ -88,4 +94,5 @@ func init() {
|
||||||
seq.Register("testpkg", 4, proxy_Keep)
|
seq.Register("testpkg", 4, proxy_Keep)
|
||||||
seq.Register("testpkg", 5, proxy_New)
|
seq.Register("testpkg", 5, proxy_New)
|
||||||
seq.Register("testpkg", 6, proxy_NumSCollected)
|
seq.Register("testpkg", 6, proxy_NumSCollected)
|
||||||
|
seq.Register("testpkg", 7, proxy_StrDup)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,3 +56,7 @@ func Add(x, y int) int {
|
||||||
func NumSCollected() int {
|
func NumSCollected() int {
|
||||||
return numSCollected
|
return numSCollected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StrDup(s string) string {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue