Created
November 26, 2013 04:08
-
-
Save anonymous/7653326 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/compile.c b/compile.c | |
index 9ff3bf5..306fd80 100644 | |
--- a/compile.c | |
+++ b/compile.c | |
@@ -172,10 +172,10 @@ r_value(VALUE value) | |
(((rb_iseq_t*)DATA_PTR(iseq))->filepath) | |
#define NEW_ISEQVAL(node, name, type, line_no) \ | |
- new_child_iseq(iseq, (node), (name), 0, (type), (line_no)) | |
+ new_child_iseq(iseq, (node), rb_str_frozen_literal(name), 0, (type), (line_no)) | |
#define NEW_CHILD_ISEQVAL(node, name, type, line_no) \ | |
- new_child_iseq(iseq, (node), (name), iseq->self, (type), (line_no)) | |
+ new_child_iseq(iseq, (node), rb_str_frozen_literal(name), iseq->self, (type), (line_no)) | |
/* add instructions */ | |
#define ADD_SEQ(seq1, seq2) \ | |
@@ -2201,13 +2201,20 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int *cntp | |
debugp_param("nd_lit", lit); | |
if (!NIL_P(lit)) { | |
- hide_obj(lit); | |
+ lit = rb_str_frozen_literal(lit); | |
+ /* hide_obj(lit);*/ | |
cnt++; | |
ADD_INSN1(ret, nd_line(node), putobject, lit); | |
} | |
+ /* rb_io_write(rb_stdout, rb_parser_dump_tree(node, 1));*/ | |
+ | |
while (list) { | |
COMPILE(ret, "each string", list->nd_head); | |
+ /* if (nd_type(list) == NODE_STR)*/ | |
+ /* fprintf(stderr, "WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: %d\n", nd_type(list));*/ | |
+ if (nd_type(list->nd_head) == NODE_STR) | |
+ list->nd_head->nd_lit = rb_str_frozen_literal(list->nd_head->nd_lit); | |
cnt++; | |
list = list->nd_next; | |
} | |
@@ -2300,6 +2307,10 @@ compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, | |
opt_p = Qfalse; | |
} | |
COMPILE_(anchor, "array element", node->nd_head, poped); | |
+ //if (nd_type(node->nd_head) == NODE_STR) { | |
+ // /* fprintf(stderr, "yeaaaaaabudddddddddddddddyy: %s\n", RSTRING_PTR(node->nd_head->nd_lit));*/ | |
+ // node->nd_head->nd_lit = rb_str_frozen_literal(node->nd_head->nd_lit); | |
+ //} | |
node = node->nd_next; | |
} | |
} | |
@@ -2357,7 +2368,7 @@ case_when_optimizable_literal(NODE * node) | |
break; | |
} | |
case NODE_STR: | |
- return node->nd_lit; | |
+ return rb_str_frozen_literal(node->nd_lit); | |
} | |
return Qfalse; | |
} | |
@@ -2382,7 +2393,8 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, VALUE s | |
if (nd_type(val) == NODE_STR) { | |
debugp_param("nd_lit", val->nd_lit); | |
- OBJ_FREEZE(val->nd_lit); | |
+ /* OBJ_FREEZE(val->nd_lit);*/ | |
+ val->nd_lit = rb_str_frozen_literal(val->nd_lit); | |
ADD_INSN1(cond_seq, nd_line(val), putobject, val->nd_lit); | |
} | |
else { | |
@@ -3736,7 +3748,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
case NODE_DASGN_CURR:{ | |
int idx, lv, ls; | |
COMPILE(ret, "dvalue", node->nd_value); | |
- debugp_param("dassn id", rb_str_new2(rb_id2name(node->nd_vid) ? rb_id2name(node->nd_vid) : "*")); | |
+ debugp_param("dassn id", rb_str_frozen_literal(rb_str_new2(rb_id2name(node->nd_vid) ? rb_id2name(node->nd_vid) : "*"))); | |
if (!poped) { | |
ADD_INSN(ret, nd_line(node), dup); | |
@@ -4299,6 +4311,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
INIT_ANCHOR(list); | |
switch (type) { | |
case NODE_ARRAY:{ | |
+ /* rb_io_write(rb_stdout, rb_parser_dump_tree(node->nd_head, 1));*/ | |
compile_array(iseq, list, node->nd_head, Qfalse); | |
size = OPERAND_AT(POP_ELEMENT(list), 0); | |
ADD_SEQ(ret, list); | |
@@ -4472,7 +4485,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
INIT_ANCHOR(recv); | |
INIT_ANCHOR(val); | |
switch(nd_type(node)) { | |
- case NODE_MATCH: | |
+ case NODE_MATCH: /* nd_lit is string here? */ | |
+ rb_io_write(rb_stdout, rb_parser_dump_tree(node, 1)); | |
ADD_INSN1(recv, nd_line(node), putobject, node->nd_lit); | |
ADD_INSN2(val, nd_line(node), getspecial, INT2FIX(0), | |
INT2FIX(0)); | |
@@ -4516,6 +4530,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
case NODE_LIT:{ | |
debugp_param("lit", node->nd_lit); | |
if (!poped) { | |
+ /* if (RB_TYPE_P(node->nd_lit, T_STRING))*/ | |
+ /* node->nd_lit = rb_str_frozen_literal(node->nd_lit);*/ | |
ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); | |
} | |
break; | |
@@ -4523,8 +4539,11 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
case NODE_STR:{ | |
debugp_param("nd_lit", node->nd_lit); | |
if (!poped) { | |
- OBJ_FREEZE(node->nd_lit); | |
- ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit); | |
+ /* OBJ_FREEZE(node->nd_lit);*/ | |
+ /* VALUE lit = rb_str_frozen_literal(node->nd_lit);*/ | |
+ node->nd_lit = rb_str_frozen_literal(node->nd_lit); | |
+ VALUE lit = node->nd_lit; | |
+ ADD_INSN1(ret, nd_line(node), putstring, lit); | |
} | |
break; | |
} | |
@@ -4537,7 +4556,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
break; | |
} | |
case NODE_XSTR:{ | |
- OBJ_FREEZE(node->nd_lit); | |
+ /* OBJ_FREEZE(node->nd_lit);*/ | |
+ node->nd_lit = rb_str_frozen_literal(node->nd_lit); | |
ADD_CALL_RECEIVER(ret, nd_line(node)); | |
ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); | |
ADD_CALL(ret, nd_line(node), ID2SYM(idBackquote), INT2FIX(1)); | |
@@ -4636,7 +4656,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
} | |
case NODE_DEFN:{ | |
VALUE iseqval = NEW_ISEQVAL(node->nd_defn, | |
- rb_str_dup(rb_id2str(node->nd_mid)), | |
+ rb_id2str(node->nd_mid), | |
ISEQ_TYPE_METHOD, nd_line(node)); | |
debugp_param("defn/iseq", iseqval); | |
@@ -4656,7 +4676,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
} | |
case NODE_DEFS:{ | |
VALUE iseqval = NEW_ISEQVAL(node->nd_defn, | |
- rb_str_dup(rb_id2str(node->nd_mid)), | |
+ rb_id2str(node->nd_mid), | |
ISEQ_TYPE_METHOD, nd_line(node)); | |
debugp_param("defs/iseq", iseqval); | |
@@ -4846,6 +4866,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
RSTRING_PTR(iseq->name), (void *)iseq, | |
iseq->compile_data->flip_cnt++); | |
+ key = rb_str_frozen_literal(key); | |
hide_obj(key); | |
iseq_add_mark_object_compile_time(iseq, key); | |
ADD_INSN2(ret, nd_line(node), getspecial, key, INT2FIX(0)); | |
@@ -4901,6 +4922,12 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |
} | |
break; | |
} | |
+ case NODE_FILE:{ | |
+ if (!poped) { | |
+ ADD_INSN1(ret, nd_line(node), putobject, iseq->filename); | |
+ } | |
+ break; | |
+ } | |
case NODE_ERRINFO:{ | |
if (!poped) { | |
if (iseq->type == ISEQ_TYPE_RESCUE) { | |
@@ -5206,7 +5233,7 @@ rb_insns_name_array(void) | |
VALUE ary = rb_ary_new(); | |
int i; | |
for (i = 0; i < numberof(insn_name_info); i++) { | |
- rb_ary_push(ary, rb_obj_freeze(rb_str_new2(insn_name_info[i]))); | |
+ rb_ary_push(ary, rb_str_frozen_literal(rb_str_new2(insn_name_info[i]))); | |
} | |
return rb_obj_freeze(ary); | |
} | |
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c | |
index 66e33a3..fd08158 100644 | |
--- a/ext/objspace/objspace.c | |
+++ b/ext/objspace/objspace.c | |
@@ -531,7 +531,7 @@ count_nodes(int argc, VALUE *argv, VALUE os) | |
COUNT_NODE(NODE_LAMBDA); | |
COUNT_NODE(NODE_OPTBLOCK); | |
#undef COUNT_NODE | |
- default: node = INT2FIX(nodes[i]); | |
+ default: node = INT2FIX(i); | |
} | |
rb_hash_aset(hash, node, SIZET2NUM(nodes[i])); | |
} | |
diff --git a/gc.c b/gc.c | |
index dfe4c06..7dffefa 100644 | |
--- a/gc.c | |
+++ b/gc.c | |
@@ -310,6 +310,7 @@ typedef struct RVALUE { | |
struct RRational rational; | |
struct RComplex complex; | |
} as; | |
+ unsigned int mark_count; | |
} RVALUE; | |
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) | |
@@ -1854,6 +1855,7 @@ gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr) | |
register uintptr_t *bits = GET_HEAP_BITMAP(ptr); | |
if (MARKED_IN_BITMAP(bits, ptr)) return 0; | |
MARK_IN_BITMAP(bits, ptr); | |
+ RANY(ptr)->mark_count++; | |
objspace->heap.marked_num++; | |
return 1; | |
} | |
@@ -1907,6 +1909,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) | |
bits = GET_HEAP_BITMAP(ptr); | |
if (MARKED_IN_BITMAP(bits, ptr)) return; /* already marked */ | |
MARK_IN_BITMAP(bits, ptr); | |
+ RANY(ptr)->mark_count++; | |
objspace->heap.marked_num++; | |
marking: | |
@@ -2177,6 +2180,8 @@ add_slot_local_freelist(rb_objspace_t *objspace, RVALUE *p) | |
{ | |
struct heaps_slot *slot; | |
+ if (FL_TEST(p, FL_RESERVED)) | |
+ fprintf(stderr, "FORCED BAD NEWWWWWWWWWS\n"); | |
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); | |
p->as.free.flags = 0; | |
slot = GET_HEAP_SLOT(p); | |
@@ -2286,6 +2291,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) | |
final_num++; | |
} | |
else { | |
+ if (FL_TEST(p, FL_RESERVED)) | |
+ fprintf(stderr, "BAD NEWWWWWWWWWS\n"); | |
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); | |
p->as.free.flags = 0; | |
p->as.free.next = sweep_slot->freelist; | |
@@ -2730,6 +2737,7 @@ gc_marks(rb_objspace_t *objspace) | |
rb_gc_mark_symbols(); | |
rb_gc_mark_encodings(); | |
+ rb_str_frozen_literal_mark(); | |
/* mark protected global variables */ | |
for (list = global_List; list; list = list->next) { | |
@@ -3725,6 +3733,12 @@ rb_obj_sourceline(VALUE obj) | |
return meta ? INT2FIX(meta->line) : Qnil; | |
} | |
+static VALUE | |
+rb_obj_markcount(VALUE obj) | |
+{ | |
+ return UINT2NUM(RANY(obj)->mark_count); | |
+} | |
+ | |
/* | |
* call-seq: | |
* GC.count -> Integer | |
@@ -4092,6 +4106,7 @@ Init_GC(void) | |
rb_define_method(rb_cBasicObject, "__sourcefile__", rb_obj_sourcefile, 0); | |
rb_define_method(rb_cBasicObject, "__sourceline__", rb_obj_sourceline, 0); | |
+ rb_define_method(rb_cBasicObject, "__markcount__", rb_obj_markcount, 0); | |
rb_define_module_function(rb_mObSpace, "count_objects", count_objects, -1); | |
diff --git a/include/ruby/intern.h b/include/ruby/intern.h | |
index a4eef71..0f0e5e6 100644 | |
--- a/include/ruby/intern.h | |
+++ b/include/ruby/intern.h | |
@@ -686,6 +686,7 @@ VALUE rb_str_locktmp(VALUE); | |
VALUE rb_str_unlocktmp(VALUE); | |
VALUE rb_str_dup_frozen(VALUE); | |
#define rb_str_dup_frozen rb_str_new_frozen | |
+VALUE rb_str_frozen_literal(VALUE); | |
VALUE rb_str_plus(VALUE, VALUE); | |
VALUE rb_str_times(VALUE, VALUE); | |
long rb_str_sublen(VALUE, long); | |
diff --git a/internal.h b/internal.h | |
index a819cc1..448750f 100644 | |
--- a/internal.h | |
+++ b/internal.h | |
@@ -163,6 +163,7 @@ size_t rb_strftime_timespec(char *s, size_t maxsize, const char *format, const s | |
/* string.c */ | |
int rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p); | |
+void rb_str_frozen_literal_mark(void); | |
/* struct.c */ | |
VALUE rb_struct_init_copy(VALUE copy, VALUE s); | |
diff --git a/iseq.c b/iseq.c | |
index ffbc759..7bb6165 100644 | |
--- a/iseq.c | |
+++ b/iseq.c | |
@@ -228,6 +228,8 @@ rb_iseq_add_mark_object(rb_iseq_t *iseq, VALUE obj) | |
OBJ_UNTRUST(iseq->mark_ary); | |
RBASIC(iseq->mark_ary)->klass = 0; | |
} | |
+ /* if (RB_TYPE_P(obj, T_STRING) && OBJ_FROZEN(obj))*/ | |
+ /* obj = rb_str_frozen_literal(obj);*/ | |
rb_ary_push(iseq->mark_ary, obj); | |
} | |
@@ -237,8 +239,12 @@ prepare_iseq_build(rb_iseq_t *iseq, | |
VALUE parent, enum iseq_type type, VALUE block_opt, | |
const rb_compile_option_t *option) | |
{ | |
- OBJ_FREEZE(name); | |
- OBJ_FREEZE(filename); | |
+ /* OBJ_FREEZE(name);*/ | |
+ name = rb_str_frozen_literal(name); | |
+ /* OBJ_FREEZE(filename);*/ | |
+ filename = rb_str_frozen_literal(filename); | |
+ if (RTEST(filepath) && !rb_str_cmp(filename, filepath)) | |
+ filepath = filename; | |
iseq->name = name; | |
iseq->filename = filename; | |
diff --git a/node.h b/node.h | |
index bb96107..bababf0 100644 | |
--- a/node.h | |
+++ b/node.h | |
@@ -228,6 +228,8 @@ enum node_type { | |
#define NODE_LAMBDA NODE_LAMBDA | |
NODE_OPTBLOCK, | |
#define NODE_OPTBLOCK NODE_OPTBLOCK | |
+ NODE_FILE, | |
+#define NODE_FILE NODE_FILE | |
NODE_LAST | |
#define NODE_LAST NODE_LAST | |
}; | |
@@ -447,6 +449,7 @@ typedef struct RNode { | |
#define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a) | |
#define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0) | |
#define NEW_OPTBLOCK(a) NEW_NODE(NODE_OPTBLOCK,a,0,0) | |
+#define NEW_FILE() NEW_NODE(NODE_FILE,0,0,0) | |
#if defined __GNUC__ && __GNUC__ >= 4 | |
#pragma GCC visibility push(default) | |
diff --git a/parse.y b/parse.y | |
index d36156f..9f57d38 100644 | |
--- a/parse.y | |
+++ b/parse.y | |
@@ -3918,6 +3918,7 @@ regexp : tREGEXP_BEG regexp_contents tREGEXP_END | |
case NODE_STR: | |
{ | |
VALUE src = node->nd_lit; | |
+ /* src = rb_str_frozen_literal(src);*/ | |
nd_set_type(node, NODE_LIT); | |
node->nd_lit = reg_compile(src, options); | |
} | |
@@ -5830,9 +5831,7 @@ parser_regx_options(struct parser_params *parser) | |
static void | |
dispose_string(VALUE str) | |
{ | |
- /* TODO: should use another API? */ | |
- if (RBASIC(str)->flags & RSTRING_NOEMBED) | |
- xfree(RSTRING_PTR(str)); | |
+ rb_str_free(str); | |
rb_gc_force_recycle(str); | |
} | |
@@ -8266,6 +8265,7 @@ gettable_gen(struct parser_params *parser, ID id) | |
return NEW_FALSE(); | |
} | |
else if (id == keyword__FILE__) { | |
+ return NEW_FILE(); | |
return NEW_STR(rb_external_str_new_with_enc(ruby_sourcefile, strlen(ruby_sourcefile), | |
rb_filesystem_encoding())); | |
} | |
@@ -8791,6 +8791,10 @@ reduce_nodes_gen(struct parser_params *parser, NODE **body) | |
} | |
if (!subnodes(nd_head, nd_resq)) goto end; | |
break; | |
+ case NODE_STR: | |
+ /* fprintf(stderr, "AHEYSKJFI##################: %s\n", RSTRING_PTR(node->nd_lit));*/ | |
+ /* node->nd_lit = rb_str_frozen_literal(node->nd_lit);*/ | |
+ return; | |
default: | |
return; | |
} | |
@@ -9450,6 +9454,8 @@ reg_compile_gen(struct parser_params* parser, VALUE str, int options) | |
VALUE err; | |
reg_fragment_setenc(str, options); | |
+ if (RSTRING_LEN(str) == 1) | |
+ str = rb_str_frozen_literal(str); | |
err = rb_errinfo(); | |
re = rb_reg_compile(str, options & RE_OPTION_MASK, ruby_sourcefile, ruby_sourceline); | |
if (NIL_P(re)) { | |
@@ -9781,6 +9787,7 @@ static ID | |
register_symid(ID id, const char *name, long len, rb_encoding *enc) | |
{ | |
VALUE str = rb_enc_str_new(name, len, enc); | |
+ /* str = rb_str_frozen_literal(str);*/ | |
OBJ_FREEZE(str); | |
st_add_direct(global_symbols.sym_id, (st_data_t)str, id); | |
st_add_direct(global_symbols.id_str, id, (st_data_t)str); | |
diff --git a/string.c b/string.c | |
index eaa8579..8d0a23e 100644 | |
--- a/string.c | |
+++ b/string.c | |
@@ -56,6 +56,7 @@ VALUE rb_cSymbol; | |
#define STR_NOEMBED FL_USER1 | |
#define STR_SHARED FL_USER2 /* = ELTS_SHARED */ | |
#define STR_ASSOC FL_USER3 | |
+#define STR_LITERAL FL_RESERVED | |
#define STR_SHARED_P(s) FL_ALL((s), STR_NOEMBED|ELTS_SHARED) | |
#define STR_ASSOC_P(s) FL_ALL((s), STR_NOEMBED|STR_ASSOC) | |
#define STR_NOCAPA (STR_NOEMBED|ELTS_SHARED|STR_ASSOC) | |
@@ -711,6 +712,104 @@ rb_str_new_frozen(VALUE orig) | |
RUBY_ALIAS_FUNCTION(rb_str_new4(VALUE orig), rb_str_new_frozen, (orig)) | |
#define rb_str_new4 rb_str_new_frozen | |
+int rb_str_hash_cmp(VALUE, VALUE); | |
+st_index_t rb_str_hash(VALUE); | |
+ | |
+/* static st_index_t*/ | |
+/* rstrhash(st_data_t arg)*/ | |
+/* {*/ | |
+/* register const struct RString *str = (const struct RString *)arg;*/ | |
+/* #define FNV1_32A_INIT 0x811c9dc5*/ | |
+/* return st_hash(RSTRING_PTR(str), RSTRING_LEN(str), FNV1_32A_INIT);*/ | |
+/* }*/ | |
+ | |
+static const struct st_hash_type type_rstrhash = { | |
+ rb_str_hash_cmp, | |
+ rb_str_hash | |
+}; | |
+ | |
+st_table* | |
+st_init_rstrtable(void) | |
+{ | |
+ return st_init_table(&type_rstrhash); | |
+} | |
+ | |
+static st_table *literal_strings; | |
+ | |
+static int | |
+mark_string_i(st_data_t key, st_data_t val, void *data) | |
+{ | |
+ rb_gc_mark((VALUE)val); | |
+ return ST_CONTINUE; | |
+} | |
+ | |
+void | |
+rb_str_frozen_literal_mark() | |
+{ | |
+ fprintf(stderr, "string literal table is %zu entries\n", literal_strings->num_entries); | |
+ st_foreach(literal_strings, mark_string_i, 0); | |
+} | |
+ | |
+void | |
+rb_str_frozen_literal_delete(VALUE str) | |
+{ | |
+ st_data_t key, val; | |
+ key = (st_data_t)RSTRING(str); | |
+ | |
+ assert(FL_TEST(str, STR_LITERAL)); | |
+ FL_UNSET(str, STR_LITERAL); | |
+ | |
+ /* MEMCPY(&key, RSTRING(str), struct RString, 1);*/ | |
+ | |
+ if (st_delete(literal_strings, &key, &val)) { | |
+ /* fprintf(stderr, "removing literal '%s'\n", RSTRING_PTR(str));*/ | |
+ assert((VALUE)val == str); | |
+ } else | |
+ fprintf(stderr, "DELEEEEEEEEEEEEEEEEEEEETE\n"); | |
+ | |
+} | |
+ | |
+VALUE | |
+rb_str_frozen_literal(VALUE str) | |
+{ | |
+ char *ptr; | |
+ long len; | |
+ st_data_t frozen; | |
+ | |
+ Check_Type(str, T_STRING); | |
+ ptr = RSTRING_PTR(str); | |
+ len = RSTRING_LEN(str); | |
+ | |
+ /* OBJ_FREEZE(str);*/ | |
+ /* return str;*/ | |
+ | |
+ if (FL_TEST(str, STR_LITERAL)) | |
+ return str; | |
+ | |
+ /* if (!ptr || len > 32 || ptr[len] != 0 || STR_ASSOC_P(str)) {*/ | |
+ if (ptr && (len < 64 || ptr[0] == '/') && ptr[len] == 0 && !STR_SHARED_P(str)) { | |
+ /* ok */ | |
+ } else if (!STR_EMBED_P(str)) { | |
+ OBJ_FREEZE(str); | |
+ return str; | |
+ } | |
+ | |
+ if (st_lookup(literal_strings, (st_data_t)RSTRING(str), &frozen)) { | |
+ /* STR_SET_NOEMBED(str);*/ | |
+ /* FL_SET(str, ELTS_SHARED);*/ | |
+ /* RSTRING(str)->as.heap.aux.shared = (VALUE)frozen;*/ | |
+ /* OBJ_FREEZE(str);*/ | |
+ /* fprintf(stderr, "MATCH: '%s' for '%s'\n", RSTRING_PTR(frozen), RSTRING_PTR(str));*/ | |
+ return (VALUE)frozen; | |
+ } else { | |
+ FL_SET(str, STR_LITERAL); | |
+ OBJ_FREEZE(str); | |
+ /* fprintf(stderr, "creating literal '%s'\n", RSTRING_PTR(str));*/ | |
+ st_add_direct(literal_strings, (st_data_t)RSTRING(str), (st_data_t)RSTRING(str)); | |
+ return str; | |
+ } | |
+} | |
+ | |
VALUE | |
rb_str_new_with_class(VALUE obj, const char *ptr, long len) | |
{ | |
@@ -788,6 +887,10 @@ rb_free_tmp_buffer(volatile VALUE *store) | |
void | |
rb_str_free(VALUE str) | |
{ | |
+ if (FL_TEST(str, STR_LITERAL)) { | |
+ /* if (STR_EMBED_P(str)) {*/ | |
+ rb_str_frozen_literal_delete(str); | |
+ } | |
if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) { | |
xfree(RSTRING(str)->as.heap.ptr); | |
} | |
@@ -910,7 +1013,13 @@ rb_str_dup(VALUE str) | |
VALUE | |
rb_str_resurrect(VALUE str) | |
{ | |
- return str_replace(str_alloc(rb_cString), str); | |
+ VALUE ret = str_replace(str_alloc(rb_cString), str); | |
+ if (FL_TEST(str, STR_LITERAL)) { | |
+ assert(OBJ_FROZEN(str)); | |
+ /* assert(STR_EMBED_P(str));*/ | |
+ /* fprintf(stderr, "resurructed '%s' to '%s'\n", RSTRING_PTR(str), RSTRING_PTR(ret));*/ | |
+ } | |
+ return ret; | |
} | |
/* | |
@@ -7772,6 +7881,8 @@ rb_to_id(VALUE name) | |
void | |
Init_String(void) | |
{ | |
+ literal_strings = st_init_rstrtable(); | |
+ | |
#undef rb_intern | |
#define rb_intern(str) rb_intern_const(str) | |
diff --git a/variable.c b/variable.c | |
index 303bb27..7c9c580 100644 | |
--- a/variable.c | |
+++ b/variable.c | |
@@ -65,7 +65,8 @@ fc_path(struct fc_result *fc, ID name) | |
path = tmp; | |
fc = fc->prev; | |
} | |
- OBJ_FREEZE(path); | |
+ path = rb_str_frozen_literal(path); | |
+ /* OBJ_FREEZE(path);*/ | |
return path; | |
} | |
@@ -153,7 +154,8 @@ classname(VALUE klass) | |
return find_class_path(klass); | |
} | |
path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n))); | |
- OBJ_FREEZE(path); | |
+ path = rb_str_frozen_literal(path); | |
+ /* OBJ_FREEZE(path);*/ | |
st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path); | |
n = classid; | |
st_delete(RCLASS_IV_TBL(klass), &n, 0); | |
@@ -208,7 +210,8 @@ rb_class_path(VALUE klass) | |
} | |
} | |
path = rb_sprintf("#<%s:%p>", s, (void*)klass); | |
- OBJ_FREEZE(path); | |
+ path = rb_str_frozen_literal(path); | |
+ /* OBJ_FREEZE(path);*/ | |
rb_ivar_set(klass, tmp_classpath, path); | |
return path; | |
@@ -227,7 +230,8 @@ rb_set_class_path_string(VALUE klass, VALUE under, VALUE name) | |
str = rb_str_dup(rb_class_path(under)); | |
rb_str_cat2(str, "::"); | |
rb_str_append(str, name); | |
- OBJ_FREEZE(str); | |
+ str = rb_str_frozen_literal(str); | |
+ /* OBJ_FREEZE(str);*/ | |
} | |
rb_ivar_set(klass, classpath, str); | |
} | |
@@ -245,7 +249,8 @@ rb_set_class_path(VALUE klass, VALUE under, const char *name) | |
rb_str_cat2(str, "::"); | |
rb_str_cat2(str, name); | |
} | |
- OBJ_FREEZE(str); | |
+ str = rb_str_frozen_literal(str); | |
+ /* OBJ_FREEZE(str);*/ | |
rb_ivar_set(klass, classpath, str); | |
} | |
@@ -1464,7 +1469,8 @@ rb_autoload(VALUE mod, ID id, const char *file) | |
} | |
fn = rb_str_new2(file); | |
FL_UNSET(fn, FL_TAINT); | |
- OBJ_FREEZE(fn); | |
+ fn = rb_str_frozen_literal(fn); | |
+ /* OBJ_FREEZE(fn);*/ | |
st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); | |
} | |
diff --git a/vm_eval.c b/vm_eval.c | |
index 6f2da3e..6ec6af0 100644 | |
--- a/vm_eval.c | |
+++ b/vm_eval.c | |
@@ -972,6 +972,7 @@ static VALUE | |
eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *volatile file, volatile int line) | |
{ | |
int state; | |
+ VALUE filename = Qnil; | |
VALUE result = Qundef; | |
VALUE envval; | |
rb_binding_t *bind = 0; | |
@@ -983,6 +984,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char | |
if (file == 0) { | |
file = rb_sourcefile(); | |
+ filename = rb_sourcefilename(); | |
line = rb_sourceline(); | |
} | |
@@ -999,6 +1001,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char | |
envval = bind->env; | |
if (strcmp(file, "(eval)") == 0 && bind->filename != Qnil) { | |
file = RSTRING_PTR(bind->filename); | |
+ filename = bind->filename; | |
line = bind->line_no; | |
} | |
} | |
@@ -1024,10 +1027,13 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char | |
} | |
} | |
+ if (!RTEST(filename)) | |
+ filename = rb_str_new2(file); | |
+ | |
/* make eval iseq */ | |
th->parse_in_eval++; | |
th->mild_compile_error++; | |
- iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line)); | |
+ iseqval = rb_iseq_compile(src, rb_str_frozen_literal(filename), INT2FIX(line)); | |
th->mild_compile_error--; | |
th->parse_in_eval--; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment