aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-09-24 08:36:53 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-09-24 08:36:53 +0000
commit2314b80d4c5ed712308f6b32aa8bf865d8d9ffff (patch)
tree8a531352ebd8b352e6c1b5cadeeb7d49d28da147
parent8ac52a95d577d00ed7b783fde8bca5b2b76cb404 (diff)
downloadruby-2314b80d4c5ed712308f6b32aa8bf865d8d9ffff.tar.gz
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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37025 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--compile.c24
-rw-r--r--insns.def24
-rw-r--r--iseq.c41
-rw-r--r--iseq.h15
-rw-r--r--test/ruby/test_defined.rb6
-rw-r--r--vm.c10
-rw-r--r--vm_core.h2
8 files changed, 100 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index ef8e1b60a0..1df6829c15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Mon Sep 24 17:36:51 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * 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@ruby-lang.org>
* tool/merger.rb: add --ticket option to add ticket number.
diff --git a/compile.c b/compile.c
index fc6453ad1a..2f8cbb51cd 100644
--- a/compile.c
+++ b/compile.c
@@ -2701,23 +2701,23 @@ static int
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 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
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 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
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);
diff --git a/insns.def b/insns.def
index e55ec30a07..94e1a24203 100644
--- a/insns.def
+++ b/insns.def
@@ -716,7 +716,7 @@ defined
(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 @@ defined
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 @@ defined
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 @@ defined
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 @@ defined
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 @@ defined
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 @@ defined
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 @@ defined
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 @@ defined
}
if (expr_type != 0) {
if (needstr != Qfalse) {
- val = rb_str_new2(expr_type);
+ val = rb_iseq_defined_string(expr_type);
}
else {
val = Qtrue;
diff --git a/iseq.c b/iseq.c
index 8d8d92174d..989a8a1120 100644
--- a/iseq.c
+++ b/iseq.c
@@ -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 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
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
diff --git a/iseq.h b/iseq.h
index 39f139ff94..17eebfff12 100644
--- a/iseq.h
+++ b/iseq.h
@@ -106,18 +106,27 @@ struct iseq_compile_data {
/* 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_REF,
DEFINED_ZSUPER,
+ DEFINED_SELF,
+ DEFINED_TRUE,
+ DEFINED_FALSE,
+ DEFINED_ASGN,
+ DEFINED_EXPR,
+ DEFINED_IVAR2,
+ DEFINED_REF,
DEFINED_FUNC
};
+VALUE rb_iseq_defined_string(enum defined_type type);
+
#if defined __GNUC__ && __GNUC__ >= 4
#pragma GCC visibility pop
#endif
diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb
index c02d1376b2..28e3da5f31 100644
--- a/test/ruby/test_defined.rb
+++ b/test/ruby/test_defined.rb
@@ -86,6 +86,12 @@ class TestDefined < Test::Unit::TestCase
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
diff --git a/vm.c b/vm.c
index 55ccfe7939..f842a6dfba 100644
--- a/vm.c
+++ b/vm.c
@@ -1515,6 +1515,9 @@ rb_vm_mark(void *ptr)
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 @@ vm_memsize(const void *ptr)
{
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;
diff --git a/vm_core.h b/vm_core.h
index 9d776c952d..d890c1619b 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -349,6 +349,8 @@ typedef struct rb_vm_struct {
* objects so do *NOT* mark this when you GC.
*/
struct RArray at_exit;
+
+ VALUE *defined_strings;
} rb_vm_t;
typedef struct {