mirror of
https://github.com/corda/corda.git
synced 2025-01-01 10:46:46 +00:00
implement tableswitch and lookupswitch instructions plus run loop bugfixes and tweaks
This commit is contained in:
parent
c20219df19
commit
bf230ee151
2
makefile
2
makefile
@ -16,7 +16,7 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
input = $(cls)/References.class
|
input = $(cls)/Switch.class
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
cc = gcc
|
||||||
|
178
src/run.cpp
178
src/run.cpp
@ -531,6 +531,24 @@ classInit(Thread* t, object class_, unsigned ipOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int16_t
|
||||||
|
codeReadInt16(Thread* t, unsigned& i)
|
||||||
|
{
|
||||||
|
uint8_t v1 = codeBody(t, t->code, i++);
|
||||||
|
uint8_t v2 = codeBody(t, t->code, i++);
|
||||||
|
return ((v1 << 8) | v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32_t
|
||||||
|
codeReadInt32(Thread* t, unsigned& i)
|
||||||
|
{
|
||||||
|
uint8_t v1 = codeBody(t, t->code, i++);
|
||||||
|
uint8_t v2 = codeBody(t, t->code, i++);
|
||||||
|
uint8_t v3 = codeBody(t, t->code, i++);
|
||||||
|
uint8_t v4 = codeBody(t, t->code, i++);
|
||||||
|
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
run(Thread* t)
|
run(Thread* t)
|
||||||
{
|
{
|
||||||
@ -649,9 +667,7 @@ run(Thread* t)
|
|||||||
int32_t count = popInt(t);
|
int32_t count = popInt(t);
|
||||||
|
|
||||||
if (LIKELY(count >= 0)) {
|
if (LIKELY(count >= 0)) {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -756,7 +772,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case bipush: {
|
case bipush: {
|
||||||
pushInt(t, codeBody(t, code, ip++));
|
pushInt(t, static_cast<int8_t>(codeBody(t, code, ip++)));
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case caload: {
|
case caload: {
|
||||||
@ -803,12 +819,9 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case checkcast: {
|
case checkcast: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
if (peekObject(t, sp - 1)) {
|
if (peekObject(t, sp - 1)) {
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
@ -892,9 +905,7 @@ run(Thread* t)
|
|||||||
|
|
||||||
case getfield: {
|
case getfield: {
|
||||||
if (LIKELY(peekObject(t, sp - 1))) {
|
if (LIKELY(peekObject(t, sp - 1))) {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -936,9 +947,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case getstatic: {
|
case getstatic: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -972,20 +981,13 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case goto_: {
|
case goto_: {
|
||||||
uint8_t offset1 = codeBody(t, code, ip++);
|
int16_t offset = codeReadInt16(t, ip);
|
||||||
uint8_t offset2 = codeBody(t, code, ip++);
|
ip = (ip - 3) + offset;
|
||||||
|
|
||||||
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case goto_w: {
|
case goto_w: {
|
||||||
uint8_t offset1 = codeBody(t, code, ip++);
|
int32_t offset = codeReadInt32(t, ip);
|
||||||
uint8_t offset2 = codeBody(t, code, ip++);
|
ip = (ip - 5) + offset;
|
||||||
uint8_t offset3 = codeBody(t, code, ip++);
|
|
||||||
uint8_t offset4 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
ip = (ip - 5) + static_cast<int32_t>
|
|
||||||
(((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case i2b: {
|
case i2b: {
|
||||||
@ -1319,9 +1321,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case invokeinterface: {
|
case invokeinterface: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
ip += 2;
|
ip += 2;
|
||||||
|
|
||||||
@ -1342,9 +1342,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case invokespecial: {
|
case invokespecial: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -1377,9 +1375,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case invokestatic: {
|
case invokestatic: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -1390,9 +1386,7 @@ run(Thread* t)
|
|||||||
} goto invoke;
|
} goto invoke;
|
||||||
|
|
||||||
case invokevirtual: {
|
case invokevirtual: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -1677,6 +1671,38 @@ run(Thread* t)
|
|||||||
pushLong(t, - popInt(t));
|
pushLong(t, - popInt(t));
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
|
case lookupswitch: {
|
||||||
|
int32_t base = ip - 1;
|
||||||
|
|
||||||
|
ip += 3;
|
||||||
|
ip -= (ip % 4);
|
||||||
|
|
||||||
|
int32_t default_ = codeReadInt32(t, ip);
|
||||||
|
int32_t pairCount = codeReadInt32(t, ip);
|
||||||
|
|
||||||
|
int32_t key = popInt(t);
|
||||||
|
|
||||||
|
int32_t bottom = 0;
|
||||||
|
int32_t top = pairCount;
|
||||||
|
for (int32_t span = top - bottom; span; span = top - bottom) {
|
||||||
|
int32_t middle = bottom + (span / 2);
|
||||||
|
unsigned index = ip + (middle * 8);
|
||||||
|
|
||||||
|
int32_t k = codeReadInt32(t, index);
|
||||||
|
|
||||||
|
if (key < k) {
|
||||||
|
top = middle;
|
||||||
|
} else if (key > k) {
|
||||||
|
bottom = middle + 1;
|
||||||
|
} else {
|
||||||
|
ip = base + codeReadInt32(t, index);
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = base + default_;
|
||||||
|
} goto loop;
|
||||||
|
|
||||||
case lor: {
|
case lor: {
|
||||||
int64_t b = popLong(t);
|
int64_t b = popLong(t);
|
||||||
int64_t a = popLong(t);
|
int64_t a = popLong(t);
|
||||||
@ -1778,9 +1804,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case new_: {
|
case new_: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -1853,9 +1877,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case putfield: {
|
case putfield: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -1920,9 +1942,7 @@ run(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case putstatic: {
|
case putstatic: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -2019,7 +2039,7 @@ run(Thread* t)
|
|||||||
uint8_t byte1 = codeBody(t, code, ip++);
|
uint8_t byte1 = codeBody(t, code, ip++);
|
||||||
uint8_t byte2 = codeBody(t, code, ip++);
|
uint8_t byte2 = codeBody(t, code, ip++);
|
||||||
|
|
||||||
pushInt(t, (byte1 << 8) | byte2);
|
pushInt(t, static_cast<int16_t>((byte1 << 8) | byte2));
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case swap: {
|
case swap: {
|
||||||
@ -2029,6 +2049,26 @@ run(Thread* t)
|
|||||||
memcpy(stack + ((sp - 2) * 2), tmp , BytesPerWord * 2);
|
memcpy(stack + ((sp - 2) * 2), tmp , BytesPerWord * 2);
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
|
case tableswitch: {
|
||||||
|
int32_t base = ip - 1;
|
||||||
|
|
||||||
|
ip += 3;
|
||||||
|
ip -= (ip % 4);
|
||||||
|
|
||||||
|
int32_t default_ = codeReadInt32(t, ip);
|
||||||
|
int32_t bottom = codeReadInt32(t, ip);
|
||||||
|
int32_t top = codeReadInt32(t, ip);
|
||||||
|
|
||||||
|
int32_t key = popInt(t);
|
||||||
|
|
||||||
|
if (key >= bottom and key <= top) {
|
||||||
|
unsigned index = ip + ((key - bottom) * 4);
|
||||||
|
ip = base + codeReadInt32(t, index);
|
||||||
|
} else {
|
||||||
|
ip = base + default_;
|
||||||
|
}
|
||||||
|
} goto loop;
|
||||||
|
|
||||||
case wide: goto wide;
|
case wide: goto wide;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
@ -2037,64 +2077,38 @@ run(Thread* t)
|
|||||||
wide:
|
wide:
|
||||||
switch (codeBody(t, code, ip++)) {
|
switch (codeBody(t, code, ip++)) {
|
||||||
case aload: {
|
case aload: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
pushObject(t, localObject(t, codeReadInt16(t, ip)));
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
pushObject(t, localObject(t, (index1 << 8) | index2));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case astore: {
|
case astore: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
setLocalObject(t, codeReadInt16(t, ip), popObject(t));
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
setLocalObject(t, (index1 << 8) | index2, popObject(t));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case iinc: {
|
case iinc: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
uint16_t index = codeReadInt16(t, ip);
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
uint16_t count = codeReadInt16(t, ip);
|
||||||
uint16_t index = (index1 << 8) | index2;
|
|
||||||
|
|
||||||
uint8_t count1 = codeBody(t, code, ip++);
|
|
||||||
uint8_t count2 = codeBody(t, code, ip++);
|
|
||||||
uint16_t count = (count1 << 8) | count2;
|
|
||||||
|
|
||||||
setLocalInt(t, index, localInt(t, index) + count);
|
setLocalInt(t, index, localInt(t, index) + count);
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case iload: {
|
case iload: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
pushInt(t, localInt(t, codeReadInt16(t, ip)));
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
pushInt(t, localInt(t, (index1 << 8) | index2));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case istore: {
|
case istore: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
setLocalInt(t, codeReadInt16(t, ip), popInt(t));
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
setLocalInt(t, (index1 << 8) | index2, popInt(t));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case lload: {
|
case lload: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
pushLong(t, localLong(t, codeReadInt16(t, ip)));
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
pushLong(t, localLong(t, (index1 << 8) | index2));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case lstore: {
|
case lstore: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
setLocalLong(t, codeReadInt16(t, ip), popLong(t));
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
setLocalLong(t, (index1 << 8) | index2, popLong(t));
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case ret: {
|
case ret: {
|
||||||
uint8_t index1 = codeBody(t, code, ip++);
|
ip = localInt(t, codeReadInt16(t, ip));
|
||||||
uint8_t index2 = codeBody(t, code, ip++);
|
|
||||||
|
|
||||||
ip = localInt(t, (index1 << 8) | index2);
|
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
|
66
test/Switch.java
Normal file
66
test/Switch.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
public class Switch {
|
||||||
|
private static int table(int k) {
|
||||||
|
switch (k) {
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
return 1;
|
||||||
|
case 2:
|
||||||
|
return 2;
|
||||||
|
case 9:
|
||||||
|
return 9;
|
||||||
|
case 10:
|
||||||
|
return 10;
|
||||||
|
case 11:
|
||||||
|
return 11;
|
||||||
|
case 12:
|
||||||
|
return 8;
|
||||||
|
case -5:
|
||||||
|
return 5;
|
||||||
|
default:
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int lookup(int k) {
|
||||||
|
switch (k) {
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 45:
|
||||||
|
return 45;
|
||||||
|
case 46:
|
||||||
|
return 46;
|
||||||
|
case 47:
|
||||||
|
return -47;
|
||||||
|
case 200:
|
||||||
|
return 200;
|
||||||
|
case 244:
|
||||||
|
return 244;
|
||||||
|
case 245:
|
||||||
|
return 245;
|
||||||
|
default:
|
||||||
|
return 91;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void expect(boolean v) {
|
||||||
|
if (! v) throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
expect(table(0) == 0);
|
||||||
|
expect(table(9) == 9);
|
||||||
|
expect(table(10) == 10);
|
||||||
|
expect(table(11) == 11);
|
||||||
|
expect(table(12) == 8);
|
||||||
|
expect(table(-5) == 5);
|
||||||
|
expect(table(-13) == 7);
|
||||||
|
|
||||||
|
expect(lookup(0) == 0);
|
||||||
|
expect(lookup(45) == 45);
|
||||||
|
expect(lookup(46) == 46);
|
||||||
|
expect(lookup(47) == -47);
|
||||||
|
expect(lookup(245) == 245);
|
||||||
|
expect(lookup(246) == 91);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user