Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit cf49c7e

Browse files
committed
Add long related opcodes
* ldc2_w * lload * llstore * ladd, lsub, lmul, ldiv, lrem * i2l, l2i * lcmp Add a new test script: "Long.java" This patch only supports that the first parameter is `long`. When methods have more than one `long` in parameters, these `long` values in the stack will be misplaced. It is because one stack entry stores only one `long` value in but current implementation, but in standard JVM, one stack entry only stores 4 bytes.
1 parent 42f331d commit cf49c7e

File tree

8 files changed

+270
-28
lines changed

8 files changed

+270
-28
lines changed

‎Makefile‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ TESTS = \
3636
Jumps \
3737
PalindromeProduct \
3838
Primes \
39-
Recursion
39+
Recursion \
40+
Long
4041

4142
check: $(addprefix tests/,$(TESTS:=-result.out))
4243

‎constant-pool.c‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ constant_pool_t get_constant_pool(FILE *class_file)
7979
break;
8080
}
8181

82+
case CONSTANT_Long: {
83+
CONSTANT_LongOrDouble_info *value = malloc(sizeof(*value));
84+
assert(value && "Failed to allocate long constant");
85+
value->high_bytes = read_u4(class_file);
86+
value->low_bytes = read_u4(class_file);
87+
constant->info = (u1 *) value;
88+
constant++;
89+
constant->info = NULL;
90+
i++;
91+
break;
92+
}
93+
8294
case CONSTANT_Class: {
8395
CONSTANT_Class_info *value = malloc(sizeof(*value));
8496
assert(value && "Failed to allocate class constant");

‎constant-pool.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
typedef enum {
1212
CONSTANT_Utf8 = 1,
1313
CONSTANT_Integer = 3,
14+
CONSTANT_Long = 5,
1415
CONSTANT_Class = 7,
1516
CONSTANT_FieldRef = 9,
1617
CONSTANT_MethodRef = 10,
@@ -30,6 +31,11 @@ typedef struct {
3031
int32_t bytes;
3132
} CONSTANT_Integer_info;
3233

34+
typedef struct {
35+
u4 high_bytes;
36+
u4 low_bytes;
37+
} CONSTANT_LongOrDouble_info;
38+
3339
typedef struct {
3440
u2 name_index;
3541
u2 descriptor_index;

‎jvm.c‎

Lines changed: 205 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,47 @@ typedef enum {
2020
i_iconst_3 = 0x6,
2121
i_iconst_4 = 0x7,
2222
i_iconst_5 = 0x8,
23+
i_lconst_0 = 0x9,
24+
i_lconst_1 = 0xa,
2325
i_bipush = 0x10,
2426
i_sipush = 0x11,
2527
i_ldc = 0x12,
28+
i_ldc2_w = 0x14,
2629
i_iload = 0x15,
30+
i_lload = 0x16,
2731
i_iload_0 = 0x1a,
2832
i_iload_1 = 0x1b,
2933
i_iload_2 = 0x1c,
3034
i_iload_3 = 0x1d,
35+
i_lload_0 = 0x1e,
36+
i_lload_1 = 0x1f,
37+
i_lload_2 = 0x20,
38+
i_lload_3 = 0x21,
3139
i_istore = 0x36,
40+
i_lstore = 0x37,
3241
i_istore_0 = 0x3b,
3342
i_istore_1 = 0x3c,
3443
i_istore_2 = 0x3d,
3544
i_istore_3 = 0x3e,
45+
i_lstore_0 = 0x3f,
46+
i_lstore_1 = 0x40,
47+
i_lstore_2 = 0x41,
48+
i_lstore_3 = 0x42,
3649
i_iadd = 0x60,
50+
i_ladd = 0x61,
3751
i_isub = 0x64,
52+
i_lsub = 0x65,
3853
i_imul = 0x68,
54+
i_lmul = 0x69,
3955
i_idiv = 0x6c,
56+
i_ldiv = 0x6d,
4057
i_irem = 0x70,
58+
i_lrem = 0x71,
4159
i_ineg = 0x74,
4260
i_iinc = 0x84,
61+
i_i2l = 0x85,
62+
i_l2i = 0x88,
63+
i_lcmp = 0x94,
4364
i_ifeq = 0x99,
4465
i_ifne = 0x9a,
4566
i_iflt = 0x9b,
@@ -54,6 +75,7 @@ typedef enum {
5475
i_if_icmple = 0xa4,
5576
i_goto = 0xa7,
5677
i_ireturn = 0xac,
78+
i_lreturn = 0xad,
5779
i_return = 0xb1,
5880
i_getstatic = 0xb2,
5981
i_invokevirtual = 0xb6,
@@ -128,10 +150,10 @@ static inline void ineg(stack_frame_t *op_stack)
128150

129151
static inline void invokevirtual(stack_frame_t *op_stack)
130152
{
131-
int32_t op = pop_int(op_stack);
153+
int64_t op = pop_int(op_stack);
132154

133155
/* FIXME: the implement is not correct. */
134-
printf("%d\n", op);
156+
printf("%ld\n", op);
135157
}
136158

137159
static inline void iconst(stack_frame_t *op_stack, uint8_t current)
@@ -183,6 +205,18 @@ stack_entry_t *execute(method_t *method,
183205
return ret;
184206
}
185207

208+
/* Return long from method */
209+
case i_lreturn: {
210+
stack_entry_t *ret = malloc(sizeof(stack_entry_t));
211+
ret->entry.long_value = (int64_t) pop_int(op_stack);
212+
ret->type = STACK_ENTRY_LONG;
213+
214+
free(op_stack->store);
215+
free(op_stack);
216+
217+
return ret;
218+
}
219+
186220
/* Return void from method */
187221
case i_return: {
188222
stack_entry_t *ret = malloc(sizeof(stack_entry_t));
@@ -211,6 +245,9 @@ stack_entry_t *execute(method_t *method,
211245
case STACK_ENTRY_INT:
212246
push_int(op_stack, exec_res->entry.int_value);
213247
break;
248+
case STACK_ENTRY_LONG:
249+
push_long(op_stack, exec_res->entry.long_value);
250+
break;
214251
case STACK_ENTRY_NONE:
215252
/* nothing */
216253
break;
@@ -223,6 +260,20 @@ stack_entry_t *execute(method_t *method,
223260
break;
224261
}
225262

263+
/* Compare long */
264+
case i_lcmp: {
265+
int64_t op1 = pop_int(op_stack), op2 = pop_int(op_stack);
266+
if (op1 < op2) {
267+
push_int(op_stack, 1);
268+
} else if (op1 == op2) {
269+
push_int(op_stack, 0);
270+
} else {
271+
push_int(op_stack, -1);
272+
}
273+
pc += 1;
274+
break;
275+
}
276+
226277
/* Branch if int comparison with zero succeeds: if equals */
227278
case i_ifeq: {
228279
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
@@ -393,6 +444,56 @@ stack_entry_t *execute(method_t *method,
393444
break;
394445
}
395446

447+
/* Push long or double from run-time constant pool (wide index) */
448+
case i_ldc2_w: {
449+
uint8_t param1 = code_buf[pc + 1], param2 = code_buf[pc + 2];
450+
uint16_t index = ((param1 << 8) | param2);
451+
452+
uint64_t high = ((CONSTANT_LongOrDouble_info *) get_constant(
453+
&clazz->constant_pool, index)
454+
->info)
455+
->high_bytes;
456+
uint64_t low = ((CONSTANT_LongOrDouble_info *) get_constant(
457+
&clazz->constant_pool, index)
458+
->info)
459+
->low_bytes;
460+
int64_t value = high << 32 | low;
461+
push_long(op_stack, value);
462+
pc += 3;
463+
break;
464+
}
465+
466+
/* Load long from local variable */
467+
case i_lload: {
468+
int32_t param = code_buf[pc + 1];
469+
int64_t loaded;
470+
loaded = locals[param].entry.long_value;
471+
push_long(op_stack, loaded);
472+
473+
pc += 2;
474+
break;
475+
}
476+
477+
/* FIXME: this implementation has some bugs.
478+
* In standard JVM, one stack entry only store four
479+
* bytes data, so in some method descriptor (e.g (JJ)V)
480+
* the long value will store in locals[0] and locals[2]
481+
* rather than locals[0] and locals[1].
482+
*/
483+
/* Load long from local variable */
484+
case i_lload_0:
485+
case i_lload_1:
486+
case i_lload_2:
487+
case i_lload_3: {
488+
int64_t param = current - i_lload_0;
489+
int64_t loaded;
490+
loaded = locals[param].entry.long_value;
491+
push_long(op_stack, loaded);
492+
493+
pc += 1;
494+
break;
495+
}
496+
396497
/* Load int from local variable */
397498
case i_iload_0:
398499
case i_iload_1:
@@ -419,6 +520,31 @@ stack_entry_t *execute(method_t *method,
419520
break;
420521
}
421522

523+
/* Store long into local variable */
524+
case i_lstore: {
525+
int32_t param = code_buf[pc + 1];
526+
int64_t stored = pop_int(op_stack);
527+
locals[param].entry.long_value = stored;
528+
locals[param].type = STACK_ENTRY_LONG;
529+
530+
pc += 2;
531+
break;
532+
}
533+
534+
/* Store long into local variable */
535+
case i_lstore_0:
536+
case i_lstore_1:
537+
case i_lstore_2:
538+
case i_lstore_3: {
539+
int32_t param = current - i_lstore_0;
540+
int64_t stored = pop_int(op_stack);
541+
locals[param].entry.long_value = stored;
542+
locals[param].type = STACK_ENTRY_LONG;
543+
544+
pc += 1;
545+
break;
546+
}
547+
422548
/* Store int into local variable */
423549
case i_istore: {
424550
int32_t param = code_buf[pc + 1];
@@ -451,6 +577,24 @@ stack_entry_t *execute(method_t *method,
451577
break;
452578
}
453579

580+
/* Convert int to long */
581+
case i_i2l: {
582+
int32_t stored = pop_int(op_stack);
583+
push_long(op_stack, (int64_t) stored);
584+
585+
pc += 1;
586+
break;
587+
}
588+
589+
/* Convert int to char */
590+
case i_l2i: {
591+
int64_t stored = pop_int(op_stack);
592+
push_int(op_stack, (int32_t) stored);
593+
594+
pc += 1;
595+
break;
596+
}
597+
454598
/* Push byte */
455599
case i_bipush:
456600
bipush(op_stack, pc, code_buf);
@@ -463,31 +607,81 @@ stack_entry_t *execute(method_t *method,
463607
pc += 1;
464608
break;
465609

610+
/* Add long */
611+
case i_ladd: {
612+
int64_t op1 = pop_int(op_stack);
613+
int64_t op2 = pop_int(op_stack);
614+
615+
push_long(op_stack, op1 + op2);
616+
pc += 1;
617+
break;
618+
}
619+
466620
/* Subtract int */
467621
case i_isub:
468622
isub(op_stack);
469623
pc += 1;
470624
break;
471625

626+
/* Subtract long */
627+
case i_lsub: {
628+
int64_t op1 = pop_int(op_stack);
629+
int64_t op2 = pop_int(op_stack);
630+
631+
push_long(op_stack, op2 - op1);
632+
pc += 1;
633+
break;
634+
}
635+
472636
/* Multiply int */
473637
case i_imul:
474638
imul(op_stack);
475639
pc += 1;
476640
break;
477641

642+
/* Multiply long */
643+
case i_lmul: {
644+
int64_t op1 = pop_int(op_stack);
645+
int64_t op2 = pop_int(op_stack);
646+
647+
push_long(op_stack, op1 * op2);
648+
pc += 1;
649+
break;
650+
}
651+
478652
/* Divide int */
479653
case i_idiv:
480654
idiv(op_stack);
481655
pc += 1;
482656
break;
483657

658+
/* Divide long */
659+
case i_ldiv: {
660+
int64_t op1 = pop_int(op_stack);
661+
int64_t op2 = pop_int(op_stack);
662+
663+
push_long(op_stack, op2 / op1);
664+
pc += 1;
665+
break;
666+
}
667+
484668
/* Remainder int */
485669
case i_irem:
486670
irem(op_stack);
487671
pc += 1;
488672
break;
489673

490-
/* Negate int */
674+
/* Remainder long */
675+
case i_lrem: {
676+
int64_t op1 = pop_int(op_stack);
677+
int64_t op2 = pop_int(op_stack);
678+
679+
push_long(op_stack, op2 % op1);
680+
pc += 1;
681+
break;
682+
}
683+
684+
/* Negate int */
491685
case i_ineg:
492686
ineg(op_stack);
493687
pc += 1;
@@ -517,6 +711,14 @@ stack_entry_t *execute(method_t *method,
517711
pc += 1;
518712
break;
519713

714+
/* Push long constant */
715+
case i_lconst_0:
716+
case i_lconst_1: {
717+
push_long(op_stack, current - i_lconst_0);
718+
pc += 1;
719+
break;
720+
}
721+
520722
/* Push short */
521723
case i_sipush:
522724
sipush(op_stack, pc, code_buf);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /