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

ruby-changes:40870

From: ko1 <ko1@a...>
Date: Tue, 8 Dec 2015 22:59:04 +0900 (JST)
Subject: [ruby-changes:40870] ko1:r52949 (trunk): * introduce new ISeq binary format serializer/de-serializer

ko1	2015-12-08 22:58:50 +0900 (Tue, 08 Dec 2015)

  New Revision: 52949

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=52949

  Log:
    * introduce new ISeq binary format serializer/de-serializer
      and a pre-compilation/runtime loader sample.
      [Feature #11788]
    
    * iseq.c: add new methods:
      * RubyVM::InstructionSequence#to_binary_format(extra_data = nil)
      * RubyVM::InstructionSequence.from_binary_format(binary)
      * RubyVM::InstructionSequence.from_binary_format_extra_data(binary)
    
    * compile.c: implement body of this new feature.
    
    * load.c (rb_load_internal0), iseq.c (rb_iseq_load_iseq):
      call RubyVM::InstructionSequence.load_iseq(fname) with
      loading script name if this method is defined.
    
      We can return any ISeq object as a result value.
      Otherwise loading will be continue as usual.
    
      This interface is not matured and is not extensible.
      So that we don't guarantee the future compatibility of this method.
      Basically, you should'nt use this method.
    
    * iseq.h: move ISEQ_MAJOR/MINOR_VERSION (and some definitions)
      from iseq.c.
    
    * encoding.c (rb_data_is_encoding), internal.h: added.
    
    * vm_core.h: add several supports for lazy load.
      * add USE_LAZY_LOAD macro to specify enable or disable of
        this feature.
      * add several fields to rb_iseq_t.
      * introduce new macro rb_iseq_check().
    
    * insns.def: some check for lazy loading feature.
    
    * vm_insnhelper.c: ditto.
    
    * proc.c: ditto.
    
    * vm.c: ditto.
    
    * test/lib/iseq_loader_checker.rb: enabled iff suitable
      environment variables are provided.
    
    * test/runner.rb: enable lib/iseq_loader_checker.rb.
    
    * sample/iseq_loader.rb: add sample compiler and loader.
    
        $ ruby sample/iseq_loader.rb [dir]
    
      will compile all ruby scripts in [dir].
      With default setting, this compile creates *.rb.yarb files
      in same directory of target .rb scripts.
    
        $ ruby -r sample/iseq_loader.rb [app]
    
      will run with enable to load compiled binary data.

  Added files:
    trunk/sample/iseq_loader.rb
  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/compile.c
    trunk/encoding.c
    trunk/insns.def
    trunk/internal.h
    trunk/iseq.c
    trunk/iseq.h
    trunk/load.c
    trunk/proc.c
    trunk/test/lib/iseq_loader_checker.rb
    trunk/test/runner.rb
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_insnhelper.c
Index: encoding.c
===================================================================
--- encoding.c	(revision 52948)
+++ encoding.c	(revision 52949)
@@ -86,6 +86,12 @@ static const rb_data_type_t encoding_dat https://github.com/ruby/ruby/blob/trunk/encoding.c#L86
 #define is_data_encoding(obj) (RTYPEDDATA_P(obj) && RTYPEDDATA_TYPE(obj) == &encoding_data_type)
 #define is_obj_encoding(obj) (RB_TYPE_P((obj), T_DATA) && is_data_encoding(obj))
 
+int
+rb_data_is_encoding(VALUE obj)
+{
+    return is_data_encoding(obj);
+}
+
 static VALUE
 enc_new(rb_encoding *encoding)
 {
Index: insns.def
===================================================================
--- insns.def	(revision 52948)
+++ insns.def	(revision 52949)
@@ -928,13 +928,15 @@ defineclass https://github.com/ruby/ruby/blob/trunk/insns.def#L928
 	rb_bug("unknown defineclass type: %d", (int)type);
     }
 
+    rb_iseq_check(class_iseq);
+
     /* enter scope */
     vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS, klass,
 		  VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
 		  (VALUE)vm_cref_push(th, klass, NULL, FALSE),
 		  class_iseq->body->iseq_encoded, GET_SP(),
-		  class_iseq->body->local_size, class_iseq->body->stack_max);
-
+		  class_iseq->body->local_size,
+		  class_iseq->body->stack_max);
     RESTORE_REGS();
     NEXT_INSN();
 }
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 52948)
+++ ChangeLog	(revision 52949)
@@ -1,3 +1,63 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Dec  8 22:31:58 2015  Koichi Sasada  <ko1@a...>
+
+	* introduce new ISeq binary format serializer/de-serializer
+	  and a pre-compilation/runtime loader sample.
+	  [Feature #11788]
+
+	* iseq.c: add new methods:
+	  * RubyVM::InstructionSequence#to_binary_format(extra_data = nil)
+	  * RubyVM::InstructionSequence.from_binary_format(binary)
+	  * RubyVM::InstructionSequence.from_binary_format_extra_data(binary)
+
+	* compile.c: implement body of this new feature.
+
+	* load.c (rb_load_internal0), iseq.c (rb_iseq_load_iseq):
+	  call RubyVM::InstructionSequence.load_iseq(fname) with
+	  loading script name if this method is defined.
+
+	  We can return any ISeq object as a result value.
+	  Otherwise loading will be continue as usual.
+
+	  This interface is not matured and is not extensible.
+	  So that we don't guarantee the future compatibility of this method.
+	  Basically, you should'nt use this method.
+
+	* iseq.h: move ISEQ_MAJOR/MINOR_VERSION (and some definitions)
+	  from iseq.c.
+
+	* encoding.c (rb_data_is_encoding), internal.h: added.
+
+	* vm_core.h: add several supports for lazy load.
+	  * add USE_LAZY_LOAD macro to specify enable or disable of
+	    this feature.
+	  * add several fields to rb_iseq_t.
+	  * introduce new macro rb_iseq_check().
+
+	* insns.def: some check for lazy loading feature.
+
+	* vm_insnhelper.c: ditto.
+
+	* proc.c: ditto.
+
+	* vm.c: ditto.
+
+	* test/lib/iseq_loader_checker.rb: enabled iff suitable
+	  environment variables are provided.
+
+	* test/runner.rb: enable lib/iseq_loader_checker.rb.
+
+	* sample/iseq_loader.rb: add sample compiler and loader.
+
+	    $ ruby sample/iseq_loader.rb [dir]
+
+	  will compile all ruby scripts in [dir].
+	  With default setting, this compile creates *.rb.yarb files
+	  in same directory of target .rb scripts.
+
+	    $ ruby -r sample/iseq_loader.rb [app]
+
+	  will run with enable to load compiled binary data.
+
 Tue Dec  8 21:21:16 2015  Kazuhiro NISHIYAMA  <zn@m...>
 
 	* NEWS: mention about Enumerator::Lazy#grep_v.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 52948)
+++ vm_core.h	(revision 52949)
@@ -257,10 +257,10 @@ struct rb_call_cache { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L257
 #endif
 
 typedef struct rb_iseq_location_struct {
-    const VALUE path;
-    const VALUE absolute_path;
-    const VALUE base_label;
-    const VALUE label;
+    VALUE path;
+    VALUE absolute_path;
+    VALUE base_label;
+    VALUE label;
     VALUE first_lineno; /* TODO: may be unsigned short */
 } rb_iseq_location_t;
 
@@ -376,7 +376,7 @@ struct rb_iseq_constant_body { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L376
 				      */
     struct rb_call_cache *cc_entries; /* size is ci_size = ci_kw_size */
 
-    const VALUE mark_ary;     /* Array: includes operands which should be GC marked */
+    VALUE mark_ary;     /* Array: includes operands which should be GC marked */
 
     unsigned int local_table_size;
     unsigned int is_size;
@@ -389,12 +389,40 @@ struct rb_iseq_constant_body { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L389
 /* typedef rb_iseq_t is in method.h */
 struct rb_iseq_struct {
     VALUE flags;
-    struct iseq_compile_data *compile_data_; /* used at compile time */
-    struct rb_iseq_constant_body *body;
     VALUE reserved1;
-    VALUE reserved2;
+    struct rb_iseq_constant_body *body;
+
+    union { /* 4, 5 words */
+	struct iseq_compile_data *compile_data; /* used at compile time */
+
+	struct {
+	    VALUE obj;
+	    int index;
+	} loader;
+    } aux;
 };
 
+#define USE_LAZY_LOAD 0
+
+#ifndef USE_LAZY_LOAD
+#define USE_LAZY_LOAD
+#endif
+
+#if USE_LAZY_LOAD
+const rb_iseq_t *rb_iseq_complete(const rb_iseq_t *iseq);
+
+static inline const rb_iseq_t *
+rb_iseq_check(const rb_iseq_t *iseq)
+{
+    if (iseq->body == NULL) {
+	rb_iseq_complete((rb_iseq_t *)iseq);
+    }
+    return iseq;
+}
+#else
+#define rb_iseq_check(iseq) iseq
+#endif
+
 enum ruby_special_exceptions {
     ruby_error_reenter,
     ruby_error_nomemory,
@@ -962,7 +990,7 @@ rb_block_t *rb_vm_control_frame_block_pt https://github.com/ruby/ruby/blob/trunk/vm_core.h#L990
   (!RUBY_VM_VALID_CONTROL_FRAME_P((cfp), RUBY_VM_END_CONTROL_FRAME(th)))
 
 #define RUBY_VM_IFUNC_P(ptr)        (RB_TYPE_P((VALUE)(ptr), T_IMEMO) && imemo_type((VALUE)ptr) == imemo_ifunc)
-#define RUBY_VM_NORMAL_ISEQ_P(ptr)  (RB_TYPE_P((VALUE)(ptr), T_IMEMO) && imemo_type((VALUE)ptr) == imemo_iseq)
+#define RUBY_VM_NORMAL_ISEQ_P(ptr)  (RB_TYPE_P((VALUE)(ptr), T_IMEMO) && imemo_type((VALUE)ptr) == imemo_iseq && rb_iseq_check((rb_iseq_t *)ptr))
 
 #define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self))
 #define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \
Index: sample/iseq_loader.rb
===================================================================
--- sample/iseq_loader.rb	(revision 0)
+++ sample/iseq_loader.rb	(revision 52949)
@@ -0,0 +1,240 @@ https://github.com/ruby/ruby/blob/trunk/sample/iseq_loader.rb#L1
+#
+# iseq_loader.rb - sample of compiler/loader for binary compiled file
+#
+# Usage as a compiler: ruby iseq_loader.rb [file or directory] ...
+#
+#   It compiles and stores specified files.
+#   If directories are specified, then compiles and stores all *.rb files.
+#   (using Dir.glob)
+#
+# TODO: add remove option
+# TODO: add verify option
+#
+# Usage as a loader: simply require this file with the following setting.
+#
+# Setting with environment variables.
+#
+#  * RUBY_ISEQ_LOADER_STORAGE to select storage type
+#    * dbm: use dbm
+#    * fs: [default] use file system. locate a compiled binary files in same
+#      directory of scripts like Rubinius. foo.rb.yarb will be created for foo.rb.
+#    * fs2: use file system. locate compiled file in specified directory.
+#    * nothing: do nothing.
+#
+#  * RUBY_ISEQ_LOADER_STORAGE_DIR to select directory
+#    * default: ~/.ruby_binaries/
+#
+#  * RUBY_ISEQ_LOADER_STORAGE_COMPILE_IF_NOT_COMPILED
+#    * true: store compiled file if compiled data is not available.
+#    * false: [default] do nothing if there is no compiled iseq data.
+
+class RubyVM::InstructionSequence
+  $ISEQ_LOADER_LOADED = 0
+  $ISEQ_LOADER_COMPILED = 0
+  $ISEQ_LOADER_IGNORED = 0
+  LAUNCHED_TIME = Time.now
+  COMPILE_FILE_ENABLE = false || true
+  COMPILE_VERBOSE = $VERBOSE || false # || true
+  COMPILE_DEBUG = ENV['RUBY_ISEQ_LOADER_DEBUG']
+  COMPILE_IF_NOT_COMPILED = ENV['RUBY_ISEQ_LOADER_STORAGE_COMPILE_IF_NOT_COMPILED'] == 'true'
+
+  at_exit{
+    STDERR.puts "[ISEQ_LOADER] #{Process.pid} time: #{Time.now - LAUNCHED_TIME}, " +
+                "loaded: #{$ISEQ_LOADER_LOADED}, " +
+                "compied: #{$ISEQ_LOADER_COMPILED}, " +
+                "ignored: #{$ISEQ_LOADER_IGNORED}"
+  } if COMPILE_VERBOSE
+
+  unless cf_dir = ENV['RUBY_ISEQ_LOADER_STORAGE_DIR']
+    cf_dir = File.expand_path("~/.ruby_binaries")
+    unless File.exist?(cf_dir)
+      Dir.mkdir(cf_dir)
+    end
+  end
+  CF_PREFIX = "#{cf_dir}/cb."
+
+  class NullStorage
+    def load_iseq fname; end
+    def compile_and_save_isq fname; end
+    def unlink_compiled_iseq; end
+  end
+
+  class BasicStorage
+    def initialize
+      require 'digest/sha1'
+    end
+
+    def load_iseq fname
+      iseq_key = iseq_key_name(fname)
+      if compiled_iseq_exist?(fname, iseq_key) && compiled_iseq_is_younger?(fname, iseq_key)
+        $ISEQ_LOADER_LOADED += 1
+        STDERR.puts "[ISEQ_LOADER] #{Process.pid} load #{fname} from #{iseq_key}" if COMPILE_DEBUG
+        binary = read_compiled_iseq(fname, iseq_key)
+        RubyVM::InstructionSequence.from_binary_format(binary)
+      elsif COMPILE_IF_NOT_COMPILED
+        compile_and_save_iseq(fname, iseq_key)
+      else
+        $ISEQ_LOADER_IGNORED += 1
+        # p fname
+        nil
+      end
+    end
+
+    def extra_data fname
+      "SHA-1:#{::Digest::SHA1.file(fname).digest}"
+    end
+
+    def compile_and_save_iseq fname, iseq_key = iseq_key_name(fname)
+      $ISEQ_LOADER_COMPILED += 1
+      STDERR.puts "[RUBY_COMPILED_FILE] compile #{fname}" if COMPILE_DEBUG
+      iseq = RubyVM::InstructionSequence.compile_file(fname)
+      
+      binary = iseq.to_binary_format(extra_data(fname))
+      write_compiled_iseq(fname, iseq_key, binary)
+      iseq
+    end
+
+    # def unlink_compiled_iseq; nil; end # should implement at sub classes
+
+    private
+
+    def iseq_key_name fname
+      fname
+    end
+
+    # should implement at sub classes
+    # def compiled_iseq_younger? fname, iseq_key; end
+    # def compiled_iseq_exist? fname, iseq_key; end
+    # def read_compiled_file fname, iseq_key; end
+    # def write_compiled_file fname, iseq_key, binary; end
+  end
+
+  class FSStorage < BasicStorage
+    def initialize
+      super
+      require 'fileutils'
+      @dir = CF_PREFIX + "files"
+      unless File.directory?(@dir)
+        FileUtils.mkdir_p(@dir)
+      end
+    end
+
+    def unlink_compiled_iseq
+      File.unlink(compile_file_path)
+    end
+
+    private
+
+    def iseq_key_name fname
+      "#{fname}.yarb" # same directory
+    end
+
+    def compiled_iseq_exist? fname, iseq_key
+      File.exist?(iseq_key)
+    end
+
+    def compiled_iseq_is_younger? fname, iseq_key
+      File.mtime(iseq_key) >= File.mtime(fname)
+    end
+
+    def read_compiled_iseq fname, iseq_key
+      open(iseq_key, 'rb'){|f| f.read}
+    end
+
+    def write_compiled_iseq fname, iseq_key, binary
+      open(iseq_key, 'wb'){|f| f.write(binary)}
+    end
+  end
+
+  class FS2Storage < FSStorage
+    def iseq_key_name fname
+      @dir + fname.gsub(/[^A-Za-z0-9\._-]/){|c| '%02x' % c.ord} # special directory
+    end
+  end
+
+  class DBMStorage < BasicStorage
+    def initialize
+      require 'dbm'
+      @db = DBM.open(CF_PREFIX+'db')
+    end
+
+    def unlink_compiled_iseq
+      @db.delete fname
+    end
+
+    private
+
+    def date_key_name fname
+      "date.#{fname}"
+    end
+
+    def iseq_key_name fname
+      "body.#{fname}"
+    end
+
+    def compiled_iseq_exist? fname, iseq_key
+      @db.has_key? iseq_key
+    end
+
+    def compiled_iseq_is_younger? fname, iseq_key
+      date_key = date_key_name(fname)
+      if @db.has_key? date_key
+        @db[date_key].to_i >= File.mtime(fname).to_i
+      end
+    end
+
+    def read_compiled_iseq fname, iseq_key
+      @db[iseq_key]
+    end
+
+    def write_compiled_iseq fname, iseq_key, binary
+      date_key = date_key_name(fname)
+      @db[iseq_key] = binary
+      @db[date_key] = Time.now.to_i
+    end
+  end
+
+  STORAGE = case ENV['RUBY_ISEQ_LOADER_STORAGE']
+            when 'dbm'
+              DBMStorage.new
+            when 'fs'
+              FSStorage.new
+            when 'fs2'
+              FS2Storage.new
+            when 'null'
+              NullStorage.new
+            else
+              FSStorage.new
+            end
+
+  STDERR.puts "[ISEQ_LOADER] use #{STORAGE.class} " if COMPILE_VERBOSE
+
+  def self.load_iseq fname
+    STORAGE.load_iseq(fname)
+  end
+
+  def self.compile_and_save_iseq fname
+    STORAGE.compile_and_save_iseq fname
+  end
+
+  def self.unlink_compiled_iseq fname
+    STORAGE.unlink_compiled_iseq fname
+  end
+end
+
+if __FILE__ == $0
+  ARGV.each{|path|
+    if File.directory?(path)
+      pattern = File.join(path, '**/*.rb')
+      Dir.glob(pattern){|file|
+        begin
+          RubyVM::InstructionSequence.compile_and_save_iseq(file)
+        rescue SyntaxError => e
+          STDERR.puts e
+        end
+      }
+    else
+      RubyVM::InstructionSequence.compile_and_save_iseq(path)
+    end
+  }
+end
Index: iseq.c
===================================================================
--- iseq.c	(revision 52948)
+++ iseq.c	(revision 52949)
@@ -25,9 +25,6 @@ https://github.com/ruby/ruby/blob/trunk/iseq.c#L25
 #include "insns.inc"
 #include "insns_info.inc"
 
-#define ISEQ_MAJOR_VERSION 2
-#define ISEQ_MINOR_VERSION 3
-
 VALUE rb_cISeq;
 static VALUE iseqw_new(const rb_iseq_t *iseq);
 static const rb_iseq_t *iseqw_check(VALUE iseqw);
@@ -71,30 +68,32 @@ rb_iseq_free(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L68
     RUBY_FREE_ENTER("iseq");
 
     if (iseq) {
-	ruby_xfree((void *)iseq->body->iseq_encoded);
-	ruby_xfree((void *)iseq->body->line_info_table);
-	ruby_xfree((void *)iseq->body->local_table);
-	ruby_xfree((void *)iseq->body->is_entries);
-
-	if (iseq->body->ci_entries) {
-	    unsigned int i;
-	    struct rb_call_info_with_kwarg *ci_kw_entries = (struct rb_call_info_with_kwarg *)&iseq->body->ci_entries[iseq->body->ci_size];
-	    for (i=0; i<iseq->body->ci_kw_size; i++) {
-		const struct rb_call_info_kw_arg *kw_arg = ci_kw_entries[i].kw_arg;
-		ruby_xfree((void *)kw_arg);
+	if (iseq->body) {
+	    ruby_xfree((void *)iseq->body->iseq_encoded);
+	    ruby_xfree((void *)iseq->body->line_info_table);
+	    ruby_xfree((void *)iseq->body->local_table);
+	    ruby_xfree((void *)iseq->body->is_entries);
+
+	    if (iseq->body->ci_entries) {
+		unsigned int i;
+		struct rb_call_info_with_kwarg *ci_kw_entries = (struct rb_call_info_with_kwarg *)&iseq->body->ci_entries[iseq->body->ci_size];
+		for (i=0; i<iseq->body->ci_kw_size; i++) {
+		    const struct rb_call_info_kw_arg *kw_arg = ci_kw_entries[i].kw_arg;
+		    ruby_xfree((void *)kw_arg);
+		}
+		ruby_xfree(iseq->body->ci_entries);
+		ruby_xfree(iseq->body->cc_entries);
 	    }
-	    ruby_xfree(iseq->body->ci_entries);
-	    ruby_xfree(iseq->body->cc_entries);
-	}
-	ruby_xfree((void *)iseq->body->catch_table);
-	ruby_xfree((void *)iseq->body->param.opt_table);
+	    ruby_xfree((void *)iseq->body->catch_table);
+	    ruby_xfree((void *)iseq->body->param.opt_table);
 
-	if (iseq->body->param.keyword != NULL) {
-	    ruby_xfree((void *)iseq->body->param.keyword->default_values);
-	    ruby_xfree((void *)iseq->body->param.keyword);
+	    if (iseq->body->param.keyword != NULL) {
+		ruby_xfree((void *)iseq->body->param.keyword->default_values);
+		ruby_xfree((void *)iseq->body->param.keyword);
+	    }
+	    compile_data_free(ISEQ_COMPILE_DATA(iseq));
+	    ruby_xfree(iseq->body);
 	}
-	compile_data_free(ISEQ_COMPILE_DATA(iseq));
-	ruby_xfree(iseq->body);
     }
     RUBY_FREE_LEAVE("iseq");
 }
@@ -116,9 +115,11 @@ rb_iseq_mark(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L115
 	RUBY_MARK_UNLESS_NULL(body->location.absolute_path);
     }
 
-    if (ISEQ_COMPILE_DATA(iseq) != 0) {
+    if (FL_TEST(iseq, ISEQ_NOT_LOADED_YET)) {
+	rb_gc_mark(iseq->aux.loader.obj);
+    }
+    else if (ISEQ_COMPILE_DATA(iseq) != 0) {
 	const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
-
 	RUBY_MARK_UNLESS_NULL(compile_data->mark_ary);
 	RUBY_MARK_UNLESS_NULL(compile_data->err_info);
 	RUBY_MARK_UNLESS_NULL(compile_data->catch_table_ary);
@@ -205,7 +206,7 @@ iseq_memsize(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L206
 static rb_iseq_t *
 iseq_alloc(void)
 {
-    rb_iseq_t *iseq = (rb_iseq_t *)rb_imemo_new(imemo_iseq, 0, 0, 0, 0);
+    rb_iseq_t *iseq = iseq_imemo_alloc();
     iseq->body = ZALLOC(struct rb_iseq_constant_body);
     return iseq;
 }
@@ -260,16 +261,6 @@ rb_iseq_add_mark_object(const rb_iseq_t https://github.com/ruby/ruby/blob/trunk/iseq.c#L261
 }
 
 static VALUE
-iseq_mark_ary_create(int flip_cnt)
-{
-    VALUE ary = rb_ary_tmp_new(3);
-    rb_ary_push(ary, Qnil);              /* ISEQ_MARK_ARY_COVERAGE */
-    rb_ary_push(ary, INT2FIX(flip_cnt)); /* ISEQ_MARK_ARY_FLIP_CNT */
-    rb_ary_push(ary, Qnil);              /* ISEQ_MARK_ARY_ORIGINAL_ISEQ */
-    return ary;
-}
-
-static VALUE
 prepare_iseq_build(rb_iseq_t *iseq,
 		   VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno,
 		   const rb_iseq_t *parent, enum iseq_type type,
@@ -485,6 +476,19 @@ rb_iseq_new_with_opt(NODE *node, VALUE n https://github.com/ruby/ruby/blob/trunk/iseq.c#L476
     return iseq_translate(iseq);
 }
 
+const rb_iseq_t *
+rb_iseq_load_iseq(VALUE fname)
+{
+    if (rb_respond_to(rb_cISeq, rb_intern("load_iseq"))) {
+	VALUE iseqv = rb_funcall(rb_cISeq, rb_intern("load_iseq"), 1, fname);
+	if (CLASS_OF(iseqv) == rb_cISeq) {
+	    return  iseqw_check(iseqv);
+	}
+    }
+
+    return NULL;
+}
+
 #define CHECK_ARRAY(v)   rb_convert_type((v), T_ARRAY, "Array", "to_ary")
 #define CHECK_HASH(v)    rb_convert_type((v), T_HASH, "Hash", "to_hash")
 #define CHECK_STRING(v)  rb_convert_type((v), T_STRING, "String", "to_str")
@@ -583,8 +587,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/iseq.c#L587
 iseq_s_load(int argc, VALUE *argv, VALUE self)
 {
     VALUE data, opt=Qnil;
-    rb_scan_args(argc, argv, "11", &data, &opt);
-
+    rb_scan_args(argc, argv, "01", &opt);
     return iseq_load(data, NULL, opt);
 }
 
@@ -892,7 +895,11 @@ iseqw_s_compile_option_get(VALUE self) https://github.com/ruby/ruby/blob/trunk/iseq.c#L895
 static const rb_iseq_t *
 iseqw_check(VALUE iseqw)
 {
-    const rb_iseq_t *iseq = DATA_PTR(iseqw);
+    rb_iseq_t *iseq = DATA_PTR(iseqw);
+
+    if (!iseq->body) {
+	ibf_load_iseq_complete(iseq);
+    }
 
     if (!iseq->body->location.label) {
 	rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
@@ -1235,7 +1242,7 @@ rb_insn_operand_intern(const rb_iseq_t * https://github.com/ruby/ruby/blob/trunk/iseq.c#L1242
 {
     const char *types = insn_op_types(insn);
     char type = types[op_no];
-    VALUE ret;
+    VALUE ret = Qundef;
 
     switch (type) {
       case TS_OFFSET:		/* LONG */
@@ -1281,8 +1288,8 @@ rb_insn_operand_intern(const rb_iseq_t * https://github.com/ruby/ruby/blob/trunk/iseq.c#L1288
 
       case TS_ISEQ:		/* iseq */
 	{
-	    rb_iseq_t *iseq = (rb_iseq_t *)op;
-	    if (iseq) {
+	    if (op) {
+		const rb_iseq_t *iseq = rb_iseq_check((rb_iseq_t *)op);
 		ret = iseq->body->location.label;
 		if (child) {
 		    rb_ary_push(child, (VALUE)iseq);
@@ -1492,7 +1499,7 @@ rb_iseq_disasm(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L1499
 			catch_type((int)entry->type), (int)entry->start,
 			(int)entry->end, (int)entry->sp, (int)entry->cont);
 	    if (entry->iseq) {
-		rb_str_concat(str, rb_iseq_disasm(entry->iseq));
+		rb_str_concat(str, rb_iseq_disasm(rb_iseq_check(entry->iseq)));
 	    }
 	}
     }
@@ -1561,7 +1568,7 @@ rb_iseq_disasm(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L1568
 
     for (l = 0; l < RARRAY_LEN(child); l++) {
 	VALUE isv = rb_ary_entry(child, l);
-	rb_str_concat(str, rb_ise (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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