[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]