Docs GODI Archive
Projects Blog Link DB

Search GODI:


More options
File lib/felix/rtl/flx_run.cxx GODI Package apps-felix
 
   flx_run.cxx  
#line 1111 "lpsrc/flx_rtl.ipk"
#include <cstdlib>
#include <stdio.h>
#include <vector>
#include <list>
#include <map>
#include <cstring>
#include <cassert>

#include <string>
//#include <unistd.h>
#include "flx_rtl.hpp"

#include "flx_collector.hpp"
#include "flx_dynlink.hpp"
using namespace std;
using namespace flx::rtl;
#ifdef HAVE_GXX_X86
register void *sp __asm__("esp");
#else
static void *sp = 0;
#endif

void print_loc(FILE *ef,flx_range_srcref_t x,char *cf, int cl)
{
  fprintf(ef,"Felix location: %s %d[%d]-%d[%d]\n",
    x.filename,
    x.startline,
    x.startcol,
    x.endline,
    x.endcol
  );
  fprintf(ef,"C++ location  : %s %d\n", cf, cl);
}

int main(int argc, char** argv)
{
#ifndef FLX_STATIC_LINK
  bool static_link = false;
  if (argc<2)
  {
    printf("usage: flx_run [--debug] dll_filename options ..\n");
    return 1;
  }
  char *filename = argv[1];
  char **flx_argv = argv+1;
  int flx_argc = argc-1;
  bool debug = (argc > 1) && (strcmp(argv[1],"--debug")==0);
  if(debug)
  {
    if(argc<3)
    {
      printf("usage: flx_run [--debug] dll_filename options ..\n");
      return 1;
    }
    filename = argv[2];
    --flx_argc;
    ++flx_argv;
  }
#else
  bool static_link = true;
  char *filename = argv[0];
  char **flx_argv = argv;
  int flx_argc = argc;
  bool debug = false;
//  printf("Statically linked Felix program running\n");
#endif
  char *debug_env = std::getenv("FLX_DEBUG");
  debug = debug || debug_env != 0;
  if(debug)
  {
    fprintf(stderr,"Debug enabled for %s link program\n",static_link?"static":"dynamic");
  }
  char *finalise_env= std::getenv("FLX_FINALISE");
  bool finalise = finalise_env != 0;
  if(debug)
    fprintf(stderr,"Finalisation %s\n",finalise? "Enabled" : "Disabled");
#ifdef HAVE_GXX
    if(debug) fprintf(stderr, "Compiled by g++\n");
    static void *init_sp = sp;
    static void *init_fframe FLX_UNUSED = __builtin_frame_address(0);
    static void *init_ret = __builtin_return_address(0);
#endif
  if(debug)
    for(int i=0; i<flx_argc; ++i)
    fprintf(stderr,"flx_argv[%d]->%s\n",i,flx_argv[i]);
  try
  {
    if(debug)
      fprintf(stderr,"flx_run driver begins %s\n",flx_argv[0]);
    flx_dynlink_t library;
    flx_libinit_t instance;

    library.link(filename);
    flx::gc::collector::malloc_free allocator;
    allocator.set_debug(debug);
    flx::gc::collector::flx_collector_t collector(&allocator);
    collector.set_debug(debug);
    instance.create(&library, &collector,flx_argc,flx_argv,stdin,stdout,stderr);
    if(debug) {
      fprintf(stderr,"loaded library %s at %p\n",filename,library.library);
      fprintf(stderr,"thread frame at %p\n",instance.thread_frame);
      fprintf(stderr,"initial continuation at %p\n",instance.start_proc);
    }
    int gc_counter = 0;
    unsigned long collections = 0;

    con_t *top = instance.start_proc;
    fthread_t *ft = new (collector,_fthread_ptr_map) fthread_t(top);
    collector.add_root(ft);
    _uctor_ *request = ft->run();

    while( request && request->variant  == svc_yield)
    {
      gc_counter++;
      if(gc_counter == 1000)
      {
        gc_counter = 0;
        ++collections;
        unsigned long n = collector.collect();
        if(debug)fprintf(stderr,"collected %ld objects\n",n);
      }
      request = ft->run();
    }
    if(debug){
      unsigned long uncollected = collector.get_allocation_count();
      unsigned long roots = collector.get_root_count();
      fprintf(stderr,"program finished, %ld collections, %ld uncollected objects, roots %ld\n",collections,uncollected,roots);
    }
    if(finalise)
    {
      if(debug) fprintf(stderr,"Finalising\n");
      if(debug)fprintf(stderr,"removing thread %p\n",ft);
      collector.remove_root(ft);
      {
        if(debug)
          fprintf(stderr,"Data collection starts ..\n");
        unsigned long n = collector.collect();
        unsigned long a = collector.get_allocation_count();
        if(debug)
          fprintf(stderr,"flx_run collected %ld objects, %ld left\n",n,a);
      }
      if(debug)
        fprintf(stderr,"Destroying program instance\n");
      instance.destroy();

      if(debug)
        fprintf(stderr,"Final collection starts ..\n");
      unsigned long n = collector.collect();
      unsigned long a = collector.get_allocation_count();
      if(debug)
        fprintf(stderr,"Collected %ld objects, %ld left (should be 0)\n",n,a);
      if(a!=0){
        fprintf(stderr,"flx_run %ld uncollected objects, should be zero!!\n",a);
        return 5;
      }
      if(debug)
        fprintf(stderr,"Libref cnt = %ld\n",library.refcnt);
      if(library.refcnt >0)
      {
        if(debug)
          fprintf(stderr,"flx_run %p library still referenced %ld times (expected 1)\n",library.library,library.refcnt);
      }
      if(debug)
        fprintf(stderr,"Unlinking library ..\n");
      library.unlink();
      if(library.refcnt >0)
      {
        fprintf(stderr,"flx_run %p library still referenced %ld times?!\n",library.library,library.refcnt);
        return 6;
      }
      if(debug)
        fprintf(stderr,"flx_run driver ends with finalisation complete, collected %ld,left=%ld\n",n,a);
    }
    else {
      if(debug) {
        unsigned long a = collector.get_allocation_count();
        fprintf(stderr,"flx_run driver ends with finalisation skipped, %ld uncollected objects\n",a);
      }
    }
  }
  catch (flx_link_failure_t x)
  {
    fprintf(stderr,"Dynamic linkage error\n");
    fprintf(stderr,"filename: %s\n",x.filename.data());
    fprintf(stderr,"operation: %s\n",x.operation.data());
    fprintf(stderr,"what: %s\n",x.what.data());
    return 2;
  }
  catch (flx_exec_failure_t x)
  {
    fprintf(stderr,"Execution error\n");
    fprintf(stderr,"filename: %s\n",x.filename.data());
    fprintf(stderr,"operation: %s\n",x.operation.data());
    fprintf(stderr,"what: %s\n",x.what.data());
    return 3;
  }
  catch (flx_assert_failure_t x)
  {
    fprintf(stderr,"Assertion Failure\n");
    print_loc(stderr,x.flx_loc,x.cxx_srcfile, x.cxx_srcline);
    return 3;
  }
  catch (flx_match_failure_t x)
  {
    fprintf(stderr,"Match Failure\n");
    print_loc(stderr,x.flx_loc,x.cxx_srcfile, x.cxx_srcline);
    return 3;
  }
  catch (...)
  {
    fprintf(stderr,"flx_run driver ends with unknown EXCEPTION\n");
    return 4;
  }
#ifdef HAVE_GXX
    // check the frame pointer isn't corrupted
    static void *fin_sp = sp;
    static void *fin_fframe FLX_UNUSED = __builtin_frame_address(0);
    static void *fin_ret = __builtin_return_address(0);
    if (init_sp != fin_sp ) {
      fprintf(stderr,"g++: STACK POINTER ERROR %p != %p\n",init_sp,fin_sp);
    }
// I have to comment this out, because it only applies if the
// gcc compiler is using the frame pointer.. it doesn't if you
// say -fomit-frame-pointer, for example .. I don't know if there
// is a way to tell inside the code ..
#if 0
    if (init_fframe != fin_fframe) {
      fprintf(stderr,"g++: FRAME POINTER ERROR %p != %p\n",init_fframe,fin_fframe);
    }
#endif
    else if (init_ret != fin_ret) {
      fprintf(stderr,"g++: RETURN ADDRESS ERROR %p != %p\n",init_ret,fin_ret);
    }
#endif
  if(debug)fprintf(stderr,"flx_run driver ends OK\n");
  return 0;
}


This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml