From e65912ae72f42ba4bc4bd86e8d93149ed87c37a9 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Thu, 27 Jul 2017 08:32:16 +0000 Subject: [PATCH] improved gcfin handling a bit attempted to use XLoadFontSet in the x11 plugin experimentally --- moo/kernel/System.moo | 2 +- moo/kernel/X11.moo | 1 + moo/lib/comp.c | 4 +- moo/lib/exec.c | 73 +++++++++++-------- moo/lib/gc.c | 21 +++--- moo/lib/main.c | 3 + moo/lib/moo-prv.h | 1 + moo/lib/moo.c | 8 ++- moo/lib/moo.h | 1 - moo/mod/_x11.h | 1 + moo/mod/x11.c | 159 +++++++++++++++++++++++++++++++----------- 11 files changed, 189 insertions(+), 85 deletions(-) diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index 363e602..69d0d49 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -36,7 +36,7 @@ class System(Apex) gc := false. fin_sem := Semaphore new. - + Processor signalOnGCFin: fin_sem. [ while (true) diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index 4b700c0..bb4f530 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -172,6 +172,7 @@ class X11.GC(Object) fontName := nil. var fontPtr := nil. + var fontSet := nil. method(#class) new { diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 10d70e7..1f801a3 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -1945,7 +1945,9 @@ retry: break; } -MOO_DEBUG3 (moo, "TOKEN: [%.*js] %d\n", (moo_ooi_t)moo->c->tok.name.len, moo->c->tok.name.ptr, (int)moo->c->tok.type); +#if defined(MOO_DEBUG_LEXER) + MOO_DEBUG3 (moo, "TOKEN: [%.*js] %d\n", (moo_ooi_t)moo->c->tok.name.len, moo->c->tok.name.ptr, (int)moo->c->tok.type); +#endif return 0; } diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 7deb8d6..df0f220 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -4537,11 +4537,12 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) * having the following line causes to skip firing the * timed semaphore that would expire between now and the * moment the next inspection occurs. */ - if (moo->processor->active != moo->nil_process) goto finalization; + if (moo->processor->active != moo->nil_process) goto switch_to_next; } else { /* no running process, no io semaphore */ + if (moo->sem_gcfin != moo->_nil && moo->sem_gcfin_sigreq) goto signal_sem_gcfin; vm_sleep (moo, &ft); } vm_gettime (moo, &now); @@ -4576,11 +4577,14 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) } } - if (moo->sem_gcfin_sigreq) + + if ((moo_oop_t)moo->sem_gcfin != moo->_nil) { - if ((moo_oop_t)moo->sem_gcfin != moo->_nil) + moo_oop_process_t proc; + + if (moo->sem_gcfin_sigreq) { - moo_oop_process_t proc; + signal_sem_gcfin: MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Signalled GCFIN semaphore\n"); proc = signal_semaphore (moo, moo->sem_gcfin); @@ -4590,24 +4594,47 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) MOO_ASSERT (moo, proc == moo->processor->runnable.first); switch_to_process_from_nil (moo, proc); } + + moo->sem_gcfin_sigreq = 0; } - moo->sem_gcfin_sigreq = 0; - } - else - { - if ((moo_oop_t)moo->sem_gcfin != moo->_nil && moo->processor->active == moo->nil_process) + else { - moo_oop_process_t proc; - proc = signal_semaphore (moo, moo->sem_gcfin); - if ((moo_oop_t)proc != moo->_nil) + /* the gcfin semaphore signalling is not requested and there are + * no runnable processes nor no waiting semaphores. if there is + * process waiting on the gcfin semaphore, i will just schedule + * it to run */ + /* TODO: check if this is the best implementation practice */ + if (moo->processor->active == moo->nil_process) { - MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); - MOO_ASSERT (moo, proc == moo->processor->runnable.first); - switch_to_process_from_nil (moo, proc); + MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Signalled GCFIN semaphore without gcfin signal request\n"); + proc = signal_semaphore (moo, moo->sem_gcfin); + if ((moo_oop_t)proc != moo->_nil) + { + MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); + MOO_ASSERT (moo, proc == moo->processor->runnable.first); + switch_to_process_from_nil (moo, proc); + } } } } +#if 0 + while (moo->sem_list_count > 0) + { + /* handle async signals */ + --moo->sem_list_count; + signal_semaphore (moo, moo->sem_list[moo->sem_list_count]); + if (moo->processor->active == moo->nil_process) + { + } + } + /* + if (semaphore heap has pending request) + { + signal them... + }*/ +#endif + if (moo->processor->active == moo->nil_process) { /* no more waiting semaphore and no more process */ @@ -4616,21 +4643,7 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) return 0; } -finalization: -#if 0 - while (moo->sem_list_count > 0) - { - /* handle async signals */ - --moo->sem_list_count; - signal_semaphore (moo, moo->sem_list[moo->sem_list_count]); - } -#endif - /* - if (semaphore heap has pending request) - { - signal them... - }*/ - +switch_to_next: /* TODO: implement different process switching scheme - time-slice or clock based??? */ #if defined(MOO_EXTERNAL_PROCESS_SWITCH) if (!moo->proc_switched && moo->switch_proc) { switch_to_next_runnable_process (moo); } diff --git a/moo/lib/gc.c b/moo/lib/gc.c index b67d466..3113dfb 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -118,7 +118,7 @@ static kernel_class_info_t kernel_classes[] = }; -static void move_finalizable_objects (moo_t* moo); +static moo_oow_t move_finalizable_objects (moo_t* moo); /* ----------------------------------------------------------------------- * BOOTSTRAPPER @@ -630,6 +630,7 @@ void moo_gc (moo_t* moo) moo_oop_t old_nil; moo_oow_t i; moo_cb_t* cb; + moo_oow_t gcfin_count; if (moo->active_context) { @@ -712,10 +713,11 @@ void moo_gc (moo_t* moo) /* scan the new heap to move referenced objects */ scan_ptr = scan_new_heap (moo, scan_ptr); -/* FINALIZATION */ - move_finalizable_objects (moo); + /* check finalizable objects registered and scan the heap again. + * symbol table compation is placed after this phase assuming that + * no symbol is added to be finalized. */ + gcfin_count = move_finalizable_objects (moo); scan_ptr = scan_new_heap (moo, scan_ptr); -/* END FINALIZATION */ /* traverse the symbol table for unreferenced symbols. * if the symbol has not moved to the new heap, the symbol @@ -760,8 +762,7 @@ void moo_gc (moo_t* moo) */ if (moo->active_method) SET_ACTIVE_METHOD_CODE (moo); /* update moo->active_code */ - /*if (moo->sem_gcfin_count > 0) signal_semaphore (moo, moo->sem_gcfin);*/ - if (moo->sem_gcfin_count > 0) moo->sem_gcfin_sigreq = 1; + if (gcfin_count > 0) moo->sem_gcfin_sigreq = 1; /* TODO: include some gc statstics like number of live objects, gc performance, etc */ MOO_LOG4 (moo, MOO_LOG_GC | MOO_LOG_INFO, @@ -878,11 +879,11 @@ int moo_deregfinalizable (moo_t* moo, moo_oop_t oop) return -1; } -static void move_finalizable_objects (moo_t* moo) +static moo_oow_t move_finalizable_objects (moo_t* moo) { moo_finalizable_t* x, * y; + moo_oow_t count = 0; - moo->sem_gcfin_count = 0; for (x = moo->collectable.first; x; x = x->next) { MOO_ASSERT (moo, (MOO_OBJ_GET_FLAGS_GCFIN(x->oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) == MOO_GCFIN_FINALIZABLE); @@ -914,7 +915,7 @@ static void move_finalizable_objects (moo_t* moo) /* add it to the collectable list */ MOO_APPEND_TO_LIST (&moo->collectable, x); - moo->sem_gcfin_count++; + count++; } else { @@ -923,4 +924,6 @@ static void move_finalizable_objects (moo_t* moo) x = y; } + + return count; } diff --git a/moo/lib/main.c b/moo/lib/main.c index b6b112e..ccefb5b 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -31,6 +31,7 @@ #include #include #include +#include #if !defined(__DOS__) # define USE_THREAD @@ -1758,6 +1759,8 @@ int main (int argc, char* argv[]) } #endif + setlocale (LC_ALL, ""); + memset (&vmprim, 0, MOO_SIZEOF(vmprim)); vmprim.dl_open = dl_open; vmprim.dl_close = dl_close; diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index cca33a3..16a3a00 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -47,6 +47,7 @@ #if !defined(NDEBUG) /* this is for gc debugging */ #define MOO_DEBUG_GC +/*#define MOO_DEBUG_LEXER*/ #define MOO_DEBUG_COMPILER /*#define MOO_DEBUG_VM_PROCESSOR*/ /*#define MOO_DEBUG_VM_EXEC*/ diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 33c5fcb..9e06a75 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -386,9 +386,13 @@ void moo_freemem (moo_t* moo, void* ptr) #if defined(MOO_ENABLE_STATIC_MODULE) #include "../mod/console.h" -#include "../mod/_ffi.h" +#if defined(MOO_ENABLE_MOD_FFI) +# include "../mod/_ffi.h" +#endif #include "../mod/_stdio.h" -#include "../mod/_x11.h" +#if defined(MOO_ENABLE_MOD_X11) +# include "../mod/_x11.h" +#endif static struct { diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 0832bee..3955265 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1175,7 +1175,6 @@ struct moo_t /* semaphore to notify finalizable objects */ moo_oop_semaphore_t sem_gcfin; int sem_gcfin_sigreq; - moo_oow_t sem_gcfin_count; moo_oop_t* tmp_stack[256]; /* stack for temporaries */ moo_oow_t tmp_count; diff --git a/moo/mod/_x11.h b/moo/mod/_x11.h index 2d46ddc..c6aec87 100644 --- a/moo/mod/_x11.h +++ b/moo/mod/_x11.h @@ -63,6 +63,7 @@ struct x11_gc_t moo_oop_t font_name; moo_oop_t font_ptr; + moo_oop_t font_set; /* XFontSet */ }; typedef struct x11_widget_t* oop_x11_widget_t; diff --git a/moo/mod/x11.c b/moo/mod/x11.c index acca5d0..38ff614 100644 --- a/moo/mod/x11.c +++ b/moo/mod/x11.c @@ -466,7 +466,6 @@ static moo_pfrc_t pf_destroy_gc (moo_t* moo, moo_ooi_t nargs) Display* disp; - x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); gc = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0); /* GC object */ @@ -477,6 +476,13 @@ static moo_pfrc_t pf_destroy_gc (moo_t* moo, moo_ooi_t nargs) gc->font_ptr = moo->_nil; } + if (MOO_OOP_IS_SMPTR(gc->font_set)) + { + XFreeFontSet (disp, MOO_OOP_TO_SMPTR(gc->font_set)); + gc->font_set = moo->_nil; +MOO_DEBUG0 (moo, "Freed Font Set\n"); + } + if (MOO_OOP_IS_SMPTR(gc->gc_handle)) { XFreeGC (disp, MOO_OOP_TO_SMPTR(gc->gc_handle)); @@ -496,7 +502,6 @@ static moo_pfrc_t pf_apply_gc (moo_t* moo, moo_ooi_t nargs) unsigned long int mask = 0; XGCValues v; - x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); a0 = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0); /* TODO check if a0 is an instance of X11.GC */ @@ -513,30 +518,66 @@ static moo_pfrc_t pf_apply_gc (moo_t* moo, moo_ooi_t nargs) if (MOO_OBJ_IS_CHAR_POINTER(a0->font_name) && MOO_OBJ_GET_SIZE(a0->font_name) > 0) { - XFontStruct* font; -/* TODO: .... use font_name */ - font = XLoadQueryFont (disp, "-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1"); - if (font) + XFontSet fs; + char **missing_charsets; + int num_missing_charsets = 0; + char *default_string; + +/* TODO: don't create this again and again */ +/* TODO: use font name */ + fs = XCreateFontSet (disp, "-adobe-*-medium-r-normal-*-14-*-*-*-*-*-*-*,-baekmuk-*-medium-r-normal-*-14-*-*-*-*-*-*-*,-*-*-medium-r-normal-*-*-*-*-*-*-*-*-*", + &missing_charsets, &num_missing_charsets, &default_string); + if (num_missing_charsets) { - if (!MOO_IN_SMPTR_RANGE(font)) + int i; + + MOO_DEBUG0 (moo, "The following charsets are missing:\n"); + for(i = 0; i < num_missing_charsets; i++) + MOO_DEBUG1 (moo, "\t%s\n", missing_charsets[i]); + MOO_DEBUG1 (moo, "The string %s will be used in place of any characters from those set\n", default_string); + XFreeStringList(missing_charsets); + } + + if (fs) + { +/* TODO: error handling. rollback upon failure... etc */ + MOO_ASSERT (moo, MOO_IN_SMPTR_RANGE(fs)); + if (MOO_OOP_IS_SMPTR(a0->font_set)) { - MOO_DEBUG0 (moo, " Font pointer not in small pointer range\n"); - XFreeFont (disp, font); - MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); - return MOO_PF_SUCCESS; - } - else - { - XSetFont (disp, gc, font->fid); - if (MOO_OOP_IS_SMPTR(a0->font_ptr)) XFreeFont (disp, MOO_OOP_TO_SMPTR(a0->font_ptr)); - a0->font_ptr = MOO_SMPTR_TO_OOP(font); +MOO_DEBUG0 (moo, "Freed Font Set ..\n"); + XFreeFontSet (disp, MOO_OOP_TO_SMPTR(a0->font_set)); } + a0->font_set = MOO_SMPTR_TO_OOP (fs); +MOO_DEBUG0 (moo, "XCreateFontSet ok....\n"); } else { - MOO_DEBUG2 (moo, " Cannot load font - %.*js\n", MOO_OBJ_GET_SIZE(a0->font_name), MOO_OBJ_GET_CHAR_SLOT(a0->font_name)); - MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR); - return MOO_PF_SUCCESS; + XFontStruct* font; + + /* TODO: .... use font_name */ + font = XLoadQueryFont (disp, "-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1"); + if (font) + { + if (!MOO_IN_SMPTR_RANGE(font)) + { + MOO_DEBUG0 (moo, " Font pointer not in small pointer range\n"); + XFreeFont (disp, font); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); + return MOO_PF_SUCCESS; + } + else + { + XSetFont (disp, gc, font->fid); + if (MOO_OOP_IS_SMPTR(a0->font_ptr)) XFreeFont (disp, MOO_OOP_TO_SMPTR(a0->font_ptr)); + a0->font_ptr = MOO_SMPTR_TO_OOP(font); + } + } + else + { + MOO_DEBUG2 (moo, " Cannot load font - %.*js\n", MOO_OBJ_GET_SIZE(a0->font_name), MOO_OBJ_GET_CHAR_SLOT(a0->font_name)); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR); + return MOO_PF_SUCCESS; + } } } @@ -638,15 +679,11 @@ static moo_pfrc_t pf_fill_rectangle (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_draw_string (moo_t* moo, moo_ooi_t nargs) { - oop_x11_t x11; oop_x11_gc_t gc; moo_oop_t a1, a2, a3; Display* disp; - XChar2b* stptr; - moo_oow_t stlen; - int ascent = 0; x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); disp = MOO_OOP_TO_SMPTR(x11->display); @@ -666,26 +703,66 @@ static moo_pfrc_t pf_draw_string (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } -/* TODO: draw string chunk by chunk to avoid memory allocation in uchars_to_xchars2bstr */ - stptr = uchars_to_xchar2bstr (moo, MOO_OBJ_GET_CHAR_SLOT(a3), MOO_OBJ_GET_SIZE(a3), &stlen); - if (!stptr) + if (MOO_OOP_IS_SMPTR(gc->font_set)) { - MOO_DEBUG0 (moo, " Error in converting a string\n"); - MOO_STACK_SETRETTOERRNUM (moo, nargs); - return MOO_PF_SUCCESS; + moo_oow_t ucslen, bcslen; + moo_bch_t* bb; + int ascent = 10; + XRectangle r; + + ucslen = MOO_OBJ_GET_SIZE(a3); + if (moo_convootobchars (moo, MOO_OBJ_GET_CHAR_SLOT(a3), &ucslen, MOO_NULL, &bcslen) <= -1 || + !(bb = moo_allocmem (moo, MOO_SIZEOF(moo_bch_t) * bcslen))) + { + MOO_DEBUG0 (moo, " Error in converting a string\n"); + MOO_STACK_SETRETTOERRNUM (moo, nargs); + return MOO_PF_SUCCESS; + } + + //#if defined(MOO_OOCH_IS_UCH) + moo_convootobchars (moo, MOO_OBJ_GET_CHAR_SLOT(a3), &ucslen, bb, &bcslen); + //#else + // moo_copybcstr (&bb->fn[parlen], bcslen + 1, arg->name); + //#endif + + XmbTextExtents(MOO_OOP_TO_SMPTR(gc->font_set), bb, bcslen, MOO_NULL, &r); + ascent = r.height; + + XmbDrawString (disp, (Window)MOO_OOP_TO_SMOOI(((oop_x11_widget_t)gc->widget)->window_handle), + MOO_OOP_TO_SMPTR(gc->font_set), MOO_OOP_TO_SMPTR(gc->gc_handle), + MOO_OOP_TO_SMOOI(a1), MOO_OOP_TO_SMOOI(a2) + ascent, bb, bcslen); + + moo_freemem (moo, bb); + } + else + { + XChar2b* stptr; + moo_oow_t stlen; + int ascent = 0; + + /* TODO: draw string chunk by chunk to avoid memory allocation in uchars_to_xchars2bstr */ + stptr = uchars_to_xchar2bstr (moo, MOO_OBJ_GET_CHAR_SLOT(a3), MOO_OBJ_GET_SIZE(a3), &stlen); + if (!stptr) + { + MOO_DEBUG0 (moo, " Error in converting a string\n"); + MOO_STACK_SETRETTOERRNUM (moo, nargs); + return MOO_PF_SUCCESS; + } + + if (MOO_OOP_IS_SMPTR(gc->font_ptr)) + { + int direction, descent; + XCharStruct overall; + XTextExtents16 (MOO_OOP_TO_SMPTR(gc->font_ptr), stptr, stlen, &direction, &ascent, &descent, &overall); + } + + XDrawString16 (disp, (Window)MOO_OOP_TO_SMOOI(((oop_x11_widget_t)gc->widget)->window_handle), MOO_OOP_TO_SMPTR(gc->gc_handle), + MOO_OOP_TO_SMOOI(a1), MOO_OOP_TO_SMOOI(a2) + ascent, stptr, stlen); + + moo_freemem (moo, stptr); } - if (MOO_OOP_IS_SMPTR(gc->font_ptr)) - { - int direction, descent; - XCharStruct overall; - XTextExtents16 (MOO_OOP_TO_SMPTR(gc->font_ptr), stptr, stlen, &direction, &ascent, &descent, &overall); - } - - XDrawString16 (disp, (Window)MOO_OOP_TO_SMOOI(((oop_x11_widget_t)gc->widget)->window_handle), MOO_OOP_TO_SMPTR(gc->gc_handle), - MOO_OOP_TO_SMOOI(a1), MOO_OOP_TO_SMOOI(a2) + ascent, stptr, stlen); - - moo_freemem (moo, stptr); + MOO_STACK_SETRETTORCV (moo, nargs); return MOO_PF_SUCCESS; }