diff options
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | compile.c | 11 | ||||
-rw-r--r-- | defs/id.def | 1 | ||||
-rw-r--r-- | insns.def | 14 | ||||
-rw-r--r-- | string.c | 1 | ||||
-rw-r--r-- | vm.c | 1 | ||||
-rw-r--r-- | vm_insnhelper.h | 1 |
7 files changed, 49 insertions, 0 deletions
@@ -1,3 +1,23 @@ +Sun Nov 10 06:14:39 2013 Charlie Somerville <charliesome@ruby-lang.org> + + * compile.c (iseq_compile_each): emit opt_str_freeze if the #freeze + method is called on a static string literal with no arguments. + + * defs/id.def (firstline): add freeze so idFreeze is available + + * insns.def (opt_str_freeze): add opt_str_freeze instruction which + pushes a frozen string literal without allocating a new object if + String#freeze is not overriden + + * string.c (Init_String): define String#freeze + + * vm.c (vm_init_redefined_flag): define BOP_FREEZE on String class as + a basic operation + + * vm_insnhelper.h: ditto + + [Feature #8992] [ruby-core:57705] + Sun Nov 10 01:34:14 2013 Koichi Sasada <ko1@atdot.net> * gc.c (vm_malloc_increase): sweep immediately on GC due to malloc(). @@ -4314,6 +4314,17 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } case NODE_CALL: + if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR && + node->nd_mid == idFreeze && node->nd_args == NULL) + { + VALUE str = rb_fstring(node->nd_recv->nd_lit); + iseq_add_mark_object(iseq, str); + ADD_INSN1(ret, line, opt_str_freeze, str); + if (poped) { + ADD_INSN(ret, line, pop); + } + break; + } case NODE_FCALL: case NODE_VCALL:{ /* VCALL: variable or call */ /* diff --git a/defs/id.def b/defs/id.def index 57c0ae9f14..53ed3775ad 100644 --- a/defs/id.def +++ b/defs/id.def @@ -1,5 +1,6 @@ # -*- mode: ruby; coding: us-ascii -*- firstline, predefined = __LINE__+1, %[\ + freeze inspect intern object_id @@ -999,6 +999,20 @@ send CALL_METHOD(ci); } +DEFINE_INSN +opt_str_freeze +(VALUE str) +() +(VALUE val) +{ + if (BASIC_OP_UNREDEFINED_P(BOP_FREEZE, STRING_REDEFINED_OP_FLAG)) { + val = str; + } + else { + val = rb_funcall(rb_str_resurrect(str), idFreeze, 0); + } +} + /** @c optimize @e Invoke method without block, splat @@ -8745,6 +8745,7 @@ Init_String(void) rb_define_method(rb_cString, "byteslice", rb_str_byteslice, -1); rb_define_method(rb_cString, "scrub", str_scrub, -1); rb_define_method(rb_cString, "scrub!", str_scrub_bang, -1); + rb_define_method(rb_cString, "freeze", rb_obj_freeze, 0); rb_define_method(rb_cString, "to_i", rb_str_to_i, -1); rb_define_method(rb_cString, "to_f", rb_str_to_f, 0); @@ -1082,6 +1082,7 @@ vm_init_redefined_flag(void) OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash)); OP(Succ, SUCC), (C(Fixnum), C(String), C(Time)); OP(EqTilde, MATCH), (C(Regexp), C(String)); + OP(Freeze, FREEZE), (C(String)); #undef C #undef OP } diff --git a/vm_insnhelper.h b/vm_insnhelper.h index 8870fca47c..c637407cbc 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -56,6 +56,7 @@ enum { BOP_NOT, BOP_NEQ, BOP_MATCH, + BOP_FREEZE, BOP_LAST_ }; |