[前][次][番号順一覧][スレッド一覧]

ruby-changes:24973

From: nobu <ko1@a...>
Date: Mon, 24 Sep 2012 17:37:05 +0900 (JST)
Subject: [ruby-changes:24973] nobu:r37025 (trunk): Feature #7035

nobu	2012-09-24 17:36:53 +0900 (Mon, 24 Sep 2012)

  New Revision: 37025

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37025

  Log:
    Feature #7035
    
    * compile.c (defined_expr), insns.def (defined): share single frozen
      strings.  [EXPERIMENTAL] [ruby-core:47558][Feature #7035]
    * iseq.c (rb_iseq_defined_string): make expression strings.

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/insns.def
    trunk/iseq.c
    trunk/iseq.h
    trunk/test/ruby/test_defined.rb
    trunk/vm.c
    trunk/vm_core.h

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37024)
+++ ChangeLog	(revision 37025)
@@ -1,3 +1,10 @@
+Mon Sep 24 17:36:51 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* compile.c (defined_expr), insns.def (defined): share single frozen
+	  strings.  [EXPERIMENTAL] [ruby-core:47558][Feature #7035]
+
+	* iseq.c (rb_iseq_defined_string): make expression strings.
+
 Mon Sep 24 11:22:36 2012  NARUSE, Yui  <naruse@r...>
 
 	* tool/merger.rb: add --ticket option to add ticket number.
Index: insns.def
===================================================================
--- insns.def	(revision 37024)
+++ insns.def	(revision 37025)
@@ -716,7 +716,7 @@
 (VALUE val)
 {
     VALUE klass;
-    const char *expr_type = 0;
+    enum defined_type expr_type = 0;
     enum defined_type type = (enum defined_type)op_type;
 
     val = Qnil;
@@ -724,7 +724,7 @@
     switch (type) {
       case DEFINED_IVAR:
 	if (rb_ivar_defined(GET_SELF(), SYM2ID(obj))) {
-	    expr_type = "instance-variable";
+	    expr_type = DEFINED_IVAR;
 	}
 	break;
       case DEFINED_IVAR2:
@@ -732,7 +732,7 @@
 	break;
       case DEFINED_GVAR:
 	if (rb_gvar_defined(rb_global_entry(SYM2ID(obj)))) {
-	    expr_type = "global-variable";
+	    expr_type = DEFINED_GVAR;
 	}
 	break;
       case DEFINED_CVAR:
@@ -740,20 +740,20 @@
 	NODE *cref = rb_vm_get_cref(GET_ISEQ(), GET_EP());
 	klass = vm_get_cvar_base(cref, GET_CFP());
 	if (rb_cvar_defined(klass, SYM2ID(obj))) {
-	    expr_type = "class variable";
+	    expr_type = DEFINED_CVAR;
 	}
 	break;
 	}
       case DEFINED_CONST:
 	klass = v;
 	if (vm_get_ev_const(th, GET_ISEQ(), klass, SYM2ID(obj), 1)) {
-	    expr_type = "constant";
+	    expr_type = DEFINED_CONST;
 	}
 	break;
       case DEFINED_FUNC:
 	klass = CLASS_OF(v);
 	if (rb_method_boundp(klass, SYM2ID(obj), 0)) {
-	    expr_type = "method";
+	    expr_type = DEFINED_METHOD;
 	}
 	break;
       case DEFINED_METHOD:{
@@ -765,7 +765,7 @@
 		if (!((me->flag & NOEX_PROTECTED) &&
 		      !rb_obj_is_kind_of(GET_SELF(),
 					 rb_class_real(klass)))) {
-		    expr_type = "method";
+		    expr_type = DEFINED_METHOD;
 		}
 	    }
 	}
@@ -776,13 +776,13 @@
 	    args[0] = obj; args[1] = Qfalse;
 	    r = rb_check_funcall(v, rb_intern("respond_to_missing?"), 2, args);
 	    if (r != Qundef && RTEST(r))
-		expr_type = "method";
+		expr_type = DEFINED_METHOD;
 	}
 	break;
       }
       case DEFINED_YIELD:
 	if (GET_BLOCK_PTR()) {
-	    expr_type = "yield";
+	    expr_type = DEFINED_YIELD;
 	}
 	break;
       case DEFINED_ZSUPER:{
@@ -791,7 +791,7 @@
 	    VALUE klass = vm_search_normal_superclass(GET_CFP()->klass);
 	    ID id = me->def ? me->def->original_id : me->called_id;
 	    if (rb_method_boundp(klass, id, 0)) {
-		expr_type = "super";
+		expr_type = DEFINED_ZSUPER;
 	    }
 	}
 	break;
@@ -799,7 +799,7 @@
       case DEFINED_REF:{
 	val = vm_getspecial(th, GET_LEP(), Qfalse, FIX2INT(obj));
 	if (val != Qnil) {
-	    expr_type = "global-variable";
+	    expr_type = DEFINED_GVAR;
 	}
 	break;
       }
@@ -809,7 +809,7 @@
     }
     if (expr_type != 0) {
 	if (needstr != Qfalse) {
-	    val = rb_str_new2(expr_type);
+	    val = rb_iseq_defined_string(expr_type);
 	}
 	else {
 	    val = Qtrue;
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 37024)
+++ vm_core.h	(revision 37025)
@@ -349,6 +349,8 @@
      * objects so do *NOT* mark this when you GC.
      */
     struct RArray at_exit;
+
+    VALUE *defined_strings;
 } rb_vm_t;
 
 typedef struct {
Index: iseq.c
===================================================================
--- iseq.c	(revision 37024)
+++ iseq.c	(revision 37025)
@@ -18,6 +18,8 @@
 #include "vm_core.h"
 #include "iseq.h"
 
+#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
+
 #include "insns.inc"
 #include "insns_info.inc"
 
@@ -1747,6 +1749,45 @@
     return args;
 }
 
+VALUE
+rb_iseq_defined_string(enum defined_type type)
+{
+    static const char expr_names[][18] = {
+	"nil",
+	"instance-variable",
+	"local-variable",
+	"global-variable",
+	"class variable",
+	"constant",
+	"method",
+	"yield",
+	"super",
+	"self",
+	"true",
+	"false",
+	"assignment",
+	"expression",
+    };
+    const char *estr;
+    VALUE *defs, str;
+
+    if ((unsigned)(type - 1) >= (unsigned)numberof(expr_names)) return 0;
+    estr = expr_names[type - 1];
+    if (!estr[0]) return 0;
+    defs = GET_VM()->defined_strings;
+    if (!defs) {
+	defs = ruby_xcalloc(numberof(expr_names), sizeof(VALUE));
+	GET_VM()->defined_strings = defs;
+    }
+    str = defs[type];
+    if (!str) {
+	str = rb_str_new_cstr(estr);;
+	OBJ_FREEZE(str);
+	defs[type] = str;
+    }
+    return str;
+}
+
 /* ruby2cext */
 
 VALUE
Index: iseq.h
===================================================================
--- iseq.h	(revision 37024)
+++ iseq.h	(revision 37025)
@@ -106,18 +106,27 @@
 /* defined? */
 
 enum defined_type {
-    DEFINED_IVAR = 1,
-    DEFINED_IVAR2,
+    DEFINED_NIL = 1,
+    DEFINED_IVAR,
+    DEFINED_LVAR,
     DEFINED_GVAR,
     DEFINED_CVAR,
     DEFINED_CONST,
     DEFINED_METHOD,
     DEFINED_YIELD,
+    DEFINED_ZSUPER,
+    DEFINED_SELF,
+    DEFINED_TRUE,
+    DEFINED_FALSE,
+    DEFINED_ASGN,
+    DEFINED_EXPR,
+    DEFINED_IVAR2,
     DEFINED_REF,
-    DEFINED_ZSUPER,
     DEFINED_FUNC
 };
 
+VALUE rb_iseq_defined_string(enum defined_type type);
+
 #if defined __GNUC__ && __GNUC__ >= 4
 #pragma GCC visibility pop
 #endif
Index: compile.c
===================================================================
--- compile.c	(revision 37024)
+++ compile.c	(revision 37025)
@@ -2701,23 +2701,23 @@
 defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
 	     NODE *node, LABEL **lfinish, VALUE needstr)
 {
-    const char *estr = 0;
+    enum defined_type expr_type = 0;
     enum node_type type;
 
     switch (type = nd_type(node)) {
 
 	/* easy literals */
       case NODE_NIL:
-	estr = "nil";
+	expr_type = DEFINED_NIL;
 	break;
       case NODE_SELF:
-	estr = "self";
+	expr_type = DEFINED_SELF;
 	break;
       case NODE_TRUE:
-	estr = "true";
+	expr_type = DEFINED_TRUE;
 	break;
       case NODE_FALSE:
-	estr = "false";
+	expr_type = DEFINED_FALSE;
 	break;
 
       case NODE_ARRAY:{
@@ -2738,13 +2738,13 @@
       case NODE_AND:
       case NODE_OR:
       default:
-	estr = "expression";
+	expr_type = DEFINED_EXPR;
 	break;
 
 	/* variables */
       case NODE_LVAR:
       case NODE_DVAR:
-	estr = "local-variable";
+	expr_type = DEFINED_LVAR;
 	break;
 
       case NODE_IVAR:
@@ -2866,16 +2866,14 @@
       case NODE_CDECL:
       case NODE_CVDECL:
       case NODE_CVASGN:
-	estr = "assignment";
+	expr_type = DEFINED_ASGN;
 	break;
     }
 
-    if (estr != 0) {
+    if (expr_type) {
 	if (needstr != Qfalse) {
-	    VALUE str = rb_str_new2(estr);
-	    hide_obj(str);
-	    ADD_INSN1(ret, nd_line(node), putstring, str);
-	    iseq_add_mark_object_compile_time(iseq, str);
+	    VALUE str = rb_iseq_defined_string(expr_type);
+	    ADD_INSN1(ret, nd_line(node), putobject, str);
 	}
 	else {
 	    ADD_INSN1(ret, nd_line(node), putobject, Qtrue);
Index: vm.c
===================================================================
--- vm.c	(revision 37024)
+++ vm.c	(revision 37025)
@@ -1515,6 +1515,9 @@
 	    if (vm->trap_list[i].cmd)
 		rb_gc_mark(vm->trap_list[i].cmd);
 	}
+	if (vm->defined_strings) {
+	    rb_gc_mark_locations(vm->defined_strings, vm->defined_strings + DEFINED_EXPR);
+	}
     }
 
     RUBY_MARK_LEAVE("vm");
@@ -1560,7 +1563,12 @@
 {
     if (ptr) {
 	const rb_vm_t *vmobj = ptr;
-	return sizeof(rb_vm_t) + st_memsize(vmobj->living_threads);
+	size_t size = sizeof(rb_vm_t);
+	size += st_memsize(vmobj->living_threads);
+	if (vmobj->defined_strings) {
+	    size += DEFINED_EXPR * sizeof(VALUE);
+	}
+	return size;
     }
     else {
 	return 0;
Index: test/ruby/test_defined.rb
===================================================================
--- test/ruby/test_defined.rb	(revision 37024)
+++ test/ruby/test_defined.rb	(revision 37025)
@@ -86,6 +86,12 @@
     assert_equal nil, defined?($2)
   end
 
+  def test_defined_impl_specific
+    feature7035 = '[ruby-core:47558]' # not spec
+    assert_operator(defined?(Foo), :frozen?, feature7035)
+    assert_same(defined?(Foo), defined?(Array), feature7035)
+  end
+
   class TestAutoloadedSuperclass
     autoload :A, "a"
   end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]