diff options
author | Pekka Enberg <penberg@kernel.org> | 2012-04-27 09:44:39 +0300 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-04-27 12:26:34 +0300 |
commit | c3c1ad51170eb442e25e8f8803abe1a19724867c (patch) | |
tree | c33fb83857a3a1aed1ef570dceaa9dc3ecba0511 | |
parent | e6de5aa83283e10cf68b19c5da8d924c453cc2bc (diff) | |
download | jato-c3c1ad51170eb442e25e8f8803abe1a19724867c.tar.gz |
test/integration: Add LDC bytecode integration tests
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | test/integration/bytecode-test.c | 194 |
1 files changed, 190 insertions, 4 deletions
diff --git a/test/integration/bytecode-test.c b/test/integration/bytecode-test.c index 7911ab41..048e08e5 100644 --- a/test/integration/bytecode-test.c +++ b/test/integration/bytecode-test.c @@ -27,18 +27,83 @@ #include <stdint.h> #include <stdlib.h> #include <stdio.h> +#include <math.h> /* isnan et al */ bool running_on_valgrind; bool opt_ssa_enable; -static jint do_execute(uint8_t *code, unsigned long code_length) +static jint do_jint_execute(uint8_t *code, unsigned long code_length) { + struct cafebabe_constant_pool constant_pool[2]; struct cafebabe_method_info method_info; + struct cafebabe_class class_info; struct vm_object class_object; struct vm_method vmm; struct vm_class vmc; jint (*method)(void); + constant_pool[1].tag = CAFEBABE_CONSTANT_TAG_INTEGER; + constant_pool[1].integer_.bytes = 0xffffffffUL; + + class_info = (struct cafebabe_class) { + .constant_pool = constant_pool, + .constant_pool_count = ARRAY_SIZE(constant_pool), + }; + + class_object = (struct vm_object) { + }; + + vmc = (struct vm_class) { + .object = &class_object, + .name = "Foo", + .state = VM_CLASS_LINKED, + .class = &class_info, + }; + + vm_class_init(&vmc); + + method_info = (struct cafebabe_method_info) { + .access_flags = CAFEBABE_METHOD_ACC_STATIC, + }; + + vmm = (struct vm_method) { + .method = &method_info, + .name = "foo", + .class = &vmc, + .code_attribute = (struct cafebabe_code_attribute) { + .max_locals = 8, + .code = code, + .code_length = code_length, + }, + }; + + if (vm_method_prepare_jit(&vmm)) + die("unable to prepare method"); + + method = vm_method_trampoline_ptr(&vmm); + + return method(); +} + +static jlong do_jlong_execute(uint8_t *code, unsigned long code_length) +{ + struct cafebabe_constant_pool constant_pool[2]; + struct cafebabe_method_info method_info; + struct cafebabe_class class_info; + struct vm_object class_object; + struct vm_method vmm; + struct vm_class vmc; + jlong (*method)(void); + + constant_pool[1].tag = CAFEBABE_CONSTANT_TAG_LONG; + constant_pool[1].long_.low_bytes = 0xffffffffUL; + constant_pool[1].long_.high_bytes = 0xffffffffUL; + + class_info = (struct cafebabe_class) { + .constant_pool = constant_pool, + .constant_pool_count = ARRAY_SIZE(constant_pool), + }; + class_object = (struct vm_object) { }; @@ -46,6 +111,7 @@ static jint do_execute(uint8_t *code, unsigned long code_length) .object = &class_object, .name = "Foo", .state = VM_CLASS_LINKED, + .class = &class_info, }; vm_class_init(&vmc); @@ -73,14 +139,41 @@ static jint do_execute(uint8_t *code, unsigned long code_length) return method(); } +enum { + CP_IDX_DOUBLE_NAN = 1, + CP_IDX_DOUBLE_ZERO = 2, + CP_IDX_DOUBLE_POINT_75 = 3, + + CP_DOUBLE_SIZE /* keep last */ +}; + static jdouble do_jdouble_execute(uint8_t *code, unsigned long code_length) { + struct cafebabe_constant_pool constant_pool[CP_DOUBLE_SIZE]; struct cafebabe_method_info method_info; + struct cafebabe_class class_info; struct vm_object class_object; struct vm_method vmm; struct vm_class vmc; jdouble (*method)(void); + constant_pool[CP_IDX_DOUBLE_NAN].tag = CAFEBABE_CONSTANT_TAG_DOUBLE; + constant_pool[CP_IDX_DOUBLE_NAN].double_.low_bytes = 0xffffffffUL; + constant_pool[CP_IDX_DOUBLE_NAN].double_.high_bytes = 0xffffffffUL; + + constant_pool[CP_IDX_DOUBLE_ZERO].tag = CAFEBABE_CONSTANT_TAG_DOUBLE; + constant_pool[CP_IDX_DOUBLE_ZERO].double_.low_bytes = 0; + constant_pool[CP_IDX_DOUBLE_ZERO].double_.high_bytes = 0; + + constant_pool[CP_IDX_DOUBLE_POINT_75].tag = CAFEBABE_CONSTANT_TAG_DOUBLE; + constant_pool[CP_IDX_DOUBLE_POINT_75].double_.low_bytes = 0; + constant_pool[CP_IDX_DOUBLE_POINT_75].double_.high_bytes = 0x3fe80000UL; + + class_info = (struct cafebabe_class) { + .constant_pool = constant_pool, + .constant_pool_count = ARRAY_SIZE(constant_pool), + }; + class_object = (struct vm_object) { }; @@ -88,6 +181,7 @@ static jdouble do_jdouble_execute(uint8_t *code, unsigned long code_length) .object = &class_object, .name = "Foo", .state = VM_CLASS_LINKED, + .class = &class_info, }; vm_class_init(&vmc); @@ -115,14 +209,38 @@ static jdouble do_jdouble_execute(uint8_t *code, unsigned long code_length) return method(); } +enum { + CP_IDX_FLOAT_ZERO = 1, + CP_IDX_FLOAT_NAN = 2, + CP_IDX_FLOAT_POINT_75 = 3, + + CP_FLOAT_SIZE /* keep last */ +}; + static jfloat do_jfloat_execute(uint8_t *code, unsigned long code_length) { + struct cafebabe_constant_pool constant_pool[CP_FLOAT_SIZE]; struct cafebabe_method_info method_info; + struct cafebabe_class class_info; struct vm_object class_object; struct vm_method vmm; struct vm_class vmc; jfloat (*method)(void); + constant_pool[CP_IDX_FLOAT_ZERO].tag = CAFEBABE_CONSTANT_TAG_FLOAT; + constant_pool[CP_IDX_FLOAT_ZERO].float_.bytes = 0; + + constant_pool[CP_IDX_FLOAT_NAN].tag = CAFEBABE_CONSTANT_TAG_FLOAT; + constant_pool[CP_IDX_FLOAT_NAN].float_.bytes = 0xffffffffUL; + + constant_pool[CP_IDX_FLOAT_POINT_75].tag = CAFEBABE_CONSTANT_TAG_FLOAT; + constant_pool[CP_IDX_FLOAT_POINT_75].float_.bytes = 0x3f400000UL; + + class_info = (struct cafebabe_class) { + .constant_pool = constant_pool, + .constant_pool_count = ARRAY_SIZE(constant_pool), + }; + class_object = (struct vm_object) { }; @@ -130,6 +248,7 @@ static jfloat do_jfloat_execute(uint8_t *code, unsigned long code_length) .object = &class_object, .name = "Foo", .state = VM_CLASS_LINKED, + .class = &class_info, }; vm_class_init(&vmc); @@ -159,12 +278,19 @@ static jfloat do_jfloat_execute(uint8_t *code, unsigned long code_length) static jobject do_jobject_execute(uint8_t *code, unsigned long code_length) { + struct cafebabe_constant_pool constant_pool[2]; struct cafebabe_method_info method_info; + struct cafebabe_class class_info; struct vm_object class_object; struct vm_method vmm; struct vm_class vmc; jobject (*method)(void); + class_info = (struct cafebabe_class) { + .constant_pool = constant_pool, + .constant_pool_count = ARRAY_SIZE(constant_pool), + }; + class_object = (struct vm_object) { }; @@ -172,6 +298,7 @@ static jobject do_jobject_execute(uint8_t *code, unsigned long code_length) .object = &class_object, .name = "Foo", .state = VM_CLASS_LINKED, + .class = &class_info, }; vm_class_init(&vmc); @@ -199,8 +326,9 @@ static jobject do_jobject_execute(uint8_t *code, unsigned long code_length) return method(); } -#define execute(bytecode) do_execute(bytecode, ARRAY_SIZE(bytecode)) -#define jlong_run(bytecode) do_execute(bytecode, ARRAY_SIZE(bytecode)) +#define execute(bytecode) do_jint_execute(bytecode, ARRAY_SIZE(bytecode)) +#define jint_run(bytecode) do_jint_execute(bytecode, ARRAY_SIZE(bytecode)) +#define jlong_run(bytecode) do_jlong_execute(bytecode, ARRAY_SIZE(bytecode)) #define jdouble_run(bytecode) do_jdouble_execute(bytecode, ARRAY_SIZE(bytecode)) #define jfloat_run(bytecode) do_jfloat_execute(bytecode, ARRAY_SIZE(bytecode)) #define jobject_run(bytecode) do_jobject_execute(bytecode, ARRAY_SIZE(bytecode)) @@ -237,6 +365,16 @@ static void init(void) static unsigned long nr_assertions; +static void do_assert_true(const char *function, const char *file, int line, bool condition) +{ + if (!condition) + die("%s:%d::%s: Expected true, but was false", file, line, function); + + nr_assertions++; +} + +#define assert_true(condition) do_assert_true(__func__, __FILE__, __LINE__, condition) + static void do_assert_int_equals(const char *function, const char *file, int line, jint expected, jint actual) { if (expected != actual) @@ -302,6 +440,54 @@ static void test_sipush(void) assert_int_equals(256, execute(bytecode)); } +static void test_ldc_double(void) +{ + uint8_t nan[] = { OPC_LDC, CP_IDX_DOUBLE_NAN, 0x00, OPC_DRETURN }; + uint8_t zero[] = { OPC_LDC, CP_IDX_DOUBLE_ZERO, 0x00, OPC_DRETURN }; + uint8_t _75[] = { OPC_LDC, CP_IDX_DOUBLE_POINT_75, 0x00, OPC_DRETURN }; + + assert_true(isnan(jdouble_run(nan))); + + assert_double_equals(0.0, jdouble_run(zero)); + + assert_double_equals(0.75, jdouble_run(_75)); +} + +static void test_ldc_float(void) +{ + uint8_t nan[] = { OPC_LDC, CP_IDX_FLOAT_NAN, 0x00, OPC_FRETURN }; + uint8_t zero[] = { OPC_LDC, CP_IDX_FLOAT_ZERO, 0x00, OPC_FRETURN }; + uint8_t _75[] = { OPC_LDC, CP_IDX_FLOAT_POINT_75, 0x00, OPC_FRETURN }; + + assert_true(isnan(jfloat_run(nan))); + + assert_float_equals(0.0f, jfloat_run(zero)); + + assert_float_equals(0.75f, jfloat_run(_75)); +} + +static void test_ldc_long(void) +{ + uint8_t bytecode[] = { OPC_LDC, 0x01, 0x00, OPC_LRETURN }; + + assert_long_equals(-1, jlong_run(bytecode)); +} + +static void test_ldc_int(void) +{ + uint8_t bytecode[] = { OPC_LDC, 0x01, 0x00, OPC_IRETURN }; + + assert_int_equals(-1, jint_run(bytecode)); +} + +static void test_ldc(void) +{ + test_ldc_int(); + test_ldc_long(); + test_ldc_float(); + test_ldc_double(); +} + static void test_if_icmpeq(void) { uint8_t bytecode_1[] = { OPC_ICONST_1, OPC_ICONST_1, OPC_IF_ICMPEQ, 0x00, 0x05, OPC_ICONST_1, OPC_IRETURN, OPC_ICONST_0, OPC_IRETURN }; @@ -1185,7 +1371,7 @@ static void run_tests(void) test_bipush(); #ifndef CONFIG_ARM test_sipush(); - /* test_ldc(); */ + test_ldc(); /* test_ldc_w(); */ /* test_ldc2_w(); */ /* test_iload(); */ |