diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 59 |
1 files changed, 42 insertions, 17 deletions
@@ -465,6 +465,46 @@ static void traverseweakvalue (global_State *g, Table *h) { | |||
465 | } | 465 | } |
466 | 466 | ||
467 | 467 | ||
468 | #define BK2(x) cast(lua_Unsigned, ((x) << 8) | BIT_ISCOLLECTABLE) | ||
469 | /* | ||
470 | ** Check whether some value in the cell starting at index 'i' | ||
471 | ** is collectable | ||
472 | */ | ||
473 | static int checkBulkCollectable (Table *h, unsigned i) { | ||
474 | const lua_Unsigned bitscoll = BK2(BK2(BK2(BK2(BK2(BK2(BK2(BK2(~0u)))))))); | ||
475 | int j; | ||
476 | i /= NM; | ||
477 | for (j = 0; j < BKSZ; j++) { | ||
478 | if (h->array[i].u.bulk[j] & bitscoll) | ||
479 | return 1; | ||
480 | } | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | |||
485 | /* | ||
486 | ** Traverse the array part of a table. The traversal is made by cells, | ||
487 | ** only traversing a cell if it has some collectable tag among its tags. | ||
488 | */ | ||
489 | static int traversearray (global_State *g, Table *h) { | ||
490 | unsigned asize = luaH_realasize(h); | ||
491 | int marked = 0; /* true if some object is marked in this traversal */ | ||
492 | unsigned i; | ||
493 | for (i = 0; i < asize; i += NM) { /* traverse array in cells */ | ||
494 | if (checkBulkCollectable(h, i)) { /* something to mark in this cell? */ | ||
495 | unsigned j; | ||
496 | for (j = 0; j < NM && i + j < asize; j++) { | ||
497 | GCObject *o = gcvalarr(h, i + j); | ||
498 | if (o != NULL && iswhite(o)) { | ||
499 | marked = 1; | ||
500 | reallymarkobject(g, o); | ||
501 | } | ||
502 | } | ||
503 | } | ||
504 | } | ||
505 | return marked; | ||
506 | } | ||
507 | |||
468 | /* | 508 | /* |
469 | ** Traverse an ephemeron table and link it to proper list. Returns true | 509 | ** Traverse an ephemeron table and link it to proper list. Returns true |
470 | ** iff any object was marked during this traversal (which implies that | 510 | ** iff any object was marked during this traversal (which implies that |
@@ -478,20 +518,11 @@ static void traverseweakvalue (global_State *g, Table *h) { | |||
478 | ** by 'genlink'. | 518 | ** by 'genlink'. |
479 | */ | 519 | */ |
480 | static int traverseephemeron (global_State *g, Table *h, int inv) { | 520 | static int traverseephemeron (global_State *g, Table *h, int inv) { |
481 | int marked = 0; /* true if an object is marked in this traversal */ | ||
482 | int hasclears = 0; /* true if table has white keys */ | 521 | int hasclears = 0; /* true if table has white keys */ |
483 | int hasww = 0; /* true if table has entry "white-key -> white-value" */ | 522 | int hasww = 0; /* true if table has entry "white-key -> white-value" */ |
484 | unsigned int i; | 523 | unsigned int i; |
485 | unsigned int asize = luaH_realasize(h); | ||
486 | unsigned int nsize = sizenode(h); | 524 | unsigned int nsize = sizenode(h); |
487 | /* traverse array part */ | 525 | int marked = traversearray(g, h); /* traverse array part */ |
488 | for (i = 0; i < asize; i++) { | ||
489 | GCObject *o = gcvalarr(h, i); | ||
490 | if (o != NULL && iswhite(o)) { | ||
491 | marked = 1; | ||
492 | reallymarkobject(g, o); | ||
493 | } | ||
494 | } | ||
495 | /* traverse hash part; if 'inv', traverse descending | 526 | /* traverse hash part; if 'inv', traverse descending |
496 | (see 'convergeephemerons') */ | 527 | (see 'convergeephemerons') */ |
497 | for (i = 0; i < nsize; i++) { | 528 | for (i = 0; i < nsize; i++) { |
@@ -523,13 +554,7 @@ static int traverseephemeron (global_State *g, Table *h, int inv) { | |||
523 | 554 | ||
524 | static void traversestrongtable (global_State *g, Table *h) { | 555 | static void traversestrongtable (global_State *g, Table *h) { |
525 | Node *n, *limit = gnodelast(h); | 556 | Node *n, *limit = gnodelast(h); |
526 | unsigned int i; | 557 | traversearray(g, h); |
527 | unsigned int asize = luaH_realasize(h); | ||
528 | for (i = 0; i < asize; i++) { /* traverse array part */ | ||
529 | GCObject *o = gcvalarr(h, i); | ||
530 | if (o != NULL && iswhite(o)) | ||
531 | reallymarkobject(g, o); | ||
532 | } | ||
533 | for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ | 558 | for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ |
534 | if (isempty(gval(n))) /* entry is empty? */ | 559 | if (isempty(gval(n))) /* entry is empty? */ |
535 | clearkey(n); /* clear its key */ | 560 | clearkey(n); /* clear its key */ |