Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Put objects on the longlife heap.

  • Loading branch information...
commit 07ff959e6afd9ab91902b09e15cb321ac4c0ab64 1 parent ee40b95
Evan Weaver authored
Showing with 260 additions and 61 deletions.
  1. +93 −34 eval.c
  2. +4 −3 node.h
  3. +86 −5 object.c
  4. +9 −11 parse.y
  5. +68 −8 string.c
View
127 eval.c
@@ -33,6 +33,10 @@
#include "st.h"
#include "dln.h"
+#ifdef GC_DEBUG
+RUBY_EXTERN int gc_debug_dump;
+#endif
+
#ifdef __APPLE__
#include <crt_externs.h>
#endif
@@ -257,13 +261,6 @@ VALUE (*ruby_sandbox_save)_((rb_thread_t));
VALUE (*ruby_sandbox_restore)_((rb_thread_t));
NODE* ruby_current_node;
-#if 0
-#define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \
- ruby_sourceline = nd_line(ruby_current_node))
-#else
-#define SET_CURRENT_SOURCE() ((void)0)
-#endif
-
void
ruby_set_current_source()
{
@@ -273,13 +270,6 @@ ruby_set_current_source()
}
}
-#ifdef MBARI_API
-#define SET_METHOD_SOURCE() ruby_set_current_source()
-#else
-#define SET_METHOD_SOURCE() (void)0
-#endif
-
-
int ruby_safe_level = 0;
/* safe-level:
0 - strings from streams/environment/ARGV are tainted (default)
@@ -500,7 +490,7 @@ rb_undef_alloc_func(klass)
rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
}
-static NODE*
+NODE*
search_method(klass, id, origin)
VALUE klass, *origin;
ID id;
@@ -764,7 +754,7 @@ rb_attr(klass, id, read, write, ex)
if (!name) {
rb_raise(rb_eArgError, "argument needs to be symbol or string");
}
- SET_METHOD_SOURCE();
+ GC_DEBUG_SET_SOURCE
len = strlen(name)+2;
buf = ALLOCA_N(char,len);
snprintf(buf, len, "@%s", name);
@@ -777,8 +767,6 @@ rb_attr(klass, id, read, write, ex)
}
}
-extern int ruby_in_compile;
-
VALUE ruby_errinfo = Qnil;
extern NODE *ruby_eval_tree_begin;
extern NODE *ruby_eval_tree;
@@ -796,16 +784,31 @@ static struct SCOPE *top_scope;
static unsigned long frame_unique = 0;
+#ifdef GC_DEBUG
+#define CREATE_FRAME_SOURCE_POS(pframe) \
+ gc_debug_get_frame_source_pos(pframe);
+#define CREATE_FRAME_SOURCE_POS_FOR_PUSH(pframe) \
+ _frame.self = 0; \
+ _frame.last_func = 0; \
+ _frame.orig_func = 0; \
+ _frame.last_class = 0; \
+ CREATE_FRAME_SOURCE_POS(pframe);
+#else
+#define CREATE_FRAME_SOURCE_POS(pframe)
+#define CREATE_FRAME_SOURCE_POS_FOR_PUSH(pframe)
+#endif
+
#define PUSH_FRAME() do { \
volatile struct FRAME _frame; \
_frame.prev = ruby_frame; \
- _frame.tmp = 0; \
_frame.node = ruby_current_node; \
_frame.iter = ruby_iter->iter; \
+ _frame.tmp = 0; \
_frame.argc = 0; \
_frame.flags = 0; \
_frame.uniq = frame_unique++; \
- ruby_frame = &_frame
+ CREATE_FRAME_SOURCE_POS_FOR_PUSH((struct FRAME *)&_frame) \
+ ruby_frame = &_frame;
#define POP_FRAME() \
ruby_current_node = _frame.node; \
@@ -849,6 +852,7 @@ static unsigned long block_unique = 1;
_block.frame.node = ruby_current_node;\
_block.scope = ruby_scope; \
_block.prev = ruby_block; \
+ CREATE_FRAME_SOURCE_POS(&_block.frame); \
_block.outer = ruby_block; \
_block.iter = ruby_iter->iter; \
_block.vmode = scope_vmode; \
@@ -1418,6 +1422,21 @@ ruby_native_thread_kill(sig)
# endif
#endif
+void Init_sym _((void));
+void Init_source_filenames _((void));
+void Init_source_positions _((void));
+
+#ifdef GC_DEBUG
+#define SET_GC_DEBUG_SOURCEFUNC(x) \
+ ID old_ruby_sourcefunc = ruby_sourcefunc; \
+ ruby_sourcefunc = rb_intern(x);
+#define RESET_GC_DEBUG_SOURCEFUNC \
+ ruby_sourcefunc = old_ruby_sourcefunc;
+#else
+#define SET_GC_DEBUG_SOURCEFUNC(x)
+#define RESET_GC_DEBUG_SOURCEFUNC
+#endif
+
void
ruby_init()
{
@@ -1444,6 +1463,15 @@ ruby_init()
Init_stack((void*)&state);
Init_heap();
+ Init_sym();
+ Init_source_filenames();
+ ruby_current_node = 0;
+#ifdef GC_DEBUG
+ if (GC_DEBUG_ON && gc_debug_dump) {
+ Init_source_positions();
+ }
+ SET_GC_DEBUG_SOURCEFUNC("<ruby_init>")
+#endif
PUSH_SCOPE();
ruby_scope->local_vars = 0;
ruby_scope->local_tbl = 0;
@@ -1475,6 +1503,7 @@ ruby_init()
POP_SCOPE();
ruby_scope = top_scope;
top_scope->flags &= ~SCOPE_NOSTACK;
+ RESET_GC_DEBUG_SOURCEFUNC
ruby_running = 1;
}
@@ -1583,7 +1612,8 @@ ruby_options(argc, argv)
char **argv;
{
int state;
-
+ ruby_current_node = 0;
+ SET_GC_DEBUG_SOURCEFUNC("<ruby_options>")
Init_stack((void*)&state);
PUSH_TAG(PROT_EMPTY);
if ((state = EXEC_TAG()) == 0) {
@@ -1595,6 +1625,7 @@ ruby_options(argc, argv)
exit(error_handle(state));
}
POP_TAG();
+ RESET_GC_DEBUG_SOURCEFUNC
}
void rb_exec_end_proc _((void));
@@ -1639,6 +1670,7 @@ ruby_cleanup(exArg)
errs[1] = ruby_errinfo;
ruby_safe_level = 0;
Init_stack((void *)&state);
+ SET_GC_DEBUG_SOURCEFUNC("<ruby_cleanup>")
ruby_finalize_0();
errs[0] = ruby_errinfo;
PUSH_TAG(PROT_EMPTY);
@@ -1655,6 +1687,7 @@ ruby_cleanup(exArg)
ex = error_handle(ex);
ruby_finalize_1();
POP_TAG();
+ RESET_GC_DEBUG_SOURCEFUNC
for (nerr = 0; nerr < sizeof(errs) / sizeof(errs[0]); ++nerr) {
VALUE err = errs[nerr];
@@ -1692,6 +1725,7 @@ ruby_exec_internal()
{
int state;
+ SET_GC_DEBUG_SOURCEFUNC("<ruby_exec_internal>");
PUSH_TAG(PROT_EMPTY);
PUSH_ITER(ITER_NOT);
/* default visibility is private at toplevel */
@@ -1701,6 +1735,7 @@ ruby_exec_internal()
}
POP_ITER();
POP_TAG();
+ RESET_GC_DEBUG_SOURCEFUNC
return state;
}
@@ -1760,9 +1795,10 @@ rb_eval_string(str)
ruby_current_node = 0;
ruby_sourcefile = rb_source_filename("(eval)");
+ SET_GC_DEBUG_SOURCEFUNC("<rb_eval_string>")
v = eval(ruby_top_self, rb_str_new2(str), Qnil, 0, 0);
ruby_current_node = oldsrc;
-
+ RESET_GC_DEBUG_SOURCEFUNC
return v;
}
@@ -2309,7 +2345,7 @@ rb_copy_node_scope(node, rval)
{
NODE *copy;
- SET_METHOD_SOURCE();
+ GC_DEBUG_SET_SOURCE
copy=NEW_NODE(NODE_SCOPE,0,rval,node->nd_next);
if (node->nd_tbl) {
@@ -2823,7 +2859,7 @@ call_trace_func(event, node, self, id, klass)
tracing = 0;
ruby_current_node = node_save;
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
if (state) JUMP_TAG(state);
}
@@ -3220,7 +3256,7 @@ eval_node_volatile(iter, VALUE)
result = rb_eval(self, node->nd_iter);
END_CALLARGS;
ruby_current_node = (NODE *)node;
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
result = rb_call(CLASS_OF(result),result,each,0,0,0,self);
}
POP_ITER();
@@ -3374,7 +3410,7 @@ eval_node(attrasgn, VALUE)
END_CALLARGS;
ruby_current_node = node;
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope,self);
return argv[argc-1];
}
@@ -3392,7 +3428,7 @@ eval_node(call, VALUE)
END_CALLARGS;
ruby_current_node = node;
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,self);
}
@@ -3407,7 +3443,7 @@ eval_node(fcall, VALUE)
END_CALLARGS;
ruby_current_node = node;
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
return rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1,self);
}
@@ -3452,7 +3488,7 @@ eval_node(super, VALUE)
ruby_current_node = node;
}
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
return rb_call_super(argc, argv);
}
@@ -3619,6 +3655,7 @@ eval_node(slit, VALUE)
node->nd_cflag);
nd_set_type(node, NODE_LIT);
RB_GC_GUARD(str); /* ensure str is not GC'd in rb_reg_new */
+ maybe_add_to_longlife_recent_allocations(node);
return node->nd_lit = str2;
case NODE_LIT:
/* other thread may replace NODE_DREGX_ONCE to NODE_LIT */
@@ -3998,7 +4035,7 @@ rb_eval(self, node)
else {
result = Qundef; /* no arg */
}
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
result = rb_yield_0(result, 0, 0, 0, node->nd_state);
break;
@@ -4070,7 +4107,7 @@ rb_eval(self, node)
break;
case NODE_VCALL:
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,2,self);
break;
@@ -4127,8 +4164,10 @@ rb_eval(self, node)
break;
case NODE_GASGN:
+ ruby_in_longlife_context++;
result = rb_eval(self, node->nd_value);
rb_gvar_set(node->nd_entry, result);
+ ruby_in_longlife_context--;
break;
case NODE_IASGN:
@@ -4137,21 +4176,27 @@ rb_eval(self, node)
break;
case NODE_CDECL:
+ ruby_in_longlife_context++;
result = rb_eval(self, node->nd_value);
eval_cdecl(self, node, result);
+ ruby_in_longlife_context--;
break;
case NODE_CVDECL:
if (NIL_P(ruby_cbase)) {
rb_raise(rb_eTypeError, "no class/module to define class variable");
}
+ ruby_in_longlife_context++;
result = rb_eval(self, node->nd_value);
eval_cvar_set(node, result, Qtrue);
+ ruby_in_longlife_context--;
break;
case NODE_CVASGN:
+ ruby_in_longlife_context++;
result = rb_eval(self, node->nd_value);
eval_cvar_set(node, result, Qfalse);
+ ruby_in_longlife_context--;
break;
case NODE_LVAR:
@@ -5125,6 +5170,7 @@ rb_yield_0(val, self, klass, flags, avalue)
frame = block->frame;
frame.prev = ruby_frame;
frame.node = cnode;
+ CREATE_FRAME_SOURCE_POS(&frame);
ruby_frame = &(frame);
old_cref = (VALUE)ruby_cref;
ruby_cref = block->cref;
@@ -5466,7 +5512,9 @@ assign(self, lhs, val, pcall)
}
switch (nd_type(lhs)) {
case NODE_GASGN:
+ ruby_in_longlife_context++;
rb_gvar_set(lhs->nd_entry, val);
+ ruby_in_longlife_context--;
break;
case NODE_IASGN:
@@ -5488,27 +5536,35 @@ assign(self, lhs, val, pcall)
break;
case NODE_CDECL:
+ ruby_in_longlife_context++;
if (lhs->nd_vid == 0) {
rb_const_set(class_prefix(self, lhs->nd_else), lhs->nd_else->nd_mid, val);
}
else {
rb_const_set(ruby_cbase, lhs->nd_vid, val);
}
+ ruby_in_longlife_context--;
break;
case NODE_CVDECL:
+ ruby_in_longlife_context++;
if (RTEST(ruby_verbose) && FL_TEST(ruby_cbase, FL_SINGLETON)) {
rb_warn("declaring singleton class variable");
}
rb_cvar_set(cvar_cbase(), lhs->nd_vid, val, Qtrue);
+ ruby_in_longlife_context--;
break;
case NODE_CVASGN:
+ ruby_in_longlife_context++;
rb_cvar_set(cvar_cbase(), lhs->nd_vid, val, Qfalse);
+ ruby_in_longlife_context--;
break;
case NODE_MASGN:
+ ruby_in_longlife_context++;
massign(self, lhs, svalue_to_mrhs(val, lhs->nd_head), pcall);
+ ruby_in_longlife_context--;
break;
case NODE_CALL:
@@ -5527,7 +5583,7 @@ assign(self, lhs, val, pcall)
if (!lhs->nd_args) {
/* attr set */
ruby_current_node = lhs;
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope, self);
}
else {
@@ -5537,7 +5593,7 @@ assign(self, lhs, val, pcall)
args = rb_eval(self, lhs->nd_args);
rb_ary_push(args, val);
ruby_current_node = lhs;
- SET_CURRENT_SOURCE();
+ GC_DEBUG_SET_SOURCE
rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
RARRAY(args)->len, RARRAY(args)->ptr, scope, self);
}
@@ -6710,6 +6766,7 @@ eval(self, src, scope, file, line)
if (TYPE(ruby_class) == T_ICLASS) {
ruby_class = RBASIC(ruby_class)->klass;
}
+ SET_GC_DEBUG_SOURCEFUNC("<eval>")
PUSH_TAG(PROT_EMPTY);
if ((state = EXEC_TAG()) == 0) {
NODE *node;
@@ -6726,6 +6783,7 @@ eval(self, src, scope, file, line)
result = eval_tree(self, node);
}
POP_TAG();
+ RESET_GC_DEBUG_SOURCEFUNC
POP_CLASS();
ruby_in_eval--;
if (!NIL_P(scope)) {
@@ -10022,6 +10080,7 @@ mproc(method)
/* emulate ruby's method call */
PUSH_ITER(ITER_CUR);
PUSH_FRAME();
+ _frame.last_class = 0;
proc = rb_block_proc();
POP_FRAME();
POP_ITER();
@@ -10151,7 +10210,7 @@ rb_mod_define_method(argc, argv, mod)
else {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
}
- SET_METHOD_SOURCE();
+ GC_DEBUG_SET_SOURCE
if (RDATA(body)->dmark == (RUBY_DATA_FUNC)bm_mark) {
node = NEW_DMETHOD(method_unbind(body));
}
View
7 node.h
@@ -238,14 +238,15 @@ extern NODE *ruby_top_cref;
#define NEW_NODE_EDEN(t,a0,a1,a2) rb_node_newnode_eden((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
#define NEW_NODE_LONGLIFE(t,a0,a1,a2) rb_node_newnode_longlife((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
+/* IFUNC nodes are created whenever an enumeration runs; see rb_iterate(). For
+ this reason, they're allocated in ordinary heap. */
+#define NEW_IFUNC(f,c) NEW_NODE_EDEN(NODE_IFUNC,f,c,0)
+
#define NEW_METHOD(n,x) NEW_NODE(NODE_METHOD,x,n,0)
#define NEW_FBODY(n,i,o) NEW_NODE(NODE_FBODY,n,i,o)
#define NEW_DEFN(i,a,d,p) NEW_NODE(NODE_DEFN,p,i,NEW_RFUNC(a,d))
#define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_RFUNC(a,d))
#define NEW_CFUNC(f,c) NEW_NODE(NODE_CFUNC,f,c,0)
-/* IFUNC nodes are created whenever an enumeration runs; see rb_iterate(). For
- this reason, they're allocated in ordinary heap. */
-#define NEW_IFUNC(f,c) NEW_NODE_EDEN(NODE_IFUNC,f,c,0)
#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
#define NEW_SCOPE(b) NEW_NODE(NODE_SCOPE,local_tbl(),0,(b))
#define NEW_BLOCK(a) NEW_NODE(NODE_BLOCK,a,0,0)
View
91 object.c
@@ -31,6 +31,10 @@ VALUE rb_cTrueClass;
VALUE rb_cFalseClass;
VALUE rb_cSymbol;
+#ifdef GC_DEBUG
+int longlife_moved_objs_count = 0;
+#endif
+
static ID id_eq, id_eql, id_inspect, id_init_copy;
/*
@@ -113,6 +117,16 @@ rb_obj_id_obsolete(obj)
return rb_obj_id(obj);
}
+#ifdef GC_DEBUG
+VALUE
+rb_obj_ptr(obj)
+ VALUE obj;
+{
+ printf("rb_obj_ptr 0x%lx\n", obj);
+ return Qnil;
+}
+#endif
+
VALUE
rb_class_real(cl)
VALUE cl;
@@ -230,6 +244,33 @@ rb_obj_clone(obj)
return clone;
}
+/* :nodoc: */
+VALUE
+rb_obj_freeze(VALUE obj)
+{
+ int i;
+ if (!OBJ_MOVED(obj)) {
+ obj = rb_obj_move(obj);
+ switch (TYPE(obj)) {
+ case T_HASH:
+ st_foreach_map(RHASH(obj)->tbl, rb_obj_freeze, rb_obj_freeze);
+ break;
+ case T_ARRAY:
+ for (i = 0; i < RARRAY(obj)->len; i++) {
+ rb_ary_store(obj, i, rb_obj_freeze(rb_ary_entry(obj, i)));
+ }
+ break;
+ }
+ }
+ if (!OBJ_FROZEN(obj)) {
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
+ }
+ OBJ_FREEZE(obj);
+ }
+ return obj;
+}
+
/*
* call-seq:
* obj.dup -> an_object
@@ -750,14 +791,16 @@ rb_obj_infect(obj1, obj2)
*/
VALUE
-rb_obj_freeze(obj)
+rb_obj_move(obj)
VALUE obj;
{
- if (!OBJ_FROZEN(obj)) {
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
- rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
+ if (!OBJ_MOVED(obj)) {
+ if (TYPE(obj) == T_STRING) {
+ obj = rb_str_move(obj);
+ } else {
+ /* Currently has no real effect */
+ OBJ_MOVE(obj);
}
- OBJ_FREEZE(obj);
}
return obj;
}
@@ -781,6 +824,37 @@ rb_obj_frozen_p(obj)
return Qfalse;
}
+/*
+ * call-seq:
+ * obj.moved? => true or false
+ *
+ * Returns the moved status of <i>obj</i>.
+ *
+ */
+
+static VALUE
+rb_obj_moved_p(obj)
+ VALUE obj;
+{
+ if (OBJ_MOVED(obj)) return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * call-seq:
+ * obj.longlived? => true or false
+ *
+ * Returns whether <i>obj</i> is on the longlife heap.
+ *
+ */
+
+static VALUE
+rb_obj_longlived_p(obj)
+ VALUE obj;
+{
+ if (OBJ_LONGLIVED(obj)) return Qtrue;
+ return Qfalse;
+}
/*
* Document-class: NilClass
@@ -2722,6 +2796,7 @@ Init_Object()
rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
+ rb_define_method(rb_mKernel, "clone_string_values", rb_obj_clone, 0);
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
@@ -2730,6 +2805,8 @@ Init_Object()
rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);
+ rb_define_method(rb_mKernel, "moved?", rb_obj_moved_p, 0);
+ rb_define_method(rb_mKernel, "longlived?", rb_obj_longlived_p, 0);
rb_define_method(rb_mKernel, "to_a", rb_any_to_a, 0); /* to be removed */
rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
@@ -2879,6 +2956,10 @@ Init_Object()
rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
rb_define_global_const("FALSE", Qfalse);
+#ifdef GC_DEBUG
+ rb_define_method(rb_mKernel, "__ptr__", rb_obj_ptr, 0);
+#endif
+
id_eq = rb_intern("==");
id_eql = rb_intern("eql?");
id_inspect = rb_intern("inspect");
View
20 parse.y
@@ -77,6 +77,11 @@ NODE *ruby_eval_tree = 0;
char *ruby_sourcefile; /* current source file */
int ruby_sourceline; /* current line no. */
+#ifdef GC_DEBUG
+ID ruby_sourcefunc; /* current func if no other context */
+VALUE ruby_sourcefunc_line; /* current func if no other context */
+char* ruby_sourcefunc_file; /* current func if no other context */
+#endif
static int yylex();
static int yyerror();
@@ -2662,6 +2667,7 @@ yycompile(f, line)
struct RVarmap *vp, *vars = ruby_dyna_vars;
ruby_in_compile = 1;
+ ruby_in_longlife_context++;
if (!compile_for_eval && rb_safe_level() == 0 &&
rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
VALUE hash, fname;
@@ -2693,6 +2699,7 @@ yycompile(f, line)
ruby_debug_lines = 0;
compile_for_eval = 0;
ruby_in_compile = 0;
+ ruby_in_longlife_context--;
cond_stack = 0;
cmdarg_stack = 0;
command_start = 1;
@@ -3197,7 +3204,7 @@ tokadd_string(func, term, paren, nest)
}
#define NEW_STRTERM(func, term, paren) \
- NEW_NODE_EDEN(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
+ NEW_NODE(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
static int
parse_string(quote)
@@ -3303,7 +3310,7 @@ heredoc_identifier()
tokfix();
len = lex_p - lex_pbeg;
lex_p = lex_pend;
- lex_strterm = NEW_NODE_EDEN(NODE_HEREDOC,
+ lex_strterm = NEW_NODE(NODE_HEREDOC,
rb_str_new(tok(), toklen()), /* nd_lit */
len, /* nd_nth */
lex_lastline); /* nd_orig */
@@ -5960,15 +5967,6 @@ rb_gc_mark_parser()
#elif defined yystacksize
if (yyvsp) rb_gc_mark_locations((VALUE *)yyvs, (VALUE *)yyvsp);
#endif
-
- if (!ruby_in_compile) return;
-
- rb_gc_mark_maybe((VALUE)yylval.node);
- rb_gc_mark(ruby_debug_lines);
- rb_gc_mark(lex_lastline);
- rb_gc_mark(lex_input);
- rb_gc_mark((VALUE)lex_strterm);
- rb_gc_mark((VALUE)deferred_nodes);
}
void
View
76 string.c
@@ -59,12 +59,12 @@ str_frozen_check(s)
}
}
-static VALUE str_alloc _((VALUE));
static VALUE
-str_alloc(klass)
+str_alloc_eden(klass)
VALUE klass;
{
- NEWOBJ(str, struct RString);
+ struct RString *str;
+ str = ( struct RString*)rb_newobj_eden(-1);
OBJSETUP(str, klass, T_STRING);
str->ptr = 0;
@@ -75,6 +75,32 @@ str_alloc(klass)
}
static VALUE
+str_alloc_longlife(klass)
+ VALUE klass;
+{
+ struct RString *str;
+ str = ( struct RString*)rb_newobj_longlife(-1);
+ OBJSETUP(str, klass, T_STRING);
+
+ str->ptr = 0;
+ str->len = 0;
+ str->aux.capa = 0;
+
+ return (VALUE)str;
+}
+
+static VALUE
+str_alloc(klass)
+ VALUE klass;
+{
+ if (ruby_in_longlife_context) {
+ return str_alloc_longlife(klass);
+ } else {
+ return str_alloc_eden(klass);
+ }
+}
+
+static VALUE
str_new(klass, ptr, len)
VALUE klass;
const char *ptr;
@@ -175,6 +201,7 @@ str_new4(klass, str)
else {
FL_SET(str, ELTS_SHARED);
RSTRING(str)->aux.shared = str2;
+ maybe_add_to_longlife_recent_allocations(str);
}
return str2;
@@ -293,6 +320,7 @@ rb_str_shared_replace(str, str2)
RSTRING(str2)->aux.capa = 0;
FL_UNSET(str2, STR_NOCAPA);
if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
+ maybe_add_to_longlife_recent_allocations((void *)str);
}
static ID id_to_s;
@@ -325,7 +353,6 @@ rb_str_dup(str)
return dup;
}
-
/*
* call-seq:
* String.new(str="") => new_str
@@ -529,6 +556,7 @@ rb_str_associate(str, add)
}
RSTRING(str)->aux.shared = add;
FL_SET(str, STR_ASSOC);
+ maybe_add_to_longlife_recent_allocations((void *)str);
}
}
@@ -640,11 +668,39 @@ rb_str_substr(str, beg, len)
return str2;
}
+#ifdef GC_DEBUG
VALUE
-rb_str_freeze(str)
- VALUE str;
+rb_str_char_ptr(VALUE str)
{
- return rb_obj_freeze(str);
+ printf("rb_str_char_ptr 0x%lx\n", (RSTRING(str)->ptr));
+ return Qnil;
+}
+#endif
+
+VALUE
+rb_str_move(str2)
+ VALUE str2;
+{
+ VALUE str;
+
+ int len = RSTRING(str2)->len;
+ char * ptr = RSTRING(str2)->ptr;
+
+ str = str_alloc_longlife(rb_obj_class(str2));
+ RSTRING(str)->len = len;
+ RSTRING(str)->aux.capa = len;
+ RSTRING(str)->ptr = ALLOC_N(char,len+1);
+ if (ptr) {
+ memcpy(RSTRING(str)->ptr, ptr, len);
+ }
+ RSTRING(str)->ptr[len] = '\0';
+
+ OBJ_FREEZE(str2);
+ OBJ_INFECT(str, str2);
+#ifdef GC_DEBUG
+ longlife_moved_objs_count++;
+#endif
+ return str;
}
VALUE
@@ -2057,7 +2113,6 @@ rb_str_sub_bang(argc, argv, str)
RSTRING(str)->len += RSTRING(repl)->len - plen;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
if (tainted) OBJ_TAINT(str);
-
return str;
}
return Qnil;
@@ -2341,6 +2396,7 @@ rb_str_replace(str, str2)
}
OBJ_INFECT(str, str2);
+ maybe_add_to_longlife_recent_allocations((void *) str);
return str;
}
@@ -5057,6 +5113,10 @@ Init_String()
rb_define_method(rb_cString, "partition", rb_str_partition, -1);
rb_define_method(rb_cString, "rpartition", rb_str_rpartition, 1);
+#ifdef GC_DEBUG
+ rb_define_method(rb_cString, "__char_ptr__", rb_str_char_ptr, 0);
+#endif
+
id_to_s = rb_intern("to_s");
rb_fs = Qnil;
Please sign in to comment.
Something went wrong with that request. Please try again.