implement long
This commit is contained in:
parent
baa3db16b1
commit
eef2c848e8
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@
|
||||
*.out
|
||||
main
|
||||
print_class
|
||||
__pycache__
|
@ -142,8 +142,14 @@ struct class_file * class_file_parse(const uint8_t * buf)
|
||||
break;
|
||||
case CONSTANT_Long: [[fallthrough]];
|
||||
case CONSTANT_Double:
|
||||
constant->_long.high_bytes = parse_u4(&buf);
|
||||
constant->_long.low_bytes = parse_u4(&buf);
|
||||
{
|
||||
uint64_t high_bytes = parse_u4(&buf);
|
||||
uint64_t low_bytes = parse_u4(&buf);
|
||||
constant->_long.bytes = high_bytes << 32 | low_bytes;
|
||||
// long and double use two constant pool entries
|
||||
class_file->constant_pool[i + 1].tag = 0;
|
||||
i += 1;
|
||||
}
|
||||
break;
|
||||
case CONSTANT_NameAndType:
|
||||
constant->nameandtype.name_index = parse_u2(&buf);
|
||||
@ -170,9 +176,7 @@ struct class_file * class_file_parse(const uint8_t * buf)
|
||||
constant->module.name_index = parse_u2(&buf);
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
assert(false);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t u8;
|
||||
typedef uint32_t u4;
|
||||
typedef uint16_t u2;
|
||||
typedef uint8_t u1;
|
||||
@ -58,13 +59,11 @@ struct constant_Float_info {
|
||||
};
|
||||
|
||||
struct constant_Long_info {
|
||||
u4 high_bytes;
|
||||
u4 low_bytes;
|
||||
u8 bytes;
|
||||
};
|
||||
|
||||
struct constant_Double_info {
|
||||
u4 high_bytes;
|
||||
u4 low_bytes;
|
||||
u8 bytes;
|
||||
};
|
||||
|
||||
struct constant_NameAndType_info {
|
||||
|
@ -181,7 +181,8 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent
|
||||
method_name_length,
|
||||
method_descriptor,
|
||||
method_descriptor_length);
|
||||
assert(e != nullptr);
|
||||
if (e == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return (struct method_info *)e->value;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "class_file.h"
|
||||
#include "bytes.h"
|
||||
@ -50,14 +51,12 @@ void print_constant(struct constant * constant)
|
||||
*(float *)(&constant->_float.bytes));
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
printf("CONSTANT_Long high_bytes=%d low_bytes=%d\n",
|
||||
constant->_long.high_bytes,
|
||||
constant->_long.low_bytes);
|
||||
printf("CONSTANT_Long bytes=%" PRId64 "\n",
|
||||
constant->_long.bytes);
|
||||
break;
|
||||
case CONSTANT_Double:
|
||||
printf("CONSTANT_Double high_bytes=%d low_bytes=%d\n",
|
||||
constant->_long.high_bytes,
|
||||
constant->_long.low_bytes);
|
||||
printf("CONSTANT_Double bytes=%f\n",
|
||||
*(double *)(&constant->_double.bytes));
|
||||
break;
|
||||
case CONSTANT_NameAndType:
|
||||
printf("CONSTANT_NameAndType %d %d\n",
|
||||
@ -221,8 +220,10 @@ void print_class_file(struct class_file * class_file)
|
||||
|
||||
printf("constants:\n");
|
||||
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
|
||||
printf("% 3d: ", i + 1);
|
||||
print_constant(&class_file->constant_pool[i]);
|
||||
if (class_file->constant_pool[i].tag != 0) {
|
||||
printf("% 3d: ", i + 1);
|
||||
print_constant(&class_file->constant_pool[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("access_flags %04x\n", class_file->access_flags);
|
||||
|
209
c/execute.c
209
c/execute.c
@ -321,7 +321,9 @@ void op_f2i(struct vm * vm)
|
||||
|
||||
void op_f2l(struct vm * vm)
|
||||
{
|
||||
assert(!"op_f2l");
|
||||
float value = operand_stack_pop_f32(vm->current_frame);
|
||||
int64_t result = (int64_t)value;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_fadd(struct vm * vm)
|
||||
@ -599,7 +601,9 @@ void op_i2f(struct vm * vm)
|
||||
|
||||
void op_i2l(struct vm * vm)
|
||||
{
|
||||
assert(!"op_i2l");
|
||||
int32_t value = operand_stack_pop_u32(vm->current_frame);
|
||||
int64_t result = (int64_t)value;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_i2s(struct vm * vm)
|
||||
@ -629,9 +633,9 @@ void op_iaload(struct vm * vm)
|
||||
|
||||
void op_iand(struct vm * vm)
|
||||
{
|
||||
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
|
||||
int32_t value1 = operand_stack_pop_u32(vm->current_frame);
|
||||
int32_t result = value1 & value2;
|
||||
uint32_t value2 = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t value1 = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t result = value1 & value2;
|
||||
operand_stack_push_u32(vm->current_frame, result);
|
||||
}
|
||||
|
||||
@ -954,7 +958,7 @@ void op_ior(struct vm * vm)
|
||||
{
|
||||
uint32_t value2 = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t value1 = operand_stack_pop_u32(vm->current_frame);
|
||||
int32_t result = value1 | value2;
|
||||
uint32_t result = value1 | value2;
|
||||
operand_stack_push_u32(vm->current_frame, result);
|
||||
}
|
||||
|
||||
@ -1072,7 +1076,7 @@ void op_ixor(struct vm * vm)
|
||||
{
|
||||
uint32_t value2 = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t value1 = operand_stack_pop_u32(vm->current_frame);
|
||||
int32_t result = value1 ^ value2;
|
||||
uint32_t result = value1 ^ value2;
|
||||
operand_stack_push_u32(vm->current_frame, result);
|
||||
}
|
||||
|
||||
@ -1093,47 +1097,79 @@ void op_l2d(struct vm * vm)
|
||||
|
||||
void op_l2f(struct vm * vm)
|
||||
{
|
||||
assert(!"op_l2f");
|
||||
int64_t value = operand_stack_pop_u64(vm->current_frame);
|
||||
float result = (float)value;
|
||||
operand_stack_push_f32(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_l2i(struct vm * vm)
|
||||
{
|
||||
assert(!"op_l2i");
|
||||
int64_t value = operand_stack_pop_u64(vm->current_frame);
|
||||
int32_t result = (int32_t)value;
|
||||
operand_stack_push_u32(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_ladd(struct vm * vm)
|
||||
{
|
||||
assert(!"op_ladd");
|
||||
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t result = value1 + value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_laload(struct vm * vm)
|
||||
{
|
||||
assert(!"op_laload");
|
||||
int32_t index = operand_stack_pop_u32(vm->current_frame);
|
||||
int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
|
||||
assert(arrayref[0] > 0 && index < arrayref[0]);
|
||||
int64_t * longarray = (int64_t *)&arrayref[1];
|
||||
int64_t value = longarray[index];
|
||||
operand_stack_push_u64(vm->current_frame, value);
|
||||
}
|
||||
|
||||
void op_land(struct vm * vm)
|
||||
{
|
||||
assert(!"op_land");
|
||||
uint64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
uint64_t result = value1 & value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lastore(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lastore");
|
||||
int64_t value = operand_stack_pop_u64(vm->current_frame);
|
||||
int32_t index = operand_stack_pop_u32(vm->current_frame);
|
||||
int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
|
||||
assert(arrayref[0] > 0 && index < arrayref[0]);
|
||||
int64_t * longarray = (int64_t *)&arrayref[1];
|
||||
longarray[index] = value;
|
||||
}
|
||||
|
||||
void op_lcmp(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lcmp");
|
||||
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
bool greater = value1 > value2;
|
||||
bool equal = value1 == value2;
|
||||
int32_t value;
|
||||
if (equal) {
|
||||
value = 0;
|
||||
} else if (greater) {
|
||||
value = 1;
|
||||
} else { // less than
|
||||
value = -1;
|
||||
}
|
||||
operand_stack_push_u32(vm->current_frame, value);
|
||||
}
|
||||
|
||||
void op_lconst_0(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lconst_0");
|
||||
operand_stack_push_u64(vm->current_frame, 0);
|
||||
}
|
||||
|
||||
void op_lconst_1(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lconst_1");
|
||||
operand_stack_push_u64(vm->current_frame, 1);
|
||||
}
|
||||
|
||||
void op_ldc(struct vm * vm, uint32_t index)
|
||||
@ -1148,7 +1184,12 @@ void op_ldc(struct vm * vm, uint32_t index)
|
||||
|
||||
void op_ldc2_w(struct vm * vm, uint32_t index)
|
||||
{
|
||||
assert(!"op_ldc2_w");
|
||||
struct constant * constant = &vm->current_thread.current_class->constant_pool[index - 1];
|
||||
#ifdef DEBUG
|
||||
assert(constant->tag == CONSTANT_Long || constant->tag == CONSTANT_Double);
|
||||
#endif
|
||||
int64_t value = constant->_long.bytes;
|
||||
operand_stack_push_u64(vm->current_frame, value);
|
||||
}
|
||||
|
||||
void op_ldc_w(struct vm * vm, uint32_t index)
|
||||
@ -1158,42 +1199,65 @@ void op_ldc_w(struct vm * vm, uint32_t index)
|
||||
|
||||
void op_ldiv(struct vm * vm)
|
||||
{
|
||||
assert(!"op_ldiv");
|
||||
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t result = value1 / value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lload(struct vm * vm, uint32_t index)
|
||||
{
|
||||
assert(!"op_lload");
|
||||
uint32_t low = vm->current_frame->local_variable[index];
|
||||
uint32_t high = vm->current_frame->local_variable[index + 1];
|
||||
operand_stack_push_u32(vm->current_frame, low);
|
||||
operand_stack_push_u32(vm->current_frame, high);
|
||||
}
|
||||
|
||||
void op_lload_0(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lload_0");
|
||||
uint32_t low = vm->current_frame->local_variable[0];
|
||||
uint32_t high = vm->current_frame->local_variable[0 + 1];
|
||||
operand_stack_push_u32(vm->current_frame, low);
|
||||
operand_stack_push_u32(vm->current_frame, high);
|
||||
}
|
||||
|
||||
void op_lload_1(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lload_1");
|
||||
uint32_t low = vm->current_frame->local_variable[1];
|
||||
uint32_t high = vm->current_frame->local_variable[1 + 1];
|
||||
operand_stack_push_u32(vm->current_frame, low);
|
||||
operand_stack_push_u32(vm->current_frame, high);
|
||||
}
|
||||
|
||||
void op_lload_2(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lload_2");
|
||||
uint32_t low = vm->current_frame->local_variable[2];
|
||||
uint32_t high = vm->current_frame->local_variable[2 + 1];
|
||||
operand_stack_push_u32(vm->current_frame, low);
|
||||
operand_stack_push_u32(vm->current_frame, high);
|
||||
}
|
||||
|
||||
void op_lload_3(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lload_3");
|
||||
uint32_t low = vm->current_frame->local_variable[3];
|
||||
uint32_t high = vm->current_frame->local_variable[3 + 1];
|
||||
operand_stack_push_u32(vm->current_frame, low);
|
||||
operand_stack_push_u32(vm->current_frame, high);
|
||||
}
|
||||
|
||||
void op_lmul(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lmul");
|
||||
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t result = value1 * value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lneg(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lneg");
|
||||
int64_t value = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t result = -value;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lookupswitch(struct vm * vm)
|
||||
@ -1203,67 +1267,107 @@ void op_lookupswitch(struct vm * vm)
|
||||
|
||||
void op_lor(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lor");
|
||||
uint64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
uint64_t result = value1 | value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lrem(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lrem");
|
||||
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t result = value1 % value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lreturn(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lreturn");
|
||||
assert(vm->current_frame->return_type == 'J');
|
||||
vm_method_return(vm);
|
||||
}
|
||||
|
||||
void op_lshl(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lshl");
|
||||
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int s = value2 & 0b111111;
|
||||
int64_t result = value1 << s;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lshr(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lshr");
|
||||
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int s = value2 & 0b111111;
|
||||
int64_t result = value1 >> s;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lstore(struct vm * vm, uint32_t index)
|
||||
{
|
||||
assert(!"op_lstore");
|
||||
uint32_t high = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
||||
vm->current_frame->local_variable[index + 1] = high;
|
||||
vm->current_frame->local_variable[index] = low;
|
||||
}
|
||||
|
||||
void op_lstore_0(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lstore_0");
|
||||
uint32_t high = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
||||
vm->current_frame->local_variable[0 + 1] = high;
|
||||
vm->current_frame->local_variable[0] = low;
|
||||
}
|
||||
|
||||
void op_lstore_1(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lstore_1");
|
||||
uint32_t high = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
||||
vm->current_frame->local_variable[1 + 1] = high;
|
||||
vm->current_frame->local_variable[1] = low;
|
||||
}
|
||||
|
||||
void op_lstore_2(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lstore_2");
|
||||
uint32_t high = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
||||
vm->current_frame->local_variable[2 + 1] = high;
|
||||
vm->current_frame->local_variable[2] = low;
|
||||
}
|
||||
|
||||
void op_lstore_3(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lstore_3");
|
||||
uint32_t high = operand_stack_pop_u32(vm->current_frame);
|
||||
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
||||
vm->current_frame->local_variable[3 + 1] = high;
|
||||
vm->current_frame->local_variable[3] = low;
|
||||
}
|
||||
|
||||
void op_lsub(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lsub");
|
||||
int64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int64_t result = value1 - value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lushr(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lushr");
|
||||
int32_t value2 = operand_stack_pop_u32(vm->current_frame);
|
||||
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
int s = value2 & 0b111111;
|
||||
uint64_t result = value1 >> s;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_lxor(struct vm * vm)
|
||||
{
|
||||
assert(!"op_lxor");
|
||||
uint64_t value2 = operand_stack_pop_u64(vm->current_frame);
|
||||
uint64_t value1 = operand_stack_pop_u64(vm->current_frame);
|
||||
uint64_t result = value1 ^ value2;
|
||||
operand_stack_push_u64(vm->current_frame, result);
|
||||
}
|
||||
|
||||
void op_monitorenter(struct vm * vm)
|
||||
@ -1283,16 +1387,38 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions)
|
||||
|
||||
void op_new(struct vm * vm, uint32_t index)
|
||||
{
|
||||
struct constant * class_constant = &vm->current_thread.current_class->constant_pool[index - 1];
|
||||
#ifdef DEBUG
|
||||
assert(class_constant->tag == CONSTANT_Class);
|
||||
#endif
|
||||
struct constant * class_name_constant = &vm->current_thread.current_class->constant_pool[class_constant->class.name_index - 1];
|
||||
#ifdef DEBUG
|
||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||
#endif
|
||||
|
||||
struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
||||
vm->class_hash_table.entry,
|
||||
class_name_constant->utf8.bytes,
|
||||
class_name_constant->utf8.length);
|
||||
assert(class_entry != nullptr);
|
||||
|
||||
/* On successful resolution of the class, it is initialized if it has not
|
||||
already been initialized (§5.5).
|
||||
|
||||
(new) Upon execution of a new instruction, the class to be initialized is
|
||||
the class referenced by the instruction. */
|
||||
|
||||
/*
|
||||
if (!vm_initialize_class(vm, class_entry))
|
||||
return;
|
||||
*/
|
||||
|
||||
/* Memory for a new instance of that class is allocated from the
|
||||
garbage-collected heap, and the instance variables of the new object are
|
||||
initialized to their default initial values (§2.3, §2.4). The objectref, a
|
||||
reference to the instance, is pushed onto the operand stack. */
|
||||
|
||||
int fields_count = class_entry->class_file->fields_count;
|
||||
(void)fields_count;
|
||||
//int32_t * arrayref = memory_allocate();
|
||||
|
||||
assert(!"op_new");
|
||||
}
|
||||
@ -1363,7 +1489,8 @@ void op_pop(struct vm * vm)
|
||||
|
||||
void op_pop2(struct vm * vm)
|
||||
{
|
||||
assert(!"op_pop2");
|
||||
operand_stack_pop_u32(vm->current_frame);
|
||||
operand_stack_pop_u32(vm->current_frame);
|
||||
}
|
||||
|
||||
void op_putfield(struct vm * vm, uint32_t index)
|
||||
|
67
c/frame.c
67
c/frame.c
@ -60,10 +60,20 @@ static int descriptor_nargs(struct constant * descriptor_constant)
|
||||
int i = 1;
|
||||
int nargs = 0;
|
||||
while (i < descriptor_constant->utf8.length) {
|
||||
if (descriptor_constant->utf8.bytes[i] == ')')
|
||||
uint8_t byte = descriptor_constant->utf8.bytes[i];
|
||||
if (byte == ')')
|
||||
break;
|
||||
if (descriptor_constant->utf8.bytes[i] != '[')
|
||||
switch (byte) {
|
||||
case '[':
|
||||
break;
|
||||
case 'D': [[fallthrough]];
|
||||
case 'J':
|
||||
nargs += 2;
|
||||
break;
|
||||
default:
|
||||
nargs += 1;
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
assert(i + 2 == descriptor_constant->utf8.length);
|
||||
@ -92,28 +102,28 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
||||
struct class_file * class_file = class_entry->class_file;
|
||||
|
||||
int constantvalue_name_index = find_constantvalue_name_index(class_file);
|
||||
assert(constantvalue_name_index != 0);
|
||||
if (constantvalue_name_index != 0) {
|
||||
for (int i = 0; i < class_file->fields_count; i++) {
|
||||
struct field_info * field_info = &class_file->fields[i];
|
||||
if (!(field_info->access_flags & FIELD_ACC_STATIC))
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < class_file->fields_count; i++) {
|
||||
struct field_info * field_info = &class_file->fields[i];
|
||||
if (!(field_info->access_flags & FIELD_ACC_STATIC))
|
||||
continue;
|
||||
for (int j = 0; j < field_info->attributes_count; j++) {
|
||||
if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) {
|
||||
struct attribute_info * attribute = &field_info->attributes[j];
|
||||
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
||||
assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String
|
||||
|
||||
for (int j = 0; j < field_info->attributes_count; j++) {
|
||||
if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) {
|
||||
struct attribute_info * attribute = &field_info->attributes[j];
|
||||
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
||||
assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String
|
||||
|
||||
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
|
||||
assert(name_constant->tag == CONSTANT_Utf8);
|
||||
struct field_entry * field_entry = class_resolver_lookup_field(class_entry,
|
||||
name_constant->utf8.bytes,
|
||||
name_constant->utf8.length);
|
||||
assert(field_entry != nullptr);
|
||||
field_entry->value = constantvalue->integer.bytes;
|
||||
printf(" constantvalue: %d\n", field_entry->value);
|
||||
break;
|
||||
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
|
||||
assert(name_constant->tag == CONSTANT_Utf8);
|
||||
struct field_entry * field_entry = class_resolver_lookup_field(class_entry,
|
||||
name_constant->utf8.bytes,
|
||||
name_constant->utf8.length);
|
||||
assert(field_entry != nullptr);
|
||||
field_entry->value = constantvalue->integer.bytes;
|
||||
printf(" constantvalue: %d\n", field_entry->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,8 +242,17 @@ void vm_method_return(struct vm * vm)
|
||||
case 'S': [[fallthrough]];
|
||||
case 'I': [[fallthrough]];
|
||||
case 'F':
|
||||
uint32_t value = operand_stack_pop_u32(old_frame);
|
||||
operand_stack_push_u32(vm->current_frame, value);
|
||||
{
|
||||
uint32_t value = operand_stack_pop_u32(old_frame);
|
||||
operand_stack_push_u32(vm->current_frame, value);
|
||||
}
|
||||
break;
|
||||
case 'D': [[fallthrough]];
|
||||
case 'J':
|
||||
{
|
||||
uint64_t value = operand_stack_pop_u64(old_frame);
|
||||
operand_stack_push_u64(vm->current_frame, value);
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
break;
|
||||
|
18
c/frame.h
18
c/frame.h
@ -109,6 +109,24 @@ static inline float operand_stack_pop_f32(struct frame * frame)
|
||||
return f;
|
||||
}
|
||||
|
||||
static inline void operand_stack_push_u64(struct frame * frame, uint64_t value)
|
||||
{
|
||||
frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 0);
|
||||
frame->operand_stack_ix++;
|
||||
frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 32);
|
||||
frame->operand_stack_ix++;
|
||||
}
|
||||
|
||||
static inline uint64_t operand_stack_pop_u64(struct frame * frame)
|
||||
{
|
||||
frame->operand_stack_ix--;
|
||||
uint64_t high = frame->operand_stack[frame->operand_stack_ix];
|
||||
frame->operand_stack_ix--;
|
||||
uint64_t low = frame->operand_stack[frame->operand_stack_ix];
|
||||
uint64_t value = (high << 32) | (low << 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
|
||||
void vm_static_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info);
|
||||
void vm_method_return(struct vm * vm);
|
||||
|
2
c/main.c
2
c/main.c
@ -18,6 +18,7 @@ int main(int argc, const char * argv[])
|
||||
class_hash_table,
|
||||
(const uint8_t *)main_class,
|
||||
string_length(main_class));
|
||||
assert(class_entry != nullptr);
|
||||
|
||||
const char * method_name = "main";
|
||||
int method_name_length = string_length(method_name);
|
||||
@ -28,6 +29,7 @@ int main(int argc, const char * argv[])
|
||||
method_name_length,
|
||||
(const uint8_t *)method_descriptor,
|
||||
method_descriptor_length);
|
||||
assert(method_info != nullptr);
|
||||
|
||||
struct vm vm;
|
||||
vm.class_hash_table.entry = class_hash_table;
|
||||
|
@ -1,17 +1,11 @@
|
||||
import struct
|
||||
import sys
|
||||
from binascii import hexlify
|
||||
import csv
|
||||
|
||||
def parse_row(s):
|
||||
a, b, c, d = s.strip().split(',')
|
||||
return int(a), c, int(d)
|
||||
from gen_decoder import parse_opcode_table
|
||||
|
||||
def parse_opcode_table(buf):
|
||||
rows = [parse_row(i) for i in buf.strip().split('\n')]
|
||||
return {opcode: (name, args) for opcode, name, args in rows}
|
||||
|
||||
with open('opcodes.csv', 'r') as f:
|
||||
opcode_table = parse_opcode_table(f.read())
|
||||
opcode_table = parse_opcode_table()
|
||||
|
||||
def size_to_format(size):
|
||||
if size == 4:
|
||||
@ -60,7 +54,11 @@ def parse_cp_info(buf):
|
||||
buf, value = field(buf, field_size)
|
||||
last_value = value
|
||||
d[field_name] = value
|
||||
return buf, (name, d)
|
||||
if tag in {5, 6}:
|
||||
entries = 2
|
||||
else:
|
||||
entries = 1
|
||||
return buf, (name, d), entries
|
||||
|
||||
def parse_attribute_info(buf):
|
||||
buf, attribute_name_index = field(buf, 2)
|
||||
@ -96,12 +94,12 @@ def dump_opcodes(buf, indent):
|
||||
ix = 0
|
||||
while len(buf) > 0:
|
||||
op = buf[0]
|
||||
name, arg_length = opcode_table[op]
|
||||
instruction = opcode_table[op]
|
||||
buf = buf[1:]
|
||||
args = list(buf[0:arg_length])
|
||||
print(indent, f"{ix:> 3}", name, args)
|
||||
ix += 1 + arg_length
|
||||
buf = buf[arg_length:]
|
||||
args = list(buf[0:instruction.arguments_size])
|
||||
print(indent, f"{ix:> 3}", instruction.mnemonic, args)
|
||||
ix += 1 + instruction.arguments_size
|
||||
buf = buf[instruction.arguments_size:]
|
||||
|
||||
def print_code_info(buf, indent, constant_pool):
|
||||
code_attribute = [
|
||||
@ -158,10 +156,14 @@ def parse_class(buf):
|
||||
|
||||
print("constant_pool:")
|
||||
constant_pool = []
|
||||
for i in range(constant_pool_count - 1):
|
||||
buf, cp_info = parse_cp_info(buf)
|
||||
i = 1
|
||||
while i < constant_pool_count:
|
||||
buf, cp_info, entries = parse_cp_info(buf)
|
||||
constant_pool.append(cp_info)
|
||||
print(i + 1, cp_info)
|
||||
if entries == 2:
|
||||
constant_pool.append(None)
|
||||
print(i, cp_info)
|
||||
i += entries
|
||||
|
||||
buf, access_flags = field(buf, 2)
|
||||
buf, this_class = field(buf, 2)
|
||||
|
@ -240,7 +240,8 @@ def renderer():
|
||||
return _render(out, lines)
|
||||
return render, out
|
||||
|
||||
render, out = renderer()
|
||||
render(generate_print_decoder())
|
||||
render(generate_execute_decoder())
|
||||
sys.stdout.write(out.getvalue())
|
||||
if __name__ == "__main__":
|
||||
render, out = renderer()
|
||||
render(generate_print_decoder())
|
||||
render(generate_execute_decoder())
|
||||
sys.stdout.write(out.getvalue())
|
||||
|
57
p/Long.java
Normal file
57
p/Long.java
Normal file
@ -0,0 +1,57 @@
|
||||
package p;
|
||||
|
||||
class Long {
|
||||
static long test(long n, long m) {
|
||||
long y = n + m; // 21
|
||||
long z = y % 9999; // 21
|
||||
long a = z * 5; // 105
|
||||
long b = a + 1; // 106
|
||||
long c = b / 3;
|
||||
long d = c & 0x0ffffffff0L; // 32
|
||||
long e = d | 0x1000000000L; // 68719476768 (16, 32)
|
||||
long f = e - 2; // 68719476766 (16, 30)
|
||||
long g = -f; // -68719476766 (-17, -30)
|
||||
long h = g >> 1;
|
||||
long i = h << 2;
|
||||
long j = i >>> 1;
|
||||
long k = j ^ 0xffffffffffffffffL; // -9223371968135299043
|
||||
return k;
|
||||
}
|
||||
|
||||
static void test2(long a) {
|
||||
int b = (int)a;
|
||||
float c = (float)a;
|
||||
long d = (long)b;
|
||||
long e = (long)c;
|
||||
}
|
||||
|
||||
static boolean test3(long a, long b) {
|
||||
boolean c = a > b;
|
||||
if (c) {
|
||||
return -a == b;
|
||||
} else {
|
||||
return -b <= a;
|
||||
}
|
||||
}
|
||||
|
||||
static long test4() {
|
||||
long[] arr = {1, 2, 3, 4};
|
||||
long sum = 0;
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
sum += arr[i];
|
||||
}
|
||||
boolean b = sum > 1;
|
||||
return sum * 4; // 40
|
||||
}
|
||||
|
||||
// -9223371968135299059
|
||||
// -2147483632
|
||||
// 13
|
||||
public static void main() {
|
||||
long a = test(10, 11);
|
||||
int b = (int)a;
|
||||
test2(10);
|
||||
test3(88, 123);
|
||||
test4();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user