1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
nobu 2012-09-24 08:36:53 +00:00
parent 8ac52a95d5
commit 2314b80d4c
8 changed files with 100 additions and 29 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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;

41
iseq.c
View file

@ -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

15
iseq.h
View file

@ -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

View file

@ -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

10
vm.c
View file

@ -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;

View file

@ -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 {