blitz_ex.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "blitz.h"
  2. #define EX_GROW 10
  3. typedef struct BBExEnv{
  4. BBExJmpBuf buf;
  5. BBObject * ex;
  6. int jmp_status;
  7. }BBExEnv;
  8. typedef struct BBExStack{
  9. BBExEnv *ex_base,*ex_sp,*ex_end;
  10. }BBExStack;
  11. #ifdef _WIN32
  12. #include <windows.h>
  13. static DWORD exKey(){
  14. static int done;
  15. static DWORD key;
  16. if( !done ){
  17. key=TlsAlloc();
  18. done=1;
  19. }
  20. return key;
  21. }
  22. BBExStack *getExStack(){
  23. return (BBExStack*)TlsGetValue( exKey() );
  24. }
  25. void setExStack( BBExStack *st ){
  26. TlsSetValue( exKey(),st );
  27. }
  28. #elif __SWITCH__
  29. BBExStack *getExStack(){
  30. // TODO
  31. //return (BBExStack*)pthread_getspecific( exKey() );
  32. return NULL;
  33. }
  34. void setExStack( BBExStack *st ){
  35. //pthread_setspecific( exKey(),st );
  36. }
  37. #else
  38. #include <pthread.h>
  39. static pthread_key_t exKey(){
  40. static int done;
  41. static pthread_key_t key;
  42. if( !done ){
  43. pthread_key_create( &key,0 );
  44. done=1;
  45. }
  46. return key;
  47. }
  48. BBExStack *getExStack(){
  49. return (BBExStack*)pthread_getspecific( exKey() );
  50. }
  51. void setExStack( BBExStack *st ){
  52. pthread_setspecific( exKey(),st );
  53. }
  54. #endif
  55. static BBExStack *exStack(){
  56. BBExStack *st=getExStack();
  57. if( !st ){
  58. st=(BBExStack*)bbMemAlloc( sizeof( BBExStack ) );
  59. memset( st,0,sizeof( BBExStack ) );
  60. setExStack( st );
  61. }
  62. return st;
  63. }
  64. static void freeExStack( BBExStack *st ){
  65. bbMemFree( st->ex_base );
  66. bbMemFree( st );
  67. setExStack( 0 );
  68. }
  69. BBExJmpBuf *bbExEnter(){
  70. BBExStack *st=exStack();
  71. if( st->ex_sp==st->ex_end ){
  72. int len=st->ex_sp-st->ex_base,new_len=len+EX_GROW;
  73. st->ex_base=(BBExEnv*)bbMemExtend( st->ex_base,len*sizeof(BBExEnv),new_len*sizeof(BBExEnv) );
  74. st->ex_end=st->ex_base+new_len;
  75. st->ex_sp=st->ex_base+len;
  76. }
  77. st->ex_sp->jmp_status=1;
  78. return &((st->ex_sp++)->buf);
  79. }
  80. BBObject* bbExCatchAndReenter() {
  81. BBExStack *st=getExStack();
  82. BBObject *ex=st->ex_sp->ex;
  83. st->ex_sp->jmp_status=2;
  84. st->ex_sp++;
  85. return ex;
  86. }
  87. BBObject* bbExCatch() {
  88. BBExStack *st=getExStack();
  89. BBObject *ex=st->ex_sp->ex;
  90. if (st->ex_sp==st->ex_base) {
  91. freeExStack(st);
  92. }
  93. return ex;
  94. }
  95. void bbExLeave(){
  96. BBExStack *st=getExStack();
  97. //invariant...leaving a Try!
  98. //assert( st && st->ex_sp!=st->ex_base );
  99. if( --st->ex_sp==st->ex_base ){
  100. freeExStack( st );
  101. }
  102. }
  103. void bbExThrow( BBObject *p ){
  104. BBExStack *st=getExStack();
  105. if( !st ) bbOnDebugUnhandledEx( p );
  106. --st->ex_sp;
  107. st->ex_sp->ex = p;
  108. #ifdef __MINGW64__
  109. #ifdef __clang__
  110. longjmp(st->ex_sp->buf, st->ex_sp->jmp_status);
  111. #else
  112. __builtin_longjmp(st->ex_sp->buf, 1); // only allows status 1
  113. #endif
  114. #elif __APPLE__
  115. _longjmp(st->ex_sp->buf, st->ex_sp->jmp_status);
  116. #else
  117. longjmp(st->ex_sp->buf, st->ex_sp->jmp_status);
  118. #endif
  119. }
  120. int bbExStatus(){
  121. BBExStack *st=getExStack();
  122. return st->ex_sp->jmp_status;
  123. }
  124. void bbExThrowCString( const char *p ){
  125. bbExThrow( (BBObject*)bbStringFromCString( p ) );
  126. }