1 # depends on: module.rb
6 # This const controls what the lowest version of compiled methods we can
7 # allow is. This allows us to cut off compability at some point, or just
8 # increment when major changes are made to the compiler.
10 CompiledMethodVersion = 6
15 # A module for selecting which Rubinius compiler to use.
21 DefaultCompiler = "compiler"
23 def self.register_compiler(obj)
25 $stderr.puts "[Registered #{obj} as system compiler]"
30 def self.find_compiler
33 loading_rbc_directly do
34 require "#{DefaultCompiler}/init"
37 STDERR.puts "Unable to load default compiler: #{e.message}"
38 puts e.awesome_backtrace.show
42 if @compiler == :loading
43 raise "Attempted to load DefaultCompiler, but no compiler was registered"
50 return @compiler if @compiler and @compiler != :loading
54 def self.version_number
55 # Until the compiler is loaded, load any versions. This
56 # lets us bootstrap the compiler into the system no matter
57 # what version it is. This is important because we don't want
58 # to keep the compiler from loading at all because it might have
59 # older versioned files.
60 return @compiler.version_number if @compiler and @compiler != :loading
64 def self.compile_file(path, flags=nil)
65 compiler.compile_file(path, flags)
68 def self.compile_string(string, flags=nil, filename="(eval)", line=1)
69 compiler.compile_string(string, flags, filename, line)
72 def self.execute(string)
73 eval(string, TOPLEVEL_BINDING)
76 # Sets a flag so that the next script to be loaded gets a breakpoint set at
77 # the first instruction
78 def self.debug_script!
82 # By calling require in the block passed to this, require will
83 # load rbc if they exist without checking mtime's and such.
84 @load_rbc_directly = false
86 def self.loading_rbc_directly
88 @load_rbc_directly = true
91 @load_rbc_directly = false
95 # Called when we encounter a break keyword that we do not support
96 # TODO - This leaves a moderately lame stack trace entry
97 def self.__unexpected_break__
98 raise LocalJumpError, "unexpected break"
101 # Internally used by #load and #require. Determines whether to
102 # load the file directly or by prefixing it with the paths in
103 # $LOAD_PATH and then attempts to locate and load the file.
104 def self.unified_load(path, rb, rbc, ext, requiring = nil, options = {:recompile => false})
105 # forces the compiler to be loaded. We need this to get
106 # the proper version_number calculation.
108 self.compiler unless @compiler
111 if path =~ %r{\A(?:(\.\.?)|(~))?/}
114 rbc.slice! '~/' if rbc
115 ext.slice! '~/' if ext
116 res = Compile.single_load "#{ENV['HOME']}/", rb, rbc, ext, requiring, options
119 res = Compile.single_load '', rb, rbc, ext, requiring, options
122 return res unless res.nil? # false is valid
126 $LOAD_PATH.each do |dir|
127 if rbc and dir.suffix? '.rba' and File.file? dir and !options[:recompile]
129 _, _, _, _, _, data = Ar.new(dir).extract rbc
134 unmarshal_object data, 0
136 data = Ar.new(dir).extract rbc
137 unmarshal_object data, version_number
141 return false if requiring and $LOADED_FEATURES.include? rb
144 cm.hints = { :source => :rba }
145 cm.as_script do |script|
149 $LOADED_FEATURES << rb if requiring
151 # Add script CM to CompiledMethod.scripts
152 CompiledMethod.scripts[rb] = cm
159 res = Compile.single_load "#{dir}/", rb, rbc, ext, requiring, options
160 return res unless res.nil? # false is valid
164 raise LoadError, "no such file to load -- #{path}"
167 def self.compile_feature(rb, requiring, &block)
168 $LOADED_FEATURES << rb if requiring
171 rescue Exception => e
172 $LOADED_FEATURES.delete(rb) if requiring
177 # Internally used by #unified_load. This attempts to load the
178 # designated file from a single prefix path.
179 def self.single_load(dir, rb, rbc, ext, requiring, options)
180 # Force compiler loading, required for version calculation
181 self.compiler unless @compiler
184 return false if requiring and $LOADED_FEATURES.include? rb
186 rb_path = "#{dir}#{rb}"
188 if File.file? rb_path
189 rbc_path = "#{dir}#{rbc}"
193 # Try to load rbc directly if requested
194 if @load_rbc_directly and File.file?(rbc_path)
195 compile_feature(rb, requiring) do
196 cm = CompiledMethod.load_from_file(rbc_path, version_number)
197 raise LoadError, "Invalid .rbc: #{rbc_path}" unless cm
200 # Prefer compiled whenever possible
201 elsif !File.file?(rbc_path) or File.mtime(rb_path) > File.mtime(rbc_path) or options[:recompile]
203 if !File.file?(rbc_path)
204 STDERR.puts "[Compiling #{rb_path}: Missing compiled version]"
206 STDERR.puts "[Compiling #{rb_path}: Newer source file]"
210 compile_feature(rb, requiring) do
211 cm = Compile.compile_file(rb_path)
212 raise LoadError, "Unable to compile: #{rb_path}" unless cm
215 # Store it for the future
216 Marshal.dump_to_file cm, rbc_path, version_number
218 compile_feature(rb, requiring) do
219 cm = CompiledMethod.load_from_file(rbc_path, version_number)
220 # cm is nil if the file is out of date, version wise.
223 STDERR.puts "[Recompling #{rb_path}, old version]"
226 compile_feature(rb, requiring) do
227 cm = Compile.compile_file(rb_path)
228 raise LoadError, "Unable to compile: #{rb_path}" unless cm
231 Marshal.dump_to_file cm, rbc_path, version_number
236 # Add script CM to CompiledMethod.scripts
237 CompiledMethod.scripts[rb] = cm
241 cm.hints = { :source => :rb }
242 # Set a breakpoint on the script CompiledMethod if flag is set
244 Debugger.instance.set_breakpoint cm, 0
245 @debug_script = false
247 cm.as_script do |script|
248 script.path = rb_path
250 rescue Exception => e
251 $LOADED_FEATURES.delete(rb) if requiring
261 return false if requiring and $LOADED_FEATURES.include?(rb)
263 rbc_path = "#{dir}#{rbc}"
265 if File.file? rbc_path and !options[:recompile]
266 compile_feature(rb, requiring) do
267 cm = CompiledMethod.load_from_file(rbc_path, version_number)
268 raise LoadError, "Invalid .rbc: #{rbc_path}" unless cm
273 cm.hints = { :source => :rbc }
274 cm.as_script do |script|
275 script.path = rb_path
277 rescue Exception => e
278 $LOADED_FEATURES.delete(rb) if requiring
287 return false if requiring and $LOADED_FEATURES.include? ext
289 ext_path = "#{dir}#{ext}"
290 ext_name = File.basename ext, ".#{Rubinius::LIBSUFFIX}"
292 if File.file? ext_path
293 case Rubinius::VM.load_library(ext_path, ext_name)
295 $LOADED_FEATURES << ext if requiring
297 when 0 # Absent or invalid
299 when 1 # Valid library, but no entry point
300 raise LoadError, "Invalid extension at '#{ext_path}'. " \
301 "Did you define Init_#{ext_name}?"
309 def self.load_from_extension(path)
310 path = StringValue(path)
312 if path.suffix? '.rbc'
313 rb, rbc, ext = nil, path, nil
314 elsif path.suffix? '.rb'
315 rb, rbc, ext = path, "#{path}c", nil
316 elsif path.suffix? ".#{Rubinius::LIBSUFFIX}"
317 rb, rbc, ext = nil, nil, path
319 dir, name = File.split(path)
320 name = ".#{name}" unless name[0] == ?.
321 rb, rbc, ext = path, "#{dir}/#{name}.compiled.rbc", nil
324 Compile.single_load '', rb, rbc, ext, false, {}
327 def self.unmarshal_object(data, version)
328 Ruby.primitive :unmarshal_object
334 def compile(path, out=nil, flags=nil)
335 out = "#{path}c" unless out
336 cm = Compile.compile_file(path, flags)
337 raise LoadError, "Unable to compile '#{path}'" unless cm
338 Marshal.dump_to_file cm, out, Compile.version_number
341 module_function :compile
344 # Loads the given file as executable code and returns true. If
345 # the file cannot be found, cannot be compiled or some other
346 # error occurs, LoadError is raised with an explanation.
348 # Unlike #require, the file extension if any must be present but
349 # is not restricted to .rb, .rbc or .<platform shared lib ext>.
350 # Any other extensions (or no extension) are assumed to be plain
351 # Ruby files. The only exceptions to this rule are:
353 # 1. if given a .rb or no/any-extensioned file and there is a
354 # compiled version of the same file that is not older than
355 # the source file (based on File.mtime), the compiled one
356 # is loaded directly to avoid the compilation overhead.
357 # 2. if a .rb file is given but it does not exist, the system
358 # will try to load the corresponding .rbc instead (to allow
359 # distributing just .rbc files.)
361 # If the path given starts with ./, ../, ~/ or /, it is treated
362 # as a "qualified" file and will be loaded directly (after path
363 # expansion) instead of matching against $LOAD_PATH. The relative
366 # If the filename is plain (unqualified) then it is sequentially
367 # prefixed with each path in $LOAD_PATH ($:) to locate the file,
368 # using the first one that exists. If none of the resulting paths
369 # exist, LoadError is raised. Unqualified names may contain path
370 # elements so directories are valid targets and can be used with
373 # A few extra options are supported. If the second parameter is
374 # true, then the module is wrapped inside an anonymous module for
375 # loading to avoid polluting the namespace. This is actually a
376 # shorthand for passing in :wrap => true-ish in the second arg
377 # which may be an option Hash.
379 # If :recompile in option Hash is true-ish then the file in
380 # question is recompiled each time. If the source file is not
381 # present when recompiling is requested, a LoadError is raised.
383 # TODO: Support non-UNIX paths.
385 # TODO: The anonymous module wrapping is not implemented at all.
387 def load(path, opts = {:wrap => false, :recompile => false})
388 path = StringValue(path)
390 opts = {:wrap => !!opts, :recompile => false} unless Hash === opts
392 if path.suffix? '.rbc'
393 rb, rbc, ext = nil, path, nil
394 elsif path.suffix? '.rb'
395 rb, rbc, ext = path, "#{path}c", nil
396 elsif path.suffix? ".#{Rubinius::LIBSUFFIX}"
397 rb, rbc, ext = nil, nil, path
399 dir, name = File.split(path)
400 name = ".#{name}" unless name[0] == ?.
401 rb, rbc, ext = path, "#{dir}/#{name}.compiled.rbc", nil
404 Compile.unified_load path, rb, rbc, ext, nil, opts
406 module_function :load
409 # Attempt to load the given file, returning true if successful.
410 # If the file has already been successfully loaded and exists
411 # in $LOADED_FEATURES, it will not be re-evaluated and false
412 # is returned instead. If the filename cannot be resolved,
413 # a LoadError is raised.
415 # The file can have one of the following extensions:
417 # [.rb] Plain Ruby source file.
418 # [.rbc] Compiled Ruby source file.
419 # [.o, .so, .dylib, .dll] Shared library (platform-specific.)
420 # [<none>] Filename without extension.
422 # (.rba files should be loaded using CodeArchive.load_everything.)
424 # If the file does not have an extension, #require attempts to
425 # match it using .rb, .rbc and .<shared extension> as extensions,
426 # in that order, instead. If foo.rb does not exist but foo.rbc
427 # does, the latter will be loaded even if called with foo.rb.
429 # If the path given starts with ./, ../, ~/ or /, it is treated
430 # as a "qualified" file and will be loaded directly (after path
431 # expansion) instead of matching against $LOAD_PATH. The relative
434 # If the filename is plain (unqualified) then it is sequentially
435 # prefixed with each path in $LOAD_PATH ($:) to locate the file,
436 # using the first one that exists. If none of the resulting paths
437 # exist, LoadError is raised. Unqualified names may contain path
438 # elements so directories are valid targets and can be used with
441 # TODO: Support non-UNIX paths.
443 # TODO: See if we can safely use 1.9 rules with $LOADED_FEATURES,
444 # i.e. expand paths into it. This should be possible if it
445 # is completely transparent to the user in all normal cases.
447 # Each successfully loaded file is added to $LOADED_FEATURES
448 # ($"), using the original unexpanded filename (with the
449 # exception that the file extension is added.)
452 path = StringValue(path)
453 rb, rbc, ext = __split_path__ path
455 Compile.unified_load path, rb, rbc, ext, true
457 module_function :require
459 def __split_path__(path)
460 if path.suffix? '.rbc'
461 rb, rbc, ext = nil, path, nil
462 elsif path.suffix? '.rb'
463 rb, rbc, ext = path, "#{path}c", nil
464 elsif path.suffix? ".#{Rubinius::LIBSUFFIX}"
465 rb, rbc, ext = nil, nil, path
467 rb, rbc, ext = "#{path}.rb", "#{path}.rbc", "#{path}.#{Rubinius::LIBSUFFIX}"
471 private :__split_path__