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