ruby-changes:56876
From: Nobuyoshi <ko1@a...>
Date: Thu, 8 Aug 2019 22:34:52 +0900 (JST)
Subject: [ruby-changes:56876] Nobuyoshi Nakada: 995c2e9536 (master): Reduce unnecessary EXEC_TAG in require
https://git.ruby-lang.org/ruby.git/commit/?id=995c2e9536 From 995c2e9536a7c0f0476d1f62ac3c9bcb68513c59 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Thu, 8 Aug 2019 22:17:22 +0900 Subject: Reduce unnecessary EXEC_TAG in require diff --git a/load.c b/load.c index ba84ec0..8b872a8 100644 --- a/load.c +++ b/load.c @@ -569,6 +569,24 @@ rb_provide(const char *feature) https://github.com/ruby/ruby/blob/trunk/load.c#L569 NORETURN(static void load_failed(VALUE)); static inline void +load_iseq_eval(rb_execution_context_t *ec, VALUE fname) +{ + const rb_iseq_t *iseq = rb_iseq_load_iseq(fname); + + if (!iseq) { + rb_ast_t *ast; + VALUE parser = rb_parser_new(); + rb_parser_set_context(parser, NULL, FALSE); + ast = (rb_ast_t *)rb_parser_load_file(parser, fname); + iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"), + fname, rb_realpath_internal(Qnil, fname, 1), NULL); + rb_ast_dispose(ast); + } + rb_exec_event_hook_script_compiled(ec, iseq, Qnil); + rb_iseq_eval(iseq); +} + +static inline enum ruby_tag_type rb_load_internal0(rb_execution_context_t *ec, VALUE fname, int wrap) { enum ruby_tag_type state; @@ -594,22 +612,7 @@ rb_load_internal0(rb_execution_context_t *ec, VALUE fname, int wrap) https://github.com/ruby/ruby/blob/trunk/load.c#L612 EC_PUSH_TAG(ec); state = EC_EXEC_TAG(); if (state == TAG_NONE) { - rb_ast_t *ast; - const rb_iseq_t *iseq; - - if ((iseq = rb_iseq_load_iseq(fname)) != NULL) { - /* OK */ - } - else { - VALUE parser = rb_parser_new(); - rb_parser_set_context(parser, NULL, FALSE); - ast = (rb_ast_t *)rb_parser_load_file(parser, fname); - iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"), - fname, rb_realpath_internal(Qnil, fname, 1), NULL); - rb_ast_dispose(ast); - } - rb_exec_event_hook_script_compiled(ec, iseq, Qnil); - rb_iseq_eval(iseq); + load_iseq_eval(ec, fname); } EC_POP_TAG(); @@ -619,7 +622,12 @@ rb_load_internal0(rb_execution_context_t *ec, VALUE fname, int wrap) https://github.com/ruby/ruby/blob/trunk/load.c#L622 #endif th->top_self = self; th->top_wrapper = wrapper; + return state; +} +static inline void +raise_load_if_failed(rb_execution_context_t *ec, enum ruby_tag_type state) +{ if (state) { rb_vm_jump_tag_but_local_jump(state); } @@ -633,7 +641,7 @@ static void https://github.com/ruby/ruby/blob/trunk/load.c#L641 rb_load_internal(VALUE fname, int wrap) { rb_execution_context_t *ec = GET_EC(); - rb_load_internal0(ec, fname, wrap); + raise_load_if_failed(ec, rb_load_internal0(ec, fname, wrap)); } void @@ -966,11 +974,10 @@ rb_resolve_feature_path(VALUE klass, VALUE fname) https://github.com/ruby/ruby/blob/trunk/load.c#L974 * <0: not found (LoadError) * >1: exception */ -int -rb_require_internal(VALUE fname, int safe) +static int +require_internal(rb_execution_context_t *ec, VALUE fname, int safe, int exception) { volatile int result = -1; - rb_execution_context_t *ec = GET_EC(); volatile VALUE errinfo = ec->errinfo; enum ruby_tag_type state; struct { @@ -985,6 +992,7 @@ rb_require_internal(VALUE fname, int safe) https://github.com/ruby/ruby/blob/trunk/load.c#L992 EC_PUSH_TAG(ec); saved.safe = rb_safe_level(); + ec->errinfo = Qnil; /* ensure */ if ((state = EC_EXEC_TAG()) == TAG_NONE) { long handle; int found; @@ -1006,7 +1014,7 @@ rb_require_internal(VALUE fname, int safe) https://github.com/ruby/ruby/blob/trunk/load.c#L1014 else { switch (found) { case 'r': - rb_load_internal(path, 0); + load_iseq_eval(ec, path); break; case 's': @@ -1025,10 +1033,24 @@ rb_require_internal(VALUE fname, int safe) https://github.com/ruby/ruby/blob/trunk/load.c#L1033 rb_set_safe_level_force(saved.safe); if (state) { + if (exception) { + /* usually state == TAG_RAISE only, except for + * rb_iseq_load_iseq in load_iseq_eval case */ + VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef); + if (!NIL_P(exc)) ec->errinfo = exc; + return TAG_RAISE; + } + else if (state == TAG_RETURN) { + return TAG_RAISE; + } RB_GC_GUARD(fname); /* never TAG_RETURN */ return state; } + if (!NIL_P(ec->errinfo)) { + if (!exception) return TAG_RAISE; + rb_exc_raise(ec->errinfo); + } ec->errinfo = errinfo; @@ -1038,11 +1060,19 @@ rb_require_internal(VALUE fname, int safe) https://github.com/ruby/ruby/blob/trunk/load.c#L1060 } int +rb_require_internal(VALUE fname, int safe) +{ + rb_execution_context_t *ec = GET_EC(); + return require_internal(ec, fname, safe, 1); +} + +int ruby_require_internal(const char *fname, unsigned int len) { struct RString fake; VALUE str = rb_setup_fake_str(&fake, fname, len, 0); - int result = rb_require_internal(str, 0); + rb_execution_context_t *ec = GET_EC(); + int result = require_internal(ec, str, 0, 0); rb_set_errinfo(Qnil); return result == TAG_RETURN ? 1 : result ? -1 : 0; } @@ -1050,10 +1080,11 @@ ruby_require_internal(const char *fname, unsigned int len) https://github.com/ruby/ruby/blob/trunk/load.c#L1080 VALUE rb_require_safe(VALUE fname, int safe) { - int result = rb_require_internal(fname, safe); + rb_execution_context_t *ec = GET_EC(); + int result = require_internal(ec, fname, safe, 1); if (result > TAG_RETURN) { - EC_JUMP_TAG(GET_EC(), result); + EC_JUMP_TAG(ec, result); } if (result < 0) { load_failed(fname); diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb index 56dfd95..2504b9e 100644 --- a/test/ruby/test_require.rb +++ b/test/ruby/test_require.rb @@ -260,8 +260,8 @@ class TestRequire < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_require.rb#L260 e = assert_raise_with_message(SyntaxError, /unexpected/) { yield req } - assert_not_nil(bt = e.backtrace) - assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}) + assert_not_nil(bt = e.backtrace, "no backtrace") + assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}, proc {bt.inspect}) end end -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/