diff --git a/Rakefile b/Rakefile index dbc41f0335..44b6a88abe 100644 --- a/Rakefile +++ b/Rakefile @@ -4,6 +4,7 @@ $VERBOSE = true $verbose = Rake.application.options.trace $dlext = Config::CONFIG["DLEXT"] $redcloth_available = nil +$compiler = nil require 'tsort' require 'rakelib/struct_generator' @@ -100,33 +101,49 @@ def create_load_order(files, output=".load_order.txt") end end -def compile(name, output) +def compile(name, output, check_mtime=false) dir = File.dirname(output) unless File.exists?(dir) FileUtils.mkdir_p dir end + + if check_mtime and File.exists?(output) and File.mtime(output) > File.mtime(name) + return + end + + if $compiler + inc = "-I#{$compiler}" + else + inc = "" + end if ENV['GDB'] - sh "shotgun/rubinius --gdb compile #{name} #{output}", :verbose => $verbose + sh "shotgun/rubinius --gdb #{inc} compile #{name} #{output}", :verbose => $verbose else - sh "shotgun/rubinius compile #{name} #{output}", :verbose => $verbose + sh "shotgun/rubinius #{inc} compile #{name} #{output}", :verbose => $verbose end end -task :compiler do +def compile_dir(dir) + (Dir["#{dir}/*.rb"] + Dir["#{dir}/**/*.rb"]).each do |file| + compile file, "#{file}c", true + end +end + +task :stable_compiler do if ENV['USE_CURRENT'] puts "Use current versions, not stable." else + $compiler = "runtime/stable/compiler1.rba" ENV['RBX_BOOTSTRAP'] = "runtime/stable/bootstrap.rba" - ENV['RBX_COMPILER'] = "runtime/stable/compiler.rba" ENV['RBX_CORE'] = "runtime/stable/core.rba" ENV['RBX_LOADER'] = "runtime/stable/loader.rbc" ENV['RBX_PLATFORM'] = "runtime/stable/platform.rba" end end -task :stable_shell => :compiler do +task :stable_shell => :stable_compiler do sh "shotgun/rubinius --gdb" end @@ -134,11 +151,6 @@ rule ".rbc" => %w[compiler .rb] do |t| compile t.source, t.name end -#file 'runtime/core/kernel/core/proc.rbc' => 'kernel/core/proc.rb' do |t| -# p t.prerequisites -# p t.name -#end - class CodeGroup def initialize(files, compile_dir, rba_name, load_order=true) @@ -238,7 +250,6 @@ Core = CodeGroup.new(files, 'runtime/core', 'core') Bootstrap = CodeGroup.new 'kernel/bootstrap/*.rb', 'runtime/bootstrap', 'bootstrap' Platform = CodeGroup.new 'kernel/platform/*.rb', 'runtime/platform', 'platform' -Compiler = CodeGroup.new 'compiler/**/*.rb', 'runtime', 'compiler', false file 'runtime/loader.rbc' => 'kernel/loader.rb' do compile 'kernel/loader.rb', 'runtime/loader.rbc' @@ -248,6 +259,10 @@ file 'runtime/stable/loader.rbc' => 'runtime/loader.rbc' do cp 'runtime/loader.rbc', 'runtime/stable', :verbose => $verbose end +file 'runtime/stable/compiler1.rba' => 'build:compiler1' do + sh "cd lib; zip -r ../runtime/stable/compiler1.rba compiler1 -x \\*.rb" +end + Rake::StructGeneratorTask.new do |t| t.dest = "kernel/core/dir.rb" end @@ -260,7 +275,7 @@ Rake::StructGeneratorTask.new do |t| t.dest = 'lib/zlib.rb' end -AllPreCompiled = Core.output + Bootstrap.output + Platform.output + Compiler.output +AllPreCompiled = Core.output + Bootstrap.output + Platform.output AllPreCompiled << "runtime/loader.rbc" # spec tasks @@ -367,6 +382,12 @@ task :config_env => 'shotgun/config.mk' do end end +task :compiledir => :stable_compiler do + dir = ENV['DIR'] + raise "Use DIR= to set which directory" if !dir or dir.empty? + compile_dir(dir) +end + desc "Recompile all ruby system files" task :rebuild => %w[clean:rbc clean:shotgun build:all] @@ -380,6 +401,7 @@ task :pristine do FileList['**/*.rbc'].each do |fn| next if /^runtime/.match(fn) next if /require\/require_spec_.\.rbc/.match(fn) + next if %r!lib/compiler1!.match(fn) FileUtils.rm fn rescue nil end end @@ -391,6 +413,10 @@ namespace :clean do AllPreCompiled.each do |f| rm_f f, :verbose => $verbose end + + (Dir["lib/compiler1/*.rbc"] + Dir["lib/compiler1/**/*.rbc"]).each do |f| + rm_f f, :verbose => $verbose + end end desc "Cleans up VM building site" @@ -409,6 +435,7 @@ namespace :build do task :all => %w[ build:shotgun build:rbc + compiler1 lib/etc.rb lib/rbconfig.rb extensions @@ -441,16 +468,20 @@ namespace :build do desc "Compiles shotgun (the C-code VM)" task :shotgun => %w[configure shotgun/rubinius.bin] - task :setup_rbc => :compiler + task :setup_rbc => :stable_compiler task :rbc => ([:setup_rbc] + AllPreCompiled) + + task :compiler1 => :stable_compiler do + compile_dir "lib/compiler1" + end desc "Rebuild runtime/stable/*. If you don't know why you're running this, don't." task :stable => %w[ build:all runtime/stable/bootstrap.rba - runtime/stable/compiler.rba runtime/stable/core.rba + runtime/stable/compiler1.rba runtime/stable/loader.rbc runtime/stable/platform.rba ] diff --git a/compiler2/compiler.rb b/compiler2/compiler.rb deleted file mode 100644 index 6b65c94a67..0000000000 --- a/compiler2/compiler.rb +++ /dev/null @@ -1,165 +0,0 @@ -class Compiler - - class Error < RuntimeError - end - - class Node - Mapping = {} - - def self.kind(name=nil) - return @kind unless name - Mapping[name] = self - @kind = name - end - - def self.create(compiler, sexp) - sexp.shift - - node = new(compiler) - args = node.consume(sexp) - - begin - if node.respond_to? :normalize - node = node.normalize(*args) - else - node.args(*args) - end - rescue ArgumentError => e - raise ArgumentError, "#{kind} (#{self}) takes #{args.size} argument(s): passed #{args.inspect} (#{e.message})", e.context - end - - return node - end - - def initialize(compiler) - @compiler = compiler - end - - def convert(x) - @compiler.convert_sexp(x) - end - - def consume(sexp) - # This lets nil come back from convert_sexp which means - # leave it out of the stream. This is primarily so that - # expressions can be optimized away and wont be seen at - # all in the output stream. - out = [] - sexp.each do |x| - if x.kind_of? Array - v = @compiler.convert_sexp(x) - out << v unless v.nil? - else - out << x - end - end - - return out - end - - def args - end - - def get(tag) - @compiler.get(tag) - end - - def set(tag, val=true, &b) - @compiler.set(tag, val, &b) - end - - def inspect - kind = self.class.kind - if kind - prefix = "Compiler:#{self.class.kind}" - else - prefix = self.class.name - end - prefix - - super(prefix) - end - - def is?(clas) - self.kind_of?(clas) - end - end - - def initialize(gen_class) - @variables = {} - @generator_class = gen_class - @call_plugins = [] - - @file = "(unknown)" - @line = 0 - - load_plugins - end - - attr_reader :generator_class, :call_plugins - - def set_position(file, line) - @file, @line = file, line - end - - def load_plugins - require File.dirname(__FILE__) + '/plugins' - - # The default plugins - activate :block_given - activate :primitive - activate :assembly - end - - def activate(name) - cls = Compiler::Plugins.find_plugin(name) - raise Error, "Unknown plugin '#{name}'" unless cls - @call_plugins << cls.new(self) - end - - def inspect - "#<#{self.class}>" - end - - def convert_sexp(sexp) - return nil if sexp.nil? - - klass = Compiler::Node::Mapping[sexp.first] - - raise Error, "Unable to resolve #{sexp.first}" unless klass - - return klass.create(self, sexp) - end - - def into_script(sexp) - begin - convert_sexp([:script, sexp]) - rescue Object => e - puts "Compilation error detected: #{e.message}" - puts " near #{@file}:#{@line}" - puts - puts e.backtrace.show - end - end - - def get(tag) - @variables[tag] - end - - def set(tag, val=true) - cur = @variables.dup - if tag.kind_of? Hash - @variables.merge! tag - else - @variables[tag] = val - end - begin - yield - ensure - @variables = cur - end - end -end - -require File.dirname(__FILE__) + '/nodes' -require File.dirname(__FILE__) + '/local' diff --git a/doc/vm/op_code_info.rb b/doc/vm/op_code_info.rb index 2e2ec9b228..ac31650d32 100755 --- a/doc/vm/op_code_info.rb +++ b/doc/vm/op_code_info.rb @@ -1,6 +1,6 @@ -$: << File.dirname(__FILE__) + '/../../compiler' -require 'bytecode/encoder' -require 'bytecode/assembler' +$: << File.dirname(__FILE__) + '/../../lib' +require 'compiler1/bytecode/encoder' +require 'compiler1/bytecode/assembler' require 'yaml' @@ -20,11 +20,11 @@ module OpCode # Some information is gleaned from Rubinius source files, while # descriptive info comes from opcode YAML files. class Info - @@op_codes = Bytecode::InstructionEncoder::OpCodes - @@int_arg = Bytecode::InstructionEncoder::IntArg - @@two_int = Bytecode::InstructionEncoder::TwoInt + @@op_codes = Compiler1::Bytecode::InstructionEncoder::OpCodes + @@int_arg = Compiler1::Bytecode::InstructionEncoder::IntArg + @@two_int = Compiler1::Bytecode::InstructionEncoder::TwoInt @@instructs = ShotgunInstructions.new - @@translations = Bytecode::Assembler::Translations.invert + @@translations = Compiler1::Bytecode::Assembler::Translations.invert def self.op_codes @@op_codes @@ -71,4 +71,4 @@ def <=>(b) to_s <=> b.to_s end end -end \ No newline at end of file +end diff --git a/kernel/core/compile.rb b/kernel/core/compile.rb index 01617401d0..c53c5f0e72 100644 --- a/kernel/core/compile.rb +++ b/kernel/core/compile.rb @@ -6,26 +6,43 @@ module Rubinius end module Compile + + @compiler = nil + + DefaultCompiler = "compiler1" + + def self.register_compiler(obj) + if $DEBUG + $stderr.puts "[Registered #{obj} as system compiler]" + end + @compiler = obj + end + + def self.find_compiler + begin + require "#{DefaultCompiler}/init" + rescue Exception + raise "Unable to load default compiler" + end + + unless @compiler + raise "Attempted to load DefaultCompiler, but no compiler was registered" + end + + return @compiler + end + + def self.compiler + return @compiler if @compiler + return find_compiler + end + def self.compile_file(path, flags=nil) - require 'bytecode/compiler' - require 'bytecode/rubinius' - sexp = File.to_sexp(path, true) - comp = Bytecode::Compiler.new - comp.import_flags(flags) if flags - desc = comp.compile_as_script(sexp, :__script__) - return desc.to_cmethod + compiler.compile_file(path, flags) end - def self.compile_string(string, flags=nil) - require 'bytecode/compiler' - require 'bytecode/rubinius' - sexp = string.to_sexp - comp = Bytecode::Compiler.new - comp.import_flags(flags) if flags - state = RsLocalState.new - state.uses_eval = true - desc = comp.compile_as_method(sexp, :__eval_script__, state) - return desc.to_cmethod + def self.compile_string(string, flags=nil, filename="(eval)", line=1) + compiler.compile_string(string, flags, filename, line) end def self.execute(string) @@ -92,21 +109,10 @@ def self.require_feature(dir, rb_file, rbc_file, base_file) end end -class String - def compile_as_method(filename = "(eval)", line = 1, newlines = true) - require 'bytecode/compiler' - require 'bytecode/rubinius' - sexp = self.to_sexp(filename, line, newlines) - comp = Bytecode::Compiler.new - desc = comp.compile_as_method(sexp, :__script__) - return desc.to_cmethod - end -end - module Kernel def load(path) path = StringValue(path) - + if path.suffix? ".rbc" compiled = path elsif path.suffix? ".rb" diff --git a/kernel/core/global.rb b/kernel/core/global.rb index 8b3b51b882..c6a465771d 100644 --- a/kernel/core/global.rb +++ b/kernel/core/global.rb @@ -1,7 +1,7 @@ # Class that allows global variables to have aliases class GlobalVariables def initialize - load_path = ["runtime/compiler", "lib", "stdlib", "."] + load_path = ["lib", "stdlib", "."] loaded_features = [] @internal = { diff --git a/kernel/core/kernel.rb b/kernel/core/kernel.rb index 4ce5f5fcb7..709f9c3b3b 100644 --- a/kernel/core/kernel.rb +++ b/kernel/core/kernel.rb @@ -192,7 +192,7 @@ def lambda(&prc) alias_method :proc, :lambda def eval(string, binding = self, filename = '(eval)', lineno = 1) - compiled_method = string.compile_as_method(filename, lineno) + compiled_method = Compile.compile_string string, nil, filename, lineno method = Method.new(binding, nil, compiled_method) method.call end diff --git a/kernel/core/object.rb b/kernel/core/object.rb index e9a1ba9873..1b805f388a 100644 --- a/kernel/core/object.rb +++ b/kernel/core/object.rb @@ -148,7 +148,8 @@ def instance_eval(string = nil, filename = "(eval)", line = 1, &prc) elsif string string = StringValue(string) mod = nil # FIXME - cm = string.compile_as_method(filename, line) + + cm = Compile.compile_string string, nil, filename, line cm.activate(self, mod, []) else raise ArgumentError, 'block not supplied' diff --git a/kernel/loader.rb b/kernel/loader.rb index f4bf21fdf3..05e6481b22 100644 --- a/kernel/loader.rb +++ b/kernel/loader.rb @@ -45,14 +45,6 @@ additions = [] -# If there is no compiler.rba or RBX_COMPILER env variable, use the system one. -if ENV['RBX_COMPILER'] and File.exists? ENV['RBX_COMPILER'] - additions << ENV['RBX_COMPILER'] -end - -additions << File.join(Rubinius::RBA_PATH, "compiler") -additions << File.join(Rubinius::RBA_PATH, "compiler.rba") - # The main stdlib location additions << Rubinius::CODE_PATH @@ -79,12 +71,6 @@ END -# script = ARGV.shift - -if ARGV.include?('-p') - ARGV.delete '-p' - require 'profile' -end $VERBOSE = false code = 0 @@ -107,12 +93,8 @@ puts "[Code loading debugging enabled]" when '-d' $DEBUG = true - when '-c' - puts "Deprecated. Use 'rbx compile' instead." - file = ARGV.shift - path = compile(file) - puts "Compiled #{file} to #{path}" - exit 1 + when '-p' + require 'profile' when '-e' $0 = "(eval)" Compile.execute ARGV.shift diff --git a/lib/bin/compile.rb b/lib/bin/compile.rb index dfa5b94079..64c79a5af5 100644 --- a/lib/bin/compile.rb +++ b/lib/bin/compile.rb @@ -1,5 +1,3 @@ -require 'bytecode/compiler' -require 'bytecode/rubinius' class ExtensionCompiler def initialize(extra=[], flags=[]) diff --git a/lib/bin/describe.rb b/lib/bin/describe.rb index 687571757c..18d5bdb041 100644 --- a/lib/bin/describe.rb +++ b/lib/bin/describe.rb @@ -1,5 +1,5 @@ -require 'bytecode/compiler' -require 'bytecode/rubinius' +require 'compiler1/bytecode/compiler' +require 'compiler1/bytecode/rubinius' file = ARGV.shift @@ -10,8 +10,8 @@ puts "Path: #{file}" puts "Size: #{code.size} bytes" -compiler = Bytecode::Compiler.new -state = RsLocalState.new +compiler = Compiler1::Bytecode::Compiler.new +state = Compiler1::RsLocalState.new sexp = code.to_sexp puts "\nSexp:\n #{sexp.indented_inspect}" @@ -30,7 +30,7 @@ def show_method(parent) parent.literals.each do |lit| - if Bytecode::MethodDescription === lit + if Compiler1::Bytecode::MethodDescription === lit puts "\n[[ #{parent.name} >> #{lit.name} ]]" puts lit.assembly show_method(lit) diff --git a/lib/bin/sirb.rb b/lib/bin/sirb.rb index 1300560fba..20369cb68a 100644 --- a/lib/bin/sirb.rb +++ b/lib/bin/sirb.rb @@ -1,7 +1,6 @@ #!/usr/bin/env rbx -require 'bytecode/compiler' -require 'bytecode/rubinius' +require 'compiler1/bytecode/rubinius' require 'readline' # recognize a few simple options @@ -66,11 +65,11 @@ def print_bytecodes(bc) context = "" line = 0 -compiler = Bytecode::Compiler.new +compiler = Compiler1::Bytecode::Compiler.new # We use the same compiler state for each evaluation so we can save # stuff like locals between statements. -compiler_state = RsLocalState.new +compiler_state = Compiler1::RsLocalState.new compiler_state.uses_eval = true # Don't allocate locals on the stack # Start off with just 10 slots, but we enlarge as needed below. diff --git a/compiler/bytecode/assembler.rb b/lib/compiler1/bytecode/assembler.rb similarity index 99% rename from compiler/bytecode/assembler.rb rename to lib/compiler1/bytecode/assembler.rb index 8d4821896c..a61a1f293c 100755 --- a/compiler/bytecode/assembler.rb +++ b/lib/compiler1/bytecode/assembler.rb @@ -1,5 +1,6 @@ -require 'bytecode/encoder' +require 'compiler1/bytecode/encoder' +module Compiler1 module Bytecode class Assembler @@ -544,3 +545,4 @@ def parse_operation(*parts) end end end +end \ No newline at end of file diff --git a/compiler/bytecode/compiler.rb b/lib/compiler1/bytecode/compiler.rb similarity index 98% rename from compiler/bytecode/compiler.rb rename to lib/compiler1/bytecode/compiler.rb index 2afa78dea3..13e83c792f 100755 --- a/compiler/bytecode/compiler.rb +++ b/lib/compiler1/bytecode/compiler.rb @@ -1,9 +1,10 @@ -require 'sexp/simple_processor' -require 'translation/normalize' -require 'translation/local_scoping' -require 'sexp/composite_processor' -require 'translation/states' +require 'compiler1/sexp/simple_processor' +require 'compiler1/translation/normalize' +require 'compiler1/translation/local_scoping' +require 'compiler1/sexp/composite_processor' +require 'compiler1/translation/states' +module Compiler1 module Bytecode class MethodDescription @@ -32,6 +33,25 @@ def prepend_asm(str) end class Compiler + + def self.compile_file(path, flags=nil) + sexp = File.to_sexp(path, true) + comp = Bytecode::Compiler.new + comp.import_flags(flags) if flags + desc = comp.compile_as_script(sexp, :__script__) + return desc.to_cmethod + end + + def self.compile_string(string, flags=nil, filename="(eval)", line=1) + sexp = string.to_sexp(filename, line, true) + comp = Bytecode::Compiler.new + comp.import_flags(flags) if flags + state = RsLocalState.new + state.uses_eval = true + desc = comp.compile_as_method(sexp, :__eval_script__, state) + return desc.to_cmethod + end + def initialize @path = [] @current_class = nil @@ -2565,5 +2585,6 @@ def process_cvar(x) end end end +end -require 'bytecode/plugins' +require 'compiler1/bytecode/plugins' diff --git a/compiler/bytecode/disassembler.rb b/lib/compiler1/bytecode/disassembler.rb similarity index 98% rename from compiler/bytecode/disassembler.rb rename to lib/compiler1/bytecode/disassembler.rb index 2120feae37..5e45e2d9b9 100644 --- a/compiler/bytecode/disassembler.rb +++ b/lib/compiler1/bytecode/disassembler.rb @@ -1,4 +1,4 @@ -require 'bytecode/encoder' +require 'compiler1/bytecode/encoder' # At present, Rubinius has not implemented String::unpack, so hack a simple int unpack @@ -130,6 +130,7 @@ def process_instructions end end +module Compiler1 module Bytecode class Disassembler def initialize(string, endian=?b) @@ -174,6 +175,7 @@ def process_all end end end +end emit = MarshalEmitter.process_rbc(ARGV.shift) diff --git a/compiler/bytecode/encoder.rb b/lib/compiler1/bytecode/encoder.rb similarity index 99% rename from compiler/bytecode/encoder.rb rename to lib/compiler1/bytecode/encoder.rb index 4bea782625..84e3473942 100755 --- a/compiler/bytecode/encoder.rb +++ b/lib/compiler1/bytecode/encoder.rb @@ -1,3 +1,4 @@ +module Compiler1 module Bytecode class InstructionEncoder @@ -429,3 +430,4 @@ def process_args(kind, opcode, args) end end end +end diff --git a/compiler/bytecode/plugins.rb b/lib/compiler1/bytecode/plugins.rb similarity index 99% rename from compiler/bytecode/plugins.rb rename to lib/compiler1/bytecode/plugins.rb index d0e26cf3c1..dca249f544 100644 --- a/compiler/bytecode/plugins.rb +++ b/lib/compiler1/bytecode/plugins.rb @@ -1,3 +1,4 @@ +module Compiler1 class Bytecode::Compiler class Plugin @@ -380,3 +381,5 @@ def process(recv, meth, args) end end =end + +end \ No newline at end of file diff --git a/compiler/bytecode/primitive_names.rb b/lib/compiler1/bytecode/primitive_names.rb similarity index 99% rename from compiler/bytecode/primitive_names.rb rename to lib/compiler1/bytecode/primitive_names.rb index 130020dd51..c7bda803c3 100755 --- a/compiler/bytecode/primitive_names.rb +++ b/lib/compiler1/bytecode/primitive_names.rb @@ -1,3 +1,4 @@ +module Compiler1 module Bytecode class Compiler Primitives = [ @@ -192,3 +193,4 @@ class Compiler end end +end diff --git a/compiler/bytecode/rubinius.rb b/lib/compiler1/bytecode/rubinius.rb similarity index 93% rename from compiler/bytecode/rubinius.rb rename to lib/compiler1/bytecode/rubinius.rb index 3df35addf9..0466630c15 100644 --- a/compiler/bytecode/rubinius.rb +++ b/lib/compiler1/bytecode/rubinius.rb @@ -1,8 +1,11 @@ -require 'bytecode/assembler' -require 'bytecode/primitive_names' -require 'bytecode/system_hints' -Bytecode::Compiler.load_system_hints(Rubinius::Bootstrap::HINTS) +require 'compiler1/bytecode/compiler' +require 'compiler1/bytecode/assembler' +require 'compiler1/bytecode/primitive_names' +require 'compiler1/bytecode/system_hints' +Compiler1::Bytecode::Compiler.load_system_hints(Rubinius::Bootstrap::HINTS) + +module Compiler1 module Bytecode class MethodDescription @@ -158,3 +161,4 @@ def primitive_to_index(sym) end end end +end diff --git a/compiler/bytecode/system_hints.rb b/lib/compiler1/bytecode/system_hints.rb similarity index 100% rename from compiler/bytecode/system_hints.rb rename to lib/compiler1/bytecode/system_hints.rb diff --git a/lib/compiler1/init.rb b/lib/compiler1/init.rb new file mode 100644 index 0000000000..dd8da7b722 --- /dev/null +++ b/lib/compiler1/init.rb @@ -0,0 +1,4 @@ +require 'compiler1/bytecode/rubinius' + +Compile.register_compiler Compiler1::Bytecode::Compiler + diff --git a/compiler/sexp/composite_processor.rb b/lib/compiler1/sexp/composite_processor.rb similarity index 97% rename from compiler/sexp/composite_processor.rb rename to lib/compiler1/sexp/composite_processor.rb index 146e619bdd..cadf58db0a 100644 --- a/compiler/sexp/composite_processor.rb +++ b/lib/compiler1/sexp/composite_processor.rb @@ -7,6 +7,7 @@ # something when +generate+ is called, allowing for deferred final # processing. +module Compiler1 class CompositeSexpProcessor ## @@ -42,3 +43,4 @@ def on_error_in(node_type, &block) end end end +end diff --git a/compiler/sexp/exceptions.rb b/lib/compiler1/sexp/exceptions.rb similarity index 96% rename from compiler/sexp/exceptions.rb rename to lib/compiler1/sexp/exceptions.rb index ed6dca24b5..425f4c6bd3 100644 --- a/compiler/sexp/exceptions.rb +++ b/lib/compiler1/sexp/exceptions.rb @@ -1,3 +1,5 @@ +module Compiler1 + ## # SexpProcessor base exception class. @@ -26,3 +28,4 @@ class NotEmptyError < SexpProcessorError; end class SexpTypeError < SexpProcessorError; end +end diff --git a/compiler/sexp/simple_processor.rb b/lib/compiler1/sexp/simple_processor.rb similarity index 96% rename from compiler/sexp/simple_processor.rb rename to lib/compiler1/sexp/simple_processor.rb index 2df5550a72..2edf7542e3 100755 --- a/compiler/sexp/simple_processor.rb +++ b/lib/compiler1/sexp/simple_processor.rb @@ -1,5 +1,6 @@ -require 'sexp/exceptions' +require 'compiler1/sexp/exceptions' +module Compiler1 class SimpleSexpProcessor def initialize @default_object = nil @@ -84,3 +85,4 @@ def concat_all(obj, x) return obj end end +end diff --git a/compiler/translation/local_scoping.rb b/lib/compiler1/translation/local_scoping.rb similarity index 98% rename from compiler/translation/local_scoping.rb rename to lib/compiler1/translation/local_scoping.rb index f88faddeaa..817d16361d 100755 --- a/compiler/translation/local_scoping.rb +++ b/lib/compiler1/translation/local_scoping.rb @@ -1,5 +1,5 @@ -require 'sexp/simple_processor' -require 'translation/states' +require 'compiler1/sexp/simple_processor' +require 'compiler1/translation/states' # This converts a ruby 1.8.x sexp's idea of the scoping of # local variables into rubinius 1.0's idea. @@ -36,6 +36,7 @@ # 3) Any lvar accessed in a block is converted to a normal lvar. # 4) An argument lvar that is stored to is converted. +module Compiler1 class RsMethodBodyOnly < SimpleSexpProcessor def process_defs(x) @@ -392,3 +393,4 @@ def process_call(x) [:call, r2, meth, a2, options] end end +end diff --git a/compiler/translation/normalize.rb b/lib/compiler1/translation/normalize.rb similarity index 98% rename from compiler/translation/normalize.rb rename to lib/compiler1/translation/normalize.rb index db4cc42441..cd1ed43e01 100755 --- a/compiler/translation/normalize.rb +++ b/lib/compiler1/translation/normalize.rb @@ -1,6 +1,7 @@ -require 'sexp/simple_processor' -require 'translation/states' +require 'compiler1/sexp/simple_processor' +require 'compiler1/translation/states' +module Compiler1 class RsNormalizer < SimpleSexpProcessor def initialize(state=nil, full=false, lines=false) @@ -347,4 +348,4 @@ def disjoin_conditions(conditions) end end end - +end diff --git a/compiler/translation/states.rb b/lib/compiler1/translation/states.rb similarity index 99% rename from compiler/translation/states.rb rename to lib/compiler1/translation/states.rb index b036d537d2..c7815f87e8 100755 --- a/compiler/translation/states.rb +++ b/lib/compiler1/translation/states.rb @@ -1,3 +1,5 @@ +module Compiler1 + class RsLocalState class LocalVariable def initialize(name) @@ -135,10 +137,7 @@ def set_assembly(idx=nil) end end -end - -class RsLocalState def initialize reset end @@ -421,3 +420,4 @@ def stack_locals_tuple end end +end \ No newline at end of file diff --git a/compiler2/compile.rb b/lib/compiler2/compile.rb similarity index 81% rename from compiler2/compile.rb rename to lib/compiler2/compile.rb index ac91b73e64..6d37fb9bf2 100644 --- a/compiler2/compile.rb +++ b/lib/compiler2/compile.rb @@ -51,17 +51,31 @@ def batch(opts) puts " Generating AST...\n" if verbose n = c.into_script(x) - puts " Generating bytecode...\n" if verbose + puts " Generating bytecode...\n" if verbose + if verbose + c.generator_class = Compiler::TextGenerator + txt = Compiler::TextGenerator.new + n.bytecode(txt) + txt.close + puts txt.text + end + meth = n.to_description puts " Encoding..." if verbose cm = meth.to_cmethod - if verbose + if false # verbose puts "\n Decoded:\n" puts " ========\n" puts " " << cm.decode.join("\n ") end + + if opts['output'] + out = opts['output'].first + puts " Saving to '#{out}'...\n" + Marshal.dump_to_file cm, out, Rubinius::CompiledMethodVersion + end # This is pretty pointless until we actually start compiling to file if opts['execute'] @@ -87,6 +101,7 @@ def batch(opts) o.option '-v --verbose Print diagnostic info' o.option '-i --interactive Present prompt' o.option '-h --help Show this help message.' + o.option '-o --output Where to save the compiled file', :one o.on_error {|opt, ex| $stderr.puts opt.usage; exit 1 } end diff --git a/compiler2/bytecode.rb b/lib/compiler2/compiler/bytecode.rb similarity index 98% rename from compiler2/bytecode.rb rename to lib/compiler2/compiler/bytecode.rb index 1b6460f63d..ebe6ef4a42 100644 --- a/compiler2/bytecode.rb +++ b/lib/compiler2/compiler/bytecode.rb @@ -1,7 +1,7 @@ # Implements methods on each Node subclass for generatng bytecode # from itself. -require 'compiler2/generator' +require 'compiler/generator' class Compiler class MethodDescription @@ -17,10 +17,10 @@ def initialize(gen_class, locals) attr_reader :generator, :locals attr_accessor :required, :optional, :name - def run(top) - @generator.run(top) - @required, @optional = top.argument_info - @name = top.name + def run(container, body) + @generator.run(body) + @required, @optional = container.argument_info + @name = container.name end def ==(desc) @@ -60,12 +60,13 @@ def new_description Compiler::MethodDescription.new(@compiler.generator_class, self.locals) end - def to_description + def to_description(name=nil) desc = new_description() + desc.name = name if name gen = desc.generator show_errors(gen) do - desc.run(self) + desc.run(self, self) gen.close end return desc @@ -79,12 +80,12 @@ def attach_and_call(g, name) desc = new_description() meth = desc.generator - prelude(meth) + prelude(g, meth) meth.push :self meth.set_encloser show_errors(meth) do - @body.bytecode(meth) + desc.run self, @body end meth.sret meth.close @@ -98,7 +99,12 @@ def attach_and_call(g, name) g.push_encloser end - def prelude(g) + def prelude(orig, g) + + if orig + g.set_line orig.line, orig.file + end + # Allocate some stack to store locals. if @alloca > 0 @@ -115,7 +121,7 @@ def bytecode(g) class Script def bytecode(g) - prelude(g) + prelude(nil, g) @body.bytecode(g) g.pop g.push :true @@ -616,7 +622,7 @@ def bytecode(g) do_value(g) if @in_block - g.soft_return + g.caller_return elsif g.break g.goto g.break else @@ -1844,20 +1850,18 @@ def bytecode(g) class Define def argument_info - req = @arguments.required.size - opt = @arguments.optional.size - [req, opt] + [@arguments.arity, @arguments.optional.size] end - def compile_body + def compile_body(g) desc = new_description() meth = desc.generator - prelude(meth) + prelude(g, meth) show_errors(meth) do @arguments.bytecode(meth) - @body.bytecode(meth) + desc.run self, @body end meth.sret meth.close @@ -1866,7 +1870,7 @@ def compile_body end def bytecode(g) - g.push_literal compile_body() + g.push_literal compile_body(g) g.push :self g.add_method @name end @@ -1875,7 +1879,7 @@ def bytecode(g) # TESTED class DefineSingleton def bytecode(g) - g.push_literal compile_body() + g.push_literal compile_body(g) @object.bytecode(g) g.attach_method @name end diff --git a/lib/compiler2/compiler/compiler.rb b/lib/compiler2/compiler/compiler.rb new file mode 100644 index 0000000000..f9f16782e3 --- /dev/null +++ b/lib/compiler2/compiler/compiler.rb @@ -0,0 +1,107 @@ +class Compiler + + class Error < RuntimeError + end + + def self.compile_file(path, flags=nil) + sexp = File.to_sexp(path, true) + + comp = new(Compiler::Generator) + node = comp.into_script(sexp) + return node.to_description(:__script__).to_cmethod + end + + def self.compile_string(string, flags=nil, filename="(eval)", line=1) + sexp = string.to_sexp(filename, line, true) + + comp = new(Compiler::Generator) + node = comp.into_script(sexp) + return node.to_description(:__eval_script__).to_cmethod + end + + def initialize(gen_class) + @variables = {} + @generator_class = gen_class + @call_plugins = [] + + @file = "(unknown)" + @line = 0 + + load_plugins + end + + attr_reader :call_plugins + attr_accessor :generator_class + + def set_position(file, line) + @file, @line = file, line + end + + def load_plugins + # The default plugins + activate :block_given + activate :primitive + activate :assembly + end + + def activate(name) + cls = Compiler::Plugins.find_plugin(name) + raise Error, "Unknown plugin '#{name}'" unless cls + @call_plugins << cls.new(self) + end + + def inspect + "#<#{self.class}>" + end + + def convert_sexp(sexp) + return nil if sexp.nil? + + klass = Compiler::Node::Mapping[sexp.first] + + raise Error, "Unable to resolve #{sexp.first}" unless klass + + return klass.create(self, sexp) + end + + def into_script(sexp) + begin + convert_sexp([:script, sexp]) + rescue Object => e + puts "Compilation error detected: #{e.message}" + puts " near #{@file}:#{@line}" + puts + puts e.backtrace.show + end + end + + def get(tag) + @variables[tag] + end + + def set(tag, val=true) + if tag.kind_of? Hash + cur = @variables.dup + @variables.merge! tag + begin + yield + ensure + @variables = cur + end + else + cur = @variables[tag] + @variables[tag] = val + begin + yield + ensure + @variables[tag] = cur + end + end + end +end + +require 'compiler/nodes' +require 'compiler/local' +require 'compiler/generator' +require 'compiler/plugins' + diff --git a/compiler2/encoder.rb b/lib/compiler2/compiler/encoder.rb similarity index 100% rename from compiler2/encoder.rb rename to lib/compiler2/compiler/encoder.rb diff --git a/compiler2/execute.rb b/lib/compiler2/compiler/execute.rb similarity index 100% rename from compiler2/execute.rb rename to lib/compiler2/compiler/execute.rb diff --git a/compiler2/garnet/bindingagent.rb b/lib/compiler2/compiler/garnet/bindingagent.rb similarity index 100% rename from compiler2/garnet/bindingagent.rb rename to lib/compiler2/compiler/garnet/bindingagent.rb diff --git a/lib/compiler2/compiler/garnet/cerberus.rb b/lib/compiler2/compiler/garnet/cerberus.rb new file mode 100644 index 0000000000..1835ba8bc6 --- /dev/null +++ b/lib/compiler2/compiler/garnet/cerberus.rb @@ -0,0 +1,39 @@ +class Compiler +class Node + + class GenerationError < RuntimeError; end + + def to_cerb + raise GenerationError, "#{self.class} does not support cerb" + end + + class Call + def to_cerb + + end + + def collapse_args(e) + unless @arguments.kind_of? Array + raise GenerationError, "Direct arguments are the only support type" + end + + args = @arguments.map { |a| a.to_cerb(e) } + args.join(', ') + end + + end + + class FCall + def to_cerb(e) + if @arguments.empty? + "#{@method}()" + else + "#{@method}(#{collapse_args(e)}" + end + end + end + + class + +end +end \ No newline at end of file diff --git a/lib/compiler2/compiler/garnet/garnet.rb b/lib/compiler2/compiler/garnet/garnet.rb new file mode 100644 index 0000000000..98a1ef95a3 --- /dev/null +++ b/lib/compiler2/compiler/garnet/garnet.rb @@ -0,0 +1,18 @@ +class RubiniusObject < 'OBJECT' + def at(idx) + NTH_FIELD(self, idx) + end + + def put(idx, obj) + SET_FIELD(self, idx, obj) + end +end + +declare 'allocate' => 'OBJECT' + +def main + obj = allocate(10) + obj.put 0, 13.to_object + obj.at 0 +end + diff --git a/compiler2/garnet/test.rb b/lib/compiler2/compiler/garnet/test.rb similarity index 100% rename from compiler2/garnet/test.rb rename to lib/compiler2/compiler/garnet/test.rb diff --git a/compiler2/generator.rb b/lib/compiler2/compiler/generator.rb similarity index 98% rename from compiler2/generator.rb rename to lib/compiler2/compiler/generator.rb index a195a1d6fc..908e0b4705 100644 --- a/compiler2/generator.rb +++ b/lib/compiler2/compiler/generator.rb @@ -1,3 +1,5 @@ +require 'compiler/encoder' + class Compiler class Generator @@ -109,12 +111,17 @@ def to_cmethod(desc) cm.name = desc.name - #cm.primitive = @primitive + if @primitive + cm.primitive = @primitive + else + cm.primitive = -1 + end + cm.literals = encode_literals() cm.lines = encode_lines() cm.exceptions = encode_exceptions() cm.serial = 0 - + return cm end diff --git a/compiler2/graph.rb b/lib/compiler2/compiler/graph.rb similarity index 100% rename from compiler2/graph.rb rename to lib/compiler2/compiler/graph.rb diff --git a/compiler2/local.rb b/lib/compiler2/compiler/local.rb similarity index 100% rename from compiler2/local.rb rename to lib/compiler2/compiler/local.rb diff --git a/lib/compiler2/compiler/macro.rb b/lib/compiler2/compiler/macro.rb new file mode 100644 index 0000000000..2a8f189825 --- /dev/null +++ b/lib/compiler2/compiler/macro.rb @@ -0,0 +1,26 @@ +class Compiler + class MacroGenerator + + def initialize(compiler) + @compiler = compiler + end + + def make(kind, *args) + obj = kind.new(@compiler) + obj.args *args + return obj + end + + def call(who, meth, *args) + make Compiler::Node::Call, who, meth, args + end + + def const(name) + make ConstFind, name + end + + def lit(obj) + make Literal, obj + end + end +end \ No newline at end of file diff --git a/compiler2/nodes.rb b/lib/compiler2/compiler/nodes.rb similarity index 94% rename from compiler2/nodes.rb rename to lib/compiler2/compiler/nodes.rb index 8965250567..7d5bbe8a27 100644 --- a/compiler2/nodes.rb +++ b/lib/compiler2/compiler/nodes.rb @@ -1,5 +1,86 @@ class Compiler class Node + Mapping = {} + + def self.kind(name=nil) + return @kind unless name + Mapping[name] = self + @kind = name + end + + def self.create(compiler, sexp) + sexp.shift + + node = new(compiler) + args = node.consume(sexp) + + begin + if node.respond_to? :normalize + node = node.normalize(*args) + else + node.args(*args) + end + rescue ArgumentError => e + raise ArgumentError, "#{kind} (#{self}) takes #{args.size} argument(s): passed #{args.inspect} (#{e.message})", e.context + end + + return node + end + + def initialize(compiler) + @compiler = compiler + end + + def convert(x) + @compiler.convert_sexp(x) + end + + def consume(sexp) + # This lets nil come back from convert_sexp which means + # leave it out of the stream. This is primarily so that + # expressions can be optimized away and wont be seen at + # all in the output stream. + out = [] + sexp.each do |x| + if x.kind_of? Array + v = @compiler.convert_sexp(x) + out << v unless v.nil? + else + out << x + end + end + + return out + end + + def args + end + + def get(tag) + @compiler.get(tag) + end + + def set(tag, val=true, &b) + @compiler.set(tag, val, &b) + end + + def inspect + kind = self.class.kind + if kind + prefix = "Compiler:#{self.class.kind}" + else + prefix = self.class.name + end + prefix + + super(prefix) + end + + def is?(clas) + self.kind_of?(clas) + end + + # Start of Node subclasses class ClosedScope < Node def initialize(comp) @@ -121,7 +202,7 @@ def allocate_slot return i end end - + class Snippit < ClosedScope kind :snippit @@ -445,6 +526,14 @@ def args(req, optional, splat, defaults) attr_accessor :required, :optional, :splat, :defaults, :block_arg + def arity + if !@optional.empty? or @splat + return -(@required.size + 1) + end + + return @required.size + end + def populate i = 0 scope = get(:scope) @@ -1417,6 +1506,14 @@ def args(child) @child = child end + def names + if @child.is? LocalAssignment + [@child.name] + else + @child.assigns.body.map { |i| i.name } + end + end + attr_accessor :child end diff --git a/compiler2/plugins.rb b/lib/compiler2/compiler/plugins.rb similarity index 69% rename from compiler2/plugins.rb rename to lib/compiler2/compiler/plugins.rb index c5244072f1..1f606df375 100644 --- a/compiler2/plugins.rb +++ b/lib/compiler2/compiler/plugins.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/execute' +require 'compiler/execute' module Compiler::Plugins @@ -37,8 +37,10 @@ class BlockGiven < Plugin def handle(g, call) if call.fcall? if call.method == :block_given? or call.method == :iterator? - g.push :true - g.send_primitive :block_given, 0 + push :true + g.push_block + g.is_nil + g.equal return true end end @@ -52,7 +54,6 @@ class PrimitiveDeclaration < Plugin plugin :primitive def handle(g, call) - return false unless g.ip == 0 return false unless call_match(call, :Ruby, :primitive) prim = call.arguments.first.value @@ -72,6 +73,14 @@ def handle(g, call) return false unless call.block exc = Compiler::ExecuteContext.new(g) + i = 0 + args = call.arguments + + call.block.arguments.names.each do |name| + exc.set_local name, args[i] + i += 1 + end + exc.execute call.block.body return true @@ -79,6 +88,63 @@ def handle(g, call) end + class VMOperation < Plugin + plugin :vmops + + def handle(g, call) + return false unless call_match(call, :Rubinius, :vmop) + + name = call.arguments.shift.value + + send("op_#{name}", g, call) + end + + def op_kind_of(g, call) + call.arguments.shift.bytecode(g) + g.push :self + g.kind_of + end + + def op_locate(g, call) + g.push :self + call.arguments[0].bytecode(g) + call.arguments[1].bytecode(g) + g.locate_method + end + + def op_push_block(g, call) + g.push_block + end + + def op_send(g, call) + call.arguments[0].bytecode(g) + g.push_array + g.push :self + call.arguments[1].bytecode(g) + call.arguments[2].bytecode(g) + call.arguments[3].bytecode(g) + g.set_args + g.set_call_flags 1 + g.send_off_stack + end + + def op_activate(g, call) + + end + + def op_string_append(g, call) + call.arguments[1].bytecode(g) + call.arguments[0].bytecode(g) + g.string_append + end + + def op_string_dup(g, call) + call.arguments[0].bytecode(g) + g.string_dup + end + + end + class FastMathOperators < Plugin plugin :fastmath diff --git a/compiler2/text.rb b/lib/compiler2/compiler/text.rb similarity index 99% rename from compiler2/text.rb rename to lib/compiler2/compiler/text.rb index 62e42c78db..a022648511 100644 --- a/compiler2/text.rb +++ b/lib/compiler2/compiler/text.rb @@ -112,4 +112,4 @@ def as_primitive(name) end end -end \ No newline at end of file +end diff --git a/compiler2/describe.rb b/lib/compiler2/describe.rb similarity index 100% rename from compiler2/describe.rb rename to lib/compiler2/describe.rb diff --git a/lib/compiler2/init.rb b/lib/compiler2/init.rb new file mode 100644 index 0000000000..083fb6fbbe --- /dev/null +++ b/lib/compiler2/init.rb @@ -0,0 +1,3 @@ +require 'compiler/compiler' + +Compile.register_compiler Compiler diff --git a/compiler2/spec/array_spec.rb b/lib/compiler2/spec/array_spec.rb similarity index 100% rename from compiler2/spec/array_spec.rb rename to lib/compiler2/spec/array_spec.rb diff --git a/compiler2/spec/call_spec.rb b/lib/compiler2/spec/call_spec.rb similarity index 100% rename from compiler2/spec/call_spec.rb rename to lib/compiler2/spec/call_spec.rb diff --git a/compiler2/spec/control_spec.rb b/lib/compiler2/spec/control_spec.rb similarity index 100% rename from compiler2/spec/control_spec.rb rename to lib/compiler2/spec/control_spec.rb diff --git a/compiler2/spec/exception_spec.rb b/lib/compiler2/spec/exception_spec.rb similarity index 100% rename from compiler2/spec/exception_spec.rb rename to lib/compiler2/spec/exception_spec.rb diff --git a/compiler2/spec/helper.rb b/lib/compiler2/spec/helper.rb similarity index 100% rename from compiler2/spec/helper.rb rename to lib/compiler2/spec/helper.rb diff --git a/compiler2/spec/hints_spec.rb b/lib/compiler2/spec/hints_spec.rb similarity index 100% rename from compiler2/spec/hints_spec.rb rename to lib/compiler2/spec/hints_spec.rb diff --git a/compiler2/spec/masgn_spec.rb b/lib/compiler2/spec/masgn_spec.rb similarity index 100% rename from compiler2/spec/masgn_spec.rb rename to lib/compiler2/spec/masgn_spec.rb diff --git a/compiler2/spec/op_assign_spec.rb b/lib/compiler2/spec/op_assign_spec.rb similarity index 100% rename from compiler2/spec/op_assign_spec.rb rename to lib/compiler2/spec/op_assign_spec.rb diff --git a/compiler2/spec/scopes_spec.rb b/lib/compiler2/spec/scopes_spec.rb similarity index 100% rename from compiler2/spec/scopes_spec.rb rename to lib/compiler2/spec/scopes_spec.rb diff --git a/compiler2/spec/simple_spec.rb b/lib/compiler2/spec/simple_spec.rb similarity index 100% rename from compiler2/spec/simple_spec.rb rename to lib/compiler2/spec/simple_spec.rb diff --git a/compiler2/spec/variables_spec.rb b/lib/compiler2/spec/variables_spec.rb similarity index 100% rename from compiler2/spec/variables_spec.rb rename to lib/compiler2/spec/variables_spec.rb diff --git a/runtime/stable/bootstrap.rba b/runtime/stable/bootstrap.rba index f424756e01..ea0dbc897a 100644 Binary files a/runtime/stable/bootstrap.rba and b/runtime/stable/bootstrap.rba differ diff --git a/runtime/stable/compiler.rba b/runtime/stable/compiler.rba deleted file mode 100644 index 1eff02227d..0000000000 Binary files a/runtime/stable/compiler.rba and /dev/null differ diff --git a/runtime/stable/compiler1.rba b/runtime/stable/compiler1.rba new file mode 100644 index 0000000000..98d70793dc Binary files /dev/null and b/runtime/stable/compiler1.rba differ diff --git a/runtime/stable/core.rba b/runtime/stable/core.rba index f73b6cbafe..4aa7f98d17 100644 Binary files a/runtime/stable/core.rba and b/runtime/stable/core.rba differ diff --git a/runtime/stable/loader.rbc b/runtime/stable/loader.rbc index f7e1c35f36..c100765883 100644 Binary files a/runtime/stable/loader.rbc and b/runtime/stable/loader.rbc differ diff --git a/runtime/stable/platform.rba b/runtime/stable/platform.rba index 6c7d39c7e3..fbb74ae22a 100644 Binary files a/runtime/stable/platform.rba and b/runtime/stable/platform.rba differ diff --git a/shotgun/lib/Makefile b/shotgun/lib/Makefile index 31e071b1ea..153020b8cc 100644 --- a/shotgun/lib/Makefile +++ b/shotgun/lib/Makefile @@ -76,8 +76,7 @@ SOURCES=$(sort \ node_types.c \ ) OBJS=$(SOURCES:.c=.o) subtend/PortableUContext_asm.o -RUBY=ruby -I../../compiler - +RUBY=ruby -I../../lib %.o: %.c $(COMP) $(CFLAGS) $(OPTIMIZATIONS) -c $< -o $@ @@ -109,7 +108,7 @@ instruction_names.c instruction_names.h instructions.gen: instructions.rb system_primitives.gen: primitives.rb $(RUBY) primitives.rb > system_primitives.gen -auto.h auto.c: genheader.rb ../../compiler/bytecode/system_hints.rb +auto.h auto.c: genheader.rb ../../lib/compiler1/bytecode/system_hints.rb $(RUBY) genheader.rb > auto.c node_types.c node_types.h: node_types.rb diff --git a/shotgun/lib/cpu.c b/shotgun/lib/cpu.c index ec794c7f15..33aeee5cf3 100644 --- a/shotgun/lib/cpu.c +++ b/shotgun/lib/cpu.c @@ -417,7 +417,6 @@ OBJECT cpu_const_set(STATE, cpu c, OBJECT sym, OBJECT val, OBJECT under) { void cpu_set_encloser_path(STATE, cpu c, OBJECT cls) { int len; len = ptr_array_length(c->paths); - /* add stuff for @paths here */ ptr_array_append(c->paths, (xpointer)c->enclosing_class); cmethod_set_staticscope(cpu_current_method(state, c), diff --git a/shotgun/lib/cpu_instructions.c b/shotgun/lib/cpu_instructions.c index 1be3ec931d..7e6ef26b5d 100644 --- a/shotgun/lib/cpu_instructions.c +++ b/shotgun/lib/cpu_instructions.c @@ -12,6 +12,8 @@ #include "bytearray.h" #include "fixnum.h" +#include "primitive_util.h" + #include #include @@ -476,33 +478,47 @@ void cpu_raise_primitive_failure(STATE, cpu c, int primitive_idx) { } static inline int cpu_try_primitive(STATE, cpu c, OBJECT mo, OBJECT recv, int args, OBJECT sym, OBJECT mod) { - int prim, req, ret; + int prim, req; + OBJECT prim_obj; + + prim_obj = cmethod_get_primitive(mo); - prim = FIXNUM_TO_INT(cmethod_get_primitive(mo)); + if(!FIXNUM_P(prim_obj)) { + if(SYMBOL_P(prim_obj)) { + prim = calc_primitive_index(state, symbol_to_string(state, prim_obj)); + } else { + prim = -1; + } + cmethod_set_primitive(mo, I2N(prim)); + } else { + prim = FIXNUM_TO_INT(prim_obj); + } + + if(prim < 0) return FALSE; + req = FIXNUM_TO_INT(cmethod_get_required(mo)); - ret = FALSE; - if(prim > -1) { - if(req < 0 || args == req) { - stack_push(recv); - // printf("Running primitive: %d\n", prim); - if(cpu_perform_primitive(state, c, prim, mo, args, sym, mod)) { - /* Worked! */ - return TRUE; - } - /* Didn't work, need to remove the recv we put on before. */ - stack_pop(); - if(EXCESSIVE_TRACING) { - printf("[[ Primitive failed! -- %d ]]\n", prim); - } - } else if(req >= 0) { // not sure why this was here... } && object_kind_of_p(state, mo, state->global->cmethod)) { - /* raise an exception about them not doing it right. */ - cpu_raise_arg_error(state, c, args, req); - ret = TRUE; + if(args == req || req < 0) { + stack_push(recv); + if(cpu_perform_primitive(state, c, prim, mo, args, sym, mod)) { + /* Worked! */ + return TRUE; + } + /* Didn't work, need to remove the recv we put on before. */ + stack_pop(); + if(EXCESSIVE_TRACING) { + printf("[[ Primitive failed! -- %d ]]\n", prim); } + + return FALSE; } + + /* raise an exception about them not doing it right. */ + cpu_raise_arg_error(state, c, args, req); - return ret; + /* Return TRUE to indicate that the work for this primitive has + been done. */ + return TRUE; } /* Raw most functions for moving in a method. Adjusts register. */ @@ -520,7 +536,6 @@ inline void cpu_save_registers(STATE, cpu c, int offset) { fc->ip = c->ip; } -#include inline void cpu_restore_context_with_home(STATE, cpu c, OBJECT ctx, OBJECT home, int ret, int is_block) { struct fast_context *fc; diff --git a/shotgun/lib/genheader.rb b/shotgun/lib/genheader.rb index 98c68d27ef..d117aeb458 100644 --- a/shotgun/lib/genheader.rb +++ b/shotgun/lib/genheader.rb @@ -1,4 +1,4 @@ -require '../../compiler/bytecode/system_hints' +require '../../lib/compiler1/bytecode/system_hints' klasses = [] diff --git a/shotgun/lib/instructions.rb b/shotgun/lib/instructions.rb index 47b0013bf5..a37520329b 100644 --- a/shotgun/lib/instructions.rb +++ b/shotgun/lib/instructions.rb @@ -1,12 +1,12 @@ -require 'bytecode/encoder' +require 'compiler1/bytecode/encoder' class ShotgunInstructions def generate_switch(fd, op="op") i = 0 - order = Bytecode::InstructionEncoder::OpCodes - ci = Bytecode::InstructionEncoder::CheckInterupts - term = Bytecode::InstructionEncoder::Terminators + order = Compiler1::Bytecode::InstructionEncoder::OpCodes + ci = Compiler1::Bytecode::InstructionEncoder::CheckInterupts + term = Compiler1::Bytecode::InstructionEncoder::Terminators fd.puts "switch(#{op}) {" order.each do |ins| @@ -34,9 +34,9 @@ def generate_switch(fd, op="op") def generate_threaded(fd, op="op") i = 0 - order = Bytecode::InstructionEncoder::OpCodes - ci = Bytecode::InstructionEncoder::CheckInterupts - term = Bytecode::InstructionEncoder::Terminators + order = Compiler1::Bytecode::InstructionEncoder::OpCodes + ci = Compiler1::Bytecode::InstructionEncoder::CheckInterupts + term = Compiler1::Bytecode::InstructionEncoder::Terminators order.each do |ins| code = send(ins) rescue nil @@ -61,9 +61,9 @@ def generate_threaded(fd, op="op") end def generate_dter - order = Bytecode::InstructionEncoder::OpCodes - two = Bytecode::InstructionEncoder::TwoInt - one = Bytecode::InstructionEncoder::IntArg - two + order = Compiler1::Bytecode::InstructionEncoder::OpCodes + two = Compiler1::Bytecode::InstructionEncoder::TwoInt + one = Compiler1::Bytecode::InstructionEncoder::IntArg - two code = "static int _ip_size(uint32_t bc) {\nswitch(bc) {\n" two.each do |ins| @@ -128,7 +128,7 @@ def generate_declarations(fd) end def generate_names - order = Bytecode::InstructionEncoder::OpCodes; + order = Compiler1::Bytecode::InstructionEncoder::OpCodes; str = "static const char instruction_names[] = {\n" order.each do |ins| str << " \"#{ins.to_s}\\0\"\n" @@ -152,7 +152,7 @@ def generate_names def generate_names_header str = "const char *get_instruction_name(int op);\n" - order = Bytecode::InstructionEncoder::OpCodes; + order = Compiler1::Bytecode::InstructionEncoder::OpCodes; i = 0 order.each do |ins| str << "#define CPU_INSTRUCTION_#{ins.to_s.upcase} #{i}\n" @@ -727,7 +727,6 @@ def send_method t2 = Qnil; j = 0; goto perform_send; - // cpu_unified_send(state, c, t1, _int, 0, Qnil); CODE end @@ -738,7 +737,6 @@ def meta_send_stack_1 t2 = Qnil; j = 1; goto perform_send; - // cpu_unified_send(state, c, stack_pop(), _int, 1, Qnil); CODE end @@ -749,7 +747,6 @@ def meta_send_stack_2 t2 = Qnil; j = 2; goto perform_send; - // cpu_unified_send(state, c, stack_pop(), _int, 2, Qnil); CODE end @@ -760,9 +757,6 @@ def meta_send_stack_3 t2 = Qnil; j = 3; goto perform_send; - - // next_int; - // cpu_unified_send(state, c, stack_pop(), _int, 3, Qnil); CODE end @@ -772,10 +766,7 @@ def meta_send_stack_4 t1 = stack_pop(); t2 = Qnil; j = 4; - goto perform_send; - - // next_int; - // cpu_unified_send(state, c, stack_pop(), _int, 4, Qnil); + goto perform_send; CODE end @@ -788,7 +779,6 @@ def send_stack j = _int; // num_args goto perform_send; - // cpu_unified_send(state, c, stack_pop(), j, k, Qnil); CODE end @@ -801,7 +791,6 @@ def send_stack_with_block j = _int; goto perform_send; - // cpu_unified_send(state, c, t1, j, _int, t2); CODE end @@ -852,7 +841,6 @@ def send_off_stack stack_push(t3); _lit = state->global->sym_send; j = c->args; - // cpu_send_method2(state, c, t1, state->global->sym_send, c->args + 1, t2); goto perform_send; } } @@ -861,8 +849,6 @@ def send_off_stack _lit = t3; j = c->args; goto perform_send; - // cpu_send_method2(state, c, t1, t3, c->args, t2); - // sos_done: CODE end @@ -887,7 +873,6 @@ def meta_send_op_plus t2 = Qnil; j = 1; goto perform_send; - // cpu_send_method(state, c, t1, state->global->sym_plus, 1); } CODE end @@ -904,7 +889,6 @@ def meta_send_op_minus t2 = Qnil; j = 1; goto perform_send; - // cpu_send_method(state, c, t1, state->global->sym_minus, 1); } CODE end @@ -922,7 +906,6 @@ def meta_send_op_equal t2 = Qnil; j = 1; goto perform_send; - // cpu_send_method(state, c, t1, state->global->sym_equal, 1); } CODE end @@ -940,8 +923,6 @@ def meta_send_op_nequal t2 = Qnil; j = 1; goto perform_send; - - // cpu_send_method(state, c, t1, state->global->sym_nequal, 1); } CODE end @@ -960,8 +941,6 @@ def meta_send_op_tequal t2 = Qnil; j = 1; goto perform_send; - - // cpu_send_method(state, c, t1, state->global->sym_tequal, 1); } CODE end @@ -980,8 +959,6 @@ def meta_send_op_lt t2 = Qnil; j = 1; goto perform_send; - - // cpu_send_method(state, c, t1, state->global->sym_lt, 1); } CODE end @@ -1000,7 +977,6 @@ def meta_send_op_gt t2 = Qnil; j = 1; goto perform_send; - // cpu_send_method(state, c, t1, state->global->sym_gt, 1); } CODE end @@ -1015,12 +991,9 @@ def soft_return def caller_return <<-CODE t2 = stack_pop(); - t1 = c->active_context; - c->active_context = cpu_current_sender(c); - if(cpu_return_to_sender(state, c, t2, TRUE, FALSE)) { - methctx_reference(state, t1); - stack_push(t1); - } + + cpu_return_to_sender(state, c, Qnil, FALSE, TRUE); + cpu_return_to_sender(state, c, t2, FALSE, FALSE); CODE end diff --git a/shotgun/rubinius b/shotgun/rubinius index 33653378f6..5305a5c13d 100755 --- a/shotgun/rubinius +++ b/shotgun/rubinius @@ -1,59 +1,79 @@ -#!/bin/sh +#!/usr/bin/env ruby -PREFIX=`echo $0 | sed -e 's/shotgun\/rubinius//'` +m = %r!(.*?)[/]?shotgun/rubinius!.match($0) -REAL=${PREFIX}shotgun/rubinius.bin +prefix = m[1] +prefix = "" if prefix == "./" -export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${PREFIX}shotgun/lib -export LD_LIBRARY_PATH_64=$LD_LIBRARY_PATH_64:${PREFIX}shotgun/lib -export SH_LIB=$SH_LIB:${PREFIX}shotgun/lib -export LIBPATH=$LIBPATH:${PREFIX}shotgun/lib -export PATH=$PATH:${PREFIX}shotgun/lib -export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:${PREFIX}shotgun/lib +unless prefix[0] == ?/ + prefix = File.expand_path File.join(Dir.getwd, prefix) +end -if [ "x${PREFIX}" != "x" ]; then +real = File.join(prefix, 'shotgun/rubinius.bin') - RUNTIME=${PREFIX}runtime/ +# Setup all the crazy library path stuff so that librubinus is picked +# up properly. - if [ "x${RBX_PREFIX}" = "x" ]; then - export RBX_PREFIX=${PREFIX} - fi +@prefix = prefix - if [ "x${RBX_BOOTSTRAP}" = "x" ]; then - export RBX_BOOTSTRAP=${RUNTIME}bootstrap - fi +def set_env(name) + addition = "#{@prefix}/shotgun/lib" + + if cur = ENV[name] + ENV[name] = "#{addition}:#{cur}" + else + ENV[name] = addition + end +end - if [ "x${RBX_COMPILER}" = "x" ]; then - export RBX_COMPILER=${RUNTIME}compiler - fi +set_env 'LD_LIBRARY_PATH' +set_env 'LD_LIBRARY_PATH_64' +set_env 'SHLIB' +set_env 'LIBPATH' +set_env 'PATH' +set_env 'DYLD_LIBRARY_PATH' +set_env 'DYLD_FALLBACK_LIBRARY_PATH' - if [ "x${RBX_CORE}" = "x" ]; then - export RBX_CORE=${RUNTIME}core - fi +ENV['RBX_IN_BUILDDIR'] = "1" - if [ "x${RBX_LOADER}" = "x" ]; then - export RBX_LOADER=${RUNTIME}loader.rbc - fi +ENV['RBX_PREFIX'] = "#{prefix}/" - if [ "x${RBX_PLATFORM}" = "x" ]; then - export RBX_PLATFORM=${RUNTIME}platform - fi -fi +unless ENV['RBX_BOOTSTRAP'] + ENV['RBX_BOOTSTRAP'] = "#{prefix}/runtime/bootstrap" +end -if test "x$1" = "x--gdb"; then - shift - export PATH=${PREFIX}shotgun:$PATH +unless ENV['RBX_CORE'] + ENV['RBX_CORE'] = "#{prefix}/runtime/core" +end - gdb_command="gdb -x ${PREFIX}shotgun/gdbcommands" - if [ `uname -s` = "Darwin" ] && [ `uname -r | cut -d '.' -f 1` -lt "9" ]; then - gdb_command="${gdb_command} -x ${PREFIX}shotgun/gdbenvironment" - fi - gdb_command="${gdb_command} --args /dev/null" +unless ENV['RBX_PLATFORM'] + ENV['RBX_PLATFORM'] = "#{prefix}/runtime/platform" +end - exec $gdb_command "$@" -elif test "x$1" = "x--valgrind"; then - shift - exec valgrind -v $REAL "$@" +unless ENV['RBX_LOADER'] + ENV['RBX_LOADER'] = "#{prefix}/runtime/loader.rbc" +end + +if ARGV[0] == "--gdb" + ARGV.shift + + ENV['PATH'] = "#{prefix}/shotgun:#{ENV['PATH']}" + args = ['-x', "#{prefix}/shotgun/gdbcommands"] + if `uname -s` == "Darwin" and `uname -r`.split(".")[0].to_i < 9 + args << '-x' << "#{prefix}/shotgun/gdbenvironment" + end + args << '--args' << "/dev/null" + + exec "gdb", *(args + ARGV) +elsif ARGV[0] == "--valgrind" + ARGV.shift + args = ['-v', real] + exec 'valgrind', *(args + ARGV) +elsif ARGV[0] == "--shark" + ARGV.shift + puts "Starting up rubinius, then pausing for shark to start" + pid = fork { sleep 5; exec real, *ARGV } + exec "shark -o rbxshark -i -1 -a #{pid}" else - exec $REAL "$@" -fi + exec real, *ARGV +end