aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-03-15 11:01:34 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-03-15 11:01:34 -0300
commit3823fc6c814d20f2b2a0a1e3be8782084440040f (patch)
treecb9b5ef3919dea45cb917ad79cc23c74a3c87681 /lgc.c
parent52aa2b5d24c560fb4d7a642971571ff9cbeabfcd (diff)
downloadlua-3823fc6c814d20f2b2a0a1e3be8782084440040f.tar.gz
lua-3823fc6c814d20f2b2a0a1e3be8782084440040f.tar.bz2
lua-3823fc6c814d20f2b2a0a1e3be8782084440040f.zip
Added "bulk operations" to arrays
A few operations on arrays can be performed "in bulk", treating all tags of a cell as a simple (or a few) word(s).
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c59
1 files changed, 42 insertions, 17 deletions
diff --git a/lgc.c b/lgc.c
index f813038f..f76e851e 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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*/
473static 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*/
489static 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*/
480static int traverseephemeron (global_State *g, Table *h, int inv) { 520static 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
524static void traversestrongtable (global_State *g, Table *h) { 555static 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 */