PageRenderTime 58ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/test/language/unclassified/test_overload011.c

http://github.com/tybor/Liberty
C | 2439 lines | 1834 code | 173 blank | 432 comment | 410 complexity | 786908f8b66825480dcd99b05168bb80 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, GPL-2.0
  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4. /*
  5. ANSI C code generated by SmartEiffel The GNU Eiffel Compiler, Eiffel tools and libraries
  6. Release 2.4 (??? June ??th 2008) [????]
  7. Copyright (C), 1994-2002 - INRIA - LORIA - ESIAL UHP Nancy 1 - FRANCE
  8. Copyright (C), 2003-2005 - INRIA - LORIA - IUT Charlemagne Nancy 2 - FRANCE
  9. D.COLNET, P.RIBET, C.ADRIAN, V.CROIZIER F.MERIZEN - SmartEiffel@loria.fr
  10. http://SmartEiffel.loria.fr
  11. C Compiler options used: -pipe
  12. */
  13. #ifdef __cplusplus
  14. }
  15. #endif
  16. #include "test_overload01.h"
  17. #ifdef __cplusplus
  18. extern "C" {
  19. #endif
  20. /*
  21. -- ------------------------------------------------------------------------------------------------------------
  22. -- Copyright notice below. Please read.
  23. --
  24. -- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE
  25. -- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
  26. --
  27. -- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
  28. --
  29. -- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  30. -- documentation files (the "Software"), to deal in the Software without restriction, including without
  31. -- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  32. -- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
  33. -- conditions:
  34. --
  35. -- The above copyright notice and this permission notice shall be included in all copies or substantial
  36. -- portions of the Software.
  37. --
  38. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  39. -- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
  40. -- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  41. -- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  42. -- OR OTHER DEALINGS IN THE SOFTWARE.
  43. --
  44. -- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
  45. -- ------------------------------------------------------------------------------------------------------------
  46. */
  47. /*
  48. This file (SmartEiffel/sys/runtime/base.c) is included for _all_ modes of
  49. compilation (-boost, -no_check, ... -all_check).
  50. */
  51. /*
  52. Byte swapping function
  53. */
  54. void copy_swap_16(const uint16_t *src, uint16_t *dest, int count){
  55. while (count--) {
  56. *dest++ = (*src << 8) | (*src >> 8);
  57. src++;
  58. }
  59. }
  60. /*
  61. The wrapper for `malloc' (generated C code is supposed to use
  62. only `se_malloc' instead of direct `malloc').
  63. */
  64. void* se_malloc(size_t size) {
  65. void *result = malloc(size);
  66. if (result == NULL) {
  67. handle(SE_HANDLE_NO_MORE_MEMORY, NULL);
  68. #ifdef SE_EXCEPTIONS
  69. internal_exception_handler(No_more_memory);
  70. #elif !defined(SE_BOOST)
  71. error0("No more memory.", NULL);
  72. #else
  73. fprintf(SE_ERR,"No more memory (malloc failed).\n");
  74. exit(EXIT_FAILURE);
  75. #endif
  76. }
  77. return result;
  78. }
  79. /*
  80. The wrapper for `calloc' (generated C code is supposed to use
  81. only `se_calloc' instead of direct `calloc').
  82. */
  83. void* se_calloc(size_t nmemb, size_t size) {
  84. void *result = calloc(nmemb,size);
  85. if (result == NULL) {
  86. handle(SE_HANDLE_NO_MORE_MEMORY, NULL);
  87. #ifdef SE_EXCEPTIONS
  88. internal_exception_handler(No_more_memory);
  89. #elif !defined(SE_BOOST)
  90. error0("No more memory.", NULL);
  91. #else
  92. fprintf(SE_ERR,"No more memory (calloc failed).\n");
  93. exit(EXIT_FAILURE);
  94. #endif
  95. }
  96. return result;
  97. }
  98. /*
  99. The wrapper for `realloc' (generated C code is supposed to use
  100. only `se_realloc' instead of direct `realloc').
  101. */
  102. void* se_realloc(void* src, size_t size) {
  103. void *result = realloc(src, size);
  104. if (result == NULL) {
  105. handle(SE_HANDLE_NO_MORE_MEMORY, NULL);
  106. #ifdef SE_EXCEPTIONS
  107. internal_exception_handler(No_more_memory);
  108. #elif !defined(SE_BOOST)
  109. error0("No more memory.", NULL);
  110. #else
  111. fprintf(SE_ERR,"No more memory (realloc failed).\n");
  112. exit(EXIT_FAILURE);
  113. #endif
  114. }
  115. return result;
  116. }
  117. /* ---------------------------------------------------------------------- */
  118. void se_die (int code) {
  119. handle(SE_HANDLE_DIE_WITH_CODE, &code);
  120. exit(code);
  121. }
  122. /*
  123. Runtime hooks
  124. */
  125. static se_runtime_handler_t** handlers = NULL;
  126. int handlers_count=0;
  127. void register_handler(se_runtime_handler_t*handler) {
  128. int new_count = handlers_count + 1;
  129. handlers = (se_runtime_handler_t**)se_realloc(handlers, (new_count) * sizeof(void*));
  130. handlers[handlers_count] = handler;
  131. handlers_count = new_count;
  132. }
  133. void _handle(se_handler_action_t action, void*data) {
  134. int i;
  135. for (i = 0; i < handlers_count; i++) {
  136. handlers[i](action, data);
  137. /* *** Check type of this array. Function pointer may have different size from data pointer. (PH 17/07/08) */
  138. }
  139. }
  140. /*
  141. -- ------------------------------------------------------------------------------------------------------------
  142. -- Copyright notice below. Please read.
  143. --
  144. -- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE
  145. -- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
  146. --
  147. -- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
  148. --
  149. -- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  150. -- documentation files (the "Software"), to deal in the Software without restriction, including without
  151. -- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  152. -- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
  153. -- conditions:
  154. --
  155. -- The above copyright notice and this permission notice shall be included in all copies or substantial
  156. -- portions of the Software.
  157. --
  158. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  159. -- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
  160. -- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  161. -- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  162. -- OR OTHER DEALINGS IN THE SOFTWARE.
  163. --
  164. -- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
  165. -- ------------------------------------------------------------------------------------------------------------
  166. */
  167. #if defined __USE_POSIX || defined __unix__ || defined _POSIX_C_SOURCE
  168. /* macro read is used of read_stdin */
  169. void io_copy (char*source, char*target) {
  170. /* We use the low-level descriptor functions rather than stream-oriented functions.
  171. * This allows us to copy the file's permissions. */
  172. int src;
  173. int tgt;
  174. struct stat info;
  175. static char *buffer = NULL;
  176. static int bufsize = 0;
  177. int read_count, write_count, written;
  178. src=open (source, O_RDONLY);
  179. if (fstat (src, &info))
  180. return; /* Ooops */
  181. if (bufsize < info.st_blksize)
  182. buffer=se_realloc (buffer, info.st_blksize);
  183. tgt=creat (target, info.st_mode);
  184. do {
  185. read_count = read (src, buffer, info.st_blksize);
  186. write_count = 0; written = 0;
  187. while ((write_count < read_count) && (written >= 0))
  188. {
  189. written = write (tgt, buffer + write_count, read_count - write_count);
  190. write_count += written;
  191. }
  192. } while ((read_count > 0) && (written >= 0));
  193. close (src);
  194. close (tgt);
  195. }
  196. int io_same_physical_file(char*path1,char*path2) {
  197. struct stat info1, info2;
  198. if (stat(path1, &info1))
  199. return 0; /* oops */
  200. if (stat(path2, &info2))
  201. return 0; /* oops */
  202. return (info1.st_dev == info2.st_dev) && (info1.st_ino == info2.st_ino);
  203. }
  204. #else
  205. #define IO_COPY_BUFSIZE 4096
  206. int read_stdin(EIF_CHARACTER *buffer, int size) {
  207. int c;
  208. c = getc(stdin);
  209. if (c==EOF)
  210. return 0;
  211. *buffer = (EIF_CHARACTER)c;
  212. return 1;
  213. }
  214. void io_copy(char*source, char*target) {
  215. static char *buffer = NULL;
  216. int read_count;
  217. FILE*src=fopen(source, "rb");
  218. FILE*tgt=fopen(target, "wb");
  219. if(!buffer)
  220. buffer = (char*)se_malloc(IO_COPY_BUFSIZE);
  221. while ((read_count = fread(buffer, 1, IO_COPY_BUFSIZE, src)), read_count) {
  222. size_t dummy = fwrite(buffer, 1, read_count, tgt);
  223. }
  224. fclose(src);
  225. fclose(tgt);
  226. }
  227. int io_same_physical_file(char*path1,char*path2) {
  228. /* default implementation returns true only if the paths are the same */
  229. return !strcmp(path1, path2);
  230. }
  231. #endif
  232. int io_file_exists(char*source) {
  233. FILE*src=fopen(source, "rb");
  234. if (src!=NULL) {
  235. fclose(src);
  236. return 1;
  237. }
  238. else {
  239. return (errno != ENOENT);
  240. }
  241. }
  242. T53 M53={53,0};
  243. void se_prinT53(FILE* file,T53**o){
  244. if(*o==NULL){
  245. fprintf(file, "void");
  246. return;}
  247. fprintf(file,"COUNTER");
  248. fprintf(file,"#%p",(void*)*o);
  249. fprintf(file,"\n\t[ ");
  250. fprintf(file,"value = ");
  251. se_prinT2(file,(&((*o)->_value)));
  252. fprintf(file,"\n\t]");
  253. }/*--*/
  254. T49 M49={49,(void*)0,0,(void*)0,0};
  255. void se_prinT49(FILE* file,T49**o){
  256. if(*o==NULL){
  257. fprintf(file, "void");
  258. return;}
  259. fprintf(file,"STD_OUTPUT");
  260. fprintf(file,"#%p",(void*)*o);
  261. fprintf(file,"\n\t[ ");
  262. fprintf(file,"filter = ");
  263. se_prinT0(file,(T0**)(&((*o)->_filter)));
  264. fprintf(file,"\n\t ");
  265. fprintf(file,"buffer_position = ");
  266. se_prinT2(file,(&((*o)->_buffer_position)));
  267. fprintf(file,"\n\t ");
  268. fprintf(file,"buffer = ");
  269. se_prinT9(file,(&((*o)->_buffer)));
  270. fprintf(file,"\n\t ");
  271. fprintf(file,"capacity = ");
  272. se_prinT2(file,(&((*o)->_capacity)));
  273. fprintf(file,"\n\t]");
  274. }/*--*/
  275. T25 M25={25,0,(void*)0};
  276. void se_prinT25(FILE* file,T25**o){
  277. if(*o==NULL){
  278. fprintf(file, "void");
  279. return;}
  280. fprintf(file,"TEST_OVERLOAD01");
  281. fprintf(file,"#%p",(void*)*o);
  282. fprintf(file,"\n\t[ ");
  283. fprintf(file,"assertion_level = ");
  284. se_prinT2(file,(&((*o)->_assertion_level)));
  285. fprintf(file,"\n\t ");
  286. fprintf(file,"external_object = ");
  287. se_prinT8(file,(&((*o)->_external_object)));
  288. fprintf(file,"\n\t]");
  289. }/*--*/
  290. void se_prinT9(FILE* file,T9*o){
  291. fprintf(file,"NATIVE_ARRAY[CHARACTER]");
  292. fprintf(file,"#%p",(void*)*o);
  293. }/*--*/
  294. T7 M7={7,(void*)0,0,0};
  295. /*Aliased storage area or unicode storage.*/
  296. char*s26_0="";
  297. char*s26_212160365="require_check";
  298. char*s26_48390502="all_check";
  299. char*s26_1690381566="invariant_check";
  300. char*s26_1992063831="ensure_check";
  301. char*s26_1325941860="ERROR: \173""EIFFELTEST_TOOLS\175"".assert call ";
  302. char*s26_113001857=" in class ";
  303. char*s26_2167877="number ";
  304. char*s26_718083334="no_check or boost";
  305. char*s26_1075456615="Assertion level was ";
  306. char*s26_265093627="loop_check";
  307. char*s26_1682790378=" failed.\nRerun this test under the -sedb debugger to find out what is going wrong.\n";
  308. /*
  309. -- ------------------------------------------------------------------------------------------------------------
  310. -- Copyright notice below. Please read.
  311. --
  312. -- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE
  313. -- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
  314. --
  315. -- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
  316. --
  317. -- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  318. -- documentation files (the "Software"), to deal in the Software without restriction, including without
  319. -- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  320. -- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
  321. -- conditions:
  322. --
  323. -- The above copyright notice and this permission notice shall be included in all copies or substantial
  324. -- portions of the Software.
  325. --
  326. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  327. -- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
  328. -- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  329. -- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  330. -- OR OTHER DEALINGS IN THE SOFTWARE.
  331. --
  332. -- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
  333. -- ------------------------------------------------------------------------------------------------------------
  334. */
  335. /*
  336. This file (SmartEiffel/sys/runtime/no_check.c) is automatically included
  337. when `ace.no_check' is true (ie. all modes except -boost).
  338. */
  339. int assertion_depth=1;
  340. /*
  341. To print object into the trace-stack :
  342. */
  343. void se_prinT0(FILE* file, T0** o) {
  344. if (*o == NULL) {
  345. fprintf(file,"Void");
  346. }
  347. else {
  348. fprintf(file,"#%p",(void*)*o);
  349. }
  350. }
  351. void se_prinT1(FILE* file, EIF_INTEGER_8* o) {
  352. fprintf(file,"%"PRId8,*o);
  353. }
  354. void se_prinT2(FILE* file, EIF_INTEGER* o) {
  355. fprintf(file,"%"PRId32,*o);
  356. }
  357. void se_prinT10(FILE* file, EIF_INTEGER_16* o) {
  358. fprintf(file,"%"PRId16,*o);
  359. }
  360. void se_prinT11(FILE* file,EIF_INTEGER_64* o) {
  361. fprintf(file,"%"PRId64,*o);
  362. }
  363. static void se_print_character(FILE* file, char c) {
  364. /* Produce a visible output of `c' using an Eiffelish notation.
  365. */
  366. if ((' ' <= c)&&(c <= '~')&&(c != '\'')&&(c != '\"')&&(c != '%')) {
  367. putc(c,file);
  368. }
  369. else {
  370. switch (c) {
  371. case '\b': fprintf(file,"%%B"); break;
  372. case '\f': fprintf(file,"%%F"); break;
  373. case '\n': fprintf(file,"%%N"); break;
  374. case '\r': fprintf(file,"%%R"); break;
  375. case '\t': fprintf(file,"%%T"); break;
  376. case '\0': fprintf(file,"%%U"); break;
  377. case '\'': fprintf(file,"%%\'"); break;
  378. case '\"': fprintf(file,"%%\""); break;
  379. case '%': fprintf(file,"%%%%"); break;
  380. default:
  381. fprintf(file,"%%/%d/", (int) ((unsigned char) c));
  382. }
  383. }
  384. }
  385. void se_prinT3(FILE* file,EIF_CHARACTER* o) {
  386. putc('\'',file);
  387. se_print_character(file, *o);
  388. putc('\'',file);
  389. }
  390. void se_prinT4(FILE* file, EIF_REAL_32* o) {
  391. fprintf(file, "%.7e", ((real64_t)*o));
  392. }
  393. void se_prinT5(FILE* file, EIF_REAL_64* o) {
  394. fprintf(file, "%.16e", *o);
  395. }
  396. void se_prinT12(FILE* file, EIF_REAL_EXTENDED* o) {
  397. fprintf(file, "%.19Le", *o);
  398. }
  399. void se_prinT6(FILE* file, EIF_BOOLEAN* o) {
  400. if (*o) {
  401. fprintf(file,"True");
  402. }
  403. else {
  404. fprintf(file,"False");
  405. }
  406. }
  407. void se_prinT7(FILE* file, EIF_STRING* o) {
  408. if (*o == NULL) {
  409. fprintf(file,"Void");
  410. }
  411. else {
  412. T3* storage = (*o)->_storage;
  413. int count = (*o)->_count;
  414. int i = 0;
  415. putc('\"',file);
  416. while (i < count) {
  417. se_print_character(file, storage[i++]);
  418. }
  419. putc('\"',file);
  420. }
  421. }
  422. void se_prinT8(FILE* file, EIF_POINTER* o) {
  423. if (*o == NULL) {
  424. fprintf(file,"NULL");
  425. }
  426. else {
  427. fprintf(file,"POINTER#%p",(void*)*o);
  428. }
  429. }
  430. /*
  431. The upper most context (SmartEiffel Dump stack Top) :
  432. */
  433. se_dump_stack* se_dst=NULL;
  434. int se_stack_size(se_dump_stack* ds) {
  435. int result = 0;
  436. while (ds != NULL) {
  437. ds = ds->caller;
  438. result ++;
  439. }
  440. return result;
  441. }
  442. void se_print_run_time_stack(void) {
  443. se_print_run_time_stack_in(SE_ERR);
  444. }
  445. void se_print_run_time_stack_in(FILE* file) {
  446. /* ANY.print_run_time_stack */
  447. se_dump_stack* origin;
  448. se_dump_stack* ds;
  449. se_dump_stack* ds2;
  450. int frame_count = 1;
  451. int rescue = 0;
  452. handle(SE_HANDLE_ENTER_PRINT_STACK, NULL);
  453. origin = se_dst;
  454. if (origin == NULL) {
  455. fprintf(file,"Empty stack.\n");
  456. return ;
  457. }
  458. else {
  459. while (origin->exception_origin != NULL) {
  460. origin = origin->exception_origin;
  461. }
  462. ds = origin;
  463. while (ds->caller != NULL) {
  464. ds = ds->caller;
  465. frame_count++;
  466. }
  467. }
  468. fprintf(file,"%d frames in current stack.\n",frame_count);
  469. fprintf(file,"===== Bottom of run-time stack =====\n");
  470. while (ds != NULL) {
  471. se_print_one_frame_in(file,ds);
  472. /* Next frame : */
  473. if (ds == origin) {
  474. ds = NULL;
  475. }
  476. else if (ds->exception_origin != NULL) {
  477. rescue = 1;
  478. ds = ds->exception_origin;
  479. }
  480. else {
  481. ds2 = se_dst;
  482. while (ds2->caller != ds) {
  483. ds2 = ds2->caller;
  484. }
  485. ds = ds2;
  486. }
  487. if (--frame_count) {
  488. if (!rescue) {
  489. fprintf(file,"======================================\n");
  490. }
  491. else {
  492. fprintf(file,"==== Rescue stack =================\n");
  493. }
  494. }
  495. }
  496. fprintf(file,"===== Top of run-time stack =====\n");
  497. handle(SE_HANDLE_EXIT_PRINT_STACK, NULL);
  498. }
  499. int se_print_one_frame(se_dump_stack* ds) {
  500. return se_print_one_frame_in(SE_ERR, ds);
  501. }
  502. int se_print_one_frame_in(FILE* file, se_dump_stack* ds) {
  503. /* Return 1 for an ordinary frame (not a cecil frame or some dynamic
  504. dispatch extra frame). */
  505. se_frame_descriptor* fd = ds->fd;
  506. int i = 0;
  507. int local_count = 0;
  508. char* local_format;
  509. int expanded;
  510. int id;
  511. void** var;
  512. if (fd == NULL) {
  513. fprintf(file,"External CECIL call.\n");
  514. return 0;
  515. }
  516. fprintf(file,"%s\n",fd->name);
  517. if (ds->p == 0) return 0;
  518. local_format = fd->local_format;
  519. if (fd->use_current) {
  520. fprintf(file,"Current = ");
  521. i = 2;
  522. id = 0;
  523. while (local_format[i] != '%') {
  524. id = (id * 10) + (local_format[i] - '0');
  525. i++;
  526. }
  527. i++;
  528. (se_prinT[id])(file, ds->current);
  529. fprintf(file,"\n");
  530. }
  531. while (local_count < fd->local_count) {
  532. while (local_format[i] != '%') {
  533. fprintf(file,"%c",local_format[i]);
  534. i++;
  535. }
  536. i++;
  537. expanded = ((local_format[i++] == 'E')?1:0);
  538. fprintf(file," = ");
  539. id = 0;
  540. while (local_format[i] != '%') {
  541. id = (id * 10) + (local_format[i] - '0');
  542. i++;
  543. }
  544. i++;
  545. if (ds->locals == NULL) {
  546. fprintf(file,"<unavailable>");
  547. }
  548. else {
  549. var = (ds->locals)[local_count];
  550. if (expanded) {
  551. (se_prinT[id])(file, (void**)(var));
  552. }
  553. else if (*var == NULL) {
  554. fprintf(file,"Void");
  555. }
  556. else {
  557. (se_prinT[((T0*)(*var))->id])(file, (void**)(var));
  558. }
  559. }
  560. fprintf(file,"\n");
  561. local_count++;
  562. }
  563. fprintf(file,"line %d ",se_position2line(ds->p));
  564. fflush(file);
  565. fprintf(file,"column %d ",se_position2column(ds->p));
  566. fflush(file);
  567. fprintf(file,"file %s \n",p[se_position2path_id(ds->p)]);
  568. fflush(file);
  569. return 1;
  570. }
  571. int se_rci(se_dump_stack*caller,void*C) {
  572. /* Where `caller' is supposed to be reference type non Void Current
  573. object. This function return 1 if the class invariant must be
  574. checked for `C' before leaving the routine.
  575. */
  576. if (caller != NULL) {
  577. se_frame_descriptor* fd = caller->fd;
  578. if (fd == NULL) {
  579. /* As for example when coming via CECIL. */
  580. return 0;
  581. }
  582. else {
  583. if (fd->use_current) {
  584. if (fd->local_format[1] == 'R') {
  585. if ((*((void**)caller->current)) == C) {
  586. return 0;
  587. }
  588. }
  589. }
  590. }
  591. }
  592. return 1;
  593. }
  594. void error0(char* m, char* vv) {
  595. /* When there is nothing more to do than to exit or to go back
  596. into the debugger.
  597. */
  598. static char*f="*** Error at Run Time ***: %s\n";
  599. fprintf(SE_ERR,f,m);
  600. if (vv!=NULL) fprintf(SE_ERR,f,vv);
  601. #ifdef SE_EXCEPTIONS
  602. print_exception();
  603. #endif
  604. #ifdef SE_SEDB
  605. sedb_break(se_dst,0);
  606. #else
  607. handle(SE_HANDLE_RUNTIME_ERROR, m);
  608. se_print_run_time_stack();
  609. fprintf(SE_ERR,f,m);
  610. if (vv!=NULL)
  611. fprintf(SE_ERR,f,vv);
  612. exit(EXIT_FAILURE);
  613. #endif
  614. }
  615. void error1(char*m,se_position position) {
  616. /* When there is nothing more to do than to exit or to go back
  617. into the debugger.
  618. */
  619. int l = se_position2line(position);
  620. int c = se_position2column(position);
  621. int f = se_position2path_id(position);
  622. char* f1 = "Line : %d column %d in %s.\n";
  623. char* f2 = "*** Error at Run Time ***: %s\n";
  624. fprintf(SE_ERR,f1,l,c,p[f]);
  625. fprintf(SE_ERR,f2,m);
  626. #ifdef SE_EXCEPTIONS
  627. print_exception();
  628. #endif
  629. #ifdef SE_SEDB
  630. sedb_break(se_dst,position);
  631. #else
  632. handle(SE_HANDLE_RUNTIME_ERROR, m);
  633. se_print_run_time_stack();
  634. fprintf(SE_ERR,f1,l,c,p[f]);
  635. fprintf(SE_ERR,f2,m);
  636. exit(EXIT_FAILURE);
  637. #endif
  638. }
  639. void se_print_string(FILE*stream, EIF_STRING s) {
  640. /* To print some Eiffel STRING. */
  641. if (s == NULL) {
  642. fprintf(stream,"Void");
  643. }
  644. else {
  645. int count = s->_count;
  646. EIF_CHARACTER* storage = s->_storage;
  647. int i = 0;
  648. fprintf(stream,"\"");
  649. while (count != 0) {
  650. fprintf(stream,"%c",storage[i]);
  651. i++;
  652. count--;
  653. }
  654. fprintf(stream,"\"");
  655. }
  656. }
  657. void se_print_bad_target(FILE*stream, int id, T0* o, int l, int c, int f) {
  658. /* Print Bad Target Type Error Message. */
  659. if (l != 0) {
  660. fprintf(stream,"Line : %d column %d in %s.\n",l,c,p[f]);
  661. }
  662. fprintf(stream,"*** Error at Run Time *** :\n");
  663. fprintf(stream," Target is not valid (not the good type).\n");
  664. fprintf(stream," Expected: ");
  665. se_print_string(stream,t[id]);
  666. fprintf(stream,", Actual: ");
  667. se_print_string(stream,t[o->id]);
  668. fprintf(stream,".\n");
  669. }
  670. void error2(T0*o, se_position position) {
  671. fprintf(SE_ERR,"Target Type ");
  672. se_print_string(SE_ERR,t[o->id]);
  673. fprintf(SE_ERR," is not valid.\n");
  674. error1("Bad target.",position);
  675. }
  676. T0* vc(T0* o, se_position position) {
  677. /*
  678. Void check for reference target.
  679. */
  680. if (o != NULL) {
  681. return o;
  682. }
  683. else {
  684. #ifdef SE_EXCEPTIONS
  685. internal_exception_handler(Void_call_target);
  686. #else
  687. error1("Call with a Void target.",position);
  688. #endif
  689. return NULL;
  690. }
  691. }
  692. T0* se_string_inspect_check(T0* o, se_position position) {
  693. /*
  694. Void check for expression of type STRING in inspect.
  695. */
  696. if (o != NULL) {
  697. return o;
  698. }
  699. else {
  700. #ifdef SE_EXCEPTIONS
  701. internal_exception_handler(Incorrect_inspect_value);
  702. #else
  703. error1("Expression just after \"inspect\" is Void.",position);
  704. #endif
  705. return NULL;
  706. }
  707. }
  708. T0* ci(int id, T0* o, se_position position) {
  709. /*
  710. Check Id for reference target.
  711. */
  712. if ( vc(o,position) != NULL) {
  713. if ( id == (o->id) ) {
  714. return o;
  715. }
  716. else {
  717. #ifdef SE_EXCEPTIONS
  718. internal_exception_handler(System_level_type_error);
  719. #else
  720. int l = se_position2line(position);
  721. int c = se_position2column(position);
  722. int f = se_position2path_id(position);
  723. se_print_bad_target(SE_ERR,id,o,l,c,f);
  724. se_print_run_time_stack();
  725. se_print_bad_target(SE_ERR,id,o,l,c,f);
  726. #ifdef SE_SEDB
  727. sedb_break(se_dst,0);
  728. #else
  729. exit(EXIT_FAILURE);
  730. #endif
  731. #endif
  732. }
  733. }
  734. return o;
  735. }
  736. void ac_req(int v,char*vv) {
  737. if (!v) {
  738. #ifdef SE_EXCEPTIONS
  739. internal_exception_handler(Precondition);
  740. #else
  741. error0("Require Assertion Violated.",vv);
  742. #endif
  743. }
  744. }
  745. void ac_ens(int v,char*vv) {
  746. if (!v) {
  747. #ifdef SE_EXCEPTIONS
  748. internal_exception_handler(Postcondition);
  749. #else
  750. error0("Ensure Assertion Violated.",vv);
  751. #endif
  752. }
  753. }
  754. void ac_inv(int v,char*vv) {
  755. if (!v) {
  756. #ifdef SE_EXCEPTIONS
  757. internal_exception_handler(Class_invariant);
  758. #else
  759. error0("Class Invariant Violation.",vv);
  760. #endif
  761. }
  762. }
  763. void ac_liv(int v,char*vv) {
  764. /* Assertion Check : Loop Invariant check. */
  765. if (!v) {
  766. #ifdef SE_EXCEPTIONS
  767. internal_exception_handler(Loop_invariant);
  768. #else
  769. error0("Loop Invariant Violation.",vv);
  770. #endif
  771. }
  772. }
  773. int ac_lvc(int lc,int lv1,int lv2) {
  774. /* Assertion Check : Loop Variant check. */
  775. if (lc == 0) {
  776. if (lv2 < 0) {
  777. #ifdef SE_EXCEPTIONS
  778. internal_exception_handler(Loop_variant);
  779. #else
  780. {
  781. char msg [64];
  782. sprintf(msg,"Bad First Variant Value = %d\n",lv2);
  783. error0(msg,NULL);
  784. }
  785. #endif
  786. }
  787. else {
  788. return lv2;
  789. }
  790. }
  791. else if ((lv2 < 0) || (lv2 >= lv1)) {
  792. #ifdef SE_EXCEPTIONS
  793. internal_exception_handler(Loop_variant);
  794. #else
  795. {
  796. char msg [512];
  797. sprintf(msg,
  798. "Bad loop variant.\nLoop body counter = %d (done)\n"
  799. "Previous Variant = %d\nNew Variant = %d\n",
  800. lc,lv1,lv2);
  801. error0(msg,NULL);
  802. }
  803. #endif
  804. }
  805. return lv2;
  806. }
  807. void ac_civ(int v,char*vv) {
  808. if (!v) {
  809. #ifdef SE_EXCEPTIONS
  810. internal_exception_handler(Check_instruction);
  811. #else
  812. error0("Check Assertion Violated.",vv);
  813. #endif
  814. }
  815. }
  816. T0* se_evobt(T0* o, se_position position) {
  817. /*
  818. Error Void Or Bad Type.
  819. */
  820. if (!o) {
  821. #ifdef SE_EXCEPTIONS
  822. internal_exception_handler(Void_call_target);
  823. #else
  824. error1("Target is Void.",position);
  825. #endif
  826. }
  827. else {
  828. #ifdef SE_EXCEPTIONS
  829. internal_exception_handler(System_level_type_error);
  830. #else
  831. error2(o,position);
  832. #endif
  833. }
  834. return o; /* Dummy return to avoid C warnings. */
  835. }
  836. void se_signal_handler(int sig) {
  837. printf("Received signal %d.\n",sig);
  838. #ifdef SE_SEDB
  839. signal(sig,se_signal_handler);
  840. sedb_signal_handler(sig);
  841. #else
  842. se_print_run_time_stack();
  843. exit(EXIT_FAILURE);
  844. #endif
  845. }
  846. void se_gc_check_id(void*o,int id) {
  847. if (id != (((T0*)o)->id)) {
  848. #ifdef SE_EXCEPTIONS
  849. internal_exception_handler(Routine_failure);
  850. #else
  851. fprintf(SE_ERR,"System-validity error detected during GC cycle.\n");
  852. se_print_bad_target(SE_ERR,id,(T0*)o,0,0,0);
  853. se_print_run_time_stack();
  854. fprintf(SE_ERR,"System-validity error detected during GC cycle.\n");
  855. se_print_bad_target(SE_ERR,id,(T0*)o,0,0,0);
  856. exit(EXIT_FAILURE);
  857. #endif
  858. }
  859. }
  860. se_dump_stack* se_new_dump_stack(se_dump_stack* copy) {
  861. se_dump_stack* result = NULL;
  862. se_frame_descriptor* fd;
  863. int i, j, o, p, n;
  864. int local_count;
  865. char* local_format;
  866. int id;
  867. void** var;
  868. int local_size;
  869. int expanded;
  870. void*** _i;
  871. void** _ref;
  872. char* _exp;
  873. if (copy != NULL) {
  874. fd = copy->fd;
  875. result = (se_dump_stack*)se_malloc(sizeof(se_dump_stack));
  876. if (result != NULL) {
  877. result->fd = fd;
  878. result->p = copy->p;
  879. result->caller = copy->caller;
  880. result->current = NULL;
  881. result->locals = NULL;
  882. result->exception_origin = NULL;
  883. if (fd != NULL) {
  884. local_format = fd->local_format;
  885. i = 0;
  886. if (fd->use_current) {
  887. result->current = copy->current;
  888. /* Place i after the Current definition: */
  889. i = 2;
  890. id = 0;
  891. while (local_format[i] != '%') {
  892. id = (id * 10) + (local_format[i++] - '0');
  893. }
  894. i++;
  895. }
  896. /*
  897. *
  898. * p: sum of the number of pointers ("indirections") per local
  899. * -> 1 for an expanded
  900. * -> 2 for a reference
  901. *
  902. * o: total malloc'ed size
  903. *
  904. * _i: access to the first indirection pointer
  905. *
  906. * _ref: access to the second indirection pointer of a reference object
  907. * _ref == (T0*)(*_i)
  908. *
  909. * _exp: access to a copy of the expanded object
  910. * _exp == *((char*)_i)
  911. *
  912. *
  913. *
  914. * For instance, if "0" is the first local, a reference and "4" is the
  915. * second local, an expanded type (say, a 6-byte structure noted
  916. * "XXXXXXXXXXX", with 64-bit padding "/"):
  917. *
  918. *
  919. *
  920. * result->locals
  921. * | ------------
  922. * | | |
  923. * | -----------|------------v--------------
  924. * -->| | | | |===+===|===+===|XXXXXXXXXXX|/|/|
  925. * |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|
  926. * |===+===| | | | |===+===| | | | | | | | |
  927. * ---|------------^--|-------------------
  928. * | | |
  929. * ------------ --------------------------> object
  930. *
  931. * |-> _i |-> _ref _exp <-|
  932. *
  933. *
  934. *
  935. * Note: Those "|->" denote the start value and way of
  936. * progression of the pointers
  937. *
  938. *
  939. * result->locals is defined as a (void***) but its real "type" depends on
  940. * which element is accessed (as in the live stack; but in the live stack,
  941. * only the first indirection is in the struct; the remaining data is on
  942. * the native stack).
  943. *
  944. */
  945. if (copy->locals != NULL) {
  946. j = i;
  947. local_count = local_size = p = o = 0;
  948. while (local_count < fd->local_count) {
  949. while (local_format[i++] != '%');
  950. expanded = ((local_format[i++] == 'E')?1:0);
  951. id = 0;
  952. while (local_format[i] != '%') {
  953. id = (id * 10) + (local_format[i++] - '0');
  954. }
  955. i++;
  956. if (expanded) {
  957. p++;
  958. o = se_strucT[id];
  959. o = (o + 7) & ~7; /* 64-bit align: should be fine for most systems */
  960. local_size += o;
  961. }
  962. else {
  963. p+=2;
  964. }
  965. local_count++;
  966. }
  967. o = p * sizeof(void*) + local_size;
  968. result->locals = (void***)se_malloc(o);
  969. _i = result->locals;
  970. _exp = (char*)_i + o;
  971. _ref = (void**)_i + local_count;
  972. i = j;
  973. local_count = 0;
  974. while (local_count < fd->local_count) {
  975. while (local_format[i++] != '%');
  976. expanded = ((local_format[i++] == 'E')?1:0);
  977. id = 0;
  978. while (local_format[i] != '%') {
  979. id = (id * 10) + (local_format[i++] - '0');
  980. }
  981. i++;
  982. var = (copy->locals)[local_count];
  983. if (expanded) {
  984. o = n = se_strucT[id];
  985. o = (o + 7) & ~7; /* 64-bit align: should be fine for most systems */
  986. _exp -= o;
  987. *(char**)_i = _exp;
  988. memset(_exp, 0, o);
  989. memcpy(_exp, var, n);
  990. }
  991. else {
  992. *_i = _ref;
  993. *_ref = *var;
  994. _ref++;
  995. }
  996. local_count++;
  997. _i++;
  998. }
  999. }
  1000. }
  1001. }
  1002. }
  1003. return result;
  1004. }
  1005. void se_delete_dump_stack(se_dump_stack* ds) {
  1006. if (ds != NULL) {
  1007. if (ds->locals != NULL) free(ds->locals);
  1008. free(ds);
  1009. }
  1010. }
  1011. void se_print_locals_in(FILE* file, se_dump_stack* ds, int enter) {
  1012. se_frame_descriptor* fd = ds->fd;
  1013. int i = 0;
  1014. int local_count = 0;
  1015. char* local_format;
  1016. int expanded;
  1017. int id;
  1018. void** var;
  1019. int printed = 0;
  1020. int display;
  1021. if (ds->p == 0) return;
  1022. local_format = fd->local_format;
  1023. if (fd->use_current) {
  1024. i = 2;
  1025. id = 0;
  1026. while (local_format[i] != '%') {
  1027. i++;
  1028. }
  1029. i++;
  1030. }
  1031. while (local_count < fd->local_count) {
  1032. display = (strncmp(local_format+i, "Result%", 7)==0) != enter;
  1033. if (display) {
  1034. if (printed)
  1035. fprintf(file,", ");
  1036. else
  1037. fprintf(file,"(");
  1038. printed++;
  1039. }
  1040. while (local_format[i] != '%') {
  1041. if (display) fprintf(file,"%c",local_format[i]);
  1042. i++;
  1043. }
  1044. i++;
  1045. expanded = ((local_format[i++] == 'E')?1:0);
  1046. if (display) fprintf(file," = ");
  1047. id = 0;
  1048. while (local_format[i] != '%') {
  1049. id = (id * 10) + (local_format[i] - '0');
  1050. i++;
  1051. }
  1052. i++;
  1053. if (display) {
  1054. if (ds->locals == NULL) {
  1055. fprintf(file,"<unavailable>");
  1056. }
  1057. else {
  1058. var = (ds->locals)[local_count];
  1059. if (expanded) {
  1060. (se_prinT[id])(file, (void**)(var));
  1061. }
  1062. else if (*var == NULL) {
  1063. fprintf(file,"Void");
  1064. }
  1065. else {
  1066. (se_prinT[((T0*)(*var))->id])(file, (void**)(var));
  1067. }
  1068. }
  1069. }
  1070. local_count++;
  1071. }
  1072. if (printed)
  1073. fprintf(file,")\n");
  1074. else
  1075. fprintf(file,"\n");
  1076. }
  1077. #ifdef SE_TRACE
  1078. static int se_call_depth=0;
  1079. void se_print_call_trace(se_dump_stack *ds) {
  1080. int i;
  1081. if (ds) {
  1082. int enter = ds->caller == se_dst;
  1083. if (enter)
  1084. se_call_depth++;
  1085. if (se_call_depth < 0)
  1086. se_call_depth=0;
  1087. for(i=se_call_depth<<1; i; i--)
  1088. putchar(' ');
  1089. if (enter) {
  1090. printf("enter ");
  1091. printf("%s", ds->fd->name);
  1092. se_print_locals_in(stdout, ds, 1);
  1093. } else {
  1094. if (se_dst) {
  1095. printf("leave ");
  1096. printf("%s", se_dst->fd->name);
  1097. se_print_locals_in(stdout, se_dst, 0);
  1098. se_call_depth--;
  1099. }
  1100. }
  1101. } else {
  1102. for(i=se_call_depth<<1; i; i--)
  1103. putchar(' ');
  1104. printf("leave ");
  1105. printf("%s", se_dst->fd->name);
  1106. se_print_locals_in(stdout, se_dst, 0);
  1107. se_call_depth--;
  1108. }
  1109. }
  1110. #endif
  1111. /*
  1112. -- ------------------------------------------------------------------------------------------------------------
  1113. -- Copyright notice below. Please read.
  1114. --
  1115. -- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE
  1116. -- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
  1117. --
  1118. -- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
  1119. --
  1120. -- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  1121. -- documentation files (the "Software"), to deal in the Software without restriction, including without
  1122. -- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  1123. -- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
  1124. -- conditions:
  1125. --
  1126. -- The above copyright notice and this permission notice shall be included in all copies or substantial
  1127. -- portions of the Software.
  1128. --
  1129. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  1130. -- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
  1131. -- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  1132. -- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  1133. -- OR OTHER DEALINGS IN THE SOFTWARE.
  1134. --
  1135. -- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
  1136. -- ------------------------------------------------------------------------------------------------------------
  1137. */
  1138. /*
  1139. This file (SmartEiffel/sys/runtime/gc_lib.c) is automatically included
  1140. when the Garbage Collector is used (default, unless option -no_gc has been
  1141. selected).
  1142. */
  1143. /*
  1144. The `mark_stack_and_registers' C function is called by the Garbage
  1145. Collector (GC) of SmartEiffel. It has to be customized for some systems,
  1146. but also for some C compilers. This file provides some definitions in the
  1147. end and has to be completed for systems which need specific work.
  1148. On some architectures, addresses increase as the stack grows; or,
  1149. conversely, addresses decrease as the stack grows. A C compiler may be
  1150. clever enough to hide some root object inside registers. Unfortunately all
  1151. registers are not always accessible via the C `setjmp' function!
  1152. Thus, in order to be able to use the GC on your architecture/C-compiler,
  1153. you have to provide the correct `mark_stack_and_registers' function.
  1154. What is the `mark_stack_and_registers' function supposed to do? The
  1155. `mark_stack_and_registers' function is supposed to notify the GC with all
  1156. the possible roots one can find in the C stack and registers by calling the
  1157. `gc_mark' function. A root is an object which must not be collected. The
  1158. SmartEiffel GC already knows about some root objects like once function
  1159. results or manifest strings. The `mark_stack_and_registers' function has to
  1160. notify the other possible roots. Obviously, one can find in the C stack any
  1161. kind of adresses, but the `gc_mark' function is clever enough to determine
  1162. if the passed pointer is an Eiffel object or not. When the passed pointer
  1163. reaches some Eiffel object, this object as well as its descendant(s) are
  1164. automatically marked as un-collectable.
  1165. In order to provide the most appropriate `mark_stack_and_registers'
  1166. function, the very first question is to know about the way the C stack is
  1167. managed (addresses of the stack may increase or decrease as the C stack
  1168. grows). The DEFAULT BEHAVIOUR FOR UNKNOWN SYSTEMS is to consider ADDRESSES
  1169. DECREASE AS THE STACK GROWS, as it's the most common case. The global C
  1170. variable `stack_bottom' is set with some pointer which is supposed to be
  1171. the bottom of the stack (this variable is automatically initialized in the
  1172. C main function). Note: using the current stack pointer inside
  1173. `mark_stack_and_registers', it is quite obvious to determine if addresses
  1174. increase or not as the C stack grows. Note2: on some systems, the stack is
  1175. not in contiguous addresses. In such case, `mark_stack_and_registers' has
  1176. to go through all the stack fragments.
  1177. Some roots may be stored only in registers and not in the C stack. In
  1178. order to reach the registers as well, the first attempt is to use setjmp,
  1179. in the hope that setjmp will save registers in the stack! Note: this
  1180. technique do not work on processors using windows registers (such as sparc
  1181. processors).
  1182. */
  1183. int se_gc_strategy = SE_GC_DEFAULT_MEMORY_STRATEGY;
  1184. int collector_counter = 0;
  1185. static void gcna_align_mark(rsoc*c,void*o);
  1186. static rsoc*rsocfl=NULL; /* ReSizable Object Chunk Free List. */
  1187. void**stack_bottom=NULL;
  1188. mch**gcmt=NULL; /* Garbage Collector Main Table. */
  1189. int gcmt_max=2048;
  1190. int gcmt_used=0;
  1191. fsoc*fsocfl=NULL; /* Fixed Size Object Chunk Free List. */
  1192. int gc_is_off=1;
  1193. unsigned int fsoc_count=0;
  1194. unsigned int rsoc_count=0;
  1195. void*gcmt_tail_addr=NULL;
  1196. static int chunk_rounded(int size) {
  1197. int rounded_size = size;
  1198. int diff = rounded_size%RSOC_SIZE;
  1199. if (diff != 0) rounded_size += (RSOC_SIZE-diff);
  1200. return rounded_size;
  1201. }
  1202. /* Return the index where chunk `c' is (or is to be) in the `gcmt',
  1203. between `min' and `max' indexes. */
  1204. static unsigned int binary_search_in_gcmt(register unsigned int min,
  1205. register unsigned int max,
  1206. register mch* c){
  1207. register unsigned int mid;
  1208. while (min<max){
  1209. mid=(min+max)>>1;
  1210. if (gcmt[mid]<c)
  1211. min=mid+1;
  1212. else
  1213. max=mid;
  1214. }
  1215. if (gcmt[min]<c)
  1216. return min+1;
  1217. else
  1218. return min;
  1219. }
  1220. static void may_free_rsocfl(void) {
  1221. /* May free all chunks of `rsocfl' (ReSizable Object Chunk Free List)
  1222. in some circumstances.
  1223. */
  1224. rsoc* next; register rsoc *current;
  1225. unsigned int count = rsocfl_count();
  1226. register unsigned int where = gcmt_used;
  1227. register unsigned int how_many;
  1228. if ((count > 50) && (count > (rsoc_count >> 1))) {
  1229. current=rsocfl;
  1230. rsocfl=NULL;
  1231. while (NULL != current) {
  1232. next=current->next;
  1233. if (current->isize == current->header.size) {
  1234. where = binary_search_in_gcmt(0, where-1, (mch*)current);
  1235. how_many = gcmt_used - 1 - where;
  1236. if (how_many > 0)
  1237. memmove(gcmt+where, gcmt+where+1, how_many*sizeof(mch*));
  1238. free(current); gcmt_used--; rsoc_count--;
  1239. }
  1240. else {
  1241. current->next=rsocfl;
  1242. rsocfl=current;
  1243. }
  1244. current = next;
  1245. }
  1246. }
  1247. }
  1248. int gc_memory_used(void) {
  1249. int i;
  1250. int result = 0;
  1251. mch* mch;
  1252. for (i = gcmt_used; i --> 0; ) {
  1253. mch = gcmt[i];
  1254. switch(mch->state_type) {
  1255. case RSO_USED_CHUNK:
  1256. case FSO_USED_CHUNK:
  1257. case FSO_STORE_CHUNK:
  1258. result += mch->size;
  1259. break;
  1260. default:
  1261. break;
  1262. }
  1263. }
  1264. return result;
  1265. }
  1266. void gc_sweep(void) {
  1267. mch** p2 = gcmt;
  1268. mch** p1 = gcmt+1;
  1269. mch**eogcmt=gcmt+gcmt_used;
  1270. if (FREE_CHUNK((*p2)->state_type)) {
  1271. if (RSO_FREE_CHUNK == ((*p2)->state_type)) {
  1272. ((rsoc*)(*p2))->next=NULL;
  1273. rsocfl=((rsoc*)(*p2));
  1274. }
  1275. else {
  1276. rsocfl=NULL;
  1277. }
  1278. }
  1279. else {
  1280. ((*gcmt)->swfp)(*p2);
  1281. if (RSO_FREE_CHUNK==((*p2)->state_type)) {
  1282. ((rsoc*)(*p2))->next=NULL;
  1283. rsocfl=((rsoc*)(*p2));
  1284. }
  1285. else {
  1286. rsocfl=NULL;
  1287. }
  1288. }
  1289. while (p1 < eogcmt) {
  1290. if (FREE_CHUNK((*p1)->state_type)) {
  1291. if (RSO_FREE_CHUNK == ((*p1)->state_type)) {
  1292. if (RSO_FREE_CHUNK == ((*p2)->state_type)) {
  1293. if ( (((rsoc*)*p1)->isize==0) && ((char*)(*p2))+(*p2)->size == ((char*)(*p1))) {
  1294. ((*p2)->size)+=((*p1)->size);
  1295. p1++;
  1296. }
  1297. else {
  1298. ((rsoc*)(*p1))->next=rsocfl;
  1299. rsocfl=((rsoc*)(*p1));
  1300. *(p2+1)=*p1; p2++; p1++;
  1301. }
  1302. }
  1303. else {
  1304. ((rsoc*)(*p1))->next=rsocfl;
  1305. rsocfl=((rsoc*)(*p1));
  1306. *(p2+1)=*p1; p2++; p1++;
  1307. }
  1308. }
  1309. else {
  1310. *(p2+1)=*p1; p2++; p1++;
  1311. }
  1312. }
  1313. else {
  1314. ((*p1)->swfp)(*p1);
  1315. if (RSO_FREE_CHUNK == ((*p1)->state_type)) {
  1316. if (RSO_FREE_CHUNK == ((*p2)->state_type)) {
  1317. if ( (((rsoc*)*p1)->isize==0) && ((char*)(*p2))+(*p2)->size == ((char*)(*p1))) {
  1318. ((*p2)->size)+=((*p1)->size);
  1319. p1++;
  1320. }
  1321. else {
  1322. ((rsoc*)(*p1))->next=rsocfl;
  1323. rsocfl=((rsoc*)(*p1));
  1324. *(p2+1)=*p1; p2++; p1++;
  1325. }
  1326. }
  1327. else {
  1328. ((rsoc*)(*p1))->next=rsocfl;
  1329. rsocfl=((rsoc*)(*p1));
  1330. *(p2+1)=*p1; p2++; p1++;
  1331. }
  1332. }
  1333. else {
  1334. *(p2+1)=*p1; p2++; p1++;
  1335. }
  1336. }
  1337. }
  1338. gcmt_used=(p2-gcmt)+1;
  1339. may_free_rsocfl();
  1340. }
  1341. /* return the mch containing p or NULL if p is not
  1342. * a valid address or was externally allocated
  1343. */
  1344. mch * gc_find_chunk(void * p){
  1345. if ((p>((void*)*gcmt))&&(p<=gcmt_tail_addr)) {
  1346. int i1=0;
  1347. int i2=gcmt_used-1;
  1348. int m=i2>>1;
  1349. mch*c;
  1350. for (;i2>i1;m=((i1+i2)>>1)) {
  1351. if (p<=((void*)gcmt[m+1])) {
  1352. i2=m;
  1353. }
  1354. else {
  1355. i1=m+1;
  1356. }
  1357. }
  1358. c=gcmt[i2];
  1359. if((char*)p<(char*)c+c->size) /* check for upper bound */
  1360. if (!(FREE_CHUNK(c->state_type))){
  1361. return c;
  1362. }
  1363. }
  1364. return NULL;
  1365. }
  1366. void gc_mark(void*p) {
  1367. mch * c;
  1368. c = gc_find_chunk(p);
  1369. if(NULL != c) {
  1370. (c->amfp)(c,p);
  1371. }
  1372. }
  1373. int gc_stack_size(void) {
  1374. void*stack_top[2]={NULL,NULL};
  1375. if (stack_top > stack_bottom) {
  1376. return ((void**)stack_top)-((void**)stack_bottom);
  1377. }
  1378. else {
  1379. return ((void**)stack_bottom)-((void**)stack_top);
  1380. }
  1381. }
  1382. /*
  1383. To delay Garbage Collection when the stack is too large.
  1384. To allow fast increase of ceils.
  1385. */
  1386. #define FSOC_LIMIT (10240/((FSOC_SIZE)>>10))
  1387. #define RSOC_LIMIT (10240/((RSOC_SIZE)>>10))
  1388. /*
  1389. When stack is too large, collection may be delayed.
  1390. */
  1391. #define GCLARGESTACK 50000
  1392. int garbage_delayed(void) {
  1393. /*
  1394. To delay the first GC call.
  1395. */
  1396. if (gc_stack_size() > GCLARGESTACK) {
  1397. if (fsoc_count_ceil <= fsoc_count) {
  1398. if (rsoc_count_ceil <= rsoc_count) {
  1399. if ((fsoc_count<FSOC_LIMIT)&&(rsoc_count<RSOC_LIMIT)) {
  1400. fsoc_count_ceil++;
  1401. rsoc_count_ceil++;
  1402. return 1;
  1403. }
  1404. else return 0;
  1405. }
  1406. else {
  1407. if (fsoc_count<FSOC_LIMIT) {
  1408. fsoc_count_ceil++;
  1409. return 1;
  1410. }
  1411. else return 0;
  1412. }
  1413. }
  1414. else {
  1415. if (rsoc_count_ceil <= rsoc_count) {
  1416. if (rsoc_count<RSOC_LIMIT) {
  1417. rsoc_count_ceil++;
  1418. return 1;
  1419. }
  1420. else return 0;
  1421. }
  1422. else return 0;
  1423. }
  1424. }
  1425. else {
  1426. return 0;
  1427. }
  1428. }
  1429. void gc_update_ceils(void) {
  1430. /* This function is automatically called after each collection
  1431. cycle.
  1432. */
  1433. if (se_gc_strategy == SE_GC_LOW_MEMORY_STRATEGY) {
  1434. fsoc_count_ceil = fsoc_count;
  1435. rsoc_count_ceil = rsoc_count;
  1436. /* Todo: we should also consider to free unused chunks here. */
  1437. return;
  1438. }
  1439. if (se_gc_strategy == SE_GC_HIGH_MEMORY_STRATEGY) {
  1440. fsoc_count_ceil = (256 + fsoc_count) << 2;
  1441. rsoc_count_ceil = (256 + rsoc_count) << 2;
  1442. return;
  1443. }
  1444. /* The SE_GC_DEFAULT_MEMORY_STRATEGY. */
  1445. /* Compute fsoc_count_ceil: */
  1446. /* The lines commented out with --perf-- were killing performance under certain circumstances, *
  1447. * especially with gcc -O3 <FM-15/04/2005> */
  1448. /* --perf-- if (fsocfl == NULL) { */
  1449. if (fsoc_count >= fsoc_count_ceil) {
  1450. if (fsoc_count_ceil < FSOC_LIMIT) {
  1451. fsoc_count_ceil <<= 1;
  1452. }
  1453. else {
  1454. unsigned int c = fsoc_count + (fsoc_count/3);
  1455. if (fsoc_count_ceil < c)
  1456. fsoc_count_ceil = c;
  1457. }
  1458. }
  1459. /* --perf-- }
  1460. else {
  1461. if (fsoc_count_ceil < fsoc_count) {
  1462. fsoc_count_ceil = fsoc_count;
  1463. }
  1464. }
  1465. */
  1466. /* Compute rsoc_count_ceil: */
  1467. /* --perf-- if (rsocfl == NULL) {*/
  1468. if (rsoc_count >= rsoc_count_ceil) {
  1469. if (rsoc_count_ceil < RSOC_LIMIT) {
  1470. rsoc_count_ceil <<= 1;
  1471. }
  1472. else {
  1473. unsigned int c = rsoc_count + (rsoc_count / 3);
  1474. if (rsoc_count_ceil < c) {
  1475. rsoc_count_ceil = c;
  1476. }
  1477. }
  1478. }
  1479. /* --perf -- }
  1480. else {
  1481. if (rsoc_count_ceil < rsoc_count) {
  1482. rsoc_count_ceil = rsoc_count;
  1483. }
  1484. }
  1485. */
  1486. }
  1487. static void gc_add_into_gcmt(mch*c) {
  1488. /* Update the `gcmt' (Garbage Collector Main Table) by adding the
  1489. new `mch' (Memory Chunk Header).`gcmt_used' is updated.
  1490. */
  1491. unsigned int where=0;
  1492. unsigned how_many;
  1493. if (gcmt_used>0){
  1494. where=binary_search_in_gcmt(0, gcmt_used-1, c);
  1495. if (gcmt_used == gcmt_max) {
  1496. gcmt_max <<= 1;
  1497. gcmt = ((mch**)(se_realloc(gcmt,(gcmt_max+1)*sizeof(void*))));
  1498. }
  1499. how_many = gcmt_used - where;
  1500. if (how_many > 0)
  1501. memmove(gcmt+where+1, gcmt+where, how_many*sizeof(mch*));
  1502. }
  1503. gcmt[where]=c;
  1504. gcmt_used++;
  1505. }
  1506. static char*rso_from_store(na_env*nae,unsigned int size) {
  1507. rsoh*r=(nae->store);
  1508. nae->store_left-=size;
  1509. if ((nae->store_left) > sizeof(rsoh)) {
  1510. r->header.size=size;
  1511. nae->store=((rsoh*)(((char*)(nae->store))+size));
  1512. }
  1513. else {
  1514. r->header.size=size+nae->store_left;
  1515. nae->store_left=0;
  1516. }
  1517. (r->header.magic_flag)=RSOH_UNMARKED;
  1518. ((void)memset((r+1),0,r->header.size-sizeof(rsoh)));
  1519. return (char*)(r+1);
  1520. }
  1521. static void rsoc_sweep(rsoc*c) {
  1522. na_env*nae=c->nae;
  1523. rsoh*gp=(rsoh*)&(c->first_header);
  1524. rsoh*pp;
  1525. rsoh*eoc=((rsoh*)(((char*)c)+c->header.size));
  1526. c->free_list_of_large=NULL;
  1527. if (c->header.size > RSOC_SIZE) {
  1528. if (gp->header.magic_flag == RSOH_MARKED) {
  1529. gp->header.magic_flag=RSOH_UNMARKED;
  1530. /* No need to register chunks with no free_list_of_large
  1531. c->next=nae->chunk_list;
  1532. nae->chunk_list=c;
  1533. */
  1534. }
  1535. else {
  1536. c->header.state_type=RSO_FREE_CHUNK;
  1537. }
  1538. return;
  1539. }
  1540. while (gp<eoc) {
  1541. while (gp->header.magic_flag == RSOH_MARKED) {
  1542. gp->header.magic_flag=RSOH_UNMARKED;
  1543. gp=((rsoh*)(((char*)gp)+gp->header.size));
  1544. if(gp>=eoc) {
  1545. /* No need to register chunks with no free_list_of_large
  1546. c->next=nae->chunk_list;
  1547. nae->chunk_list=c;
  1548. */
  1549. return;
  1550. }
  1551. }
  1552. gp->header.magic_flag=RSOH_FREE;
  1553. pp=(rsoh*)(((char*)gp)+gp->header.size);
  1554. while ((pp<eoc)&&(pp->header.magic_flag != RSOH_MARKED)) {
  1555. gp->header.size+=pp->header.size;
  1556. pp=((rsoh*)(((char*)pp)+pp->header.size));
  1557. }
  1558. if (gp->header.size >= RSOC_MIN_STORE) {
  1559. if (nae->store_left==0) {
  1560. nae->store_left=gp->header.size;
  1561. nae->store=gp;
  1562. nae->store_chunk=c;
  1563. }
  1564. else if (nae->store->header.size < gp->header.size) {
  1565. ((fll_rsoh*)nae->store)->nextflol=nae->store_chunk->free_list_of_large;
  1566. nae->store_chunk->free_list_of_large=((fll_rsoh*)nae->store);
  1567. nae->store_left=gp->header.size;
  1568. nae->store=gp;
  1569. nae->store_chunk=c;
  1570. }
  1571. else {
  1572. ((fll_rsoh*)gp)->nextflol=c->free_list_of_large;
  1573. c->free_list_of_large=((fll_rsoh*)gp);
  1574. }
  1575. }
  1576. gp=pp;
  1577. }
  1578. if (((rsoh*)(&c->first_header))->header.size >=
  1579. (c->header.size-sizeof(rsoc)+sizeof(rsoh))){
  1580. c->header.state_type=RSO_FREE_CHUNK;
  1581. nae->store_chunk=NULL;
  1582. nae->store_left=0;
  1583. }
  1584. else{
  1585. c->next=nae->chunk_list;
  1586. nae->chunk_list=c;
  1587. }
  1588. }
  1589. /* *** To be removed */
  1590. #ifdef __TINYC__
  1591. static rsoc MRSOC = {
  1592. #else
  1593. static const rsoc MRSOC = {
  1594. #endif
  1595. {
  1596. RSOC_SIZE,
  1597. RSO_USED_CHUNK,
  1598. ((void(*)(mch*,void*))gcna_align_mark),
  1599. ((void(*)(mch*))rsoc_sweep)
  1600. },
  1601. 0,
  1602. NULL,
  1603. NULL,
  1604. NULL,
  1605. {
  1606. {
  1607. 0,
  1608. RSOH_MARKED
  1609. }
  1610. }
  1611. };
  1612. static void rsoc_malloc(na_env*nae) {
  1613. rsoc* r = ((rsoc*)(se_malloc(RSOC_SIZE)));
  1614. rsoc_count++;
  1615. *r=MRSOC;
  1616. r->nae=nae;
  1617. r->isize=RSOC_SIZE;
  1618. nae->store=(&(r->first_header));
  1619. nae->store_left=RSOC_SIZE-sizeof(rsoc)+sizeof(rsoh);
  1620. nae->store_chunk=r;
  1621. r->next=nae->chunk_list;
  1622. nae->chunk_list=r;
  1623. gc_add_into_gcmt((mch*)r);
  1624. }
  1625. static rsoc* rsocfl_best_fit(unsigned int size) {
  1626. register unsigned int best_size = 0;
  1627. unsigned int acceptable_loss;
  1628. register rsoc *pc, *best_pc, *best_c, *c;
  1629. if (NULL==rsocfl)
  1630. return NULL;
  1631. pc=NULL;
  1632. best_pc=NULL;
  1633. best_c=NULL;
  1634. c=rsocfl;
  1635. if (SE_GC_DEFAULT_MEMORY_STRATEGY == se_gc_strategy)
  1636. acceptable_loss = (size >> 4);
  1637. else if (SE_GC_LOW_MEMORY_STRATEGY == se_gc_strategy)
  1638. acceptable_loss = 0;
  1639. else /* SE_GC_HIGH_MEMORY_STRATEGY == se_gc_strategy */
  1640. acceptable_loss = (size >> 2);
  1641. while ((NULL!=c)&&(NULL==best_c)){
  1642. if (c->header.size>=size){
  1643. best_c=c;
  1644. best_pc=pc;
  1645. best_size=c->header.size;
  1646. }
  1647. pc=c;
  1648. c=c->next;
  1649. }
  1650. if (NULL==c){
  1651. if (NULL != best_pc)
  1652. best_pc->next=best_c->next;
  1653. else if (best_c==rsocfl)
  1654. rsocfl=best_c->next;
  1655. return best_c;
  1656. }
  1657. if ((best_size - size) > acceptable_loss){
  1658. do {
  1659. if ((c->header.size >= size) && (c->header.size < best_size)) {
  1660. best_c = c;
  1661. best_pc = pc;
  1662. best_size = c->header.size;
  1663. if ((best_size - size) <= acceptable_loss) break;
  1664. }
  1665. pc=c;
  1666. c=c->next;
  1667. }
  1668. while(NULL!=c);
  1669. }
  1670. if (NULL==best_pc) {
  1671. rsocfl = best_c->next;
  1672. }
  1673. else {
  1674. best_pc->next=best_c->next;
  1675. }
  1676. return best_c;
  1677. }
  1678. static int get_store_in(rsoc*c,unsigned int size) {
  1679. na_env*nae=c->nae;
  1680. fll_rsoh*pf=NULL;
  1681. fll_rsoh*f=c->free_list_of_large;
  1682. while (f != NULL) {
  1683. if (f->rsoh_field.size >= size) {
  1684. nae->store_left=f->rsoh_field.size;
  1685. nae->store=(rsoh*)f;
  1686. nae->store_chunk=c;
  1687. if (pf == NULL) {
  1688. c->free_list_of_large=f->nextflol;
  1689. }
  1690. else {
  1691. pf->nextflol=f->nextflol;
  1692. }
  1693. return 1;
  1694. }
  1695. pf = f;
  1696. f = f->nextflol;
  1697. }
  1698. return 0;
  1699. }
  1700. char*new_na_from_chunk_list(na_env*nae,unsigned int size) {
  1701. rsoc*c=nae->chunk_list;
  1702. unsigned int csize;
  1703. while (c != NULL) {
  1704. if (get_store_in(c,size)) {
  1705. return rso_from_store(nae,size);
  1706. }
  1707. c = c->next;
  1708. }
  1709. csize=size+(sizeof(rsoc)-sizeof(rsoh));
  1710. c=rsocfl_best_fit(csize);
  1711. if (c != NULL){
  1712. if (c->header.size > RSOC_SIZE) {
  1713. if (c->header.size-csize > RSOC_MIN_STORE*4) {
  1714. int csize_left=c->header.size-csize;
  1715. if ((csize_left%sizeof(double))!=0) {
  1716. csize_left-=(csize_left%sizeof(double));
  1717. csize=c->header.size-csize_left;
  1718. }
  1719. c->header.size=csize_left;
  1720. c->next=rsocfl;
  1721. rsocfl=c;
  1722. c=(rsoc*)(((char*)c)+csize_left);
  1723. c->isize=0; /* c split from a larger chunk */
  1724. gc_add_into_gcmt((mch*)c);
  1725. c->header.amfp=(void(*)(mch*,void*))gcna_align_mark;
  1726. c->header.swfp=(void(*)(mch*))rsoc_sweep;
  1727. }
  1728. /* since objects bigger than RSOC_SIZE must be the only object in their chunk, we do not want to have
  1729. some store left after them. Therefore, we do not set csize to c->header.size in an else block
  1730. here. */
  1731. c->header.size=csize;
  1732. }
  1733. else {
  1734. csize=c->header.size;
  1735. }
  1736. c->header.state_type=RSO_USED_CHUNK;
  1737. c->free_list_of_large=NULL;
  1738. c->nae=nae;
  1739. nae->store=(&(c->first_header));
  1740. nae->store_left=csize-sizeof(rsoc)+sizeof(rsoh);
  1741. nae->store_chunk=c;
  1742. /* No need to register chunks with no free_list_of_large
  1743. c->next=nae->chunk_list;
  1744. nae->chunk_list=c;
  1745. */
  1746. return rso_from_store(nae,size);
  1747. }
  1748. return NULL;
  1749. }
  1750. /* size in bytes, including header size */
  1751. char*new_na(na_env*nae,unsigned int size) {
  1752. if (size == 0) {
  1753. #ifdef SE_BOOST
  1754. handle(SE_HANDLE_RUNTIME_ERROR, NULL);
  1755. se_print_run_time_stack();
  1756. exit(EXIT_FAILURE);
  1757. #else
  1758. char msg[512];
  1759. sprintf(msg, "Bad native array size: %d.\n", size);
  1760. error0(msg, NULL);
  1761. #endif
  1762. }
  1763. if (nae->store_left>0) {
  1764. nae->store->header.size=nae->store_left;
  1765. nae->store->header.magic_flag=RSOH_FREE;
  1766. if (nae->store_left >= RSOC_MIN_STORE) {
  1767. ((fll_rsoh*)(nae->store))->nextflol=nae->store_chunk->free_list_of_large;
  1768. nae->store_chunk->free_list_of_large=((fll_rsoh*)nae->store);
  1769. }
  1770. nae->store_left=0;
  1771. }
  1772. if ((nae->store_chunk!=NULL)&&(get_store_in(nae->store_chunk,size))) {
  1773. return rso_from_store(nae,size);
  1774. }
  1775. {
  1776. char*r=new_na_from_chunk_list(nae,size);
  1777. if (r!=NULL)
  1778. return r;
  1779. }
  1780. if (rsoc_count<rsoc_count_ceil) {
  1781. if((size+sizeof(rsoc)-sizeof(rsoh))>RSOC_SIZE){
  1782. rsoc*c;
  1783. rsoh*r;
  1784. unsigned int rounded_size= chunk_rounded(size+sizeof(rsoc)-sizeof(rsoh));
  1785. c=((rsoc*)(se_malloc(rounded_size)));
  1786. r=(&(c->first_header));
  1787. rsoc_count++;
  1788. *c=MRSOC;
  1789. c->isize = rounded_size;
  1790. c->header.size=rounded_size;
  1791. c->nae=nae;
  1792. /* No need to register chunks with no free_list_of_large
  1793. c->next=nae->chunk_list;
  1794. nae->chunk_list=c;
  1795. */
  1796. gc_add_into_gcmt((mch*)c);
  1797. r->header.size=size;
  1798. (r->header.magic_flag)=RSOH_UNMARKED;
  1799. ((void)memset((r+1),0,size-sizeof(rsoh)));
  1800. return (char*)(r+1);
  1801. }
  1802. else {
  1803. rsoc_malloc(nae);
  1804. return rso_from_store(nae,size);
  1805. }
  1806. }
  1807. gc_start();
  1808. if (size<=(nae->store_left)) {
  1809. return rso_from_store(nae,size);
  1810. }
  1811. {
  1812. char*r=new_na_from_chunk_list(nae,size);
  1813. if (r!=NULL) {
  1814. return r;
  1815. }
  1816. }
  1817. if((size+sizeof(rsoc)-sizeof(rsoh))>RSOC_SIZE){
  1818. rsoc*c;
  1819. rsoh*r;
  1820. unsigned int rounded_size = chunk_rounded(size+sizeof(rsoc)-sizeof(rsoh));
  1821. c=((rsoc*)(se_malloc(rounded_size)));
  1822. r=(&(c->first_header));
  1823. rsoc_count++;
  1824. *c=MRSOC;
  1825. c->isize = rounded_size;
  1826. c->header.size=rounded_size;
  1827. c->nae=nae;
  1828. /* No need to register chunks with no free_list_of_large
  1829. c->next=nae->chunk_list;
  1830. nae->chunk_list=c;
  1831. */
  1832. gc_add_into_gcmt((mch*)c);
  1833. r->header.size=size;
  1834. (r->header.magic_flag)=RSOH_UNMARKED;
  1835. ((void)memset((r+1),0,size-sizeof(rsoh)));
  1836. gc_update_ceils();
  1837. return (char*)(r+1);
  1838. }
  1839. else {
  1840. rsoc_malloc(nae);
  1841. gc_update_ceils();
  1842. return rso_from_store(nae,size);
  1843. }
  1844. }
  1845. static void gcna_align_mark(rsoc*c,void*o) {
  1846. na_env* nae = c->nae;
  1847. fll_rsoh* f;
  1848. fll_rsoh* pf;
  1849. char* b = (char*)&(c->first_header);
  1850. /* properly aligned ? */
  1851. if (((((char*)o)-((char*)c))%sizeof(int)) != 0) {
  1852. return;
  1853. }
  1854. /* already marked ? */
  1855. if ((((rsoh*)o)-1)->header.magic_flag != RSOH_UNMARKED) {
  1856. return;
  1857. }
  1858. if (((char*)o) < ((char*)(c+1))) {
  1859. return;
  1860. }
  1861. /* a large chunck ? */
  1862. if (c->header.size > RSOC_SIZE) {
  1863. if (o == (c+1)) {
  1864. nae->gc_mark((T0*)o);
  1865. }
  1866. return;
  1867. }
  1868. pf=NULL;
  1869. f=c->free_list_of_large;
  1870. while ((f != NULL) && (f < ((fll_rsoh*)o))) {
  1871. pf=f;
  1872. f=f->nextflol;
  1873. }
  1874. if (pf == NULL) {
  1875. pf=(fll_rsoh*)b;
  1876. }
  1877. while ((((rsoh*)pf)+1) < (rsoh*)o) {
  1878. pf = ((fll_rsoh*)(((char*)pf)+pf->rsoh_field.size));
  1879. }
  1880. if (o == (((rsoh*)pf)+1)) {
  1881. nae->gc_mark((T0*)o);
  1882. }
  1883. }
  1884. unsigned int rsocfl_count(void) {
  1885. /* Returns the number of items in the ReSizable Object Free List.
  1886. */
  1887. register unsigned int r=0;
  1888. register rsoc*p=rsocfl;
  1889. while (p!=NULL) {
  1890. r++;
  1891. p=p->next;
  1892. }
  1893. return r;
  1894. }
  1895. unsigned int fsocfl_count(void) {
  1896. register unsigned int r=0;
  1897. register fsoc*p=fsocfl;
  1898. while (p!=NULL) {
  1899. r++;
  1900. p=p->next;
  1901. }
  1902. return r;
  1903. }
  1904. void gc_dispose_before_exit(void) {
  1905. mch** p = gcmt;
  1906. mch**eogcmt=gcmt+gcmt_used;
  1907. while (p < eogcmt) {
  1908. if (((*p)->state_type == FSO_STORE_CHUNK) ||
  1909. ((*p)->state_type == FSO_USED_CHUNK)) {
  1910. ((*p)->swfp)(*p);
  1911. }
  1912. p++;
  1913. }
  1914. }
  1915. fsoc* gc_fsoc_get1(void) {
  1916. /* Get a `fsoc' (Fixed Size Object Chunk) from the free fsoc list or
  1917. allocate a new one (using `se_malloc') only when the ceil is not
  1918. yet reached. Otherwise, call the `gc_start()' function and
  1919. return NULL.
  1920. */
  1921. fsoc* result;
  1922. if (fsocfl != NULL) {
  1923. result = fsocfl;
  1924. fsocfl = fsocfl->next;
  1925. return result;
  1926. }
  1927. else if (fsoc_count_ceil > fsoc_count) {
  1928. result = ((fsoc*)se_malloc(FSOC_SIZE));
  1929. fsoc_count++;
  1930. gc_add_into_gcmt((mch*)result);
  1931. return result;
  1932. }
  1933. else {
  1934. gc_start();
  1935. return NULL;
  1936. }
  1937. }
  1938. fsoc* gc_fsoc_get2(void) {
  1939. /* Get a `fsoc' (Fixed Size Object Chunk) or force the allocation of a
  1940. new `fsoc' (using the `se_malloc' function). Update various ceils
  1941. accordingly.
  1942. */
  1943. fsoc* result;
  1944. if (fsocfl != NULL) {
  1945. result = fsocfl;
  1946. fsocfl=fsocfl->next;
  1947. return result;
  1948. }
  1949. else {
  1950. result = ((fsoc*)(se_malloc(FSOC_SIZE)));
  1951. fsoc_count++;
  1952. gc_update_ceils();
  1953. gc_add_into_gcmt((mch*)result);
  1954. return result;
  1955. }
  1956. }
  1957. #if defined(__sparc__) || defined(sparc) || defined(__sparc)
  1958. /* For SPARC architecture.
  1959. As this part contains assembly code (asm), you must not use
  1960. the flag -ansi of gcc compiler.
  1961. */
  1962. void mark_loop(void) {
  1963. void** max = stack_bottom;
  1964. void** stack_pointer;
  1965. void* stack_top[2]={NULL,NULL};
  1966. stack_pointer = stack_top;
  1967. /* Addresses decrease as the stack grows. */
  1968. while (stack_pointer <= max) {
  1969. gc_mark(*(stack_pointer++));
  1970. }
  1971. }
  1972. void mark_stack_and_registers(void) {
  1973. # if defined(__sparcv9)
  1974. asm(" flushw");
  1975. # else
  1976. asm(" ta 0x3 ! ST_FLUSH_WINDOWS");
  1977. # endif
  1978. mark_loop();
  1979. }
  1980. #elif defined(__ELATE__) || defined(ELATE)
  1981. /* GNU Eiffel's VP (Virtual Processor) garbage collector for Elate.
  1982. (c) 2000 Rudi Chiarito <rudi@amiga.com>
  1983. Thanks to Andy Stout and Kevin Croombs at Tao Group for their
  1984. precious help!
  1985. ChangeLog:
  1986. - 2000-06-12 Rudi Chiarito <rudi@amiga.com>
  1987. * Version 1.0
  1988. - 2001-01-01 Joseph Kiniry <kiniry@acm.org>
  1989. * Integrated with new SE 0.75b
  1990. - 2001-08-10 Rudi Chiarito <rudi@amiga.com>
  1991. * Inlined and optimised range marking
  1992. * Added some more comments
  1993. * Added conditional breakpoint in mark_stack_and_registers
  1994. - 2002-09-21 Rudi Chiarito <rudi@amiga.com>
  1995. * Removed redundant 'ret'
  1996. */
  1997. __inline__ void mark_stack_and_registers(void)
  1998. {
  1999. void *pointer_to_gc_mark = &gc_mark;
  2000. __asm__ __volatile__
  2001. (
  2002. /*
  2003. WARNING: funky code ahead!
  2004. \t and \n are needed to make the final output easier to read
  2005. while debugging. Hopefully you'll never have to bother with all
  2006. of this.
  2007. Registers:
  2008. p0 pointer to stack block
  2009. p1 pointer to gc_mark()
  2010. p2 scratch pointer
  2011. i0 length of current stack block
  2012. i1 scratch register
  2013. */
  2014. # ifdef __ELATE_SE_DEBUG_GC
  2015. "\tqcall sys/cii/breakpt,(-:-)\n"
  2016. # endif
  2017. "\tsync\n" /* spill all the registers */
  2018. "\tsyncreg\n" /* to the stack */
  2019. "\tcpy.p %0,p1\n" /* pointer to gc_mark() */
  2020. /* pointer to the current stack block */
  2021. "\tcpy.p [gp+PROC_STACK],p0\n"
  2022. /* point to last location in the block, before the descriptor */
  2023. "\tcpy.p p0 + ([(p0 - STK_SIZE) + STK_LENGTH] - STK_SIZE - 4),p2\n"
  2024. /* mark the contents of the current stack block */
  2025. "\twhile p2>=sp\n"
  2026. "\t\tgos p1,(p2 : -)\n"
  2027. "\t\tsub.p 4,p2\n"
  2028. "\tendwhile\n"
  2029. /* now scan other blocks (if any) */
  2030. "\tloop\n"
  2031. "\t\tcpy.p [p0 - STK_SIZE + STK_LINK],p0\n" /* get next block */
  2032. "\t\tbreakif p0=NULL\n"
  2033. /* point to last location in the block, before the descriptor */
  2034. "\t\tcpy.p p0 + ([(p0 - STK_SIZE) + STK_LENGTH] - STK_SIZE - 4),p2\n"
  2035. /* mark this block */
  2036. "\t\twhile p2>=p0\n"
  2037. "\t\t\tgos p1,(p2 : -)\n"
  2038. "\t\t\tsub.p 4,p2\n"
  2039. "\t\tendwhile\n"
  2040. "\tendloop\n"
  2041. : /* no output */
  2042. : "p" (pointer_to_gc_mark)
  2043. : "p0", "p1", "p2", "i0"
  2044. );
  2045. }
  2046. #elif defined(__hppa__) || defined(__hppa) || defined(__hp9000) || \
  2047. defined(__hp9000s300) || defined(hp9000s300) || \
  2048. defined(__hp9000s700) || defined(hp9000s700) || \
  2049. defined(__hp9000s800) || defined(hp9000s800) || defined(hp9000s820)
  2050. /****************************************************************************
  2051. * Generic code for architectures where addresses increase as the stack grows.
  2052. ****************************************************************************/
  2053. void mark_stack_and_registers(void){
  2054. void** max = stack_bottom;
  2055. JMP_BUF registers; /* The jmp_buf buffer is in the C stack. */
  2056. void**stack_pointer; /* Used to traverse the stack and registers assuming
  2057. that `setjmp' will save registers in the C stack.
  2058. */
  2059. (void)SETJMP(registers); /* To fill the C stack with registers. */
  2060. stack_pointer = (void**)(void*)(&registers) + ((sizeof(JMP_BUF)/sizeof(void*))-1);
  2061. /* stack_pointer will traverse the JMP_BUF as well (jmp_buf size is added,
  2062. otherwise stack_pointer would be below the registers structure). */
  2063. # if !defined(SE_BOOST)
  2064. if (stack_pointer < max) {
  2065. fprintf(stderr, "Wrong stack direction: your stack decrease as the stack grows (or complex stack management). Please drop an e-mail to SmartEiffel@loria.fr\n");
  2066. exit(1); }
  2067. # endif
  2068. while (stack_pointer >= max) {
  2069. gc_mark(*(stack_pointer--));
  2070. }
  2071. }
  2072. #else
  2073. /****************************************************************************
  2074. * Generic code for architectures where addresses decrease as the stack grows.
  2075. ****************************************************************************/
  2076. void mark_stack_and_registers(void){
  2077. void** max = stack_bottom;
  2078. JMP_BUF registers; /* The jmp_buf buffer is in the C stack. */
  2079. void**stack_pointer; /* Used to traverse the stack and registers assuming
  2080. that `setjmp' will save registers in the C stack.
  2081. */
  2082. (void)SETJMP(registers); /* To fill the C stack with registers. */
  2083. stack_pointer = (void**)(void*)(&registers);
  2084. # if !defined(SE_BOOST)
  2085. if (stack_pointer > max) {
  2086. fprintf(stderr, "Wrong stack direction: the stack addresses increase as the stack grows (or complex stack management). Please drop an e-mail to SmartEiffel@loria.fr\n");
  2087. exit(1); }
  2088. # endif
  2089. while (stack_pointer <= max) {
  2090. gc_mark(*(stack_pointer++));
  2091. }
  2092. }
  2093. #endif
  2094. unsigned int fsoc_count_ceil=40;
  2095. unsigned int rsoc_count_ceil=8;
  2096. /*COUNTER*/void r53increment(se_dump_stack*caller,T53* C){
  2097. static se_frame_descriptor fd={"increment"" COUNTER",1,0,"%R53%",1};
  2098. se_dump_stack ds;
  2099. ds.fd=&fd;
  2100. ds.current=(void*)&C;
  2101. ds.p=0x06A00C04/*l12c2/counter.e*/;
  2102. ds.caller=caller;
  2103. ds.locals=NULL;
  2104. ds.exception_origin=NULL;
  2105. set_dump_stack_top(&ds);/*link*/
  2106. ds.p=0x06A00F08/*l15c4/counter.e*/;
  2107. /*SFN*/(C->_value/*ip*/)=r2_ix_43(&ds,(/*RF2*/(C)->_value/*ip*/),/*IC*/(T2)(INT8_C(1)));
  2108. set_dump_stack_top(caller);/*unlink*/
  2109. }/*--*/
  2110. /*COUNTER*/void r53default_create(se_dump_stack*caller,T53* C){
  2111. static se_frame_descriptor fd={"default_create"" COUNTER",1,0,"%R53%",1};
  2112. se_dump_stack ds;
  2113. ds.fd=&fd;
  2114. ds.current=(void*)&C;
  2115. ds.p=0x01A00C04/*l12c2/any.e*/;
  2116. ds.caller=caller;
  2117. ds.locals=NULL;
  2118. ds.exception_origin=NULL;
  2119. set_dump_stack_top(&ds);/*link*/
  2120. set_dump_stack_top(caller);/*unlink*/
  2121. }/*--*/
  2122. /*STD_OUTPUT*/T6 r49can_put_character(se_dump_stack*caller,T49* C,T3 a1){
  2123. T6 R=0;
  2124. void**locals[2];
  2125. static se_frame_descriptor fd={"can_put_character"" STD_OUTPUT",1,2,"%R49%c%E3%Result%E6%",1};
  2126. se_dump_stack ds;
  2127. ds.fd=&fd;
  2128. ds.current=(void*)&C;
  2129. ds.p=0x05001104/*l17c2/terminal_output_stream.e*/;
  2130. ds.caller=caller;
  2131. ds.locals=locals;
  2132. ds.exception_origin=NULL;
  2133. locals[0]=(void**)&a1;
  2134. locals[1]=(void**)&R;
  2135. set_dump_stack_top(&ds);/*link*/
  2136. ds.p=0x05001308/*l19c4/terminal_output_stream.e*/;
  2137. R=((T6)(1));
  2138. set_dump_stack_top(caller);/*unlink*/
  2139. return R;
  2140. }/*--*/
  2141. /*STD_OUTPUT*/void r49put_new_line(se_dump_stack*caller,T49* C){
  2142. static se_frame_descriptor fd={"put_new_line"" STD_OUTPUT",1,0,"%R49%",1};
  2143. se_dump_stack ds;
  2144. ds.fd=&fd;
  2145. ds.current=(void*)&C;
  2146. ds.p=0x04010604/*l262c2/output_stream_tools.e*/;
  2147. ds.caller=caller;
  2148. ds.locals=NULL;
  2149. ds.exception_origin=NULL;
  2150. set_dump_stack_top(&ds);/*link*/
  2151. if(fd.assertion_flag){
  2152. fd.assertion_flag=0;
  2153. ds.p=0x04010908/*l265c4/output_stream_tools.e*/;
  2154. ac_req(/*RF1is_connected*/1,"is_connected");
  2155. ds.p=0x04010A08/*l266c4/output_stream_tools.e*/;
  2156. ac_req(r6_px_not(&ds,(T6)(r49is_filtered(&ds,C))),"not is_filtered");
  2157. fd.assertion_flag=1;
  2158. }
  2159. ds.p=0x04010C08/*l268c4/output_stream_tools.e*/;
  2160. r49put_character(&ds,C,((T3)'\n'));
  2161. set_dump_stack_top(caller);/*unlink*/
  2162. }/*--*/
  2163. /*STD_OUTPUT*/void r49dispose(se_dump_stack*caller,T49* C){
  2164. static se_frame_descriptor fd={"dispose"" STD_OUTPUT",1,0,"%R49%",1};
  2165. se_dump_stack ds;
  2166. ds.fd=&fd;
  2167. ds.current=(void*)&C;
  2168. ds.p=0x06209004/*l144c2/std_output.e*/;
  2169. ds.caller=caller;
  2170. ds.locals=NULL;
  2171. ds.exception_origin=NULL;
  2172. set_dump_stack_top(&ds);/*link*/
  2173. set_dump_stack_top(caller);/*unlink*/
  2174. }/*--*/
  2175. T0*oBC13std_output=(void*)0;
  2176. int fBC13std_output=0;
  2177. /*STD_OUTPUT*/T0* r49std_output(se_dump_stack*caller,T49* C){
  2178. /*[INTERNAL_C_LOCAL list*/
  2179. T0* tmp0;
  2180. /*INTERNAL_C_LOCAL list]*/
  2181. void**locals[1];
  2182. static se_frame_descriptor fd={"std_output"" STD_OUTPUT",1,1,"%R49%Result%R49%",1};
  2183. se_dump_stack ds;
  2184. ds.fd=&fd;
  2185. ds.current=(void*)&C;
  2186. ds.p=0x01A0B104/*l177c2/any.e*/;
  2187. ds.caller=caller;
  2188. ds.locals=locals;
  2189. ds.exception_origin=NULL;
  2190. locals[0]=(void**)&oBC13std_output;
  2191. set_dump_stack_top(&ds);/*link*/
  2192. if(fBC13std_output==0){fBC13std_output=1;{
  2193. tmp0/*new*/=((T0*)(new49()));
  2194. r49make(&ds,((T49*)tmp0/*new*/));
  2195. oBC13std_output=tmp0/*new*/;
  2196. /*tmp0.unlock*/
  2197. }
  2198. fBC13std_output=2;}
  2199. else{
  2200. ac_req(fBC13std_output==2, "Recursive once function.");
  2201. }
  2202. set_dump_stack_top(caller);/*unlink*/
  2203. return oBC13std_output;
  2204. }/*--*/
  2205. /*STD_OUTPUT*/void r49filtered_flush(se_dump_stack*caller,T49* C){
  2206. static se_frame_descriptor fd={"filtered_flush"" STD_OUTPUT",1,0,"%R49%",1};
  2207. se_dump_stack ds;
  2208. ds.fd=&fd;
  2209. ds.current=(void*)&C;
  2210. ds.p=0x06203904/*l57c2/std_output.e*/;
  2211. ds.caller=caller;
  2212. ds.locals=NULL;
  2213. ds.exception_origin=NULL;
  2214. set_dump_stack_top(&ds);/*link*/
  2215. if(fd.assertion_flag){
  2216. fd.assertion_flag=0;
  2217. ds.p=0x03603A08/*l58c4/output_stream.e*/;
  2218. ac_req(/*RF1is_connected*/1,"is_connected");
  2219. fd.assertion_flag=1;
  2220. }
  2221. ds.p=0x06203B2E/*l59c23/std_output.e*/;
  2222. if(r2_ix_62(&ds,(/*RF2*/(C)->_buffer_position/*i4p*/),/*IC*/(T2)(INT8_C(0)))){
  2223. ds.p=0x06203C0A/*l60c5/std_output.e*/;
  2224. r49write_buffer(&ds,C);
  2225. }
  2226. ds.p=0x06203E08/*l62c4/std_output.e*/;
  2227. io_flush(stdout);
  2228. set_dump_stack_top(caller);/*unlink*/
  2229. }/*--*/
  2230. /*STD_OUTPUT*/void r49filtered_put_character(se_dump_stack*caller,T49* C,T3 a1){
  2231. void**locals[1];
  2232. static se_frame_descriptor fd={"filtered_put_character"" STD_OUTPUT",1,1,"%R49%c%E3%",1};
  2233. se_dump_stack ds;
  2234. ds.fd=&fd;
  2235. ds.current=(void*)&C;
  2236. ds.p=0x06202D04/*l45c2/std_output.e*/;
  2237. ds.caller=caller;
  2238. ds.locals=locals;
  2239. ds.exception_origin=NULL;
  2240. locals[0]=(void**)&a1;
  2241. set_dump_stack_top(&ds);/*link*/
  2242. if(fd.assertion_flag){
  2243. fd.assertion_flag=0;
  2244. ds.p=0x03603308/*l51c4/output_stream.e*/;
  2245. ac_req(/*RF1is_connected*/1,"is_connected");
  2246. ds.p=0x03603408/*l52c4/output_stream.e*/;
  2247. ac_req(r49can_put_character(&ds,C,a1),"can_put_character(c)");
  2248. fd.assertion_flag=1;
  2249. }
  2250. ds.p=0x06202F2E/*l47c23/std_output.e*/;
  2251. if(r2_ix_6261(&ds,(/*RF2*/(C)->_buffer_position/*i4p*/),/*IC*/(T2)(INT16_C(4096)))){
  2252. ds.p=0x0620300A/*l48c5/std_output.e*/;
  2253. r49write_buffer(&ds,C);
  2254. }
  2255. ds.p=0x06203216/*l50c11/std_output.e*/;
  2256. r9put(&ds,(/*RF2*/(C)->_buffer/*i4p*/),a1,(/*RF2*/(C)->_buffer_position/*i4p*/));
  2257. ds.p=0x06203308/*l51c4/std_output.e*/;