Skip to content

Commit

Permalink
Merge branch 'master' into codedb-ffi-io
Browse files Browse the repository at this point in the history
Conflicts:
	machine/builtin/io.cpp
chuckremes committed May 2, 2016
2 parents 5e3dc89 + 4b2a14b commit 0b140bf
Showing 145 changed files with 3,003 additions and 4,099 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/9502afd22ca6c8e85fb3
on_success: change
on_success: always
on_failure: always
on_start: always
env:
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@
- Ben Brinckerhoff:
- Ben Burkert:
- Ben Curren:
- Ben Feng: { github: fengb }
- Ben Hughes:
- Benjamin Andresen:
- Benjamin Klotz: { irc: bennyklotz, github: bennyklotz, twitter: BennyKlotz }
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -4,6 +4,6 @@ gem "rake", "~> 10.0"
gem "redcard", "~> 1.0"

gem "daedalus-core", "~> 0.1"
gem "rubinius-bridge", "~> 1.0"
gem "rubinius-bridge", "~> 2.0"

gem "rubinius-code", "~> 3"
10 changes: 5 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ GEM
daedalus-core (0.5.0)
rake (10.5.0)
redcard (1.1.0)
rubinius-ast (3.2)
rubinius-bridge (1.1.0)
rubinius-ast (3.5)
rubinius-bridge (2.2)
redcard (~> 1.0)
rubinius-code (3.0)
rubinius-ast (~> 3)
@@ -14,9 +14,9 @@ GEM
rubinius-melbourne (~> 3)
rubinius-processor (~> 3)
rubinius-toolset (~> 3)
rubinius-compiler (3.1)
rubinius-compiler (3.3)
rubinius-instructions (3.0)
rubinius-melbourne (3.4)
rubinius-melbourne (3.5)
rubinius-processor (3.0)
rubinius-toolset (3.0)

@@ -27,7 +27,7 @@ DEPENDENCIES
daedalus-core (~> 0.1)
rake (~> 10.0)
redcard (~> 1.0)
rubinius-bridge (~> 1.0)
rubinius-bridge (~> 2.0)
rubinius-code (~> 3)

BUNDLED WITH
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
@@ -167,7 +167,7 @@ class Configure
@ruby_libversion = @ruby_version.split(/\./)[0..1].join.to_i

# Configure settings
@release_build = !git_directory
@release_build = !in_git?
end

# Set up system commands to run in cmd.exe on Windows. Either Windows
2 changes: 1 addition & 1 deletion core/alpha.rb
Original file line number Diff line number Diff line change
@@ -139,7 +139,7 @@ def to_s
#
# Redefined later.
#
def raise(cls, str, junk=nil)
def raise(cls, str="", junk=nil)
Rubinius::VM.write_error "Fatal error loading core library:\n "
Rubinius::VM.write_error str
Rubinius::VM.write_error "\n"
1 change: 0 additions & 1 deletion core/array.rb
Original file line number Diff line number Diff line change
@@ -570,7 +570,6 @@ def combination(num)
def compact
out = dup
out.untaint if out.tainted?
out.trust if out.untrusted?

Array.new(out.compact! || out)
end
33 changes: 25 additions & 8 deletions core/call_site.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
module Rubinius
class CallSite
attr_reader :name
attr_reader :executable

def hits
0
end
attr_reader :cache

def ip
Rubinius.primitive :call_site_ip
raise PrimitiveFailure, "CallSite#ip primitive failed"
end

def location
"#{@executable.file}:#{@executable.line_from_ip(ip)}"
def depth
Rubinius.primitive :call_site_depth
raise PrimitiveFailure, "CallSite#depth primitive failed"
end

def invokes
Rubinius.primitive :call_site_invokes
raise PrimitiveFailure, "CallSite#invokes primitive failed"
end

def hits
Rubinius.primitive :call_site_hits
raise PrimitiveFailure, "CallSite#hits primitive failed"
end

def misses
Rubinius.primitive :call_site_misses
raise PrimitiveFailure, "CallSite#misses primitive failed"
end

def reset
Rubinius.primitive :call_site_reset
raise PrimitiveFailure, "CallSite#reset primitive failed"
end

def inspect
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} #{location}##{@name}(#{hits})>"
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} name=#{@name} ip=#{ip} depth=#{depth} invokes=#{invokes} hits=#{hits} misses=#{misses}>"
end
end
end
43 changes: 26 additions & 17 deletions core/kernel.rb
Original file line number Diff line number Diff line change
@@ -69,20 +69,9 @@ def untaint
raise PrimitiveFailure, "Kernel#untaint primitive failed"
end

def trust
Rubinius.primitive :object_trust
raise PrimitiveFailure, "Kernel#trust primitive failed"
end

def untrust
Rubinius.primitive :object_untrust
raise PrimitiveFailure, "Kernel#untrust primitive failed"
end

def untrusted?
Rubinius.primitive :object_untrusted_p
raise PrimitiveFailure, "Kernel#untrusted? primitive failed"
end
alias_method :untrust, :taint
alias_method :trust, :untaint
alias_method :untrusted?, :tainted?

# NOTE: The bootstrap method used to add method definitions to the class
# method_table still returns a CompiledCode instance, so this chaining
@@ -725,9 +714,29 @@ def private_singleton_methods
end
private :private_singleton_methods

def proc(&prc)
raise ArgumentError, "block required" unless prc
return prc
def proc
env = nil

Rubinius.asm do
push_block
# assign a pushed block to the above local variable "env"
set_local 0
end

unless env
# Support for ancient pre-block-pass style:
# def something
# proc
# end
# something { a_block } => Proc instance
env = Rubinius::BlockEnvironment.of_sender

unless env
raise ArgumentError, "tried to create a Proc object without a block"
end
end

Proc.new(&env)
end
module_function :proc

2 changes: 0 additions & 2 deletions core/load_order.txt
Original file line number Diff line number Diff line change
@@ -77,7 +77,6 @@ metrics.rb
mirror.rb
missing_method.rb
module.rb
mono_inline_cache.rb
mutex.rb
native_method.rb
nil.rb
@@ -88,7 +87,6 @@ options.rb
pack.rb
pointer.rb
pointer_accessors.rb
poly_inline_cache.rb
proc.rb
proc_mirror.rb
process.rb
4 changes: 3 additions & 1 deletion core/marshal.rb
Original file line number Diff line number Diff line change
@@ -572,7 +572,9 @@ def construct(ivar_index = nil, call_proc = true)

call obj if @proc and call_proc

@stream.tainted? && !obj.frozen? ? obj.taint : obj
Rubinius::Type.infect obj, @stream unless obj.frozen?

obj
end

def construct_class
25 changes: 0 additions & 25 deletions core/mono_inline_cache.rb

This file was deleted.

16 changes: 10 additions & 6 deletions core/numeric.rb
Original file line number Diff line number Diff line change
@@ -31,23 +31,27 @@ def <=>(other)
return nil
end

def step(limit, step=1)
def step(limit=nil, step=nil, to: nil, by: nil)
unless block_given?
return to_enum(:step, limit, step) do
Rubinius::Mirror::Numeric.reflect(self).step_size(limit, step)
return to_enum(:step, limit, step, to: to, by: by) do
Rubinius::Mirror::Numeric.reflect(self).step_size(limit, step, to, by)
end
end

raise ArgumentError, "step cannot be 0" if step == 0

m = Rubinius::Mirror::Numeric.reflect(self)
values = m.step_fetch_args(limit, step)
values = m.step_fetch_args(limit, step, to, by)
value = values[0]
limit = values[1]
step = values[2]
asc = values[3]
is_float = values[4]

if step == 0
while true
yield value
end
end

if is_float
n = m.step_float_size(value, limit, step, asc)

12 changes: 9 additions & 3 deletions core/numeric_mirror.rb
Original file line number Diff line number Diff line change
@@ -21,14 +21,16 @@ def step_float_size(value, limit, step, asc)
end
end

def step_size(limit, step)
values = step_fetch_args(limit, step)
def step_size(limit, step, to, by)
values = step_fetch_args(limit, step, to, by)
value = values[0]
limit = values[1]
step = values[2]
asc = values[3]
is_float = values[4]

return Float::INFINITY if step == 0

if is_float
# Ported from MRI

@@ -43,9 +45,13 @@ def step_size(limit, step)
end
end

def step_fetch_args(limit, step)
def step_fetch_args(limit, step, to, by)
raise ArgumentError, "limit is given twice" if limit && to
raise ArgumentError, "step is given twice" if step && by
raise ArgumentError, "step cannot be 0" if step == 0

limit ||= to
step ||= by || 1
value = @object
asc = step > 0
if value.kind_of? Float or limit.kind_of? Float or step.kind_of? Float
52 changes: 0 additions & 52 deletions core/poly_inline_cache.rb

This file was deleted.

20 changes: 13 additions & 7 deletions core/random.rb
Original file line number Diff line number Diff line change
@@ -38,17 +38,17 @@ def random(limit)
elsif limit.kind_of?(Float)
raise ArgumentError, "invalid argument - #{limit}" if limit <= 0
random_float * limit
elsif limit.is_a?(Integer)
raise ArgumentError, "invalid argument - #{limit}" if limit <= 0
random_integer(limit - 1)
elsif limit.respond_to?(:to_f)
raise ArgumentError, "invalid argument - #{limit}" if limit <= 0
random_float * limit
else
limit_int = Rubinius::Type.coerce_to limit, Integer, :to_int
raise ArgumentError, "invalid argument - #{limit}" if limit_int <= 0

if limit.is_a?(Integer)
random_integer(limit - 1)
elsif limit.respond_to?(:to_f)
random_float * limit
else
random_integer(limit_int - 1)
end
random_integer(limit_int - 1)
end
end
end
@@ -66,8 +66,14 @@ def random_integer(limit)
end

def random_range(limit)
return nil if limit.first.nil? || limit.last.nil?

min, max = limit.last.coerce(limit.first)
diff = max - min

return if diff < 0
return min if diff == 0

diff += 1 if max.kind_of?(Integer) && !limit.exclude_end?
random(diff) + min
end
5 changes: 0 additions & 5 deletions core/rubinius.rb
Original file line number Diff line number Diff line change
@@ -219,11 +219,6 @@ def self.thread_state
raise PrimitiveFailure, "Rubinius.thread_state primitive failed"
end

def self.check_interrupts
Rubinius.primitive :vm_check_interrupts
raise PrimitiveFailure, "Rubinius.check_interrupts primitive failed"
end

# Used to invoke a CompiledCode instance as a script body. Sets up the MAIN
# object as self and bypasses JIT'ing (because why JIT a script you only run
# once).
102 changes: 48 additions & 54 deletions core/sprinter.rb
Original file line number Diff line number Diff line change
@@ -19,8 +19,12 @@ def self.get(format)
end

def initialize(format)
Rubinius::Type.object_singleton_class(self).dynamic_method :call do |g|
Builder.new(self, format, g).build
begin
Rubinius::Type.object_singleton_class(self).dynamic_method :call do |g|
Builder.new(self, format, g).build
end
rescue Rubinius::ToolSets::Runtime::CompileError => e
raise RuntimeError, "failed to compile printf format: #{format}", e
end
end

@@ -281,20 +285,15 @@ def build
@g.ret
end

def meta_op_minus
@op_minus ||= @g.find_literal(:-)
@g.meta_send_op_minus @op_minus
end

def invert
@g.meta_push_0
@g.push_int 0
@g.swap
meta_op_minus
@g.send :-, 1
end

def is_negative
@g.meta_push_0
@g.meta_send_op_lt @g.find_literal(:<)
@g.push_int 0
@g.send :<, 1
end

def justify(direction, may_be_negative=true)
@@ -339,7 +338,7 @@ def next_index(specified=nil)
end

def append_literal(str)
@g.push_unique_literal str
@g.push_literal str
append_str
end

@@ -353,8 +352,8 @@ def encode_value(str)
end

def is_zero
@g.meta_push_0
@g.meta_send_op_equal @g.find_literal(:==)
@g.push_int 0
@g.send :equal?, 1
end

class Atom
@@ -410,16 +409,16 @@ def set_precision(full, ref, static)
def push_value
if @name
@g.push_local 0
@g.push_unique_literal @name
@g.send(:fetch, 1)
@g.push_literal @name
@g.send :fetch, 1
else
@g.push_local @field_index
end
end

def push_width_value
if @width_static
@g.push @width_static
@g.push_int @width_static
elsif
@g.push_local @width_index
else
@@ -431,9 +430,9 @@ def push_width(adjust=true)
if @width_static
raise ArgumentError, "width too big" unless @width_static.class == Fixnum
if adjust && @full_leader_size > 0
@g.push(@width_static - @full_leader_size)
@g.push_int(@width_static - @full_leader_size)
else
@g.push @width_static
@g.push_int @width_static
end

elsif @width_index
@@ -460,7 +459,7 @@ def push_width(adjust=true)

def push_precision_value
if @prec_static
@g.push @prec_static
@g.push_int @prec_static
else
@g.push_local @prec_index
end
@@ -469,7 +468,7 @@ def push_precision_value
def push_precision
if @prec_static
raise ArgumentError, "precision too big" unless @prec_static.class == Fixnum
@g.push @prec_static
@g.push_int @prec_static

elsif @prec_index
@g.push_local @prec_index
@@ -599,8 +598,8 @@ def bytecode

@g.dup
@g.send :length, 0
@g.meta_push_1
@g.meta_send_op_equal @g.find_literal(:==)
@g.push_int 1
@g.send :equal?, 1
@b.if_false do
@b.raise_ArgumentError "%c requires a character"
end
@@ -646,7 +645,7 @@ def expand_with_width

def bytecode
if fast_common_case?
@g.push :self
@g.push_self

push_value

@@ -659,7 +658,7 @@ def bytecode

@b.append_str
else
@g.push :self
@g.push_self
push_value
@g.send :as_int, 1

@@ -670,27 +669,27 @@ def bytecode
# generic case

if @f_space
@g.push :self
@g.push_self
@g.push_stack_local val_idx
@g.send :compute_space, 1
@b.append_str
elsif @f_plus
@g.push :self
@g.push_self
@g.push_stack_local val_idx
@g.send :compute_plus, 1
@b.append_str
end

if @has_precision
@g.push :self
@g.push_self
@g.push_stack_local val_idx

push_precision_value

@g.send :digit_expand_precision, 2

if @has_width
@g.push :self
@g.push_self
@g.swap
push_width_value

@@ -704,7 +703,7 @@ def bytecode
@b.append_str

elsif @has_width
@g.push :self
@g.push_self
@g.push_stack_local val_idx

push_width_value
@@ -726,8 +725,8 @@ class ExtIntegerAtom < Atom
def pad_negative_int(padding)
zero_pad(padding) do
# decrease the width by 2 to account for the ".." below
@g.meta_push_2
@b.meta_op_minus
@g.push_int 2
@g.send :-, 1
end

@g.push_literal ".."
@@ -743,7 +742,7 @@ def prepend_prefix_bytecode
if @format_code == 'x' || @format_code == 'X'
push_value
@b.is_zero
@g.git skip_prefix
@g.goto_if_true skip_prefix
end

prepend_prefix
@@ -753,13 +752,13 @@ def prepend_prefix_bytecode

def format_negative_int(radix)
# (num + radix ** num.to_s(radix).size).to_s(radix)
@g.push radix
@g.push_int radix
@g.dup_many 2
@g.send :to_s, 1
@g.send :size, 0
@g.send :**, 1
@g.meta_send_op_plus @g.find_literal(:+)
@g.push radix
@g.send :+, 1
@g.push_int radix
@g.send :to_s, 1

(radix - 1).to_s(radix)
@@ -790,7 +789,7 @@ def bytecode
@b.invert
end

@g.push radix
@g.push_int radix
@g.send :to_s, 1
else
have_formatted = @g.new_label
@@ -799,7 +798,7 @@ def bytecode
@b.is_negative

@b.if_false do
@g.push radix
@g.push_int radix
@g.send :to_s, 1
@g.goto have_formatted
end
@@ -862,7 +861,7 @@ def string_justify
justify_width

if @has_precision
@g.meta_push_0
@g.push_int 0
push_precision
@g.send :[], 2
end
@@ -961,11 +960,9 @@ def push_Hash
end

def raise_ArgumentError(msg)
@lit_new ||= @g.add_literal(:new)

@g.push_const :ArgumentError
@g.push_unique_literal msg
@g.send_stack @lit_new, 1
@g.push_literal msg
@g.send :new, 1
@g.raise_exc
end

@@ -984,9 +981,6 @@ def force_type(klass, method=klass)
end

def try_type(klass, method)

@lit_check ||= @g.add_literal(:check_convert_type)

@g.dup
@g.push_const klass
@g.swap
@@ -995,8 +989,8 @@ def try_type(klass, method)
@g.push_type
@g.swap
@g.push_const klass
@g.push_unique_literal method
@g.send_stack @lit_check, 3
@g.push_literal method
@g.send :check_convert_type, 3
@g.dup
if_false do
yield if block_given?
@@ -1006,14 +1000,14 @@ def try_type(klass, method)

def if_true
l = @g.new_label
@g.gif l
@g.goto_if_false l
yield
l.set!
end

def if_false
l = @g.new_label
@g.git l
@g.goto_if_true l
yield
l.set!
end
@@ -1094,11 +1088,11 @@ def parse

@arg_count = 1
@g.passed_arg @arg_count
@g.git exception
@g.goto_if_true exception
push_Hash
@g.push_local 0
@g.kind_of
@g.gif exception
@g.goto_if_false exception
@g.goto continue

exception.set!
@@ -1114,11 +1108,11 @@ def parse

# Check this first; it's much faster, and generally false
@g.passed_arg @arg_count
@g.gif no_exception
@g.goto_if_false no_exception

gva = Rubinius::ToolSets::Runtime::AST::GlobalVariableAccess
gva.new(1, :$DEBUG).bytecode(@g)
@g.gif no_exception
@g.goto_if_false no_exception

raise_ArgumentError "too many arguments for format string"

97 changes: 38 additions & 59 deletions core/string.rb
Original file line number Diff line number Diff line change
@@ -224,8 +224,7 @@ def %(args)
*args = args
ret = Rubinius::Sprinter.get(self).call(*args)

ret.taint if tainted?
return ret
Rubinius::Type.infect ret, self
end

def *(num)
@@ -413,8 +412,9 @@ def crypt(other_str)
end

hash = __crypt__(other_str)
hash.taint if tainted? || other_str.tainted?
hash

Rubinius::Type.infect hash, self
Rubinius::Type.infect hash, other_str
end

def delete(*strings)
@@ -1338,32 +1338,28 @@ def sub(pattern, replacement=undefined)
raise ArgumentError, "invalid byte sequence in #{encoding}"
end

ret = byteslice(0, 0) # Empty string and string subclass

if undefined.equal? replacement
unless block_given?
raise ArgumentError, "method '#{__method__}': given 1, expected 2"
end
use_yield = true
tainted = false
else
tainted = replacement.tainted?
untrusted = replacement.untrusted?

unless replacement.kind_of?(String)
hash = Rubinius::Type.check_convert_type(replacement, Hash, :to_hash)
replacement = StringValue(replacement) unless hash
tainted ||= replacement.tainted?
untrusted ||= replacement.untrusted?
end
use_yield = false

Rubinius::Type.infect ret, replacement
end

pattern = Rubinius::Type.coerce_to_regexp(pattern, true) unless pattern.kind_of? Regexp
match = pattern.match_from(self, 0)

Regexp.last_match = match

ret = byteslice(0, 0) # Empty string and string subclass

if match
ret.append match.pre_match

@@ -1375,25 +1371,21 @@ def sub(pattern, replacement=undefined)
else
val = hash[match.to_s]
end
untrusted = true if val.untrusted?
val = val.to_s unless val.kind_of?(String)

tainted ||= val.tainted?
Rubinius::Type.infect ret, val

ret.append val
else
replacement.to_sub_replacement(ret, match)
end

Rubinius::Type.infect ret, val
ret.append(match.post_match)
tainted ||= val.tainted?
else
ret = dup
end

ret.taint if tainted
ret.untrust if untrusted

ret
end

@@ -1405,34 +1397,31 @@ def sub!(pattern, replacement=undefined)
raise ArgumentError, "invalid byte sequence in #{encoding}"
end

ret = byteslice(0, 0) # Empty string and string subclass

if undefined.equal? replacement
unless block_given?
raise ArgumentError, "method '#{__method__}': given 1, expected 2"
end
Rubinius.check_frozen
use_yield = true
tainted = false
else
Rubinius.check_frozen
tainted = replacement.tainted?
untrusted = replacement.untrusted?

unless replacement.kind_of?(String)
hash = Rubinius::Type.check_convert_type(replacement, Hash, :to_hash)
replacement = StringValue(replacement) unless hash
tainted ||= replacement.tainted?
untrusted ||= replacement.untrusted?
end
use_yield = false

Rubinius::Type.infect ret, replacement
end

pattern = Rubinius::Type.coerce_to_regexp(pattern, true) unless pattern.kind_of? Regexp
match = pattern.match_from(self, 0)

Regexp.last_match = match

ret = byteslice(0, 0) # Empty string and string subclass

if match
ret.append match.pre_match

@@ -1444,25 +1433,22 @@ def sub!(pattern, replacement=undefined)
else
val = hash[match.to_s]
end
untrusted = true if val.untrusted?
val = val.to_s unless val.kind_of?(String)

tainted ||= val.tainted?
Rubinius::Type.infect ret, val

ret.append val
else
replacement.to_sub_replacement(ret, match)
end

Rubinius::Type.infect ret, val

ret.append(match.post_match)
tainted ||= val.tainted?
else
return nil
end

ret.taint if tainted
ret.untrust if untrusted

replace(ret)
self
end
@@ -1852,23 +1838,21 @@ def gsub(pattern, replacement=undefined)
raise ArgumentError, "invalid byte sequence in #{encoding}"
end

ret = byteslice(0, 0) # Empty string and string subclass

if undefined.equal? replacement
unless block_given?
return to_enum(:gsub, pattern, replacement)
end
use_yield = true
tainted = false
else
tainted = replacement.tainted?
untrusted = replacement.untrusted?

unless replacement.kind_of?(String)
hash = Rubinius::Type.check_convert_type(replacement, Hash, :to_hash)
replacement = StringValue(replacement) unless hash
tainted ||= replacement.tainted?
untrusted ||= replacement.untrusted?
end
use_yield = false

Rubinius::Type.infect ret, replacement
end

pattern = Rubinius::Type.coerce_to_regexp(pattern, true) unless pattern.kind_of? Regexp
@@ -1886,7 +1870,6 @@ def gsub(pattern, replacement=undefined)

last_match = nil

ret = byteslice(0, 0) # Empty string and string subclass
offset = match.full.at(0) if match

while match
@@ -1902,10 +1885,9 @@ def gsub(pattern, replacement=undefined)
else
val = hash[match.to_s]
end
untrusted = true if val.untrusted?
val = val.to_s unless val.kind_of?(String)

tainted ||= val.tainted?
Rubinius::Type.infect ret, val

ret.append val

@@ -1916,7 +1898,7 @@ def gsub(pattern, replacement=undefined)
replacement.to_sub_replacement(ret, match)
end

tainted ||= val.tainted?
Rubinius::Type.infect ret, val

last_end = match.full.at(1)

@@ -1945,9 +1927,6 @@ def gsub(pattern, replacement=undefined)
ret.append str
end

ret.taint if tainted
ret.untrust if untrusted

ret
end

@@ -1959,25 +1938,24 @@ def gsub!(pattern, replacement=undefined)
raise ArgumentError, "invalid byte sequence in #{encoding}"
end

ret = byteslice(0, 0) # Empty string and string subclass

if undefined.equal? replacement
unless block_given?
return to_enum(:gsub, pattern, replacement)
end
Rubinius.check_frozen
use_yield = true
tainted = false
else
Rubinius.check_frozen
tainted = replacement.tainted?
untrusted = replacement.untrusted?

unless replacement.kind_of?(String)
hash = Rubinius::Type.check_convert_type(replacement, Hash, :to_hash)
replacement = StringValue(replacement) unless hash
tainted ||= replacement.tainted?
untrusted ||= replacement.untrusted?
end
use_yield = false

Rubinius::Type.infect ret, replacement
end

pattern = Rubinius::Type.coerce_to_regexp(pattern, true) unless pattern.kind_of? Regexp
@@ -1996,7 +1974,6 @@ def gsub!(pattern, replacement=undefined)

last_match = nil

ret = byteslice(0, 0) # Empty string and string subclass
offset = match.full.at(0)

while match
@@ -2012,10 +1989,9 @@ def gsub!(pattern, replacement=undefined)
else
val = hash[match.to_s]
end
untrusted = true if val.untrusted?
val = val.to_s unless val.kind_of?(String)

tainted ||= val.tainted?
Rubinius::Type.infect ret, val

ret.append val

@@ -2026,7 +2002,7 @@ def gsub!(pattern, replacement=undefined)
replacement.to_sub_replacement(ret, match)
end

tainted ||= val.tainted?
Rubinius::Type.infect ret, val

last_end = match.full.at(1)

@@ -2055,9 +2031,6 @@ def gsub!(pattern, replacement=undefined)
ret.append str
end

ret.taint if tainted
ret.untrust if untrusted

replace(ret)
self
end
@@ -2314,7 +2287,9 @@ def center(width, padding=" ")
m.copy_from self, 0, bs, left
end

str.taint if tainted? or padding.tainted?
Rubinius::Type.infect str, self
Rubinius::Type.infect str, padding

str.force_encoding enc
end

@@ -2363,7 +2338,9 @@ def ljust(width, padding=" ")
m.copy_from self, 0, bs, 0
end

str.taint if tainted? or padding.tainted?
Rubinius::Type.infect str, self
Rubinius::Type.infect str, padding

str.force_encoding enc
end

@@ -2398,7 +2375,9 @@ def rjust(width, padding=" ")

m.copy_from self, 0, bs, bytes

str.taint if tainted? or padding.tainted?
Rubinius::Type.infect str, self
Rubinius::Type.infect str, padding

str.force_encoding enc
end

8 changes: 4 additions & 4 deletions gems_list.txt
Original file line number Diff line number Diff line change
@@ -9,15 +9,15 @@ rake-10.5.0.gem
rb-readline-0.5.3.gem
rdoc-4.2.2.gem
redcard-1.1.0.gem
rubinius-ast-3.2.gem
rubinius-bridge-1.1.0.gem
rubinius-ast-3.5.gem
rubinius-bridge-2.2.gem
rubinius-code-3.0.gem
rubinius-compiler-3.1.gem
rubinius-compiler-3.3.gem
rubinius-coverage-2.0.3.gem
rubinius-debugger-2.4.gem
rubinius-developer_tools-2.0.0.gem
rubinius-instructions-3.0.gem
rubinius-melbourne-3.4.gem
rubinius-melbourne-3.5.gem
rubinius-processor-3.0.gem
rubinius-profiler-2.0.2.gem
rubinius-toolset-3.0.gem
10 changes: 10 additions & 0 deletions library/rubinius/configuration.rb
Original file line number Diff line number Diff line change
@@ -168,6 +168,16 @@
c.vm_variable "profiler.threshold", 1000000,
"The minimum number of nanoseconds a profiler node must have to be reported"

c.section "machine" do |s|
s.section "call_site" do |cs|
cs.vm_variable "cache", true,
"Cache executables at call sites"

cs.vm_variable "limit", 3,
"Maximum number of caches at call sites"
end
end

c.section "system" do |s|
s.vm_variable "tmp", "$TMPDIR",
"Default temp/fallback directory for the process"
28 changes: 10 additions & 18 deletions machine/builtin/block_environment.cpp
Original file line number Diff line number Diff line change
@@ -445,7 +445,9 @@ namespace rubinius {
call_frame->flags = invocation.flags | CallFrame::cMultipleScopes
| CallFrame::cBlock;

state->vm()->push_call_frame(call_frame, previous_frame);
if(!state->vm()->push_call_frame(state, call_frame, previous_frame)) {
return NULL;
}

Object* value = NULL;

@@ -460,28 +462,18 @@ namespace rubinius {

OnStack<2> os(state, env, mod);

// Check the stack and interrupts here rather than in the interpreter
// loop itself.
if(state->check_interrupts(state)) {
tooling::BlockEntry method(state, env, mod);
value = (*mcode->run)(state, mcode);
}
tooling::BlockEntry method(state, env, mod);
value = (*mcode->run)(state, mcode);
} else {
// Check the stack and interrupts here rather than in the interpreter
// loop itself.
if(state->check_interrupts(state)) {
value = (*mcode->run)(state, mcode);
}
}
#else
// Check the stack and interrupts here rather than in the interpreter
// loop itself.
if(state->check_interrupts(state)) {
value = (*mcode->run)(state, mcode);
}
#else
value = (*mcode->run)(state, mcode);
#endif

state->vm()->pop_call_frame(previous_frame);
if(!state->vm()->pop_call_frame(state, previous_frame)) {
return NULL;
}

return value;
}
276 changes: 73 additions & 203 deletions machine/builtin/call_site.cpp
Original file line number Diff line number Diff line change
@@ -1,260 +1,130 @@
#include "arguments.hpp"
#include "call_frame.hpp"
#include "global_cache.hpp"
#include "lookup_data.hpp"
#include "object_utils.hpp"
#include "memory.hpp"

#include "builtin/class.hpp"
#include "builtin/call_site.hpp"
#include "builtin/exception.hpp"
#include "builtin/executable.hpp"
#include "builtin/mono_inline_cache.hpp"
#include "builtin/object.hpp"
#include "builtin/poly_inline_cache.hpp"

#include <stdlib.h>
#include <sstream>

namespace rubinius {
int CallSite::max_caches = 0;
CallSite::Executor CallSite::default_execute = CallSite::lookup_invoke_cache;

void CallSite::bootstrap(STATE) {
GO(call_site).set(state->memory()->new_class<Class, CallSite>(
state, G(rubinius), "CallSite"));
}

CallSite* CallSite::empty(STATE, Symbol* name, Executable* executable, int ip) {
CallSite* cache = state->memory()->new_object<CallSite>(state, G(call_site));

cache->name(name);
cache->executable(state, executable);
cache->ip(ip);

return cache;
}

Integer* CallSite::ip_prim(STATE) {
return Integer::from(state, ip());
}

Object* CallSite::empty_cache(STATE, CallSite* call_site, Arguments& args) {
Object* const self = state->vm()->call_frame()->self();
Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);

LookupData lookup(self, recv->lookup_begin(state), G(sym_public));
Dispatch dispatch(call_site->name());

if(!dispatch.resolve(state, call_site->name(), lookup)) {
if(!lookup_method_missing(state, args,
dispatch, self, recv->lookup_begin(state))) {
return NULL;
}
}

state->vm()->metrics().machine.methods_invoked++;

call_site->update(state, recv_class, dispatch);

Executable* meth = dispatch.method;
Module* mod = dispatch.module;

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
if(state->shared().config.machine_call_site_cache.value) {
default_execute = lookup_invoke_cache;
} else {
return meth->execute(state, meth, mod, args);
}
}

Object* CallSite::empty_cache_private(STATE, CallSite* call_site,
Arguments& args)
{
Object* const self = state->vm()->call_frame()->self();
Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);

LookupData lookup(self, recv->lookup_begin(state), G(sym_private));
Dispatch dispatch(call_site->name());

if(!dispatch.resolve(state, dispatch.name, lookup)) {
if(!lookup_method_missing(state, args,
dispatch, self, recv->lookup_begin(state))) {
return NULL;
}
default_execute = dispatch;
}

state->vm()->metrics().machine.methods_invoked++;

call_site->update(state, recv_class, dispatch);

Executable* meth = dispatch.method;
Module* mod = dispatch.module;

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
} else {
return meth->execute(state, meth, mod, args);
}
max_caches = state->shared().config.machine_call_site_limit.value;
}

Object* CallSite::empty_cache_vcall(STATE, CallSite* call_site, Arguments& args) {
Object* const self = state->vm()->call_frame()->self();
Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);

LookupData lookup(self, recv->lookup_begin(state), G(sym_private));
Dispatch dispatch(call_site->name());

if(!dispatch.resolve(state, call_site->name(), lookup)) {
dispatch.method_missing = eVCall;
if(!lookup_method_missing(state, args,
dispatch, self, recv->lookup_begin(state))) {
return NULL;
}
}
void CallSite::Info::mark(Object* obj, memory::ObjectMark& mark) {
auto_mark(obj, mark);

state->vm()->metrics().machine.methods_invoked++;
CallSite* call_site = as<CallSite>(obj);

call_site->update(state, recv_class, dispatch);
if(!call_site->caches()) return;

Executable* meth = dispatch.method;
Module* mod = dispatch.module;
// 1. Check if individual caches should be evicted.
bool evict_p[call_site->depth()];

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
} else {
return meth->execute(state, meth, mod, args);
for(int i = 0; i < call_site->depth(); i++) {
evict_p[i] = call_site->caches()->cache[i].inefficient_p();
}
}

Object* CallSite::empty_cache_super(STATE, CallSite* call_site,
Arguments& args)
{
CallFrame* call_frame = state->vm()->call_frame();

Symbol* original_name = call_frame->original_name();
if(call_site->name() != original_name) {
call_site->name(original_name);
args.set_name(call_site->name());
int evict_count = 0;
for(int i = 0; i < call_site->depth(); i++) {
if(evict_p[i]) evict_count++;
}

Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);
Module* const start = call_frame->module()->superclass();
if(evict_count) {
VM::current()->metrics().machine.inline_cache_evicted += evict_count;

LookupData lookup(call_frame->self(), start, G(sym_private));
Dispatch dispatch(call_site->name());
int new_size = call_site->depth() - evict_count;

if(start->nil_p() || !dispatch.resolve(state, call_site->name(), lookup)) {
if(new_size == 0) {
call_site->depth(0);
delete[] call_site->caches();
call_site->caches(NULL);

LookupData missing_lookup(call_frame->self(),
recv->lookup_begin(state), G(sym_private));
Dispatch missing_dispatch(G(sym_method_missing));
call_site->execute(CallSite::default_execute);
call_site->cache_miss(CallSite::default_execute);

if(!missing_dispatch.resolve(state, G(sym_method_missing), missing_lookup)) {
std::ostringstream msg;
msg << "no method_missing for ";
msg << recv_class->to_string(state);
msg << "#" << call_site->name()->to_string(state);
return;
}

Exception::internal_error(state, msg.str().c_str());
return 0;
for(int i = 0, j = 0; i < call_site->depth() && j < new_size; i++) {
if(!evict_p[i]) {
call_site->caches()->cache[j++] = call_site->caches()->cache[i];
}
}

args.unshift(state, call_site->name());
dispatch.method = missing_dispatch.method;
dispatch.module = missing_dispatch.module;
dispatch.method_missing = eSuper;
state->vm()->set_method_missing_reason(dispatch.method_missing);
state->vm()->global_cache()->add_seen(state, call_site->name());
call_site->caches()->depth(new_size);
}

state->vm()->metrics().machine.methods_invoked++;

call_site->update(state, recv_class, dispatch);
// 2. Attempt to re-order the caches by bubbling most hit forward.
bool reorder_p = false;
int indexes[call_site->depth()];

Executable* meth = dispatch.method;
Module* mod = dispatch.module;

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
} else {
return meth->execute(state, meth, mod, args);
for(int i = 0; i < call_site->depth(); i++) {
indexes[i] = i;
}
}

void CallSite::empty_cache_updater(STATE, CallSite* call_site, Class* klass, Dispatch& dispatch) {
MonoInlineCache* cache = MonoInlineCache::create(state, call_site, klass, dispatch);
call_site->update_call_site(state, cache);
}
InlineCaches* caches = call_site->caches();

bool CallSite::update_and_validate(STATE, Object* recv, Symbol* vis, int serial) {
Class* const recv_class = recv->direct_class(state);
for(int i = 0; i < call_site->depth() - 1; i++) {
if(caches->cache[i].hits() < caches->cache[i + 1].hits()) {
int tmp = indexes[i];
indexes[i] = indexes[i + 1];
indexes[i + 1] = tmp;
reorder_p = true;

if(MonoInlineCache* mono = try_as<MonoInlineCache>(this)) {
if(recv_class->data_raw() == mono->receiver_data_raw()) {
return mono->method()->serial()->to_native() == serial;
// TODO: pass State through the GC!
VM::current()->metrics().machine.inline_cache_reordered++;
}
}

if(PolyInlineCache* cache = try_as<PolyInlineCache>(this)) {
InlineCacheEntry* ice = cache->get_entry(recv_class);
if(likely(ice)) return ice->method()->serial()->to_native() == serial;
}
if(reorder_p) {
InlineCache* inline_caches = static_cast<InlineCache*>(
alloca(sizeof(CallSite) * call_site->depth()));

LookupData lookup(state->vm()->call_frame()->self(),
recv->lookup_begin(state), G(sym_public));
Dispatch dispatch(name());
for(int i = 0; i < call_site->depth(); i++) {
inline_caches[i] = caches->cache[i];
}

if(dispatch.resolve(state, name(), lookup)) {
update(state, recv_class, dispatch);
return dispatch.method->serial()->to_native() == serial;
for(int i = 0; i < call_site->depth(); i++) {
caches->cache[i] = inline_caches[indexes[i]];
}
}
return false;
}

bool CallSite::lookup_method_missing(STATE,
Arguments& args, Dispatch& dispatch, Object* self, Module* begin)
{
LookupData missing_lookup(self, begin, G(sym_private));
Dispatch missing_dispatch(G(sym_method_missing));

if(!missing_dispatch.resolve(state, G(sym_method_missing), missing_lookup)) {
std::ostringstream msg;
msg << "no method_missing for ";
msg << begin->to_string(state);
msg << "#" << dispatch.name->to_string(state);
// 3. Mark remaining caches.
for(int i = 0; i < call_site->depth(); i++) {
InlineCache* cache = &caches->cache[i];

Exception::internal_error(state, msg.str().c_str());
return false;
}

args.unshift(state, dispatch.name);
dispatch.method = missing_dispatch.method;
dispatch.module = missing_dispatch.module;
state->vm()->set_method_missing_reason(dispatch.method_missing);
state->vm()->global_cache()->add_seen(state, dispatch.name);
if(Object* ref = mark.call(cache->receiver_class())) {
cache->receiver_class(as<Class>(ref));
mark.just_set(call_site, ref);
}

return true;
}
if(Object* ref = mark.call(cache->stored_module())) {
cache->stored_module(as<Module>(ref));
mark.just_set(call_site, ref);
}

void CallSite::Info::mark(Object* obj, memory::ObjectMark& mark) {
auto_mark(obj, mark);
if(Object* ref = mark.call(cache->executable())) {
cache->executable(as<Executable>(ref));
mark.just_set(call_site, ref);
}
}
}

}
534 changes: 466 additions & 68 deletions machine/builtin/call_site.hpp

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions machine/builtin/channel.cpp
Original file line number Diff line number Diff line change
@@ -134,7 +134,7 @@ namespace rubinius {
ts.tv_nsec = nano % NANOSECONDS;
}

if(!state->check_async(state)) {
if(state->vm()->thread_interrupted_p(state)) {
return NULL;
}

@@ -161,7 +161,7 @@ namespace rubinius {

// or there are values available.
if(self->semaphore_count() > 0 || !self->value()->empty_p()) break;
if(!state->check_async(state)) {
if(state->vm()->thread_interrupted_p(state)) {
exception = true;
break;
}
@@ -173,7 +173,7 @@ namespace rubinius {
self->unpin();
self->_waiters_--;

if(exception || !state->check_async(state)) return NULL;
if(exception) return NULL;

if(self->semaphore_count() > 0) {
self->dec_semaphore_count();
8 changes: 8 additions & 0 deletions machine/builtin/class.hpp
Original file line number Diff line number Diff line change
@@ -23,6 +23,14 @@ namespace rubinius {
union ClassData {
struct ClassFlags f;
uint64_t raw;

uint32_t class_id() const {
return f.class_id;
}

uint32_t serial_id() const {
return f.serial_id;
}
};

class Class : public Module {
6 changes: 6 additions & 0 deletions machine/builtin/code_db.cpp
Original file line number Diff line number Diff line change
@@ -5,13 +5,16 @@
#include "on_stack.hpp"
#include "ontology.hpp"
#include "marshal.hpp"
#include "metrics.hpp"
#include "thread_phase.hpp"

#include "builtin/class.hpp"
#include "builtin/code_db.hpp"
#include "builtin/compiled_code.hpp"
#include "builtin/string.hpp"

#include "instruments/timing.hpp"

#include "util/thread.hpp"

#include <fcntl.h>
@@ -148,6 +151,9 @@ namespace rubinius {
CompiledCode* CodeDB::load(STATE, const char* m_id) {
MutexLockUnmanaged guard(state, state->shared().codedb_lock());

timer::StopWatch<timer::microseconds> timer(
state->vm()->metrics().codedb.load_us);

CodeDBMap::const_iterator index = codedb_index.find(std::string(m_id));

if(index == codedb_index.end()) {
99 changes: 35 additions & 64 deletions machine/builtin/compiled_code.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "arguments.hpp"
#include "bytecode_verification.hpp"
#include "bytecode_verifier.hpp"
#include "call_frame.hpp"
#include "configuration.hpp"
#include "instruments/timing.hpp"
@@ -112,51 +112,41 @@ namespace rubinius {
return as<Fixnum>(lines()->at(fin+1))->to_native();
}

MachineCode* CompiledCode::internalize(STATE,
const char** reason, int* ip)
{
MachineCode* mcode = machine_code();
MachineCode* CompiledCode::internalize(STATE) {
timer::StopWatch<timer::microseconds> timer(
state->vm()->metrics().machine.bytecode_internalizer_us);

atomic::memory_barrier();

if(mcode) return mcode;

CompiledCode* self = this;
OnStack<1> os(state, self);
MachineCode* mcode = machine_code();

self->hard_lock(state);

mcode = self->machine_code();
if(!mcode) {
{
BytecodeVerification bv(self);
if(!bv.verify(state)) {
if(reason) *reason = bv.failure_reason();
if(ip) *ip = bv.failure_ip();
std::cerr << "Error validating bytecode: " << bv.failure_reason() << "\n";
return 0;
}
}
if(mcode) return mcode;

mcode = new MachineCode(state, self);
{
BytecodeVerifier bytecode_verifier(this);
bytecode_verifier.verify(state);
}

if(self->resolve_primitive(state)) {
mcode->fallback = execute;
} else {
mcode->setup_argument_handler();
}
mcode = new MachineCode(state, this);

// We need to have an explicit memory barrier here, because we need to
// be sure that mcode is completely initialized before it's set.
// Otherwise another thread might see a partially initialized
// MachineCode.
atomic::write(&self->_machine_code_, mcode);
if(resolve_primitive(state)) {
mcode->fallback = execute;
} else {
mcode->setup_argument_handler();
}

/* There is a race here because another Thread may have run this
* CompiledCode instance and internalized it. We attempt to store our
* version assuming that we are the only ones to do so and throw away our
* work if someone else has beat us to it.
*/
MachineCode** mcode_ptr = &_machine_code_;
if(atomic::compare_and_swap(reinterpret_cast<void**>(mcode_ptr), 0, mcode)) {
set_executor(mcode->fallback);
return mcode;
} else {
return machine_code();
}

self->hard_unlock(state);
return mcode;
}

Object* CompiledCode::primitive_failed(STATE,
@@ -196,19 +186,9 @@ namespace rubinius {
Executable* exec, Module* mod, Arguments& args)
{
CompiledCode* code = as<CompiledCode>(exec);
if(code->execute == default_executor) {
const char* reason = 0;
int ip = -1;

OnStack<5> os(state, code, exec, mod, args.recv_location(), args.block_location());

memory::VariableRootBuffer vrb(state->vm()->current_root_buffers(),
&args.arguments_location(), args.total());

if(!code->internalize(state, &reason, &ip)) {
Exception::bytecode_error(state, code, ip, reason);
return 0;
}
if(code->execute == default_executor) {
if(!code->internalize(state)) return 0;
}

return code->execute(state, exec, mod, args);
@@ -484,21 +464,13 @@ namespace rubinius {
}
#endif

for(size_t i = 0; i < mcode->call_site_count(); i++) {
size_t index = mcode->call_site_offsets()[i];
Object* old_cache = reinterpret_cast<Object*>(mcode->opcodes[index + 1]);
if(Object* new_cache = mark.call(old_cache)) {
mcode->opcodes[index + 1] = reinterpret_cast<intptr_t>(new_cache);
mark.just_set(code, new_cache);
}
}

for(size_t i = 0; i < mcode->constant_cache_count(); i++) {
size_t index = mcode->constant_cache_offsets()[i];
Object* old_cache = reinterpret_cast<Object*>(mcode->opcodes[index + 1]);
if(Object* new_cache = mark.call(old_cache)) {
mcode->opcodes[index + 1] = reinterpret_cast<intptr_t>(new_cache);
mark.just_set(code, new_cache);
for(size_t i = 0; i < mcode->references_count(); i++) {
if(size_t ip = mcode->references()[i]) {
Object* ref = reinterpret_cast<Object*>(mcode->opcodes[ip]);
if(Object* updated_ref = mark.call(ref)) {
mcode->opcodes[ip] = reinterpret_cast<intptr_t>(updated_ref);
mark.just_set(code, updated_ref);
}
}
}
}
@@ -510,7 +482,6 @@ namespace rubinius {
indent_attribute(++level, "file"); code->file()->show(state, level);
indent_attribute(level, "iseq"); code->iseq()->show(state, level);
indent_attribute(level, "lines"); code->lines()->show_simple(state, level);
indent_attribute(level, "literals"); code->literals()->show_simple(state, level);
indent_attribute(level, "local_count"); code->local_count()->show(state, level);
indent_attribute(level, "local_names"); code->local_names()->show_simple(state, level);
indent_attribute(level, "name"); code->name()->show(state, level);
2 changes: 1 addition & 1 deletion machine/builtin/compiled_code.hpp
Original file line number Diff line number Diff line change
@@ -103,7 +103,7 @@ namespace rubinius {

void post_marshal(STATE);
size_t number_of_locals();
MachineCode* internalize(STATE, const char** failure_reason=0, int* ip=0);
MachineCode* internalize(STATE);
void specialize(STATE, TypeInfo* ti);

static Object* default_executor(STATE, Executable* exec, Module* mod, Arguments& args);
31 changes: 26 additions & 5 deletions machine/builtin/exception.cpp
Original file line number Diff line number Diff line change
@@ -87,14 +87,31 @@ namespace rubinius {
state->raise_exception(exc);
}

void Exception::bytecode_error(STATE,
CompiledCode* code, int ip, const char* reason)
{
Exception* exc = Exception::make_exception(state, G(exc_vm_bad_bytecode), reason);
void Exception::bytecode_error(STATE, CompiledCode* code, int ip, const char* reason) {
std::ostringstream msg;
msg << reason;
msg << ": code: " << code->name()->cpp_str(state);
msg << ", ip: " << ip;

Exception* exc = Exception::make_exception(state,
G(exc_vm_bad_bytecode), msg.str().c_str());
exc->set_ivar(state, state->symbol("@compiled_code"), code);
exc->set_ivar(state, state->symbol("@ip"), Fixnum::from(ip));
exc->locations(state, Location::from_call_stack(state));
state->raise_exception(exc);
RubyException::raise(exc);
}

Exception* Exception::make_no_method_error(STATE, Arguments& args) {
std::ostringstream msg;
msg << "undefined method `" << args.name()->cpp_str(state)
<< "' for " << args.recv()->to_s(state)->c_str(state);

return Exception::make_exception(state,
get_no_method_error(state), msg.str().c_str());
}

void Exception::raise_no_method_error(STATE, Arguments& args) {
RubyException::raise(Exception::make_no_method_error(state, args), true);
}

Exception* Exception::make_frozen_exception(STATE, Object* obj) {
@@ -468,6 +485,10 @@ namespace rubinius {
return as<Class>(G(object)->get_const(state, "NotImplementedError"));
}

Class* Exception::get_no_method_error(STATE) {
return as<Class>(G(object)->get_const(state, "NoMethodError"));
}

Class* Exception::get_errno_error(STATE, Fixnum* ern) {
if(Class* cls = try_as<Class>(G(errno_mapping)->fetch(state, ern))) {
return cls;
10 changes: 6 additions & 4 deletions machine/builtin/exception.hpp
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ namespace rubinius {
class Class;
class Array;
class CompiledCode;
class Arguments;

class Exception : public Object {
public:
@@ -47,6 +48,7 @@ namespace rubinius {
static Exception* make_argument_error(STATE, int expected, int given, Symbol* name=0);
static Exception* make_encoding_compatibility_error(STATE, Object* a, Object* b);
static Exception* make_frozen_exception(STATE, Object* obj);
static Exception* make_no_method_error(STATE, Arguments& args);

NORETURN(static void raise_argument_error(STATE, int expected, int given));
NORETURN(static void raise_argument_error(STATE, const char* reason));
@@ -68,25 +70,24 @@ namespace rubinius {
NORETURN(static void raise_system_call_error(STATE, const char* reason));
NORETURN(static void raise_system_call_error(STATE, const std::string& reason));

NORETURN(static void bytecode_error(STATE, CompiledCode* code,
int ip, const char* reason));
NORETURN(static void raise_thread_error(STATE, const char* reason));
NORETURN(static void raise_fiber_error(STATE, const char* reason));
NORETURN(static void raise_memory_error(STATE));
NORETURN(static void raise_frozen_error(STATE, Object* obj));
NORETURN(static void raise_no_method_error(STATE, Arguments& args));
NORETURN(static void raise_encoding_compatibility_error(STATE, Object* a, Object* b));
NORETURN(static void raise_not_implemented_error(STATE, const char* feature));
NORETURN(static void raise_errno_wait_readable(STATE, int error));
NORETURN(static void raise_errno_wait_writable(STATE, int error));
NORETURN(static void raise_errno_error(STATE, const char* reason = NULL,
int ern = 0, const char* entity = 0));



static Exception* make_lje(STATE);

static void type_error(STATE, const char* reason);
static void internal_error(STATE, const char* reason);
static void bytecode_error(STATE, CompiledCode* code,
int ip, const char* reason);
static void frozen_error(STATE, Object* obj);

static void encoding_compatibility_error(STATE, Object* a, Object* b);
@@ -127,6 +128,7 @@ namespace rubinius {
static Class* get_runtime_error(STATE);
static Class* get_encoding_compatibility_error(STATE);
static Class* get_not_implemented_error(STATE);
static Class* get_no_method_error(STATE);

class Info : public TypeInfo {
public:
9 changes: 7 additions & 2 deletions machine/builtin/fiber.cpp
Original file line number Diff line number Diff line change
@@ -98,7 +98,7 @@ namespace rubinius {

// TODO: CallFrame: return from this function

assert(0 && "fatal start_on_stack error");
rubinius::bug("returning from Fiber::start_on_stack");
#else
rubinius::bug("Fibers not supported on this platform");
#endif
@@ -155,10 +155,15 @@ namespace rubinius {

cur = Fiber::current(state);

// TODO: clean up this and the following conditional.
if(state->vm()->thread_interrupted_p(state)) {
return NULL;
}

if(!cur->exception()->nil_p()) {
state->raise_exception(cur->exception());
cur->exception(state, nil<Exception>());
return 0;
return NULL;
}

Array* ret = cur->value();
8 changes: 2 additions & 6 deletions machine/builtin/fiber.hpp
Original file line number Diff line number Diff line change
@@ -69,16 +69,12 @@ namespace rubinius {
return data()->machine();
}

void* stack_region() const {
return data()->stack_address();
}

void* stack_end() const {
void* stack_address() const {
return data()->stack_address();
}

void* stack_start() const {
return (void*)((uintptr_t)stack_region() + stack_size());
return (void*)((uintptr_t)stack_address() + stack_size());
}

int stack_size() const {
4 changes: 2 additions & 2 deletions machine/builtin/io.cpp
Original file line number Diff line number Diff line change
@@ -196,7 +196,7 @@ namespace rubinius {

if(bytes_read == -1) {
if(errno == EINTR) {
if(!state->check_async(state)) return NULL;
if(state->vm()->thread_interrupted_p(state)) return NULL;
ensure_open(state);
goto retry;
} else {
@@ -523,7 +523,7 @@ namespace rubinius {

if(code == -1) {
if(errno == EAGAIN || errno == EINTR) {
if(!state->check_async(state)) return NULL;
if(state->vm()->thread_interrupted_p(state)) return NULL;
ensure_open(state);
goto retry;
}
3 changes: 3 additions & 0 deletions machine/builtin/module.cpp
Original file line number Diff line number Diff line change
@@ -490,10 +490,13 @@ namespace rubinius {
}

Object* Module::track_subclass(STATE, Module* mod) {
if(try_as<SingletonClass>(mod)) return cNil;

if(hierarchy_subclasses()->nil_p()) {
hierarchy_subclasses(state, Array::create(state, 4));
}
hierarchy_subclasses()->append(state, WeakRef::create(state, mod));

return cNil;
}

123 changes: 0 additions & 123 deletions machine/builtin/mono_inline_cache.cpp

This file was deleted.

77 changes: 0 additions & 77 deletions machine/builtin/mono_inline_cache.hpp

This file was deleted.

10 changes: 1 addition & 9 deletions machine/builtin/native_function.cpp
Original file line number Diff line number Diff line change
@@ -326,8 +326,6 @@ namespace rubinius {
FFIData* stub = reinterpret_cast<FFIData*>(user_data);

bool destroy_vm = false;
int stack_address = 0;

if(!env) {
// TODO: fix this, the threads should *always* be set up correctly
// Apparently we're running in a new thread here, setup
@@ -336,13 +334,7 @@ namespace rubinius {

VM* vm = stub->shared->thread_nexus()->new_vm(stub->shared, "ruby.ffi");

// Detect the stack size and set it up in the VM object
size_t stack_size;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_getstacksize (&attrs, &stack_size);
pthread_attr_destroy(&attrs);
vm->set_root_stack(reinterpret_cast<uintptr_t>(&stack_address), stack_size);
vm->set_stack_bounds(THREAD_STACK_SIZE);

// Setup nativemethod handles into thread local
State state(vm);
15 changes: 8 additions & 7 deletions machine/builtin/native_method.cpp
Original file line number Diff line number Diff line change
@@ -676,7 +676,9 @@ namespace rubinius {
env->set_current_native_frame(&nmf);

// Register the CallFrame, because we might GC below this.
state->vm()->push_call_frame(call_frame, previous_frame);
if(!state->vm()->push_call_frame(state, call_frame, previous_frame)) {
return NULL;
}

// Be sure to do this after installing nmf as the current
// native frame.
@@ -739,7 +741,7 @@ namespace rubinius {
} catch(const RubyException& exc) {
LEAVE_CAPI(state);

state->vm()->pop_call_frame(previous_frame);
state->vm()->pop_call_frame(state, previous_frame);
env->set_current_call_frame(saved_frame);
env->set_current_native_frame(nmf.previous());
ep.pop(env);
@@ -749,15 +751,14 @@ namespace rubinius {

LEAVE_CAPI(state);

state->vm()->pop_call_frame(previous_frame);
if(!state->vm()->pop_call_frame(state, previous_frame)) {
value = NULL;
}

env->set_current_call_frame(saved_frame);
env->set_current_native_frame(nmf.previous());
ep.pop(env);

// Handle any signals that occurred while the native method
// was running.
if(!state->check_async(state)) return NULL;

return value;
}

46 changes: 1 addition & 45 deletions machine/builtin/object.cpp
Original file line number Diff line number Diff line change
@@ -24,7 +24,6 @@
#include "builtin/method_table.hpp"
#include "builtin/object.hpp"
#include "builtin/packed_object.hpp"
#include "builtin/respond_to_cache.hpp"
#include "builtin/symbol.hpp"
#include "builtin/string.hpp"
#include "builtin/tuple.hpp"
@@ -438,10 +437,6 @@ namespace rubinius {
if(is_tainted_p()) {
other->taint(state);
}

if(is_untrusted_p()) {
other->untrust(state);
}
}

bool Object::kind_of_p(STATE, Object* module) {
@@ -829,26 +824,6 @@ namespace rubinius {
return RBOOL(is_tainted_p());
}

Object* Object::trust(STATE) {
if(is_untrusted_p()) {
check_frozen(state);
set_untrusted(0);
}
return this;
}

Object* Object::untrust(STATE) {
if(!is_untrusted_p()) {
check_frozen(state);
if(reference_p()) set_untrusted();
}
return this;
}

Object* Object::untrusted_p(STATE) {
return RBOOL(is_untrusted_p());
}

TypeInfo* Object::type_info(STATE) const {
return state->memory()->type_info[get_type()];
}
@@ -866,26 +841,7 @@ namespace rubinius {
Object* self = this;
OnStack<1> os(state, self);

Object* responds = respond_to(state, name, priv);

if(!responds) return NULL;

CompiledCode* code = NULL;
CallSiteInformation* info = state->vm()->saved_call_site_information();

if(info && (code = try_as<CompiledCode>(info->executable))) {
CallSite* existing = code->machine_code()->call_site(state, info->ip);
if(RespondToCache* rct = try_as<RespondToCache>(existing)) {
existing = rct->fallback_call_site();
}
RespondToCache* cache = RespondToCache::create(state, existing,
self, name, priv, responds, 1);
state->vm()->global_cache()->add_seen(state, name);
atomic::memory_barrier();
existing->update_call_site(state, cache);
}

return responds;
return respond_to(state, name, priv);
}

Object* Object::respond_to(STATE, Symbol* name, Object* priv) {
18 changes: 0 additions & 18 deletions machine/builtin/object.hpp
Original file line number Diff line number Diff line change
@@ -302,24 +302,6 @@ namespace rubinius {
// Rubinius.primitive :object_untaint
Object* untaint(STATE);

/**
* Returns true if this object's untrusted flag is set.
*/
// Rubinius.primitive+ :object_untrusted_p
Object* untrusted_p(STATE);

/**
* Sets the untrusted flag on this object.
*/
// Rubinius.primitive :object_untrust
Object* untrust(STATE);

/**
* Clears the untrusted flag on this object.
*/
// Rubinius.primitive :object_trust
Object* trust(STATE);

/**
* Returns an #inspect-like representation of an Object for
* use in C++ code.
9 changes: 0 additions & 9 deletions machine/builtin/pack.cpp
Original file line number Diff line number Diff line change
@@ -643,7 +643,6 @@ namespace rubinius {
native_int stop = 0;
bool rest UNUSED = false;
bool tainted UNUSED = false;
bool untrusted UNUSED = false;
bool ascii_encoding = false;
bool utf8_encoding = false;
bool string_encoding = false;
@@ -656,7 +655,6 @@ namespace rubinius {

if(directives->byte_size() == 0) ascii_encoding = true;
if(CBOOL(directives->tainted_p(state))) tainted = true;
if(CBOOL(directives->untrusted_p(state))) untrusted = true;

static const char _actions[] = {
0, 1, 0, 1, 1, 1, 2, 1,
@@ -3255,7 +3253,6 @@ static const int en_main = 1;
case 32:
{
if(CBOOL(string_value->tainted_p(state))) tainted = true;
if(CBOOL(string_value->untrusted_p(state))) untrusted = true;
native_int size = string_value->byte_size();
if(rest) count = size;
if(count <= size) {
@@ -3605,7 +3602,6 @@ static const int en_main = 1;
case 32:
{
if(CBOOL(string_value->tainted_p(state))) tainted = true;
if(CBOOL(string_value->untrusted_p(state))) untrusted = true;
native_int size = string_value->byte_size();
if(rest) count = size;
if(count <= size) {
@@ -3769,11 +3765,6 @@ static const int en_main = 1;
tainted = false;
}

if(untrusted) {
result->untrust(state);
untrusted = false;
}

return result;
}
break;
185 changes: 0 additions & 185 deletions machine/builtin/poly_inline_cache.cpp

This file was deleted.

152 changes: 0 additions & 152 deletions machine/builtin/poly_inline_cache.hpp

This file was deleted.

75 changes: 0 additions & 75 deletions machine/builtin/respond_to_cache.cpp

This file was deleted.

80 changes: 0 additions & 80 deletions machine/builtin/respond_to_cache.hpp

This file was deleted.

25 changes: 7 additions & 18 deletions machine/builtin/system.cpp
Original file line number Diff line number Diff line change
@@ -143,7 +143,7 @@ namespace rubinius {
return Primitives::failure();
}

CompiledFile* cf = CompiledFile::load(stream);
CompiledFile* cf = CompiledFile::load(state, stream);
if(cf->magic != "!RBIX") {
delete cf;
return Primitives::failure();
@@ -660,7 +660,7 @@ namespace rubinius {
switch(errno) {
case EAGAIN:
case EINTR:
if(!state->check_async(state)) {
if(state->vm()->thread_interrupted_p(state)) {
close(output[0]);
return NULL;
}
@@ -786,7 +786,7 @@ namespace rubinius {
if(pid == -1) {
if(errno == ECHILD) return cFalse;
if(errno == EINTR) {
if(!state->check_async(state)) return NULL;
if(state->vm()->thread_interrupted_p(state)) return NULL;
goto retry;
}

@@ -927,7 +927,7 @@ namespace rubinius {
state->vm()->global_cache()->clear(state, name);
mod->reset_method_cache(state, name);

state->vm()->metrics().machine.inline_cache_resets++;
state->vm()->metrics().machine.cache_resets++;

if(state->shared().config.ic_debug) {
String* mod_name = mod->get_name(state);
@@ -1094,19 +1094,11 @@ namespace rubinius {
if(!state->park(state)) return NULL;
}

if(!state->check_async(state)) return NULL;
if(state->vm()->thread_interrupted_p(state)) return NULL;

return Fixnum::from(time(0) - start);
}

Object* System::vm_check_interrupts(STATE) {
if(state->check_async(state)) {
return cNil;
} else {
return NULL;
}
}

static inline double tv_to_dbl(struct timeval* tv) {
return (double)tv->tv_sec + ((double)tv->tv_usec / 1000000.0);
}
@@ -1257,10 +1249,7 @@ namespace rubinius {
if(Class* cls = try_as<Class>(mod)) {
OnStack<5> o2(state, mod, cc, scope, vis, cls);

if(!cc->internalize(state)) {
Exception::raise_argument_error(state, "invalid bytecode method");
return 0;
}
if(!cc->internalize(state)) return 0;

object_type type = (object_type)cls->instance_type()->to_native();
TypeInfo* ti = state->memory()->type_info[type];
@@ -1808,7 +1797,7 @@ namespace rubinius {

OnStack<1> os(state, code);

code->internalize(state, 0, 0);
code->internalize(state);

#ifdef RBX_PROFILER
if(unlikely(state->vm()->tooling())) {
3 changes: 0 additions & 3 deletions machine/builtin/system.hpp
Original file line number Diff line number Diff line change
@@ -167,9 +167,6 @@ namespace rubinius {
// Rubinius.primitive :vm_sleep
static Object* vm_sleep(STATE, Object* duration);

// Rubinius.primitive :vm_check_interrupts
static Object* vm_check_interrupts(STATE);

// Rubinius.primitive :vm_times
static Array* vm_times(STATE);

4 changes: 1 addition & 3 deletions machine/builtin/thread.cpp
Original file line number Diff line number Diff line change
@@ -358,6 +358,7 @@ namespace rubinius {
VM* vm = reinterpret_cast<VM*>(ptr);
State state_obj(vm), *state = &state_obj;

vm->set_stack_bounds(THREAD_STACK_SIZE);
vm->set_current_thread();

RUBINIUS_THREAD_START(
@@ -369,9 +370,6 @@ namespace rubinius {
vm->name().c_str(), vm->thread->pid()->to_native(),
(unsigned int)thread_debug_self());

int stack_address = 0;
vm->set_root_stack(reinterpret_cast<uintptr_t>(&stack_address), THREAD_STACK_SIZE);

NativeMethod::init_thread(state);

state->vm()->become_managed();
309 changes: 0 additions & 309 deletions machine/bytecode_verification.cpp

This file was deleted.

58 changes: 0 additions & 58 deletions machine/bytecode_verification.hpp

This file was deleted.

Loading

0 comments on commit 0b140bf

Please sign in to comment.