mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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
This commit is contained in:
parent
8ac52a95d5
commit
2314b80d4c
8 changed files with 100 additions and 29 deletions
|
@ -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.
|
||||
|
|
24
compile.c
24
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);
|
||||
|
|
24
insns.def
24
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;
|
||||
|
|
41
iseq.c
41
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
|
||||
|
|
15
iseq.h
15
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
|
||||
|
|
|
@ -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
10
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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue