Skip to content

Commit 6b8269c

Browse files
committed
FEAT: slightly optimize GC by checking the most common value types first
1 parent 01ec241 commit 6b8269c

File tree

2 files changed

+51
-83
lines changed

2 files changed

+51
-83
lines changed

src/core/m-gc.c

+50-83
Original file line numberDiff line numberDiff line change
@@ -320,17 +320,49 @@ static void Mark_Series(REBSER *series, REBCNT depth);
320320
for (len = 0; len < series->tail; len++) {
321321
val = BLK_SKIP(series, len);
322322

323-
switch (VAL_TYPE(val)) {
324-
325-
case REB_END:
326-
// We should never reach the end before len above.
327-
// Exception is the stack itself.
328-
if (series != DS_Series) Crash(RP_UNEXPECTED_END);
329-
break;
323+
if (ANY_SCALAR(val)) {
324+
continue;
325+
}
326+
if (ANY_WORD(val)) {
327+
// Special word used in word frame, stack, or errors:
328+
if (VAL_GET_OPT(val, OPTS_UNWORD)) continue;
329+
// Mark its context, if it has one:
330+
if (VAL_WORD_INDEX(val) > 0 && NZ(ser = VAL_WORD_FRAME(val))) {
331+
//if (SERIES_TAIL(ser) > 100) Dump_Word_Value(val);
332+
CHECK_MARK(ser, depth);
333+
}
334+
// Possible bug above!!! We cannot mark relative words (negative
335+
// index) because the frame pointer does not point to a context,
336+
// it may point to a function body, native code, or action number.
337+
// But, what if a function is GC'd during it's own evaluation, what
338+
// keeps the function's code block from being GC'd?
339+
continue;
340+
}
341+
if (ANY_BLOCK(val)) {
342+
ser = VAL_SERIES(val);
343+
ASSERT(ser != 0, RP_NULL_SERIES);
344+
if (IS_BARE_SERIES(ser)) {
345+
MARK_SERIES(ser);
346+
continue;
347+
}
348+
#if (ALEVEL>0)
349+
if (!IS_END(BLK_SKIP(ser, SERIES_TAIL(ser))) && ser != DS_Series)
350+
Crash(RP_MISSING_END);
351+
#endif
352+
if (SERIES_WIDE(ser) != sizeof(REBVAL) && SERIES_WIDE(ser) != 4 && SERIES_WIDE(ser) != 0)
353+
Crash(RP_BAD_WIDTH, 16, SERIES_WIDE(ser), VAL_TYPE(val));
354+
QUEUE_CHECK_MARK(ser, depth);
355+
continue;
356+
}
357+
if (VAL_TYPE(val) >= REB_BINARY && VAL_TYPE(val) <= REB_BITSET) {
358+
ser = VAL_SERIES(val);
359+
if (SERIES_WIDE(ser) > sizeof(REBUNI))
360+
Crash(RP_BAD_WIDTH, sizeof(REBUNI), SERIES_WIDE(ser), VAL_TYPE(val));
361+
MARK_SERIES(ser);
362+
continue;
363+
}
330364

331-
case REB_UNSET:
332-
case REB_TYPESET:
333-
break;
365+
switch (VAL_TYPE(val)) {
334366
case REB_HANDLE:
335367
if (IS_CONTEXT_HANDLE(val)) {
336368
hob = VAL_HANDLE_CTX(val);
@@ -351,6 +383,8 @@ static void Mark_Series(REBSER *series, REBCNT depth);
351383
CHECK_MARK(VAL_TYPE_SPEC(val), depth); // check typespec.reb file
352384
}
353385
break;
386+
case REB_TYPESET:
387+
break;
354388

355389
case REB_ERROR:
356390
// If it has an actual error object, then mark it. Otherwise,
@@ -406,84 +440,11 @@ static void Mark_Series(REBSER *series, REBCNT depth);
406440
// Their bodies are not GC'd!
407441
break;
408442

409-
case REB_WORD: // (and also used for function STACK backtrace frame)
410-
case REB_SET_WORD:
411-
case REB_GET_WORD:
412-
case REB_LIT_WORD:
413-
case REB_REFINEMENT:
414-
case REB_ISSUE:
415-
// Special word used in word frame, stack, or errors:
416-
if (VAL_GET_OPT(val, OPTS_UNWORD)) break;
417-
// Mark its context, if it has one:
418-
if (VAL_WORD_INDEX(val) > 0 && NZ(ser = VAL_WORD_FRAME(val))) {
419-
//if (SERIES_TAIL(ser) > 100) Dump_Word_Value(val);
420-
CHECK_MARK(ser, depth);
421-
}
422-
// Possible bug above!!! We cannot mark relative words (negative
423-
// index) because the frame pointer does not point to a context,
424-
// it may point to a function body, native code, or action number.
425-
// But, what if a function is GC'd during it's own evaluation, what
426-
// keeps the function's code block from being GC'd?
427-
break;
428-
429-
case REB_NONE:
430-
case REB_LOGIC:
431-
case REB_INTEGER:
432-
case REB_DECIMAL:
433-
case REB_PERCENT:
434-
case REB_MONEY:
435-
case REB_TIME:
436-
case REB_DATE:
437-
case REB_CHAR:
438-
case REB_PAIR:
439-
case REB_TUPLE:
440-
break;
441-
442-
case REB_STRING:
443-
case REB_BINARY:
444-
case REB_FILE:
445-
case REB_EMAIL:
446-
case REB_URL:
447-
case REB_TAG:
448-
case REB_BITSET:
449-
case REB_REF:
450-
ser = VAL_SERIES(val);
451-
if (SERIES_WIDE(ser) > sizeof(REBUNI))
452-
Crash(RP_BAD_WIDTH, sizeof(REBUNI), SERIES_WIDE(ser), VAL_TYPE(val));
453-
MARK_SERIES(ser);
454-
break;
455-
456443
case REB_IMAGE:
457-
//MARK_SERIES(VAL_SERIES_SIDE(val)); //????
458-
MARK_SERIES(VAL_SERIES(val));
459-
break;
460-
461444
case REB_VECTOR:
462445
MARK_SERIES(VAL_SERIES(val));
463446
break;
464447

465-
case REB_BLOCK:
466-
case REB_PAREN:
467-
case REB_PATH:
468-
case REB_SET_PATH:
469-
case REB_GET_PATH:
470-
case REB_LIT_PATH:
471-
case REB_HASH:
472-
ser = VAL_SERIES(val);
473-
ASSERT(ser != 0, RP_NULL_SERIES);
474-
if (IS_BARE_SERIES(ser)) {
475-
MARK_SERIES(ser);
476-
break;
477-
}
478-
#if (ALEVEL>0)
479-
if (!IS_END(BLK_SKIP(ser, SERIES_TAIL(ser))) && ser != DS_Series)
480-
Crash(RP_MISSING_END);
481-
#endif
482-
if (SERIES_WIDE(ser) != sizeof(REBVAL) && SERIES_WIDE(ser) != 4 && SERIES_WIDE(ser) != 0)
483-
Crash(RP_BAD_WIDTH, 16, SERIES_WIDE(ser), VAL_TYPE(val));
484-
QUEUE_CHECK_MARK(ser, depth);
485-
break;
486-
487448
case REB_MAP:
488449
ser = VAL_SERIES(val);
489450
QUEUE_CHECK_MARK(ser, depth);
@@ -522,6 +483,12 @@ static void Mark_Series(REBSER *series, REBCNT depth);
522483
Mark_Event(val, depth);
523484
break;
524485

486+
case REB_END:
487+
// We should never reach the end before len above.
488+
// Exception is the stack itself.
489+
if (series != DS_Series) Crash(RP_UNEXPECTED_END);
490+
break;
491+
525492
default:
526493
Crash(RP_DATATYPE+1, VAL_TYPE(val));
527494
}

src/include/sys-value.h

+1
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,7 @@ typedef struct Reb_All {
13251325
#define ANY_EVAL_BLOCK(v) (VAL_TYPE(v) >= REB_BLOCK && VAL_TYPE(v) <= REB_PAREN)
13261326
#define ANY_OBJECT(v) (VAL_TYPE(v) >= REB_OBJECT && VAL_TYPE(v) <= REB_PORT)
13271327
#define ANY_NUMBER(v) (VAL_TYPE(v) >= REB_INTEGER && VAL_TYPE(v) <= REB_MONEY)
1328+
#define ANY_SCALAR(v) (VAL_TYPE(v) >= REB_UNSET && VAL_TYPE(v) <= REB_DATE)
13281329

13291330
#define ANY_BLOCK_TYPE(t) (t >= REB_BLOCK && t <= REB_LIT_PATH)
13301331
#define ANY_STR_TYPE(t) (t >= REB_STRING && t <= REB_TAG)

0 commit comments

Comments
 (0)