RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 10-Jul-2017 11:42:51 Branch: rpm-5_4 Handle: 2017071009425100 Added files: (Branch: rpm-5_4) rpm/rpmio rpmev.c rpmjss.cpp Log: - create. Summary: Revision Changes Path 1.1.2.1 +649 -0 rpm/rpmio/rpmev.c 1.1.2.1 +996 -0 rpm/rpmio/rpmjss.cpp ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmio/rpmev.c ============================================================================ $ cvs diff -u -r0 -r1.1.2.1 rpmev.c --- /dev/null 2017-07-10 11:35:46.000000000 +0200 +++ rpmev.c 2017-07-10 11:42:51.797005547 +0200 @@ -0,0 +1,649 @@ +#include "system.h" +#include <stdarg.h> + +#if defined(WITH_LIBEV) + +#if defined(HAVE_EV_H) +# include <ev.h> +#endif + +#else /* WITH_LIBEV */ + +/* XXX stub in enough to include rpmev.h */ +#define EV_P_ void * loop, +struct ev_watcher { + int active; + int pending; + int priority; + void * data; + void (*cb)(EV_P_ void *w, int revents); +}; + +union ev_any_watcher +{ + struct ev_watcher w; +}; + +#endif /* WITH_LIBEV */ + +#include <rpmio.h> +#include <poptIO.h> + +#define _RPMEV_INTERNAL +#include <rpmev.h> + +#include "debug.h" + +int _rpmev_debug = -1; + +#define SPEW(_fmt, ...) \ + if (_rpmev_debug || _rpmio_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) + +/*==============================================================*/ +unsigned rpmioEV = 0; +struct poptOption rpmioEVTable[] = { +#if defined(WITH_LIBEV) + { "read", '\0', POPT_BIT_SET, &rpmioEV, EV_READ, + N_("read"), N_("EV_READ") }, + { "write", '\0', POPT_BIT_SET, &rpmioEV, EV_WRITE, + N_("write"), N_("EV_WRITE") }, + { "internal", '\0', POPT_BIT_SET, &rpmioEV, EV__IOFDSET, + N_("internal"), N_("EV__IOFDSET") }, + { "timer", '\0', POPT_BIT_SET, &rpmioEV, EV_TIMER, + N_("timer"), N_("EV_TIMER") }, + { "periodic", '\0', POPT_BIT_SET, &rpmioEV, EV_PERIODIC, + N_("periodic"), N_("EV_PERIODIC") }, + { "signal", '\0', POPT_BIT_SET, &rpmioEV, EV_SIGNAL, + N_("signal"), N_("EV_SIGNAL") }, + { "child", '\0', POPT_BIT_SET, &rpmioEV, EV_CHILD, + N_("child"), N_("EV_CHILD") }, + { "stat", '\0', POPT_BIT_SET, &rpmioEV, EV_STAT, + N_("stat"), N_("EV_STAT") }, + { "idle", '\0', POPT_BIT_SET, &rpmioEV, EV_IDLE, + N_("idle"), N_("EV_IDLE") }, + { "prepare", '\0', POPT_BIT_SET, &rpmioEV, EV_PREPARE, + N_("prepare"), N_("EV_PREPARE") }, + { "check", '\0', POPT_BIT_SET, &rpmioEV, EV_CHECK, + N_("check"), N_("EV_CHECK") }, + { "embed", '\0', POPT_BIT_SET, &rpmioEV, EV_EMBED, + N_("embed"), N_("EV_EMBED") }, + { "fork", '\0', POPT_BIT_SET, &rpmioEV, EV_FORK, + N_("fork"), N_("EV_FORK") }, + { "cleanup", '\0', POPT_BIT_SET, &rpmioEV, EV_CLEANUP, + N_("cleanup"), N_("EV_CLEANUP") }, + { "async", '\0', POPT_BIT_SET, &rpmioEV, EV_ASYNC, + N_("async"), N_("EV_ASYNC") }, + { "custom", '\0', POPT_BIT_SET, &rpmioEV, EV_CUSTOM, + N_("custom"), N_("EV_CUSTOM") }, + { "error", '\0', POPT_BIT_SET, &rpmioEV, EV_ERROR, + N_("error"), N_("EV_ERROR") }, +#endif /* WITH_LIBEV */ + POPT_TABLEEND +}; + +unsigned rpmioEVFLAG = 0; +struct poptOption rpmioEVFLAGTable[] = { +#if defined(WITH_LIBEV) + { "env", '\0', POPT_BIT_CLR|POPT_ARGFLAG_TOGGLE, &rpmioEVFLAG, EVFLAG_NOENV, + N_("env"), N_("EVFLAG_NOENV") }, + { "forkcheck", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &rpmioEVFLAG, EVFLAG_FORKCHECK, + N_("forkcheck"), N_("EVFLAG_FORKCHECK") }, + { "inotify", '\0', POPT_BIT_CLR|POPT_ARGFLAG_TOGGLE, &rpmioEVFLAG, EVFLAG_NOINOTIFY, + N_("inotify"), N_("EVFLAG_NOINOTIFY") }, + { "signalfd", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &rpmioEVFLAG, EVFLAG_SIGNALFD, + N_("signalfd"), N_("EVFLAG_SIGNALFD") }, + { "sigmask", '\0', POPT_BIT_CLR|POPT_ARGFLAG_TOGGLE, &rpmioEVFLAG, EVFLAG_NOSIGMASK, + N_("sigmask"), N_("EVFLAG_NOSIGMASK") }, +#endif /* WITH_LIBEV */ + POPT_TABLEEND +}; + +unsigned rpmioEVBACKEND = 0; +struct poptOption rpmioEVBACKENDTable[] = { +#if defined(WITH_LIBEV) + { "select", '\0', POPT_BIT_SET, &rpmioEVBACKEND, EVBACKEND_SELECT, + N_("select"), N_("EVBACKEND_SELECT") }, + { "poll", '\0', POPT_BIT_SET, &rpmioEVBACKEND, EVBACKEND_POLL, + N_("poll"), N_("EVBACKEND_POLL") }, + { "epoll", '\0', POPT_BIT_SET, &rpmioEVBACKEND, EVBACKEND_EPOLL, + N_("epoll"), N_("EVBACKEND_EPOLL") }, + { "kqueue", '\0', POPT_BIT_SET, &rpmioEVBACKEND, EVBACKEND_KQUEUE, + N_("kqueue"), N_("EVBACKEND_KQUEUE") }, + { "devpoll", '\0', POPT_BIT_SET, &rpmioEVBACKEND, EVBACKEND_DEVPOLL, + N_("devpoll"), N_("EVBACKEND_DEVPOLL") }, + { "port", '\0', POPT_BIT_SET, &rpmioEVBACKEND, EVBACKEND_PORT, + N_("port"), N_("EVBACKEND_PORT") }, +#endif /* WITH_LIBEV */ + POPT_TABLEEND +}; + +/*==============================================================*/ +/* every watcher type has its own typedef'd struct */ +/* with the name ev_TYPE */ + +static rpmioItem rpmevqHead = NULL; +static rpmioItem * rpmevqTail = &rpmevqHead; + +rpmev rpmevqGetHead(void) +{ + rpmioItem item; + RPM_GNUC_TM_ATOMIC { + if ((item = rpmevqHead) != NULL) { + rpmevqHead = item->next; + item->next = NULL; + if (rpmevqHead == NULL) + rpmevqTail = &rpmevqHead; + } + } +if (item) +SPEW("<--\t%s() rc %p\n", __FUNCTION__, item); + return (rpmev) item; +} + +void rpmevqPutTail(rpmev ev) +{ +SPEW("-->\t%s(%p)\n", __FUNCTION__, ev); + if (ev == NULL) + return; + rpmioItem item = &ev->_item; + item->next = NULL; + RPM_GNUC_TM_ATOMIC { + *rpmevqTail = item; + rpmevqTail = (rpmioItem *) &item->next; + } +} + +void rpmevqPutHead(rpmev ev) +{ +SPEW("-->\t%s(%p)\n", __FUNCTION__, ev); + if (ev == NULL) + return; + rpmioItem item = &ev->_item; + RPM_GNUC_TM_ATOMIC { + item->next = rpmevqHead->next; + if (item->next == NULL) + rpmevqTail = (rpmioItem *) &item->next; + rpmevqHead->next = item; + } +} + +static void rpmevqRemove(rpmev ev) +{ +SPEW("-->\t%s(%p)\n", __FUNCTION__, ev); + if (ev == NULL) + return; + rpmioItem item = &ev->_item; + rpmioItem * prev = &rpmevqHead; + while (prev && (*prev)->next != NULL) { + if ((*prev)->next == item) { + (*prev)->next = item->next; + item->next = NULL; + if (rpmevqHead == NULL) + rpmevqTail = &rpmevqHead; + break; + } + prev = (*prev)->next; + } +} + +/* all watcher callbacks have a similar signature */ + +/* --- */ +static +void rpmevChild_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_child * w = (ev_child *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_CHILD); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s) pid %u status %u (0x%x)\n", __FUNCTION__, w, rstr, w->rpid, __WEXITSTATUS(w->rstatus), w->rstatus); + rstr = _free(rstr); + } + ev_child_stop (EV_A_ w); +#ifdef BUGGY + ev = rpmevFree(ev); /* XXX deallocate w rpmevRemove(ev)? */ +#endif +#endif /* WITH_LIBEV */ +} + +static +int rpmevStart(void) +{ + int rc; +SPEW("--> %s()\n", __FUNCTION__); + pid_t pid = fork(); + if (pid < 0) { + rc = -1; + exit(rc); + } else if (pid == 0) { + sleep(2); + rc = 42; + exit(rc); + } else { + rpmev ev = rpmevNew(RPMEV_TYPE_CHILD, NULL, pid, 0); + (void)ev; +#ifdef DYING + ev_child * w = &ev->evw.child; + w->pid = 0; + w->flags = 0; /** XXX 0=terminate, 1=stop/continue */ + ev_child_start (EV_DEFAULT_ w); +#endif + rc = 0; + } +SPEW("<-- %s() rc %d\n", __FUNCTION__, rc); + return rc; +} + +/* --- */ +static void rpmevIo_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_io * w = (ev_io *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_IO); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s) fd %d events 0x%x\n", __FUNCTION__, w, rstr, w->fd, w->events); + rstr = _free(rstr); + } + /* for one-shot events, one must manually stop the watcher */ + /* with its corresponding stop function. */ + ev_io_stop(EV_A_ w); + + /* this causes all nested ev_loop's to stop iterating */ + ev_unloop(EV_A_ EVUNLOOP_ALL); +#endif /* WITH_LIBEV */ +} +/* --- */ +static void rpmevTimer_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_timer * w = (ev_timer *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_TIMER); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s) repeat %f\n", __FUNCTION__, w, rstr, w->repeat); + rstr = _free(rstr); + } +#ifdef DYING + /* this causes the innermost ev_loop to stop iterating */ + ev_unloop(EV_A_ EVUNLOOP_ONE); +#endif + w->repeat = 5.5; + ev_timer_again(EV_A_ w); +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevPeriodic_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_periodic * w = (ev_periodic *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_PERIODIC); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s) offset %f interval %f reschedule_cb %p\n", __FUNCTION__, w, rstr, w->offset, w->interval, w->reschedule_cb); + rstr = _free(rstr); + } + rpmevStart(); +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevSignal_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_signal * w = (ev_signal *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_SIGNAL); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s) signum %d\n", __FUNCTION__, w, rstr, w->signum); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevStat_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_stat * w = (ev_stat *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_STAT); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s) path %s wd %d\n", __FUNCTION__, w, rstr, w->path, w->wd); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevIdle_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_idle * w = (ev_idle *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_IDLE); +#ifdef NOISY + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s)\n", __FUNCTION__, w, rstr); + rstr = _free(rstr); + } +#endif + struct timespec ts = { 0, 10*1000*1000 }; + nanosleep(&ts, NULL); + sched_yield(); +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevPrepare_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_prepare * w = (ev_prepare *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_PREPARE); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s)\n", __FUNCTION__, w, rstr); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevCheck_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_check * w = (ev_check *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_CHECK); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s)\n", __FUNCTION__, w, rstr); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevFork_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_fork * w = (ev_fork *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_FORK); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s)\n", __FUNCTION__, w, rstr); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevCleanup_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_cleanup * w = (ev_cleanup *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_CLEANUP); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s)\n", __FUNCTION__, w, rstr); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevEmbed_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_embed * w = (ev_embed *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_EMBED); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s)\n", __FUNCTION__, w, rstr); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +/* --- */ +static void rpmevAsync_cb(EV_P_ void * _w, int revents) +{ +#if defined(WITH_LIBEV) + ev_async * w = (ev_async *) _w; + rpmev ev = (rpmev) w->data; +assert(ev && ev->evtype == RPMEV_TYPE_ASYNC); + { char *rstr = rpmioB2N(rpmioEVTable, revents); + SPEW("--> %s(%p, %s)\n", __FUNCTION__, w, rstr); + rstr = _free(rstr); + } +#endif /* WITH_LIBEV */ +} + +void rpmevDump(const char *msg, rpmev ev, FILE *fp) +{ + if (fp == NULL) fp = stderr; + if (msg) fprintf(stderr, "========================= %s(%p)\n", msg, ev); + if (ev) { +#define PRINT(_fmt, _foo) \ + { fprintf(fp, "%25s: %"#_fmt"\n", #_foo, ev->_foo); } + PRINT(u, evtype); + PRINT(d, evw.w.active); + PRINT(d, evw.w.pending); + PRINT(p, evw.w.data); + PRINT(p, evw.w.cb); + PRINT(p, _item.next); +fprintf(stderr, "%25s: &%p next %p\n", "head", &rpmevqHead, (rpmevqHead ? rpmevqHead->next : NULL)); +fprintf(stderr, "%25s: %p next %p\n", "tail", rpmevqTail, (rpmevqTail ? *rpmevqTail : NULL)); +#undef PRINT + + } +} + +static void rpmevFini(void *_ev) +{ + rpmev ev = (rpmev) _ev; + if (ev) { + +#ifdef BUGGY + /* If still linked into thge allocation chain, unlink. */ + if (ev->_item.next) + rpmevqRemove(ev); +#endif + +#if defined(WITH_LIBEV) + /* XXX ev->loop private loops? */ + struct ev_loop *loop = ev_default_loop_uc_(); + + if (loop) + switch (ev->evtype) { + default: + case RPMEV_TYPE_UNKNOWN: + { ev_watcher * w = &ev->evw.w; + (void *)w; + } break; + case RPMEV_TYPE_IO: + { ev_io * w = &ev->evw.io; + ev_io_stop(loop, w); + } break; + case RPMEV_TYPE_TIMER: + { ev_timer * w = &ev->evw.timer; + ev_timer_stop(loop, w); + } break; + case RPMEV_TYPE_PERIODIC: + { ev_periodic * w = &ev->evw.periodic; + ev_periodic_stop(loop, w); + } break; + case RPMEV_TYPE_SIGNAL: + { ev_signal * w = &ev->evw.signal; + ev_signal_stop(loop, w); + } break; + case RPMEV_TYPE_CHILD: + { ev_child * w = &ev->evw.child; + ev_child_stop(loop, w); + } break; + case RPMEV_TYPE_STAT: + { ev_stat * w = &ev->evw.stat; + ev_stat_stop(loop, w); + w->path = _free(w->path); + } break; + case RPMEV_TYPE_IDLE: + { ev_idle * w = &ev->evw.idle; + ev_idle_stop(loop, w); + } break; + case RPMEV_TYPE_PREPARE: + { ev_prepare * w = &ev->evw.prepare; + ev_prepare_stop(loop, w); + } break; + case RPMEV_TYPE_CHECK: + { ev_check * w = &ev->evw.check; + ev_check_stop(loop, w); + } break; + case RPMEV_TYPE_FORK: + { ev_fork * w = &ev->evw.fork; + ev_fork_stop(loop, w); + } break; + case RPMEV_TYPE_CLEANUP: + { ev_cleanup * w = &ev->evw.cleanup; + ev_cleanup_stop(loop, w); + } break; + case RPMEV_TYPE_EMBED: + { ev_embed * w = &ev->evw.embed; + ev_embed_stop(loop, w); + } break; + case RPMEV_TYPE_ASYNC: + { ev_async * w = &ev->evw.async; + ev_async_stop(loop, w); + } break; + } +#endif /* WITH_LIBEV */ + + /* XXX stop/destroyiterate loop? */ + ev->evtype = 0; + } +} + +#define rpmevDbug NULL +#define rpmevInit NULL +RPMIOPOOL_MODULE(ev) + +rpmev rpmevNew(rpmevType evtype, void * _evcb, ...) +{ + rpmev ev = rpmevGetPool(_rpmevPool); + + ev->evtype = evtype; + +#if defined(WITH_LIBEV) + struct ev_loop *loop = ev_default_loop(EVFLAG_AUTO); + va_list ap; + + /* Initialize the base class. */ + ev_watcher * watcher = &ev->evw.w; + ev_init(watcher, _evcb); + watcher->data = ev; + + /* Process args and start the event. */ + va_start(ap, _evcb); + + switch (evtype) { + default: + case RPMEV_TYPE_UNKNOWN: + { ev_watcher * w = &ev->evw.w; + (void *)w; /* XXX NOTYET */ + } break; + case RPMEV_TYPE_IO: + { ev_io * w = &ev->evw.io; + w->cb = (_evcb ? _evcb : rpmevIo_cb); + w->fd = va_arg(ap, int); + w->events = va_arg(ap, int); + ev_io_start(loop, w); + } break; + case RPMEV_TYPE_TIMER: + { ev_timer * w = &ev->evw.timer; + w->cb = (_evcb ? _evcb : rpmevTimer_cb); + w->at = va_arg(ap, ev_tstamp); + w->repeat = va_arg(ap, ev_tstamp); + ev_timer_start(loop, w); + } break; + case RPMEV_TYPE_PERIODIC: + { ev_periodic * w = &ev->evw.periodic; + w->cb = (_evcb ? _evcb : rpmevPeriodic_cb); + w->offset = va_arg(ap, ev_tstamp); + w->interval = va_arg(ap, ev_tstamp); + w->reschedule_cb = va_arg(ap, void *); + ev_periodic_start(loop, w); + } break; + case RPMEV_TYPE_SIGNAL: + { ev_signal * w = &ev->evw.signal; + w->cb = (_evcb ? _evcb : rpmevSignal_cb); + w->signum = va_arg(ap, int); + ev_signal_start(loop, w); + } break; + case RPMEV_TYPE_CHILD: + { ev_child * w = &ev->evw.child; + w->cb = (_evcb ? _evcb : rpmevChild_cb); + w->flags = va_arg(ap, int); + w->pid = va_arg(ap, int); + ev_child_start (EV_DEFAULT_ w); /* XXX only main */ + } break; + case RPMEV_TYPE_STAT: + { ev_stat * w = &ev->evw.stat; + w->cb = (_evcb ? _evcb : rpmevStat_cb); + const char *path = va_arg(ap, const char *); + w->path = (path ? xstrdup(path) : NULL); + w->interval = va_arg(ap, ev_tstamp); + w->wd = -2; + ev_stat_start(loop, w); + } break; + case RPMEV_TYPE_IDLE: + { ev_idle * w = &ev->evw.idle; + w->cb = (_evcb ? _evcb : rpmevIdle_cb); +rpmevDump("IDLE", ev, NULL); + ev_idle_start(loop, w); + } break; + case RPMEV_TYPE_PREPARE: + { ev_prepare * w = &ev->evw.prepare; + w->cb = (_evcb ? _evcb : rpmevPrepare_cb); + ev_prepare_start(loop, w); + } break; + case RPMEV_TYPE_CHECK: + { ev_check * w = &ev->evw.check; + w->cb = (_evcb ? _evcb : rpmevCheck_cb); + ev_check_start(loop, w); + } break; + case RPMEV_TYPE_FORK: + { ev_fork * w = &ev->evw.fork; + w->cb = (_evcb ? _evcb : rpmevFork_cb); + ev_fork_start(loop, w); + } break; + case RPMEV_TYPE_CLEANUP: + { ev_cleanup * w = &ev->evw.cleanup; + w->cb = (_evcb ? _evcb : rpmevCleanup_cb); + ev_cleanup_start(loop, w); + } break; + case RPMEV_TYPE_EMBED: + { ev_embed * w = &ev->evw.embed; + w->cb = (_evcb ? _evcb : rpmevEmbed_cb); + w->other = va_arg(ap, void *); + ev_embed_start(loop, w); + } break; + case RPMEV_TYPE_ASYNC: + { ev_async * w = &ev->evw.async; + w->cb = (_evcb ? _evcb : rpmevAsync_cb); +rpmevDump("ASYNC", ev, NULL); + ev_async_start(loop, w); + } break; + } + + va_end(ap); + + /* XXX ev_start? */ + + /* Add to allocated event chain. */ + rpmevqPutTail(ev); +#endif /* WITH_LIBEV */ + + return rpmevLink(ev); +} + @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjss.cpp ============================================================================ $ cvs diff -u -r0 -r1.1.2.1 rpmjss.cpp --- /dev/null 2017-07-10 11:35:46.000000000 +0200 +++ rpmjss.cpp 2017-07-10 11:42:51.811005545 +0200 @@ -0,0 +1,996 @@ +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +#pragma GCC diagnostic ignored "-Wextra" + +#include "system.h" +#undef ioctl +#define rpl_ioctl ioctl + +/*==============================================================*/ +#include "shell/OSObject.cpp" +/*==============================================================*/ +#define main mozMain +#include "shell/js.cpp" +#undef main +/*==============================================================*/ +#include "shell/jsoptparse.cpp" +/*==============================================================*/ + +#include <rpmio.h> +#include <rpmlog.h> +#include <argv.h> +#include <poptIO.h> + +#define _RPMJSS_INTERNAL +#include "rpmjss.h" + +#include "debug.h" + +int _rpmjss_debug; +#define SPEW(_fmt, ...) \ + if (_rpmjss_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) + +/*==============================================================*/ +static bool +rpmSetRuntimeOptions(JSRuntime* rt, const rpmjss jss) +{ + const char * str; + + enableBaseline = ((jss->xf & XF_BASELINE) != 0); + enableIon = ((jss->xf & XF_ION) != 0); + enableAsmJS = ((jss->xf & XF_ASMJS) != 0); + enableNativeRegExp = ((jss->xf & XF_NATIVE_REGEXP) != 0); + enableUnboxedArrays = ((jss->xf & XF_UNBOXED_ARRAYS) != 0); + + JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline) + .setIon(enableIon) + .setAsmJS(enableAsmJS) + .setNativeRegExp(enableNativeRegExp) + .setUnboxedArrays(enableUnboxedArrays); + + if (!(jss->xf & XF_UNBOXED_OBJECTS)) + jit::JitOptions.disableUnboxedObjects = true; + + str = jss->ion_scalar_replacement; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableScalarReplacement = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableScalarReplacement = true; + else + return OptionFailure("ion-scalar-replacement", str); + } + + str = jss->ion_shared_stubs; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableSharedStubs = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableSharedStubs = true; + else + return OptionFailure("ion-shared-stubs", str); + } + + str = jss->ion_gvn; + if (str) { + if (strcmp(str, "off") == 0) { + jit::JitOptions.disableGvn = true; + } else if (strcmp(str, "on") != 0 && + strcmp(str, "optimistic") != 0 && + strcmp(str, "pessimistic") != 0) + { + // We accept "pessimistic" and "optimistic" as synonyms for "on" + // for backwards compatibility. + return OptionFailure("ion-gvn", str); + } + } + + str = jss->ion_licm; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableLicm = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableLicm = true; + else + return OptionFailure("ion-licm", str); + } + + str = jss->ion_edgecase_analysis; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableEdgeCaseAnalysis = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableEdgeCaseAnalysis = true; + else + return OptionFailure("ion-edgecase-analysis", str); + } + + str = jss->ion_pgo; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disablePgo = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disablePgo = true; + else + return OptionFailure("ion-pgo", str); + } + + str = jss->ion_range_analysis; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableRangeAnalysis = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableRangeAnalysis = true; + else + return OptionFailure("ion-range-analysis", str); + } + + str = jss->ion_sincos; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableSincos = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableSincos = true; + else + return OptionFailure("ion-sincos", str); + } + + str = jss->ion_sink; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableSink = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableSink = true; + else + return OptionFailure("ion-sink", str); + } + + str = jss->ion_loop_unrolling; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableLoopUnrolling = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableLoopUnrolling = true; + else + return OptionFailure("ion-loop-unrolling", str); + } + + str = jss->ion_instruction_reordering; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableInstructionReordering = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableInstructionReordering = true; + else + return OptionFailure("ion-instruction-reordering", str); + } + + if (jss->ionf & ION_CHECK_RANGE_ANALYSIS) + jit::JitOptions.checkRangeAnalysis = true; + + if (jss->ionf & ION_EXTRA_CHECKS) + jit::JitOptions.runExtraChecks = true; + + str = jss->ion_inlining; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableInlining = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableInlining = true; + else + return OptionFailure("ion-inlining", str); + } + + str = jss->ion_osr; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.osr = true; + else if (strcmp(str, "off") == 0) + jit::JitOptions.osr = false; + else + return OptionFailure("ion-osr", str); + } + + str = jss->ion_limit_script_size; + if (str) { + if (strcmp(str, "on") == 0) + jit::JitOptions.limitScriptSize = true; + else if (strcmp(str, "off") == 0) + jit::JitOptions.limitScriptSize = false; + else + return OptionFailure("ion-limit-script-size", str); + } + + int32_t warmUpThreshold = jss->ion_warmup_threshold; + if (warmUpThreshold >= 0) + jit::JitOptions.setCompilerWarmUpThreshold(warmUpThreshold); + + warmUpThreshold = jss->baseline_warmup_threshold; + if (warmUpThreshold >= 0) + jit::JitOptions.baselineWarmUpThreshold = warmUpThreshold; + + if (jss->xf & XF_BASELINE_EAGER) + jit::JitOptions.baselineWarmUpThreshold = 0; + + str = jss->ion_regalloc; + if (str) { + jit::JitOptions.forcedRegisterAllocator = jit::LookupRegisterAllocator(str); + if (!jit::JitOptions.forcedRegisterAllocator.isSome()) + return OptionFailure("ion-regalloc", str); + } + + if (jss->ionf & ION_EAGER) + jit::JitOptions.setEagerCompilation(); + + offthreadCompilation = true; + str = jss->ion_offthread_compile; + if (str) { + if (strcmp(str, "off") == 0) + offthreadCompilation = false; + else if (strcmp(str, "on") != 0) + return OptionFailure("ion-offthread-compile", str); + } + rt->setOffthreadIonCompilationEnabled(offthreadCompilation); + +#if defined(JS_CODEGEN_ARM) /* XXX FIXME */ + if (const char* str = op.getStringOption("arm-hwcap")) + jit::ParseARMHwCapFlags(str); + + int32_t fill = op.getIntOption("arm-asm-nop-fill"); + if (fill >= 0) + jit::Assembler::NopFill = fill; + + int32_t poolMaxOffset = op.getIntOption("asm-pool-max-offset"); + if (poolMaxOffset >= 5 && poolMaxOffset <= 1024) + jit::Assembler::AsmPoolMaxOffset = poolMaxOffset; +#endif + +#if defined(JS_SIMULATOR_ARM) /* XXX FIXME */ + if (op.getBoolOption("arm-sim-icache-checks")) + jit::Simulator::ICacheCheckingEnabled = true; + + int32_t stopAt = op.getIntOption("arm-sim-stop-at"); + if (stopAt >= 0) + jit::Simulator::StopSimAt = stopAt; +#elif defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64) + if (op.getBoolOption("mips-sim-icache-checks")) + jit::Simulator::ICacheCheckingEnabled = true; + + int32_t stopAt = op.getIntOption("mips-sim-stop-at"); + if (stopAt >= 0) + jit::Simulator::StopSimAt = stopAt; +#endif + + reportWarnings = ((jss->xf & XF_WARNINGS) != 0); + compileOnly = ((jss->xf & XF_COMPILE_ONLY) != 0); + printTiming = ((jss->xf & XF_PRINT_TIMING) != 0); + enableCodeCoverage = ((jss->xf & XF_CODE_COVERAGE) != 0); + enableDisassemblyDumps = ((jss->xf & XF_DUMP_BYTECODE) != 0); + rt->profilingScripts = enableCodeCoverage || enableDisassemblyDumps; + + jsCacheDir = jss->cachedir; + if (jsCacheDir) { + if (jss->xf & XF_CACHE_PER_PROCESS) + jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid()); + else + jsCacheDir = JS_strdup(rt, jsCacheDir); + jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir); + } + +#ifdef DEBUG + dumpEntrainedVariables = ((jss->xf & XF_DUMP_ENTRAINED_VARIABLES) != 0); +#endif + +#ifdef JS_GC_ZEAL + const char* zealStr = jss->gc_zeal; + gZealStr[0] = 0; + if (zealStr) { + if (!rt->gc.parseAndSetZeal(zealStr)) + return false; + strncpy(gZealStr, zealStr, sizeof(gZealStr)); + gZealStr[sizeof(gZealStr)-1] = 0; + } +#endif + + return true; +} + +/*==============================================================*/ +#undef NDEBUG +static int rpmjss_nopens; + +typedef struct JSI_s * JSI_t; +struct JSI_s { + JSRuntime *rt; + JSContext *cx; + JSObject *global; +}; + +static void mozFini(rpmjss jss) +{ + JSI_t I = (JSI_t) jss->I; + + if (enableDisassemblyDumps) + js::DumpCompartmentPCCounts(I->cx); + + if (jss->xf & XF_CACHE_PER_PROCESS) { + if (jsCacheAsmJSPath) { + unlink(jsCacheAsmJSPath); + JS_free(I->cx, const_cast<char*>(jsCacheAsmJSPath)); + } + if (jsCacheDir) { + rmdir(jsCacheDir); + JS_free(I->cx, const_cast<char*>(jsCacheDir)); + } + } + + JS::SetLargeAllocationFailureCallback(I->rt, nullptr, nullptr); + + if (I->cx) + DestroyContext(I->cx, true); + I->cx = NULL; + + KillWatchdog(I->rt); + + MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty()); + for (size_t i = 0; i < workerThreads.length(); i++) + PR_JoinThread(workerThreads[i]); + + DestructSharedArrayBufferMailbox(); + + if (I->rt) { + ShellRuntime* sr = GetShellRuntime(I->rt); + JS_DestroyRuntime(I->rt); + delete sr; + } + I->rt = NULL; + + if (--rpmjss_nopens <= 0) { + JS_ShutDown(); + rpmjss_nopens = 0; + } + if (I) + free(I); +} + +static void * mozInit(rpmjss jss) +{ + JSI_t I = (JSI_t) calloc(1, sizeof(*I)); +assert(I); + + JSPrincipals * _principals = NULL; + bool ok; + + // Start the engine. + if (rpmjss_nopens++ == 0) { + + MaybeOverrideOutFileFromEnv("JS_STDERR", stderr, &gErrFile); + MaybeOverrideOutFileFromEnv("JS_STDOUT", stdout, &gOutFile); + +#ifdef JS_CODEGEN_X86 + if (!(jss->xf & XF_FPU)) + js::jit::CPUInfo::SetFloatingPointDisabled(); +#endif + +#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) + if (!(jss->xf & XF_SSE3)) { + js::jit::CPUInfo::SetSSE3Disabled(); + PropagateFlagToNestedShells("--no-sse3"); + } + if (!(jss->xf & XF_SSE4)) { + js::jit::CPUInfo::SetSSE4Disabled(); + PropagateFlagToNestedShells("--no-sse4"); + } + if (jss->xf & XF_AVX) { + js::jit::CPUInfo::SetAVXEnabled(); + PropagateFlagToNestedShells("--enable-avx"); + } +#endif + + if (!(jss->xf && XF_THREADS)) + js::DisableExtraThreads(); + + JS_Init(); + + } + + ok = InitSharedArrayBufferMailbox(); +assert(ok); + + // The fake thread count must be set before initializing the Runtime, + // which spins up the thread pool. + int32_t threadCount = jss->thread_count; + if (threadCount >= 0) + SetFakeCPUCount(threadCount); + + static uint32_t _maxbytes = 8L * 1024L * 1024L; + uint32_t nurseryBytes = jss->nursery_size > 0 + ? jss->nursery_size : JS::DefaultNurseryBytes; + + JSRuntime * rt = JS_NewRuntime(_maxbytes, nurseryBytes); +assert(rt); + I->rt = rt; + +#ifdef DYING + mozilla::UniquePtr<ShellRuntime> sr = MakeUnique<ShellRuntime>(); +#else + ShellRuntime* sr = new ShellRuntime(); +#endif +assert(sr); + +#ifdef DYING + JS_SetRuntimePrivate(rt, (void *)jss); +#else + JS_SetRuntimePrivate(rt, sr); // XXX sr.get() +#endif + + JS_SetErrorReporter(rt, my_ErrorReporter); + JS::SetOutOfMemoryCallback(rt, my_OOMCallback, nullptr); + + ok = rpmSetRuntimeOptions(rt, jss); +assert(ok); + + sr->interruptFunc.init(rt, NullValue()); + sr->lastWarning.init(rt, NullValue()); + + JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff); + + size_t availMem = jss->available_memory; + if (availMem > 0) { + JS_SetGCParametersBasedOnAvailableMemory(rt, availMem); +assert(jss->available_memory == availMem); + } + + JS_SetTrustedPrincipals(rt, &ShellPrincipals::fullyTrusted); + JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks); + JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy); + + JS_SetInterruptCallback(rt, ShellInterruptCallback); + JS::SetAsmJSCacheOps(rt, &asmJSCacheOps); + + JS_SetNativeStackQuota(rt, gMaxStackSize); + + JS::dbg::SetDebuggerMallocSizeOf(rt, moz_malloc_size_of); + + ok = offThreadState.init(); +assert(ok); + + ok = InitWatchdog(rt); +assert(ok); + + JSContext * cx = NewContext(rt); +assert(cx); + I->cx = cx; +#ifdef DYING + JS_SetContextPrivate(cx, (void *)jss); +#else + JS_SetSecondContextPrivate(cx, (void *)jss); /* XXX */ +#endif + + JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL); + JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024 ); + + JS::SetLargeAllocationFailureCallback(rt, my_LargeAllocFailCallback, (void *)cx); + + // Set some parameters to allow incremental GC in low memory conditions, + // as is done for the browser, except in more-deterministic builds or when + // disabled by command line options. +#ifndef JS_MORE_DETERMINISTIC + if (jss->xf & XF_INCREMENTAL_GC) { + JS_SetGCParameter(rt, JSGC_DYNAMIC_HEAP_GROWTH, 1); + JS_SetGCParameter(rt, JSGC_DYNAMIC_MARK_SLICE, 1); + JS_SetGCParameter(rt, JSGC_SLICE_TIME_BUDGET, 10); + } +#endif + + js::SetPreserveWrapperCallback(rt, DummyPreserveWrapperCallback); + + // result = Shell(cx, &op, envp); + { + RootedObject glob(cx); + JS::CompartmentOptions options; + options.setVersion(JSVERSION_DEFAULT); + glob = NewGlobalObject(cx, options, _principals); +assert(glob); + I->global = glob; + + JSAutoCompartment ac(cx, glob); + +#ifdef FIXME + int result = ProcessArgs(cx, op); +#endif /* FIXME */ + } + + return I; +} + +static int mozRun(rpmjss jss, const char ** resultp, + const char * script, const char * fn, unsigned ln) +{ + JSI_t I = (JSI_t) jss->I; + JSContext* cx = I->cx; + JSObject* global = I->global; + + JS::RootedValue rval(cx); + + { // Scope for JSAutoCompartment + JSAutoCompartment ac(cx, global); + + JS::CompileOptions opts(cx); + opts.setFileAndLine(fn, ln); + + bool ok = JS::Evaluate(cx, opts, script, strlen(script), &rval); + if (!ok) + return 1; + } + + char b[128]; + size_t nb = sizeof(b); + char * t = NULL; + + if (rval.isNull()) { + t = strdup(""); + } else + if (rval.isUndefined()) { + t = strdup(""); + } else + if (rval.isBoolean()) { + snprintf(b, nb, "%c", (rval.toBoolean() ? 'T' : 'F')); + t = strdup(b); + } else + if (rval.isInt32()) { /* int32_t */ + snprintf(b, nb, "%d", rval.toInt32()); + t = strdup(b); + } else + if (rval.isDouble()) { + snprintf(b, nb, "%.16g", rval.toDouble()); + t = strdup(b); + } else + if (rval.isNumber()) { + snprintf(b, nb, "%.16g", rval.toNumber()); + t = strdup(b); + } else + if (rval.isString()) { + t = JS_EncodeString(cx, rval.toString()); + } else + t = strdup(""); + + if (resultp) + *resultp = t; + else + t = _free(t); + + return 0; +} + +static struct JSIO_s _mozjs45 = { mozFini, mozInit, mozRun }; +JSIO_t mozjs45 = &_mozjs45; + +/*==============================================================*/ +struct rpmjss_s _jss; +rpmjss jss = &_jss; + +/*==============================================================*/ +struct poptOption rpmjssIPoptTable[] = { + { "allow", '\0', POPT_BIT_SET, + &_jss.flags, RPMJSS_FLAGS_ALLOW, + N_("Allow (read-only) access to caller's environment"), NULL }, + { "cache", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.flags, RPMJSS_FLAGS_NOCACHE, + N_("Disables compiler caching via JSScript XDR serialization"), NULL }, + { "loadrc", '\0', POPT_BIT_SET, + &_jss.flags, RPMJSS_FLAGS_LOADRC, + N_("Load RC file for interpreter based on script filename."), NULL }, + { "warn", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.flags, RPMJSS_FLAGS_NOWARN, + N_("Do not report warnings"), NULL }, + + { "relimit", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.flags, RPMJSS_FLAGS_RELIMIT, + N_("Do not limit regexps to n^3 levels of backtracking"), NULL }, + { "jit", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.flags, RPMJSS_FLAGS_JIT, + N_("Disable nanojit"), NULL }, + { "strict", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.flags, RPMJSS_FLAGS_STRICT, + N_("Disable Strict mode"), NULL }, + { "utf8", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.flags, RPMJSS_FLAGS_NOUTF8, + N_("Disable UTF-8 C string processing"), NULL }, + { "xml", '\0', POPT_BIT_SET, + &_jss.flags, RPMJSS_FLAGS_XML, + N_("Parse <!-- comments --> as E4X tokens"), NULL }, + + { "anonfunfix", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN, + &_jss.flags, RPMJSS_FLAGS_ANONFUNFIX, + N_("Parse //@line number [\"filename\"] for XUL"), NULL }, + { "atline", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN, + &_jss.flags, RPMJSS_FLAGS_ATLINE, + N_("Parse //@line number [\"filename\"] for XUL"), NULL }, + { "werror", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN, + &_jss.flags, RPMJSS_FLAGS_WERROR, + N_("Convert warnings to errors"), NULL }, + POPT_TABLEEND +}; + +struct poptOption rpmjssIonPoptTable[] = { +#ifdef NOTYET + { "ion-shared-stubs", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_SHARED_STUBS, + N_("Use shared stubs (default: off)"), NULL }, + { "ion-scalar-replacement", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_SCALAR_REPLACEMENT, + N_("Scalar replacement (default: on)"), NULL }, + { "ion-gvn", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_GVN, + N_("Global value numbering (default: on)"), NULL }, + { "ion-licm", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_LICM, + N_("Loop invariant code motion (default: on)"), NULL }, + { "ion-edgecase-analysis", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_EDGECASE_ANALYSIS, + N_("Find edge cases where Ion can avoid bailouts (default: off)"), NULL }, + { "ion-pgo", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_PGO, + N_("Profile guided optimization (default: off)"), NULL }, + { "ion-range-analysis", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_RANGE_ANALYSIS, + N_("Range analysis (default: on)"), NULL }, + { "ion-sincos", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_SINCOS, + N_("Replace sin(x)/cos(x) to sincos(x) (default: on)"), NULL }, + { "ion-sink", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_SINK, + N_("Sink code motion (default: off)"), NULL }, + { "ion-loop-unrolling", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_LOOP_UNROLLING, + N_("Loop unrolling (default: off)"), NULL }, + { "ion-instruction-reordering", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_INSTRUCTION_REORDERING, + N_("Instruction reordering (default: off)"), NULL }, +#else + { "ion-shared-stubs", '\0', POPT_ARG_STRING, + &_jss.ion_shared_stubs, 0, + N_("Use shared stubs (default: off)"), NULL }, + { "ion-scalar-replacement", '\0', POPT_ARG_STRING, + &_jss.ion_scalar_replacement, 0, + N_("Scalar replacement (default: on)"), NULL }, + { "ion-gvn", '\0', POPT_ARG_STRING, + &_jss.ion_gvn, 0, + N_("Global value numbering (default: on)"), NULL }, + { "ion-licm", '\0', POPT_ARG_STRING, + &_jss.ion_licm, 0, + N_("Loop invariant code motion (default: on)"), NULL }, + { "ion-edgecase-analysis", '\0', POPT_ARG_STRING, + &_jss.ion_edgecase_analysis, 0, + N_("Find edge cases where Ion can avoid bailouts (default: off)"), NULL }, + { "ion-pgo", '\0', POPT_ARG_STRING, + &_jss.ion_pgo, 0, + N_("Profile guided optimization (default: off)"), NULL }, + { "ion-range-analysis", '\0', POPT_ARG_STRING, + &_jss.ion_range_analysis, 0, + N_("Range analysis (default: on)"), NULL }, + { "ion-sincos", '\0', POPT_ARG_STRING, + &_jss.ion_sincos, 0, + N_("Replace sin(x)/cos(x) to sincos(x) (default: on)"), NULL }, + { "ion-sink", '\0', POPT_ARG_STRING, + &_jss.ion_sink, 0, + N_("Sink code motion (default: off)"), NULL }, + { "ion-loop-unrolling", '\0', POPT_ARG_STRING, + &_jss.ion_loop_unrolling, 0, + N_("Loop unrolling (default: off)"), NULL }, + { "ion-instruction-reordering", '\0', POPT_ARG_STRING, + &_jss.ion_instruction_reordering, 0, + N_("Instruction reordering (default: off)"), NULL }, +#endif + + { "ion-check-range-analysis", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_CHECK_RANGE_ANALYSIS, + N_("Range analysis checking (default: off)"), NULL }, + { "ion-extra-checks", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_EXTRA_CHECKS, + N_("Perform extra dynamic validation checks (default: off)"), NULL }, + +#ifdef NOTYET + { "ion-inlining", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_INLINING, + N_("Inline methods where possible (default: on)"), NULL }, + { "ion-osr", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_OSR, + N_("On-Stack Replacement(default: on)"), NULL }, + { "ion-limit-script-size", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_LIMIT_SCRIPT_SIZE, + N_("Don't compile large scripts(default: on)"), NULL }, +#else + { "ion-inlining", '\0', POPT_ARG_STRING, + &_jss.ion_inlining, 0, + N_("Inline methods where possible (default: on)"), NULL }, + { "ion-osr", '\0', POPT_ARG_STRING, + &_jss.ion_osr, 0, + N_("On-Stack Replacement(default: on)"), NULL }, + { "ion-limit-script-size", '\0', POPT_ARG_STRING, + &_jss.ion_limit_script_size, 0, + N_("Don't compile large scripts(default: on)"), NULL }, +#endif + + { "ion-warmup-threshold", '\0', POPT_ARG_INT, + &_jss.ion_warmup_threshold, 0, + N_("Wait COUNT calls/iterations before compiling"), N_("COUNT") }, + { "ion-regalloc", '\0', POPT_ARG_STRING, + &_jss.ion_regalloc, 0, + N_("Specify Ion register allocation MODE"), N_("MODE") }, + { "ion-eager", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_EAGER, + N_("Always ion-compile methods (default: on)"), NULL }, + +#ifdef NOTYET + { "ion-offthread-compile", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.ionf, ION_OFFTHREAD_COMPILE, + N_("Compile scripts off thread (default: on)"), NULL }, +#else + { "ion-offthread-compile", '\0', POPT_ARG_STRING, + &_jss.ion_offthread_compile, 0, + N_("Compile scripts off thread (default: on)"), NULL }, +#endif + + POPT_TABLEEND +}; + +struct poptOption rpmjssOptionsTable[] = { + { "file", 'f', POPT_ARG_STRING, &_jss.Ifile, 0, + N_("File PATH to run"), N_("PATH") }, + { "module", 'm', POPT_ARG_STRING, &_jss.Imodule, 0, + N_("Module PATH to run"), N_("PATH") }, + { "execute", 'e', POPT_ARG_STRING, &_jss.Icode, 0, + N_("Inline CODE to run"), N_("CODE") }, + { "shell", 'i', POPT_BIT_SET, &_jss.xf, XF_INTERACTIVE, + N_("Enter prompt after running code"), NULL }, + { "compileonly", 'c', POPT_BIT_SET, &_jss.xf, XF_COMPILE_ONLY, + N_("Only compile, don't run (syntax checking mode)"), NULL }, + /* XXX collision on -w? */ + { "warnings", 'w', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_jss.xf, XF_WARNINGS, + N_("Emit warnings"), NULL }, + { "strict", 's', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_jss.xf, XF_STRICT, + N_("Check strictness"), NULL }, + { "dump-bytecode", 'D', POPT_BIT_SET, &_jss.xf, XF_DUMP_BYTECODE, + N_("Dump bytecode with exec count for all scripts"), NULL }, + { "print-timing", 'b', POPT_BIT_SET, &_jss.xf, XF_PRINT_TIMING, + N_("Dump bytecode with exec count for all scripts"), NULL }, + { "js-cache", '\0', POPT_ARG_STRING, &_jss.cachedir, 0, + N_("Enable JS caching in DIR"), N_("DIR") }, + { "js-cache-per-process",'\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_CACHE_PER_PROCESS, + N_("Deactivate per-process caching"), NULL }, + { "code-coverage", '\0', POPT_BIT_SET, &_jss.xf, XF_CODE_COVERAGE, + N_("Enable code coverage insturmentation"), NULL }, + + { "ion", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_ION, + N_("Disable IonMonkey"), NULL }, + { "asmjs", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_ASMJS, + N_("Disable asm.js compilation"), NULL }, + { "native-regexp", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_NATIVE_REGEXP, + N_("Disable native regexp compilation"), NULL }, + { "unboxed-objects", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_UNBOXED_OBJECTS, + N_("Disable creating unboxed plain objects"), NULL }, + { "unboxed-arrays", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_UNBOXED_ARRAYS, + N_("Allow creating unboxed arrays"), NULL }, + + { "print-alloc", 'O', POPT_BIT_SET, &_jss.xf, XF_PRINT_ALLOC, + N_("Print no. of allocatsions at exit"), NULL }, + { "script", '\0', POPT_ARG_STRING, &_jss.script_path, 0, + N_("Script PATH to run"), N_("PATH") }, + { "scriptArgs", '\0', POPT_ARG_STRING, &_jss.script_args, 0, + N_("Script args to bind as |scriptArgs| in global"), N_("XXX") }, + { "thread-count", '\0', POPT_ARG_INT, &_jss.thread_count, 0, + N_("Use COUNT auxiliary threads"), N_("COUNT") }, + + { "baseline", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_BASELINE, + N_("Enable baseline compiler (default: on)"), NULL }, + { "baseline-eager", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_BASELINE_EAGER, + N_("Always baseline-compile methods"), NULL }, + { "baseline-warmup-threshold", '\0', POPT_ARG_INT, + &_jss.baseline_warmup_threshold, 0, + N_("Wait COUNT calls/iterations before baseline-compiling"), N_("COUNT") }, + + { "non-writable-jitcode", '\0', POPT_BIT_SET, + &_jss.xf, XF_NONWRITABLE_JITCODE, + N_("Allocate JIT code as non-writable memory"), NULL }, +#ifdef JS_CODEGEN_X86 + { "fpu", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_FPU, + N_("Assume CPU has a FPU"), NULL }, +#endif + { "sse3", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_SSE3, + N_("Assume CPU has SSE3 instructions"), NULL }, + { "sse4", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_SSE4, + N_("Assume CPU has SSE4 instructions"), NULL }, + { "avx", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_AVX, + N_("Assume CPU has AVX instructions"), NULL }, + { "enable-avx", '\0', POPT_BIT_SET, + &_jss.xf, XF_AVX, + N_("Assume CPU has AVX instructions"), NULL }, + { "fuzzing-safe", '\0', POPT_BIT_SET, + &_jss.xf, XF_FUZZING_SAFE, + N_("Don't expose unsafe functions (when fuzzing)"), NULL }, + { "disable-oom-functions", '\0', POPT_BIT_SET, + &_jss.xf, XF_DISABLE_OOM, + N_("Disable functions that trigger OOM"), NULL }, + { "threads", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_THREADS, + N_("Disable helper threads"), NULL }, + +#ifdef DEBUG + { "dump-entrained-variables", '\0', POPT_BIT_SET, + &_jss.xf, XF_DISABLE_OOM, + N_("Print variables entrained by inner functions"), NULL }, +#endif + + { "ggc", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_GGC, + N_("Disable Generational GC"), NULL }, + { "cgc", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_CGC, + N_("Disable Compacting GC"), NULL }, + { "incremental-gc", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_jss.xf, XF_INCREMENTAL_GC, + N_("Disable Incremental GC"), NULL }, + + { "available-memory", '\0', POPT_ARG_INT, &_jss.available_memory, 0, + N_("Select GC settings based on SIZE-MB"), N_("SIZE-MB") }, + +#if defined(JS_CODEGEN_ARM) + { "arm-hwcap", '\0', POPT_ARG_STRING, &_jss.arm_hwcap, 0, + N_("Specify ARM code generation FEATURES"), N_("FEATURES") }, + + { "arm-asm-nop-fill", '\0', POPT_ARG_INT, &_jss.arm_asm_nop_fill, 0, + N_("Insert N NOP instructions in pool"), N_("N") }, + { "asm-pool-max-offset", '\0', POPT_ARG_INT, &_jss.asm_pool_max_offset, 0, + N_("Max PC-relative OFFSET in pool"), N_("OFFSET") }, +#endif + +#if defined(JS_SIMULATOR_ARM) + { "arm-sim-icache-checks", '\0', POPT_BIT_SET, + &_jss.xf, XF_ARM_SIM_ICACHE_CHECKS, + N_("(ARM) Enable icache flush checks"), NULL }, + { "arm-sim-stop-at", '\0', POPT_ARG_INT, &_jss.arm_sim_stop_at, 0, + N_("(ARM) Stop simulator after N instructions"), N_("N") }, +#endif + +#if defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64) + { "mips-sim-icache-checks", '\0', POPT_BIT_SET, + &_jss.xf, XF_MIPS_SIM_ICACHE_CHECKS, + N_("(MIPS) Enable icache flush checks"), NULL }, + { "mips-sim-stop-at", '\0', POPT_ARG_INT, &_jss.mips_sim_stop_at, 0, + N_("(MIPS) Stop simulator after N instructions"), N_("N") }, +#endif + + { "nursery-size", '\0', POPT_ARG_INT, &_jss.nursery_size, 0, + N_("Set nursery SIZE-MB"), N_("SIZE-MB") }, + +#ifdef JS_GC_ZEAL + { "gc-zeal", '\0', POPT_ARG_STRING, &_jss.gc_zeal, 0, + N_("Set GC zeal to LEVEL"), N_("LEVEL") }, +#endif + + { "module-load-path", '\0', POPT_ARG_STRING, &_jss.moduledir, 0, + N_("Load modules from DIR"), N_("DIR") }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmjssIPoptTable, 0, + N_("JS interpreter options:"), NULL }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmjssIonPoptTable, 0, + N_("JS ion interpreter options:"), NULL }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioAllPoptTable, 0, + N_("Common options for all rpmio executables:"), NULL }, + + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +}; + +static rpmjssFlags _flagsDefault = (rpmjssFlags) ( + RPMJSS_FLAGS_RELIMIT | + RPMJSS_FLAGS_JIT | + RPMJSS_FLAGS_STRICT | + 0 +); + +static rpmjssIonFlags _ionfDefault = (rpmjssIonFlags) ( + ION_SCALAR_REPLACEMENT | + ION_GVN | + ION_LICM | + ION_EDGECASE_ANALYSIS | + ION_RANGE_ANALYSIS | + ION_INLINING | + ION_OSR | + ION_LIMIT_SCRIPT_SIZE | + ION_OFFTHREAD_COMPILE | + 0 +); + +static rpmjssXFlags _xfDefault = (rpmjssXFlags) ( + XF_BASELINE | + XF_ION | + XF_ASMJS | + XF_NATIVE_REGEXP | + XF_UNBOXED_OBJECTS | + XF_CACHE_PER_PROCESS | + XF_FPU | + XF_SSE3 | + XF_SSE4 | + XF_THREADS | + XF_GGC | + XF_CGC | + XF_INCREMENTAL_GC | + 0 +); + +/*==============================================================*/ +static void rpmjssFini(void * _jss) +{ + rpmjss jss = (rpmjss) _jss; + + mozFini(jss); + jss->I = NULL; +} + +#define rpmjssDbug NULL +#define rpmjssInit NULL +RPMIOPOOL_INTERP_MODULE(jss) + +rpmjss rpmjssNew(char ** av, uint32_t flags) +{ + rpmjss jss = +#ifdef NOTYET + (flags & 0x80000000) ? rpmjsI() : +#endif + rpmjssGetPool(_rpmjssPool); + + jss->flags = _flagsDefault; + jss->thread_count = -1; + jss->ion_warmup_threshold = -1; + jss->baseline_warmup_threshold = -1; + jss->ion_warmup_threshold = -1; + jss->available_memory = 0; + jss->arm_asm_nop_fill = 0; + jss->asm_pool_max_offset = 1024; + jss->arm_sim_stop_at = -1; + jss->mips_sim_stop_at = -1; + jss->nursery_size = 16; + jss->ionf = _ionfDefault; + jss->xf = _xfDefault; + + /* XXX parse arguments */ + + JSI_t I = (JSI_t) mozInit(jss); + jss->I = I; + + return rpmjssLink(jss); +} + +rpmRC rpmjssRun(rpmjss jss, const char * str, const char ** resultp) +{ + rpmRC rc = RPMRC_FAIL; + + if (jss == NULL) jss = rpmjssI(); + + if (str && *str + && !mozRun(jss, resultp, str, __FILE__, __LINE__)) + rc = RPMRC_OK; + +SPEW("<== %s(%p,|%s|) rc %d |%s|\n", __FUNCTION__, jss, str, rc, (resultp ? *resultp : "")); + return rc; +} @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org