mirror of
https://github.com/corda/corda.git
synced 2024-12-28 16:58:55 +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
|
||||
test = test
|
||||
|
||||
input = $(cls)/References.class
|
||||
input = $(cls)/Switch.class
|
||||
|
||||
cxx = g++
|
||||
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
|
||||
run(Thread* t)
|
||||
{
|
||||
@ -649,9 +667,7 @@ run(Thread* t)
|
||||
int32_t count = popInt(t);
|
||||
|
||||
if (LIKELY(count >= 0)) {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -756,7 +772,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case bipush: {
|
||||
pushInt(t, codeBody(t, code, ip++));
|
||||
pushInt(t, static_cast<int8_t>(codeBody(t, code, ip++)));
|
||||
} goto loop;
|
||||
|
||||
case caload: {
|
||||
@ -803,12 +819,9 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case checkcast: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
if (peekObject(t, sp - 1)) {
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
|
||||
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
|
||||
@ -892,9 +905,7 @@ run(Thread* t)
|
||||
|
||||
case getfield: {
|
||||
if (LIKELY(peekObject(t, sp - 1))) {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object field = resolveField(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -936,9 +947,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case getstatic: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object field = resolveField(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -972,20 +981,13 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case goto_: {
|
||||
uint8_t offset1 = codeBody(t, code, ip++);
|
||||
uint8_t offset2 = codeBody(t, code, ip++);
|
||||
|
||||
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
||||
int16_t offset = codeReadInt16(t, ip);
|
||||
ip = (ip - 3) + offset;
|
||||
} goto loop;
|
||||
|
||||
case goto_w: {
|
||||
uint8_t offset1 = codeBody(t, code, ip++);
|
||||
uint8_t offset2 = codeBody(t, code, ip++);
|
||||
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));
|
||||
int32_t offset = codeReadInt32(t, ip);
|
||||
ip = (ip - 5) + offset;
|
||||
} goto loop;
|
||||
|
||||
case i2b: {
|
||||
@ -1319,9 +1321,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case invokeinterface: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
ip += 2;
|
||||
|
||||
@ -1342,9 +1342,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case invokespecial: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -1377,9 +1375,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case invokestatic: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -1390,9 +1386,7 @@ run(Thread* t)
|
||||
} goto invoke;
|
||||
|
||||
case invokevirtual: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -1677,6 +1671,38 @@ run(Thread* t)
|
||||
pushLong(t, - popInt(t));
|
||||
} 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: {
|
||||
int64_t b = popLong(t);
|
||||
int64_t a = popLong(t);
|
||||
@ -1778,9 +1804,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case new_: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -1853,9 +1877,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case putfield: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object field = resolveField(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -1920,9 +1942,7 @@ run(Thread* t)
|
||||
} goto loop;
|
||||
|
||||
case putstatic: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
uint16_t index = (index1 << 8) | index2;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
|
||||
object field = resolveField(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
@ -2019,7 +2039,7 @@ run(Thread* t)
|
||||
uint8_t byte1 = 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;
|
||||
|
||||
case swap: {
|
||||
@ -2029,6 +2049,26 @@ run(Thread* t)
|
||||
memcpy(stack + ((sp - 2) * 2), tmp , BytesPerWord * 2);
|
||||
} 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;
|
||||
|
||||
default: abort(t);
|
||||
@ -2037,64 +2077,38 @@ run(Thread* t)
|
||||
wide:
|
||||
switch (codeBody(t, code, ip++)) {
|
||||
case aload: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
|
||||
pushObject(t, localObject(t, (index1 << 8) | index2));
|
||||
pushObject(t, localObject(t, codeReadInt16(t, ip)));
|
||||
} goto loop;
|
||||
|
||||
case astore: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
|
||||
setLocalObject(t, (index1 << 8) | index2, popObject(t));
|
||||
setLocalObject(t, codeReadInt16(t, ip), popObject(t));
|
||||
} goto loop;
|
||||
|
||||
case iinc: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, 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;
|
||||
uint16_t index = codeReadInt16(t, ip);
|
||||
uint16_t count = codeReadInt16(t, ip);
|
||||
|
||||
setLocalInt(t, index, localInt(t, index) + count);
|
||||
} goto loop;
|
||||
|
||||
case iload: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
|
||||
pushInt(t, localInt(t, (index1 << 8) | index2));
|
||||
pushInt(t, localInt(t, codeReadInt16(t, ip)));
|
||||
} goto loop;
|
||||
|
||||
case istore: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
|
||||
setLocalInt(t, (index1 << 8) | index2, popInt(t));
|
||||
setLocalInt(t, codeReadInt16(t, ip), popInt(t));
|
||||
} goto loop;
|
||||
|
||||
case lload: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
|
||||
pushLong(t, localLong(t, (index1 << 8) | index2));
|
||||
pushLong(t, localLong(t, codeReadInt16(t, ip)));
|
||||
} goto loop;
|
||||
|
||||
case lstore: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
|
||||
setLocalLong(t, (index1 << 8) | index2, popLong(t));
|
||||
setLocalLong(t, codeReadInt16(t, ip), popLong(t));
|
||||
} goto loop;
|
||||
|
||||
case ret: {
|
||||
uint8_t index1 = codeBody(t, code, ip++);
|
||||
uint8_t index2 = codeBody(t, code, ip++);
|
||||
|
||||
ip = localInt(t, (index1 << 8) | index2);
|
||||
ip = localInt(t, codeReadInt16(t, ip));
|
||||
} goto loop;
|
||||
|
||||
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