aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-01 13:21:00 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-01 13:21:00 -0300
commite8c779736f3029df353038352c14c8ab63728811 (patch)
tree23f75fa455ec333677650198cd889b187228b735 /lgc.c
parent2fc6b55dae7a120b4272ca0e9c356d1f96053bd9 (diff)
downloadlua-e8c779736f3029df353038352c14c8ab63728811.tar.gz
lua-e8c779736f3029df353038352c14c8ab63728811.tar.bz2
lua-e8c779736f3029df353038352c14c8ab63728811.zip
Removed internal cache for closures
The mechanism of "caching the last closure created for a prototype to try to reuse it the next time a closure for that prototype is created" was removed. There are several reasons: - It is hard to find a natural example where this cache has a measurable impact on performance. - Programmers already perceive closure creation as something slow, so they tend to avoid it inside hot paths. (Any case where the cache could reuse a closure can be rewritten predefining the closure in some variable and using that variable.) - The implementation was somewhat complex, due to a bad interaction with the generational collector. (Typically, new closures are new, while prototypes are old. So, the cache breaks the invariant that old objects should not point to new ones.)
Diffstat (limited to '')
-rw-r--r--lgc.c64
1 files changed, 1 insertions, 63 deletions
diff --git a/lgc.c b/lgc.c
index 9d196a18..95a8ad5b 100644
--- a/lgc.c
+++ b/lgc.c
@@ -221,27 +221,6 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
221} 221}
222 222
223 223
224/*
225** Barrier for prototype's cache of closures. It turns the prototype
226** back to gray (it was black). For an 'OLD1' prototype, making it
227** gray stops it from being visited by 'markold', so it is linked in
228** the 'grayagain' list to ensure it will be visited. For other ages,
229** it goes to the 'protogray' list, as only its 'cache' field needs to
230** be revisited. (A prototype to be in this barrier must be already
231** finished, so its other fields cannot change and do not need to be
232** revisited.)
233*/
234LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p) {
235 global_State *g = G(L);
236 lua_assert(g->gckind != KGC_GEN || isold(p));
237 if (getage(p) == G_OLD1) /* still need to be visited? */
238 linkgclist(p, g->grayagain); /* link it in 'grayagain' */
239 else
240 linkgclist(p, g->protogray); /* link it in 'protogray' */
241 black2gray(p); /* make prototype gray */
242}
243
244
245void luaC_fix (lua_State *L, GCObject *o) { 224void luaC_fix (lua_State *L, GCObject *o) {
246 global_State *g = G(L); 225 global_State *g = G(L);
247 lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ 226 lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
@@ -379,7 +358,7 @@ static int remarkupvals (global_State *g) {
379*/ 358*/
380static void restartcollection (global_State *g) { 359static void restartcollection (global_State *g) {
381 g->gray = g->grayagain = NULL; 360 g->gray = g->grayagain = NULL;
382 g->weak = g->allweak = g->ephemeron = g->protogray = NULL; 361 g->weak = g->allweak = g->ephemeron = NULL;
383 markobject(g, g->mainthread); 362 markobject(g, g->mainthread);
384 markvalue(g, &g->l_registry); 363 markvalue(g, &g->l_registry);
385 markmt(g); 364 markmt(g);
@@ -535,39 +514,12 @@ static int traverseudata (global_State *g, Udata *u) {
535 514
536 515
537/* 516/*
538** Check the cache of a prototype, to keep invariants. If the
539** cache is white, clear it. (A cache should not prevent the
540** collection of its reference.) Otherwise, if in generational
541** mode, check the generational invariant. If the cache is old,
542** everything is ok. If the prototype is 'OLD0', everything
543** is ok too. (It will naturally be visited again.) If the
544** prototype is older than 'OLD0', then its cache (which is new)
545** must be visited again in the next collection, so the prototype
546** goes to the 'protogray' list. (If the prototype has a cache,
547** it is already immutable and does not need other barriers;
548** then, it can become gray without problems for its other fields.)
549*/
550static void checkprotocache (global_State *g, Proto *p) {
551 if (p->cache) {
552 if (iswhite(p->cache))
553 p->cache = NULL; /* allow cache to be collected */
554 else if (g->gckind == KGC_GEN && !isold(p->cache) && getage(p) >= G_OLD1) {
555 linkgclist(p, g->protogray); /* link it in 'protogray' */
556 black2gray(p); /* make prototype gray */
557 }
558 }
559 p->cachemiss = 0; /* restart counting */
560}
561
562
563/*
564** Traverse a prototype. (While a prototype is being build, its 517** Traverse a prototype. (While a prototype is being build, its
565** arrays can be larger than needed; the extra slots are filled with 518** arrays can be larger than needed; the extra slots are filled with
566** NULL, so the use of 'markobjectN') 519** NULL, so the use of 'markobjectN')
567*/ 520*/
568static int traverseproto (global_State *g, Proto *f) { 521static int traverseproto (global_State *g, Proto *f) {
569 int i; 522 int i;
570 checkprotocache(g, f);
571 markobjectN(g, f->source); 523 markobjectN(g, f->source);
572 for (i = 0; i < f->sizek; i++) /* mark literals */ 524 for (i = 0; i < f->sizek; i++) /* mark literals */
573 markvalue(g, &f->k[i]); 525 markvalue(g, &f->k[i]);
@@ -696,19 +648,6 @@ static void convergeephemerons (global_State *g) {
696** ======================================================= 648** =======================================================
697*/ 649*/
698 650
699static void clearprotolist (global_State *g) {
700 GCObject *p = g->protogray;
701 g->protogray = NULL;
702 while (p != NULL) {
703 Proto *pp = gco2p(p);
704 GCObject *next = pp->gclist;
705 lua_assert(isgray(pp) && (pp->cache != NULL || pp->cachemiss >= MAXMISS));
706 gray2black(pp);
707 checkprotocache(g, pp);
708 p = next;
709 }
710}
711
712 651
713/* 652/*
714** clear entries with unmarked keys from all weaktables in list 'l' 653** clear entries with unmarked keys from all weaktables in list 'l'
@@ -1439,7 +1378,6 @@ static lu_mem atomic (lua_State *L) {
1439 clearbyvalues(g, g->weak, origweak); 1378 clearbyvalues(g, g->weak, origweak);
1440 clearbyvalues(g, g->allweak, origall); 1379 clearbyvalues(g, g->allweak, origall);
1441 luaS_clearcache(g); 1380 luaS_clearcache(g);
1442 clearprotolist(g);
1443 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1381 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
1444 lua_assert(g->gray == NULL); 1382 lua_assert(g->gray == NULL);
1445 return work; /* estimate of slots marked by 'atomic' */ 1383 return work; /* estimate of slots marked by 'atomic' */