Changeset 331 for EcnlProtoTool/trunk/mruby-1.3.0/src/gc.c
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-1.3.0
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-1.3.0/src/gc.c
r321 r331 7 7 #include <string.h> 8 8 #include <stdlib.h> 9 #include "mruby.h" 10 #include "mruby/array.h" 11 #include "mruby/class.h" 12 #include "mruby/data.h" 13 #include "mruby/hash.h" 14 #include "mruby/proc.h" 15 #include "mruby/range.h" 16 #include "mruby/string.h" 17 #include "mruby/variable.h" 18 #include "mruby/gc.h" 19 #include "mruby/error.h" 9 #include <mruby.h> 10 #include <mruby/array.h> 11 #include <mruby/class.h> 12 #include <mruby/data.h> 13 #include <mruby/hash.h> 14 #include <mruby/proc.h> 15 #include <mruby/range.h> 16 #include <mruby/string.h> 17 #include <mruby/variable.h> 18 #include <mruby/gc.h> 19 #include <mruby/error.h> 20 #include <mruby/throw.h> 20 21 21 22 /* … … 66 67 mruby implementer and C extension library writer must insert a write 67 68 barrier when updating a reference from a field of an object. 68 When updating a reference from a field of object A to object B, 69 When updating a reference from a field of object A to object B, 69 70 two different types of write barrier are available: 70 71 … … 110 111 struct RData data; 111 112 struct RProc proc; 113 struct REnv env; 112 114 struct RException exc; 115 struct RBreak brk; 113 116 #ifdef MRB_WORD_BOXING 114 117 struct RFloat floatv; … … 138 141 fprintf(stderr, "gc_invoke: %19.3f\n", gettimeofday_time() - program_invoke_time);\ 139 142 fprintf(stderr, "is_generational: %d\n", is_generational(gc));\ 140 fprintf(stderr, "is_major_gc: %d\n", is_major_gc( mrb));\143 fprintf(stderr, "is_major_gc: %d\n", is_major_gc(gc));\ 141 144 } while(0) 142 145 … … 214 217 215 218 p2 = mrb_realloc_simple(mrb, p, len); 216 if (!p2 && len) { 219 if (len == 0) return p2; 220 if (p2 == NULL) { 217 221 if (mrb->gc.out_of_memory) { 222 mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); 218 223 /* mrb_panic(mrb); */ 219 224 } … … 367 372 } 368 373 369 static void obj_free(mrb_state *mrb, struct RBasic *obj );374 static void obj_free(mrb_state *mrb, struct RBasic *obj, int end); 370 375 371 376 void … … 381 386 for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) { 382 387 if (p->as.free.tt != MRB_TT_FREE) 383 obj_free(mrb, &p->as.basic );388 obj_free(mrb, &p->as.basic, TRUE); 384 389 } 385 390 mrb_free(mrb, tmp); … … 403 408 /* arena overflow error */ 404 409 gc->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */ 405 mrb_ raise(mrb, E_RUNTIME_ERROR, "arena overflow error");410 mrb_exc_raise(mrb, mrb_obj_value(mrb->arena_err)); 406 411 } 407 412 #else … … 429 434 Register your object when it's exported to C world, 430 435 without reference from Ruby world, e.g. callback 431 arguments. Don't forget to remove the ob ejct using436 arguments. Don't forget to remove the object using 432 437 mrb_gc_unregister, otherwise your object will leak. 433 438 */ … … 453 458 mrb_value table = mrb_gv_get(mrb, root); 454 459 struct RArray *a; 455 mrb_int i , j;460 mrb_int i; 456 461 457 462 if (mrb_nil_p(table)) return; … … 462 467 a = mrb_ary_ptr(table); 463 468 mrb_ary_modify(mrb, a); 464 for (i=j=0; i<a->len; i++) { 465 if (!mrb_obj_eq(mrb, a->ptr[i], obj)) { 466 a->ptr[j++] = a->ptr[i]; 467 } 468 } 469 a->len = j; 469 for (i = 0; i < a->len; i++) { 470 if (mrb_obj_eq(mrb, a->ptr[i], obj)) { 471 a->len--; 472 memmove(&a->ptr[i], &a->ptr[i + 1], (a->len - i) * sizeof(a->ptr[i])); 473 break; 474 } 475 } 470 476 } 471 477 … … 476 482 static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; 477 483 mrb_gc *gc = &mrb->gc; 484 485 if (cls) { 486 enum mrb_vtype tt; 487 488 switch (cls->tt) { 489 case MRB_TT_CLASS: 490 case MRB_TT_SCLASS: 491 case MRB_TT_MODULE: 492 case MRB_TT_ENV: 493 break; 494 default: 495 mrb_raise(mrb, E_TYPE_ERROR, "allocation failure"); 496 } 497 tt = MRB_INSTANCE_TT(cls); 498 if (tt != MRB_TT_FALSE && 499 ttype != MRB_TT_SCLASS && 500 ttype != MRB_TT_ICLASS && 501 ttype != MRB_TT_ENV && 502 ttype != tt) { 503 mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %S", mrb_obj_value(cls)); 504 } 505 } 478 506 479 507 #ifdef MRB_GC_STRESS … … 520 548 size_t i; 521 549 size_t e; 522 550 mrb_value nil; 551 int nregs; 552 553 if (c->stack == NULL) return; 523 554 e = c->stack - c->stbase; 524 if (c->ci) e += c->ci->nregs; 555 if (c->ci) { 556 nregs = c->ci->argc + 2; 557 if (c->ci->nregs > nregs) 558 nregs = c->ci->nregs; 559 e += nregs; 560 } 525 561 if (c->stbase + e > c->stend) e = c->stend - c->stbase; 526 562 for (i=0; i<e; i++) { … … 528 564 529 565 if (!mrb_immediate_p(v)) { 530 if (mrb_basic_ptr(v)->tt == MRB_TT_FREE) {531 c->stbase[i] = mrb_nil_value();532 533 else {534 mrb_gc_mark(mrb, mrb_basic_ptr(v));535 }536 }566 mrb_gc_mark(mrb, mrb_basic_ptr(v)); 567 } 568 } 569 e = c->stend - c->stbase; 570 nil = mrb_nil_value(); 571 for (; i<e; i++) { 572 c->stbase[i] = nil; 537 573 } 538 574 } … … 541 577 mark_context(mrb_state *mrb, struct mrb_context *c) 542 578 { 543 int i , e = 0;579 int i; 544 580 mrb_callinfo *ci; 545 581 546 /* mark stack */582 /* mark VM stack */ 547 583 mark_context_stack(mrb, c); 548 584 549 /* mark VMstack */585 /* mark call stack */ 550 586 if (c->cibase) { 551 587 for (ci = c->cibase; ci <= c->ci; ci++) { 552 if (ci->eidx > e) {553 e = ci->eidx;554 }555 588 mrb_gc_mark(mrb, (struct RBasic*)ci->env); 556 589 mrb_gc_mark(mrb, (struct RBasic*)ci->proc); … … 559 592 } 560 593 /* mark ensure stack */ 561 for (i=0; i<e; i++) { 594 for (i=0; i<c->esize; i++) { 595 if (c->ensure[i] == NULL) break; 562 596 mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]); 563 597 } 564 598 /* mark fibers */ 565 if (c->prev && c->prev->fib) { 566 mrb_gc_mark(mrb, (struct RBasic*)c->prev->fib); 599 mrb_gc_mark(mrb, (struct RBasic*)c->fib); 600 if (c->prev) { 601 mark_context(mrb, c->prev); 567 602 } 568 603 } … … 614 649 { 615 650 struct REnv *e = (struct REnv*)obj; 616 617 if (!MRB_ENV_STACK_SHARED_P(e)) { 618 mrb_int i, len; 619 620 len = MRB_ENV_STACK_LEN(e); 621 for (i=0; i<len; i++) { 622 mrb_gc_mark_value(mrb, e->stack[i]); 651 mrb_int i, len; 652 653 if (MRB_ENV_STACK_SHARED_P(e)) { 654 if (e->cxt.c->fib) { 655 mrb_gc_mark(mrb, (struct RBasic*)e->cxt.c->fib); 623 656 } 657 break; 658 } 659 len = MRB_ENV_STACK_LEN(e); 660 for (i=0; i<len; i++) { 661 mrb_gc_mark_value(mrb, e->stack[i]); 624 662 } 625 663 } … … 679 717 680 718 static void 681 obj_free(mrb_state *mrb, struct RBasic *obj )682 { 683 DEBUG( printf("obj_free(%p,tt=%d)\n",obj,obj->tt));719 obj_free(mrb_state *mrb, struct RBasic *obj, int end) 720 { 721 DEBUG(fprintf(stderr, "obj_free(%p,tt=%d)\n",obj,obj->tt)); 684 722 switch (obj->tt) { 685 723 /* immediate - no mark */ … … 698 736 699 737 case MRB_TT_OBJECT: 738 mrb_gc_free_iv(mrb, (struct RObject*)obj); 739 break; 740 700 741 case MRB_TT_EXCEPTION: 701 742 mrb_gc_free_iv(mrb, (struct RObject*)obj); … … 716 757 struct REnv *e = (struct REnv*)obj; 717 758 718 if ( !MRB_ENV_STACK_SHARED_P(e)) {719 mrb_free(mrb, e->stack);720 e->stack = NULL;759 if (MRB_ENV_STACK_SHARED_P(e)) { 760 /* cannot be freed */ 761 return; 721 762 } 763 mrb_free(mrb, e->stack); 764 e->stack = NULL; 722 765 } 723 766 break; … … 727 770 struct mrb_context *c = ((struct RFiber*)obj)->cxt; 728 771 729 if (c != mrb->root_c) 772 if (!end && c && c != mrb->root_c) { 773 mrb_callinfo *ci = c->ci; 774 mrb_callinfo *ce = c->cibase; 775 776 while (ce <= ci) { 777 struct REnv *e = ci->env; 778 if (e && !is_dead(&mrb->gc, e) && 779 e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) { 780 mrb_env_unshare(mrb, e); 781 } 782 ci--; 783 } 730 784 mrb_free_context(mrb, c); 785 } 731 786 } 732 787 break; … … 781 836 root_scan_phase(mrb_state *mrb, mrb_gc *gc) 782 837 { 783 size_t i, e;838 int i, e; 784 839 785 840 if (!is_minor_gc(gc)) { … … 795 850 /* mark class hierarchy */ 796 851 mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class); 852 853 /* mark built-in classes */ 854 mrb_gc_mark(mrb, (struct RBasic*)mrb->class_class); 855 mrb_gc_mark(mrb, (struct RBasic*)mrb->module_class); 856 mrb_gc_mark(mrb, (struct RBasic*)mrb->proc_class); 857 mrb_gc_mark(mrb, (struct RBasic*)mrb->string_class); 858 mrb_gc_mark(mrb, (struct RBasic*)mrb->array_class); 859 mrb_gc_mark(mrb, (struct RBasic*)mrb->hash_class); 860 861 mrb_gc_mark(mrb, (struct RBasic*)mrb->float_class); 862 mrb_gc_mark(mrb, (struct RBasic*)mrb->fixnum_class); 863 mrb_gc_mark(mrb, (struct RBasic*)mrb->true_class); 864 mrb_gc_mark(mrb, (struct RBasic*)mrb->false_class); 865 mrb_gc_mark(mrb, (struct RBasic*)mrb->nil_class); 866 mrb_gc_mark(mrb, (struct RBasic*)mrb->symbol_class); 867 mrb_gc_mark(mrb, (struct RBasic*)mrb->kernel_module); 868 869 mrb_gc_mark(mrb, (struct RBasic*)mrb->eException_class); 870 mrb_gc_mark(mrb, (struct RBasic*)mrb->eStandardError_class); 871 797 872 /* mark top_self */ 798 873 mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); … … 801 876 /* mark pre-allocated exception */ 802 877 mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); 803 804 mark_context(mrb, mrb->root_c); 805 if (mrb->root_c->fib) { 806 mrb_gc_mark(mrb, (struct RBasic*)mrb->root_c->fib); 807 } 878 mrb_gc_mark(mrb, (struct RBasic*)mrb->stack_err); 879 #ifdef MRB_GC_FIXED_ARENA 880 mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err); 881 #endif 882 883 mark_context(mrb, mrb->c); 808 884 if (mrb->root_c != mrb->c) { 809 mark_context(mrb, mrb-> c);885 mark_context(mrb, mrb->root_c); 810 886 } 811 887 } … … 859 935 860 936 /* mark ensure stack */ 861 children += (c->ci) ? c->ci->eidx : 0;937 children += c->eidx; 862 938 863 939 /* mark closure */ … … 920 996 final_marking_phase(mrb_state *mrb, mrb_gc *gc) 921 997 { 922 mark_context_stack(mrb, mrb->root_c); 998 int i, e; 999 1000 /* mark arena */ 1001 for (i=0,e=gc->arena_idx; i<e; i++) { 1002 mrb_gc_mark(mrb, gc->arena[i]); 1003 } 1004 mrb_gc_mark_gv(mrb); 1005 mark_context(mrb, mrb->c); 1006 mark_context(mrb, mrb->root_c); 1007 mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); 923 1008 gc_mark_gray_list(mrb, gc); 924 1009 mrb_assert(gc->gray_list == NULL); … … 958 1043 if (is_dead(gc, &p->as.basic)) { 959 1044 if (p->as.basic.tt != MRB_TT_FREE) { 960 obj_free(mrb, &p->as.basic); 961 p->as.free.next = page->freelist; 962 page->freelist = (struct RBasic*)p; 963 freed++; 1045 obj_free(mrb, &p->as.basic, FALSE); 1046 if (p->as.basic.tt == MRB_TT_FREE) { 1047 p->as.free.next = page->freelist; 1048 page->freelist = (struct RBasic*)p; 1049 freed++; 1050 } 1051 else { 1052 dead_slot = FALSE; 1053 } 964 1054 } 965 1055 } … … 967 1057 if (!is_generational(gc)) 968 1058 paint_partial_white(gc, &p->as.basic); /* next gc target */ 969 dead_slot = 0;1059 dead_slot = FALSE; 970 1060 } 971 1061 p++; … … 1080 1170 mrb_gc *gc = &mrb->gc; 1081 1171 1082 if (gc->disabled ) return;1172 if (gc->disabled || gc->iterating) return; 1083 1173 1084 1174 GC_INVOKE_TIME_REPORT("mrb_incremental_gc()"); … … 1120 1210 mrb_gc *gc = &mrb->gc; 1121 1211 1122 if (gc->disabled ) return;1212 if (gc->disabled || gc->iterating) return; 1123 1213 1124 1214 GC_INVOKE_TIME_REPORT("mrb_full_gc()"); … … 1357 1447 change_gen_gc_mode(mrb_state *mrb, mrb_gc *gc, mrb_bool enable) 1358 1448 { 1449 if (gc->disabled || gc->iterating) { 1450 mrb_raise(mrb, E_RUNTIME_ERROR, "generational mode changed when GC disabled"); 1451 return; 1452 } 1359 1453 if (is_generational(gc) && !enable) { 1360 1454 clear_all_old(mrb, gc); … … 1408 1502 gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, void *data) 1409 1503 { 1410 mrb_heap_page* page = gc->heaps; 1411 1504 mrb_heap_page* page; 1505 1506 page = gc->heaps; 1412 1507 while (page != NULL) { 1413 RVALUE *p, *pend; 1508 RVALUE *p; 1509 int i; 1414 1510 1415 1511 p = objects(page); 1416 pend = p + MRB_HEAP_PAGE_SIZE; 1417 for (;p < pend; p++) { 1418 (*callback)(mrb, &p->as.basic, data); 1419 } 1420 1512 for (i=0; i < MRB_HEAP_PAGE_SIZE; i++) { 1513 if ((*callback)(mrb, &p[i].as.basic, data) == MRB_EACH_OBJ_BREAK) 1514 return; 1515 } 1421 1516 page = page->next; 1422 1517 } … … 1426 1521 mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data) 1427 1522 { 1428 gc_each_objects(mrb, &mrb->gc, callback, data); 1523 mrb_bool iterating = mrb->gc.iterating; 1524 1525 mrb->gc.iterating = TRUE; 1526 if (iterating) { 1527 gc_each_objects(mrb, &mrb->gc, callback, data); 1528 } 1529 else { 1530 struct mrb_jmpbuf *prev_jmp = mrb->jmp; 1531 struct mrb_jmpbuf c_jmp; 1532 1533 MRB_TRY(&c_jmp) { 1534 mrb->jmp = &c_jmp; 1535 gc_each_objects(mrb, &mrb->gc, callback, data); 1536 mrb->jmp = prev_jmp; 1537 mrb->gc.iterating = iterating; 1538 } MRB_CATCH(&c_jmp) { 1539 mrb->gc.iterating = iterating; 1540 mrb->jmp = prev_jmp; 1541 MRB_THROW(prev_jmp); 1542 } MRB_END_EXC(&c_jmp); 1543 } 1429 1544 } 1430 1545
Note:
See TracChangeset
for help on using the changeset viewer.