summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gc.c94
-rw-r--r--src/kernel.c11
2 files changed, 58 insertions, 47 deletions
diff --git a/src/gc.c b/src/gc.c
index cfe48df68..7004c8c6d 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -42,18 +42,18 @@
There're two white color types in a flip-flop fassion: White-A and White-B,
which respectively represent the Current White color (the newly allocated
- objects in the current round of GC) and the Sweep Target White color (the
+ objects in the current GC cycle) and the Sweep Target White color (the
dead objects to be swept).
- A and B will be switched just at the beginning of the next round of GC. At
+ A and B will be switched just at the beginning of the next GC cycle. At
that time, all the dead objects have been swept, while the newly created
- objects in the current round of GC which finally remains White are now
+ objects in the current GC cycle which finally remains White are now
regarded as dead objects. Instead of traversing all the White-A objects and
paint them as White-B, just switch the meaning of White-A and White-B would
be much cheaper.
- As a result, the objects we sweep in the current round of GC are always
- left from the previous round of GC. This allows us to sweep objects
+ As a result, the objects we sweep in the current GC cycle are always
+ left from the previous GC cycle. This allows us to sweep objects
incrementally, without the disturbance of the newly created objects.
== Execution Timing
@@ -86,7 +86,7 @@
phase, then only sweep the newly created objects, and leave
the Old objects live.
- * Major GC - same as a full round of regular GC.
+ * Major GC - same as a full regular GC cycle.
For details, see the comments for each function.
@@ -175,7 +175,7 @@ mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
p2 = (mrb->allocf)(mrb, p, len, mrb->ud);
if (!p2 && len > 0 && mrb->heaps) {
- mrb_garbage_collect(mrb);
+ mrb_full_gc(mrb);
p2 = (mrb->allocf)(mrb, p, len, mrb->ud);
}
@@ -390,7 +390,7 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } };
#ifdef MRB_GC_STRESS
- mrb_garbage_collect(mrb);
+ mrb_full_gc(mrb);
#endif
if (mrb->gc_threshold < mrb->live) {
mrb_incremental_gc(mrb);
@@ -664,7 +664,7 @@ root_scan_phase(mrb_state *mrb)
if (!is_minor_gc(mrb)) {
mrb->gray_list = NULL;
- mrb->variable_gray_list = NULL;
+ mrb->atomic_gray_list = NULL;
}
mrb_gc_mark_gv(mrb);
@@ -774,6 +774,20 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
return children;
}
+
+static void
+gc_mark_gray_list(mrb_state *mrb, struct RBasic **gray_list) {
+ struct RBasic *obj;
+
+ while ((obj = *gray_list)) {
+ if (is_gray(obj)) {
+ gc_mark_children(mrb, obj);
+ }
+ *gray_list = obj->gcnext;
+ }
+}
+
+
static size_t
incremental_marking_phase(mrb_state *mrb, size_t limit)
{
@@ -790,21 +804,9 @@ static void
final_marking_phase(mrb_state *mrb)
{
mark_context_stack(mrb, mrb->root_c);
- while (mrb->gray_list) {
- if (is_gray(mrb->gray_list))
- gc_mark_children(mrb, mrb->gray_list);
- else
- mrb->gray_list = mrb->gray_list->gcnext;
- }
+ gc_mark_gray_list(mrb, &mrb->gray_list);
+ gc_mark_gray_list(mrb, &mrb->atomic_gray_list);
gc_assert(mrb->gray_list == NULL);
- mrb->gray_list = mrb->variable_gray_list;
- mrb->variable_gray_list = NULL;
- while (mrb->gray_list) {
- if (is_gray(mrb->gray_list))
- gc_mark_children(mrb, mrb->gray_list);
- else
- mrb->gray_list = mrb->gray_list->gcnext;
- }
gc_assert(mrb->gray_list == NULL);
}
@@ -919,6 +921,20 @@ incremental_gc_until(mrb_state *mrb, enum gc_state to_state)
}
static void
+incremental_gc_step(mrb_state *mrb)
+{
+ size_t limit = 0, result = 0;
+ limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio;
+ while (result < limit) {
+ result += incremental_gc(mrb, limit);
+ if (mrb->gc_state == GC_STATE_NONE)
+ break;
+ }
+
+ mrb->gc_threshold = mrb->live + GC_STEP_SIZE;
+}
+
+static void
clear_all_old(mrb_state *mrb)
{
size_t origin_mode = mrb->is_generational_gc_mode;
@@ -931,7 +947,7 @@ clear_all_old(mrb_state *mrb)
mrb->is_generational_gc_mode = FALSE;
prepare_incremental_sweep(mrb);
incremental_gc_until(mrb, GC_STATE_NONE);
- mrb->variable_gray_list = mrb->gray_list = NULL;
+ mrb->atomic_gray_list = mrb->gray_list = NULL;
mrb->is_generational_gc_mode = origin_mode;
}
@@ -947,13 +963,7 @@ mrb_incremental_gc(mrb_state *mrb)
incremental_gc_until(mrb, GC_STATE_NONE);
}
else {
- size_t limit = 0, result = 0;
- limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio;
- while (result < limit) {
- result += incremental_gc(mrb, limit);
- if (mrb->gc_state == GC_STATE_NONE)
- break;
- }
+ incremental_gc_step(mrb);
}
if (mrb->gc_state == GC_STATE_NONE) {
@@ -962,6 +972,7 @@ mrb_incremental_gc(mrb_state *mrb)
if (mrb->gc_threshold < GC_STEP_SIZE) {
mrb->gc_threshold = GC_STEP_SIZE;
}
+
if (is_major_gc(mrb)) {
mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
mrb->gc_full = FALSE;
@@ -973,19 +984,16 @@ mrb_incremental_gc(mrb_state *mrb)
}
}
}
- else {
- mrb->gc_threshold = mrb->live + GC_STEP_SIZE;
- }
-
GC_TIME_STOP_AND_REPORT;
}
+/* Perform a full gc cycle */
void
-mrb_garbage_collect(mrb_state *mrb)
+mrb_full_gc(mrb_state *mrb)
{
if (mrb->gc_disabled) return;
- GC_INVOKE_TIME_REPORT("mrb_garbage_collect()");
+ GC_INVOKE_TIME_REPORT("mrb_full_gc()");
GC_TIME_START;
if (mrb->gc_state == GC_STATE_SWEEP) {
@@ -1062,8 +1070,8 @@ mrb_write_barrier(mrb_state *mrb, struct RBasic *obj)
gc_assert(!is_dead(mrb, obj));
gc_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_NONE);
paint_gray(obj);
- obj->gcnext = mrb->variable_gray_list;
- mrb->variable_gray_list = obj;
+ obj->gcnext = mrb->atomic_gray_list;
+ mrb->atomic_gray_list = obj;
}
/*
@@ -1077,7 +1085,7 @@ mrb_write_barrier(mrb_state *mrb, struct RBasic *obj)
static mrb_value
gc_start(mrb_state *mrb, mrb_value obj)
{
- mrb_garbage_collect(mrb);
+ mrb_full_gc(mrb);
return mrb_nil_value();
}
@@ -1370,7 +1378,7 @@ test_mrb_write_barrier(void)
mrb_write_barrier(mrb, obj);
gc_assert(is_gray(obj));
- gc_assert(mrb->variable_gray_list == obj);
+ gc_assert(mrb->atomic_gray_list == obj);
puts(" fail with gray");
@@ -1447,8 +1455,8 @@ test_incremental_gc(void)
puts("test_incremental_gc");
change_gen_gc_mode(mrb, FALSE);
- puts(" in mrb_garbage_collect");
- mrb_garbage_collect(mrb);
+ puts(" in mrb_full_gc");
+ mrb_full_gc(mrb);
gc_assert(mrb->gc_state == GC_STATE_NONE);
puts(" in GC_STATE_NONE");
diff --git a/src/kernel.c b/src/kernel.c
index 4914b7285..eb123b51e 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -4,6 +4,8 @@
** See Copyright Notice in mruby.h
*/
+#include <assert.h>
+
#include "mruby.h"
#include "mruby/array.h"
#include "mruby/class.h"
@@ -549,7 +551,7 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self)
}
static void
-valid_iv_name(mrb_state *mrb, mrb_sym iv_name_id, const char* s, size_t len)
+valid_iv_name(mrb_state *mrb, mrb_sym iv_name_id, const char* s, size_t len)
{
if (len < 2 || !(s[0] == '@' && s[1] != '@')) {
mrb_name_error(mrb, iv_name_id, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name_id));
@@ -575,7 +577,8 @@ get_valid_iv_sym(mrb_state *mrb, mrb_value iv_name)
iv_name_id = mrb_intern_cstr(mrb, RSTRING_PTR(iv_name));
valid_iv_name(mrb, iv_name_id, RSTRING_PTR(iv_name), RSTRING_LEN(iv_name));
}
- else if(mrb_symbol_p(iv_name)) {
+ else {
+ assert(mrb_symbol_p(iv_name));
iv_name_id = mrb_symbol(iv_name);
check_iv_name(mrb, iv_name_id);
}
@@ -640,7 +643,7 @@ mrb_obj_ivar_get(mrb_state *mrb, mrb_value self)
{
mrb_sym iv_name_id;
mrb_value iv_name;
-
+
mrb_get_args(mrb, "o", &iv_name);
iv_name_id = get_valid_iv_sym(mrb, iv_name);
@@ -674,7 +677,7 @@ mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
mrb_value iv_name, val;
mrb_get_args(mrb, "oo", &iv_name, &val);
-
+
iv_name_id = get_valid_iv_sym(mrb, iv_name);
mrb_iv_set(mrb, self, iv_name_id, val);
return val;