diff --git a/ChangeLog b/ChangeLog index d4147286c5..41a0cbff3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Fri Jul 21 04:17:22 2006 Yukihiro Matsumoto + + * eval.c (rb_call): try local method look-up first for fcall, then + normal method look-up. [ruby-talk:202564] + + * eval.c (rb_get_method_body): save local method cache separately. + + * eval.c (search_method): export info whether method is local or + not. + Thu Jul 20 20:27:07 2006 Yukihiro Matsumoto * object.c (rb_mod_attr): make Module#attr to be an alias to diff --git a/eval.c b/eval.c index 5c9ec1728f..4bef97c7bd 100644 --- a/eval.c +++ b/eval.c @@ -235,7 +235,7 @@ typedef jmp_buf rb_jmpbuf_t; #include VALUE rb_cProc; -static VALUE rb_cBinding; +VALUE rb_cBinding; static VALUE proc_alloc(VALUE,struct BLOCK*,int); static VALUE proc_invoke(VALUE,VALUE,VALUE,VALUE,int); static VALUE proc_lambda(void); @@ -245,7 +245,7 @@ static struct BLOCK *passing_block(VALUE,struct BLOCK*); static int block_orphan(struct BLOCK *data); VALUE rb_cMethod; -static VALUE rb_cUnboundMethod; +VALUE rb_cUnboundMethod; static VALUE umethod_bind(VALUE, VALUE); static VALUE rb_mod_define_method(int, VALUE*, VALUE); NORETURN(static void rb_raise_jump(VALUE)); @@ -467,9 +467,10 @@ rb_undef_alloc_func(VALUE klass) #define LOOKUP_NORMAL 0 #define LOOKUP_FCALL 1 #define LOOKUP_NOSKIP 2 +#define LOOKUP_LOCAL 1 static NODE* -search_method(VALUE klass, ID id, VALUE *origin, int flag) +search_method(VALUE klass, ID id, VALUE *origin, int flag, int *out) { NODE *body; @@ -477,6 +478,7 @@ search_method(VALUE klass, ID id, VALUE *origin, int flag) if (st_lookup(RCLASS(ruby_frame->this_class)->m_tbl, id, (st_data_t *)&body) && body->nd_noex == NOEX_LOCAL) { if (origin) *origin = ruby_frame->this_class; + if (out) *out = LOOKUP_LOCAL; return body; } } @@ -484,6 +486,7 @@ search_method(VALUE klass, ID id, VALUE *origin, int flag) if (st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body) && (flag == LOOKUP_NOSKIP || body->nd_noex != NOEX_LOCAL)) { if (origin) *origin = klass; + if (out) *out = LOOKUP_NORMAL; return body; } } @@ -499,8 +502,9 @@ rb_get_method_body(VALUE *klassp, ID *idp, int *noexp) NODE * volatile body; struct cache_entry *ent; int noex = *noexp; + int lc; - if ((body = search_method(klass, id, &origin, noex)) == 0 || !body->nd_body) { + if ((body = search_method(klass, id, &origin, noex, &lc)) == 0 || !body->nd_body) { /* store empty info in cache */ ent = cache[noex] + EXPR1(klass, id); ent->klass = klass; @@ -513,9 +517,10 @@ rb_get_method_body(VALUE *klassp, ID *idp, int *noexp) } if (ruby_running) { + VALUE c = (lc == LOOKUP_LOCAL) ? origin : klass; /* store in cache */ - ent = cache[noex] + EXPR1(klass, id); - ent->klass = klass; + ent = cache[lc] + EXPR1(c, id); + ent->klass = c; ent->noex = body->nd_noex; if (noexp) *noexp = body->nd_noex; body = body->nd_body; @@ -552,7 +557,7 @@ rb_get_method_body(VALUE *klassp, ID *idp, int *noexp) NODE* rb_method_node(VALUE klass, ID id) { - int noex = 0; + int noex = LOOKUP_NORMAL; struct cache_entry *ent; ent = cache[0] + EXPR1(klass, id); @@ -641,9 +646,9 @@ rb_export_method(VALUE klass, ID name, ID noex) if (klass == rb_cObject) { rb_secure(4); } - body = search_method(klass, name, &origin, LOOKUP_NOSKIP); + body = search_method(klass, name, &origin, LOOKUP_NOSKIP, 0); if (!body && TYPE(klass) == T_MODULE) { - body = search_method(rb_cObject, name, &origin, LOOKUP_NOSKIP); + body = search_method(rb_cObject, name, &origin, LOOKUP_NOSKIP, 0); } if (!body || !body->nd_body) { raise_undef(klass, name); @@ -741,8 +746,8 @@ rb_attr(VALUE klass, ID id, int read, int write, int noex) VALUE ruby_errinfo = Qnil; extern int ruby_nerrs; -static VALUE rb_eLocalJumpError; -static VALUE rb_eSysStackError; +VALUE rb_eLocalJumpError; +VALUE rb_eSysStackError; extern VALUE ruby_top_self; @@ -1965,7 +1970,7 @@ rb_undef(VALUE klass, ID id) if (id == __id__ || id == __send__ || id == init) { rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); } - body = search_method(klass, id, &origin, LOOKUP_NOSKIP); + body = search_method(klass, id, &origin, LOOKUP_NOSKIP, 0); if (!body || !body->nd_body) { const char *s0 = " class"; VALUE c = klass; @@ -2062,10 +2067,10 @@ rb_alias(VALUE klass, ID name, ID def) if (klass == rb_cObject) { rb_secure(4); } - orig = search_method(klass, def, &origin, LOOKUP_NOSKIP); + orig = search_method(klass, def, &origin, LOOKUP_NOSKIP, 0); if (!orig || !orig->nd_body) { if (TYPE(klass) == T_MODULE) { - orig = search_method(rb_cObject, def, &origin, LOOKUP_NOSKIP); + orig = search_method(rb_cObject, def, &origin, LOOKUP_NOSKIP, 0); } } if (!orig || !orig->nd_body) { @@ -3746,7 +3751,7 @@ rb_eval(VALUE self, NODE *n) rb_id2name(node->nd_mid)); } rb_frozen_class_p(ruby_cbase); - body = search_method(ruby_cbase, node->nd_mid, &origin, LOOKUP_NOSKIP); + body = search_method(ruby_cbase, node->nd_mid, &origin, LOOKUP_NOSKIP, 0); if (body){ if (RTEST(ruby_verbose) && ruby_cbase == origin && body->nd_cnt == 0 && body->nd_body) { @@ -4147,7 +4152,7 @@ static VALUE rb_mod_public_method_defined(VALUE mod, VALUE mid) { ID id = rb_to_id(mid); - int noex = 1; + int noex = LOOKUP_NOSKIP; if (rb_get_method_body(&mod, &id, &noex)) { if (VISI_CHECK(noex, NOEX_PUBLIC)) @@ -4186,7 +4191,7 @@ static VALUE rb_mod_private_method_defined(VALUE mod, VALUE mid) { ID id = rb_to_id(mid); - int noex = 0; + int noex = LOOKUP_NOSKIP; if (rb_get_method_body(&mod, &id, &noex)) { if (VISI_CHECK(noex, NOEX_PRIVATE)) @@ -4225,7 +4230,7 @@ static VALUE rb_mod_protected_method_defined(VALUE mod, VALUE mid) { ID id = rb_to_id(mid); - int noex = 1; + int noex = LOOKUP_NOSKIP; if (rb_get_method_body(&mod, &id, &noex)) { if (VISI_CHECK(noex, NOEX_PROTECTED)) @@ -5894,7 +5899,7 @@ rb_call(VALUE klass, VALUE recv, ID mid, NODE *body; /* OK */ int noex; ID id = mid; - struct cache_entry *ent; + struct cache_entry *ent = 0; if (!klass) { rb_raise(rb_eNotImpError, "method `%s' called on terminated object (%p)", @@ -5904,7 +5909,7 @@ rb_call(VALUE klass, VALUE recv, ID mid, case CALLING_FCALL: case CALLING_VCALL: if (recv == ruby_frame->self) { - noex = LOOKUP_FCALL; + noex = LOOKUP_LOCAL; break; } /* fall thtough */ @@ -5914,8 +5919,19 @@ rb_call(VALUE klass, VALUE recv, ID mid, } /* is it in the method cache? */ - ent = cache[noex] + EXPR1(klass, mid); - if (ent->mid == mid && ent->klass == klass) { + if (noex == LOOKUP_LOCAL) { + ent = cache[LOOKUP_FCALL] + EXPR1(ruby_frame->this_class, mid); + if (ent->mid != mid || ent->klass != ruby_frame->this_class) { + ent = NULL; + } + } + if (ent) { + ent = cache[LOOKUP_NORMAL] + EXPR1(klass, mid); + if (ent->mid != mid || ent->klass != klass) { + ent = NULL; + } + } + if (ent) { if (!ent->method) return method_missing(recv, mid, argc, argv, block, scope==CALLING_VCALL?CSTAT_VCALL:0); @@ -7368,9 +7384,9 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) id = rb_to_id(argv[i]); for (;;) { - body = search_method(m, id, &m, LOOKUP_NOSKIP); + body = search_method(m, id, &m, LOOKUP_NOSKIP, 0); if (body == 0) { - body = search_method(rb_cObject, id, &m, LOOKUP_NOSKIP); + body = search_method(rb_cObject, id, &m, LOOKUP_NOSKIP, 0); } if (body == 0 || body->nd_body == 0) { rb_bug("undefined method `%s'; can't happen", rb_id2name(id)); @@ -12693,7 +12709,7 @@ rb_thread_atfork(void) * 3: 15 16 */ -static VALUE rb_cCont; +VALUE rb_cCont; /* * call-seq: diff --git a/lib/cgi-lib.rb b/lib/cgi-lib.rb deleted file mode 100644 index d6b60d66cc..0000000000 --- a/lib/cgi-lib.rb +++ /dev/null @@ -1,272 +0,0 @@ -warn "Warning:#{caller[0].sub(/:in `.*'\z/, '')}: cgi-lib is deprecated after Ruby 1.8.1; use cgi instead" - -=begin - -= simple CGI support library - -= example - -== get form values - - require "cgi-lib.rb" - query = CGI.new - query['field'] # <== value of 'field' - query.keys # <== array of fields - -and query has Hash class methods - - -== get cookie values - - require "cgi-lib.rb" - query = CGI.new - query.cookie['name'] # <== cookie value of 'name' - query.cookie.keys # <== all cookie names - -and query.cookie has Hash class methods - - -== print HTTP header and HTML string to $> - - require "cgi-lib.rb" - CGI::print{ - CGI::tag("HTML"){ - CGI::tag("HEAD"){ CGI::tag("TITLE"){"TITLE"} } + - CGI::tag("BODY"){ - CGI::tag("FORM", {"ACTION"=>"test.rb", "METHOD"=>"POST"}){ - CGI::tag("INPUT", {"TYPE"=>"submit", "VALUE"=>"submit"}) - } + - CGI::tag("HR") - } - } - } - - -== make raw cookie string - - require "cgi-lib.rb" - cookie1 = CGI::cookie({'name' => 'name', - 'value' => 'value', - 'path' => 'path', # optional - 'domain' => 'domain', # optional - 'expires' => Time.now, # optional - 'secure' => true # optional - }) - - CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" } - - -== print HTTP header and string to $> - - require "cgi-lib.rb" - CGI::print{ "string" } - # == CGI::print("Content-Type: text/html"){ "string" } - CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" } - - -=== NPH (no-parse-header) mode - - require "cgi-lib.rb" - CGI::print("nph"){ "string" } - # == CGI::print("nph", "Content-Type: text/html"){ "string" } - CGI::print("nph", "Content-Type: text/html", cookie1, cookie2){ "string" } - - -== make HTML tag string - - require "cgi-lib.rb" - CGI::tag("element", {"attribute_name"=>"attribute_value"}){"content"} - - -== make HTTP header string - - require "cgi-lib.rb" - CGI::header # == CGI::header("Content-Type: text/html") - CGI::header("Content-Type: text/html", cookie1, cookie2) - - -=== NPH (no-parse-header) mode - - CGI::header("nph") # == CGI::header("nph", "Content-Type: text/html") - CGI::header("nph", "Content-Type: text/html", cookie1, cookie2) - - -== escape url encode - - require "cgi-lib.rb" - url_encoded_string = CGI::escape("string") - - -== unescape url encoded - - require "cgi-lib.rb" - string = CGI::unescape("url encoded string") - - -== escape HTML &"<> - - require "cgi-lib.rb" - CGI::escapeHTML("string") - - -=end - -require "delegate" - -class CGI < SimpleDelegator - - CR = "\015" - LF = "\012" - EOL = CR + LF - - RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ] - RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ] - - # make rfc1123 date string - def CGI::rfc1123_date(time) - t = time.clone.gmtime - return format("%s, %.2d %s %d %.2d:%.2d:%.2d GMT", - RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year, - t.hour, t.min, t.sec) - end - - # escape url encode - def CGI::escape(str) - str.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) } - end - - # unescape url encoded - def CGI::unescape(str) - str.gsub(/\+/, ' ').gsub(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") } - end - - # escape HTML - def CGI::escapeHTML(str) - str.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/" + - (iterator? ? yield.to_s + "" : "") - end - - # make raw cookie string - def CGI::cookie(options) - "Set-Cookie: " + options['name'] + '=' + escape(options['value']) + - (options['domain'] ? '; domain=' + options['domain'] : '') + - (options['path'] ? '; path=' + options['path'] : '') + - (options['expires'] ? '; expires=' + rfc1123_date(options['expires']) : '') + - (options['secure'] ? '; secure' : '') - end - - # make HTTP header string - def CGI::header(*options) - if defined?(MOD_RUBY) - options.each{|option| - option.sub(/(.*?): (.*)/){ - Apache::request.headers_out[$1] = $2 - } - } - Apache::request.send_http_header - '' - else - if options.delete("nph") or (ENV['SERVER_SOFTWARE'] =~ /IIS/) - [(ENV['SERVER_PROTOCOL'] or "HTTP/1.0") + " 200 OK", - "Date: " + rfc1123_date(Time.now), - "Server: " + (ENV['SERVER_SOFTWARE'] or ""), - "Connection: close"] + - (options.empty? ? ["Content-Type: text/html"] : options) - else - options.empty? ? ["Content-Type: text/html"] : options - end.join(EOL) + EOL + EOL - end - end - - # print HTTP header and string to $> - def CGI::print(*options) - $>.print CGI::header(*options) + yield.to_s - end - - # print message to $> - def CGI::message(message, title = "", header = ["Content-Type: text/html"]) - if message.kind_of?(Hash) - title = message['title'] - header = message['header'] - message = message['body'] - end - CGI::print(*header){ - CGI::tag("HTML"){ - CGI::tag("HEAD"){ CGI.tag("TITLE"){ title } } + - CGI::tag("BODY"){ message } - } - } - true - end - - # print error message to $> and exit - def CGI::error - CGI::message({'title'=>'ERROR', 'body'=> - CGI::tag("PRE"){ - "ERROR: " + CGI::tag("STRONG"){ escapeHTML($!.to_s) } + "\n" + escapeHTML($@.join("\n")) - } - }) - exit - end -end diff --git a/test/rss/test_xml-stylesheet.rb b/test/rss/test_xml-stylesheet.rb index 791fded605..c88a858f56 100644 --- a/test/rss/test_xml-stylesheet.rb +++ b/test/rss/test_xml-stylesheet.rb @@ -74,12 +74,10 @@ module RSS :media => "printer", :charset => "UTF-8", :alternate => "yes"},], ].each do |xsss| - p xsss doc = REXML::Document.new(make_sample_RDF) root = doc.root xsss.each do |xss| content = xss.collect do |key, name| - p [key, name] %Q[#{key}="#{name}"] end.join(" ") pi = REXML::Instruction.new("xml-stylesheet", content)