From 78ad25231b932637403282ab07c8de8c6a4cc670 Mon Sep 17 00:00:00 2001 From: gambas Date: Fri, 18 Jun 2021 04:33:42 +0200 Subject: [PATCH] JIT compiler support for embedded array and structures variables. [INTERPRETER] * NEW: JIT compiler support for embedded array and structures variables. [GB.JIT] * NEW: JIT compiler support for embedded array and structures variables. --- main/gbx/gb.jit.h | 1 + main/gbx/gbx_api.c | 1 + main/lib/jit/gb.jit/.src/Jit.module | 6 +- main/lib/jit/gb.jit/jit.h | 12 +- main/lib/jit/jit_body.c | 257 ++++++++++++++++++---------- 5 files changed, 180 insertions(+), 97 deletions(-) diff --git a/main/gbx/gb.jit.h b/main/gbx/gb.jit.h index 33b768f16..0b89c6c27 100644 --- a/main/gbx/gb.jit.h +++ b/main/gbx/gb.jit.h @@ -111,6 +111,7 @@ typedef void *(*get_array_class)(void *cp, JIT_CTYPE ctype); void (*add_string_local)(GB_STRING *str, GB_STRING val); void (*add_string_global)(char **str, GB_STRING val); + void (*value_class_write)(void *class, GB_VALUE *value, void *addr, JIT_CTYPE ctype); } JIT_INTERFACE; diff --git a/main/gbx/gbx_api.c b/main/gbx/gbx_api.c index b5e3d87cd..d56772468 100644 --- a/main/gbx/gbx_api.c +++ b/main/gbx/gbx_api.c @@ -384,6 +384,7 @@ const void *const GAMBAS_JitApi[] = (void *)CARRAY_get_array_class, (void *)JIT_add_string_local, (void *)JIT_add_string_global, + (void *)VALUE_class_write, NULL }; diff --git a/main/lib/jit/gb.jit/.src/Jit.module b/main/lib/jit/gb.jit/.src/Jit.module index cd966678e..2507bce1b 100644 --- a/main/lib/jit/gb.jit/.src/Jit.module +++ b/main/lib/jit/gb.jit/.src/Jit.module @@ -112,7 +112,11 @@ Public Sub _Compile(sArch As String) As Boolean If Not _ClassStat.HasFast Then Continue sFile = _ClassStat.Name If $bDebug Then Error "gb.jit: translating class "; sFile - Print #hFile, __Jit.Translate(sFile, sArch) + If $bDebug Then + Print #hFile, Replace(__Jit.Translate(sFile, sArch), ";", ";\n") + Else + Print #hFile, __Jit.Translate(sFile, sArch) + Endif Next Close #hFile diff --git a/main/lib/jit/gb.jit/jit.h b/main/lib/jit/gb.jit/jit.h index 575042868..8e4b64f84 100644 --- a/main/lib/jit/gb.jit/jit.h +++ b/main/lib/jit/gb.jit/jit.h @@ -355,12 +355,9 @@ enum #define GET_o(_addr, _type) GET_OBJECT((*(char **)(_addr)), _type) #define GET_v(_addr) GET_VARIANT((*(GB_VARIANT_VALUE *)(_addr))) #define GET_S(_ref, _addr, _type) GET_OBJECT(JIT.static_struct((_ref), (_type), (_addr)), _type) - #define GET_A(_class, _ref, _addr, _type, _desc) ({ \ SP = sp; \ - GB.Unref(&ra); \ - ra = JIT.static_array((_class), (_ref), (void *)(_desc), (_addr)); \ - GET_OBJECT(ra, _type); \ + GET_OBJECT(JIT.static_array((_class), (_ref), (void *)(_desc), (_addr)), _type); \ }) #define SET_b(_addr, _val) (GET_b(_addr) = ((_val) ? -1 : 0)) @@ -375,6 +372,13 @@ enum #define SET_s(_addr, _val) ({ GB_VALUE temp = (GB_VALUE)(_val); GB.StoreString((GB_STRING *)&temp, (char **)(_addr)); }) #define SET_o(_addr, _val) ({ GB_VALUE temp = (GB_VALUE)(_val); GB.StoreObject((GB_OBJECT *)&temp, (void **)(_addr)); }) #define SET_v(_addr, _val) ({ GB_VALUE temp = (GB_VALUE)(_val); GB.StoreVariant((GB_VARIANT *)&temp, (GB_VARIANT_VALUE *)(_addr)); }) +#define SET_SA(_class, _addr, _ctype, _val) ({ \ + GB_VALUE temp = (GB_VALUE)(_val); \ + int ctype = (_ctype); \ + GB.BorrowValue(&temp); \ + JIT.value_class_write((_class), &temp, (_addr), *(JIT_CTYPE *)&ctype); \ + GB.ReleaseValue(&temp); \ +}) #define GET_ARRAY_UNSAFE(_type, _array, _index) ({ \ GB_ARRAY_IMPL *_a = (_array).value; \ diff --git a/main/lib/jit/jit_body.c b/main/lib/jit/jit_body.c index f62b0947a..3b065bab2 100644 --- a/main/lib/jit/jit_body.c +++ b/main/lib/jit/jit_body.c @@ -853,6 +853,87 @@ static void push_function(int func, int index) } +static void push_static_variable(CLASS *class, CTYPE ctype, char *addr) +{ + TYPE type = JIT_ctype_to_type(class, ctype); + char class_name[32]; + + if (class == JIT_class) + strcpy(class_name, "CP"); + else + sprintf(class_name, "CLASS(%p)", class); + + switch(ctype.id) + { + case TC_STRUCT: + if (class == JIT_class) + push(type, "GET_S(CP, %p, CLASS(%p))", addr, (CLASS *)type); + else + push(type, "GET_S(CLASS(%p), %p, CLASS(%p))", class, addr, (CLASS *)type); + break; + + case TC_ARRAY: + //declare(&_decl_ra, "void *ra = NULL"); + if (class == JIT_class) + push(type, "GET_A(CP, CP, %p, CLASS(%p), %p)", addr, (CLASS *)type, class->load->array[ctype.value]); + else + push(type, "GET_A(CLASS(%p), %p, %p, CLASS(%p), %p)", class, class, addr, (CLASS *)type, class->load->array[ctype.value]); + break; + + case T_OBJECT: + if (class == JIT_class) + { + if (TYPE_is_pure_object(type)) + push(type, "GET_o(%p, CLASS(%p))", addr, (CLASS *)type); + else + push(type, "GET_o(%p, GB_T_OBJECT)", addr); + } + else + { + if (TYPE_is_pure_object(type)) + push(type, "({ JIT.load_class(%p); GET_o(%p, CLASS(%p)); })", class, addr, (CLASS *)type); + else + push(type, "({ JIT.load_class(%p); GET_o(%p, GB_T_OBJECT); })", class, addr); + } + break; + + default: + if (class == JIT_class) + push(type, "GET_%s(%p)", JIT_get_type(type), addr); + else + push(type, "({ JIT.load_class(%p); GET_%s(%p); })", class, JIT_get_type(type), addr); + } +} + + +static void push_dynamic_variable(CLASS *class, CTYPE ctype, int pos, char *addr) +{ + TYPE type = JIT_ctype_to_type(class, ctype); + + switch(ctype.id) + { + case TC_STRUCT: + push(type, "GET_S(%s, %s + %d, CLASS(%p))", addr, addr, pos, (CLASS *)type); + break; + + case TC_ARRAY: + //declare(&_decl_ra, "void *ra = NULL"); + push(type, "GET_A(%p, %s, %s + %d, CLASS(%p), %p)", class, addr, addr, pos, (CLASS *)type, class->load->array[ctype.value]); + break; + + case T_OBJECT: + if (TYPE_is_pure_object(type)) + push(type, "GET_o(%s + %d, CLASS(%p))", addr, pos, (CLASS *)type); + else + push(type, "GET_o(%s + %d, GB_T_OBJECT)", addr, pos); + break; + + default: + push(type, "GET_%s(%s + %d)", JIT_get_type(type), addr, pos); + } +} + + static void push_unknown(int index) { TYPE type = T_UNKNOWN; @@ -874,7 +955,7 @@ static void push_unknown(int index) CLASS_DESC *desc; void *addr; int pos; - TYPE utype; + CTYPE ctype; char *sym; char *get_addr; bool static_class; @@ -910,21 +991,12 @@ static void push_unknown(int index) { case CD_STATIC_VARIABLE: - utype = JIT_ctype_to_type(class, desc->variable.ctype); - pop_stack(1); + ctype = desc->variable.ctype; addr = (char *)desc->variable.class->stat + desc->variable.offset; - if (TYPE_is_object(utype)) - { - if (TYPE_is_pure_object(utype)) - push(utype, "({ JIT.load_class(%p); GET_o(%p, CLASS(%p)); })", class, addr, (CLASS *)utype); - else - push(utype, "({ JIT.load_class(%p); GET_o(%p, GB_T_OBJECT); })", class, addr); - } - else - push(utype, "({ JIT.load_class(%p); GET_%s(%p); })", class, JIT_get_type(utype), addr); + push_static_variable(class, ctype, addr); return; @@ -932,7 +1004,7 @@ static void push_unknown(int index) // TODO: automatic class - utype = JIT_ctype_to_type(class, desc->variable.ctype); + ctype = desc->variable.ctype; expr = peek(-1, (TYPE)class); @@ -947,15 +1019,7 @@ static void push_unknown(int index) pop_stack(1); - if (TYPE_is_object(utype)) - { - if (TYPE_is_pure_object(utype)) - push(utype, "GET_o(%s + %d, CLASS(%p))", get_addr, pos, (CLASS *)utype); - else - push(utype, "GET_o(%s + %d, GB_T_OBJECT)", get_addr, pos); - } - else - push(utype, "GET_%s(%s + %d)", JIT_get_type(utype), get_addr, pos); + push_dynamic_variable(class, ctype, pos, get_addr); STR_free(get_addr); @@ -1021,6 +1085,70 @@ static void push_unknown(int index) } +static void pop_static_variable(CLASS *class, CTYPE ctype, char *addr) +{ + TYPE type = JIT_ctype_to_type(class, ctype); + char *klass; + + if (class == JIT_class) + klass = "CP"; + else + klass = STR_print("CLASS(%p)", class); + + _no_release = TRUE; + + switch(ctype.id) + { + case TC_STRUCT: + case TC_ARRAY: + + if (check_swap(type, "SET_SA(%s, %p, %d, %%s)", klass, addr, ctype)) + pop(type, "SET_SA(%s, %p, %d, %%s)", klass, addr, ctype); + + break; + + default: + if (check_swap(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr)) + pop(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr); + } + + + _no_release = FALSE; +} + + +static void pop_dynamic_variable(CLASS *class, CTYPE ctype, int pos, char *addr) +{ + TYPE type = JIT_ctype_to_type(class, ctype); + + char *klass; + + if (class == JIT_class) + klass = "CP"; + else + klass = STR_print("CLASS(%p)", class); + + _no_release = TRUE; + + switch(ctype.id) + { + case TC_STRUCT: + case TC_ARRAY: + + if (check_swap(type, "SET_SA(%s, %s + %d, %d, %%s)", klass, addr, pos, ctype)) + pop(type, "SET_SA(%s, %s + %d, %d, %%s)", klass, addr, pos, ctype); + + break; + + default: + if (check_swap(type, "SET_%s(%s + %d, %%s)", JIT_get_type(type), addr, pos)) + pop(type, "SET_%s(%s + %d, %%s)", JIT_get_type(type), addr, pos); + } + + _no_release = FALSE; +} + + static void pop_unknown(int index) { CLASS *class; @@ -1036,7 +1164,7 @@ static void pop_unknown(int index) CLASS_DESC *desc; void *addr; int pos; - TYPE utype; + CTYPE ctype; const char *sym; char *get_addr; @@ -1050,16 +1178,12 @@ static void pop_unknown(int index) { case CD_STATIC_VARIABLE: - utype = JIT_ctype_to_type(class, desc->variable.ctype); - pop_stack(1); + ctype = desc->variable.ctype; addr = (char *)desc->variable.class->stat + desc->variable.offset; - _no_release = TRUE; - if (check_swap(utype, "SET_%s(%p, %%s)", JIT_get_type(utype), addr)) - pop(utype, "SET_%s(%p, %%s)", JIT_get_type(utype), addr); - _no_release = FALSE; + pop_static_variable(class, ctype, addr); return; @@ -1067,7 +1191,7 @@ static void pop_unknown(int index) // TODO: automatic class - utype = JIT_ctype_to_type(class, desc->variable.ctype); + ctype = desc->variable.ctype; expr = peek(-1, (TYPE)class); @@ -1082,10 +1206,7 @@ static void pop_unknown(int index) pos = desc->variable.offset; - _no_release = TRUE; - if (check_swap(utype, "SET_%s(%s + %d, %%s)", JIT_get_type(utype), get_addr, pos)) - pop(utype, "SET_%s(%s + %d, %%s)", JIT_get_type(utype), get_addr, pos); - _no_release = FALSE; + pop_dynamic_variable(class, ctype, pos, get_addr); STR_free(get_addr); @@ -1132,7 +1253,7 @@ static void push_array(ushort code) //JIT_print(" // %s %d\n", class->name, class->is_array); - if (class->is_array) + if (class->is_array && !class->is_array_of_struct) { type = class->array_type; @@ -1198,7 +1319,7 @@ static void pop_array(ushort code) { CLASS *class = (CLASS *)type; - if (class->is_array) + if (class->is_array && !class->is_array_of_struct) { type = class->array_type; @@ -2869,43 +2990,19 @@ _PUSH_STATIC: index = GET_7XX(); ctype = class->load->stat[index].type; - type = JIT_ctype_to_type(class, ctype); addr = &class->stat[class->load->stat[index].pos]; - switch(ctype.id) - { - case TC_STRUCT: - push(type, "GET_S(CP, %p, CLASS(%p))", addr, (CLASS *)type); - break; - - case TC_ARRAY: - declare(&_decl_ra, "void *ra = NULL"); - push(type, "GET_A(CP, CP, %p, CLASS(%p), %p)", addr, (CLASS *)type, JIT_class->load->array[ctype.value]); - break; - - case T_OBJECT: - if (TYPE_is_pure_object(type)) - push(type, "GET_o(%p, CLASS(%p))", addr, (CLASS *)type); - else - push(type, "GET_o(%p, GB_T_OBJECT)", addr); - break; - - default: - push(type, "GET_%s(%p)", JIT_get_type(type), addr); - } - + push_static_variable(JIT_class, ctype, addr); + goto _MAIN; _POP_STATIC: index = GET_7XX(); - type = JIT_ctype_to_type(class, class->load->stat[index].type); + ctype = class->load->stat[index].type; addr = &class->stat[class->load->stat[index].pos]; - _no_release = TRUE; - if (check_swap(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr)) - pop(type, "SET_%s(%p, %%s)", JIT_get_type(type), addr); - _no_release = FALSE; + pop_static_variable(JIT_class, ctype, addr); goto _MAIN; @@ -2914,42 +3011,18 @@ _PUSH_DYNAMIC: index = GET_7XX(); pos = class->load->dyn[index].pos; ctype = class->load->dyn[index].type; - type = JIT_ctype_to_type(class, ctype); - switch(ctype.id) - { - case TC_STRUCT: - push(type, "GET_S(OP, &OP[%d], CLASS(%p))", pos, (CLASS *)type); - break; - - case TC_ARRAY: - declare(&_decl_ra, "void *ra = NULL"); - push(type, "GET_A(CP, OP, &OP[%d], CLASS(%p), %p)", pos, (CLASS *)type, JIT_class->load->array[ctype.value]); - break; - - case T_OBJECT: - if (TYPE_is_pure_object(type)) - push(type, "GET_o(&OP[%d], CLASS(%p))", pos, (CLASS *)type); - else - push(type, "GET_o(&OP[%d], GB_T_OBJECT)", pos); - break; - - default: - push(type, "GET_%s(&OP[%d])", JIT_get_type(type), pos); - } - + push_dynamic_variable(JIT_class, ctype, pos, "OP"); + goto _MAIN; _POP_DYNAMIC: index = GET_7XX(); - type = JIT_ctype_to_type(class, class->load->dyn[index].type); pos = class->load->dyn[index].pos; + ctype = class->load->dyn[index].type; - _no_release = TRUE; - if (check_swap(type, "SET_%s(&OP[%d], %%s)", JIT_get_type(type), pos)) - pop(type, "SET_%s(&OP[%d], %%s)", JIT_get_type(type), pos); - _no_release = FALSE; + pop_dynamic_variable(JIT_class, ctype, pos, "OP"); goto _MAIN;