Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/mri/monitor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def mon_owned?
def mon_synchronize(&block)
Primitive.monitor_synchronize(@mon_mutex, block)
end
Truffle::Graal.always_split instance_method(:mon_synchronize)
Primitive.always_split self, :mon_synchronize
alias synchronize mon_synchronize

#
Expand Down
34 changes: 24 additions & 10 deletions lib/truffle/strscan.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,12 @@ def charpos
def check(pattern)
scan_internal pattern, false, true, true
end
Primitive.always_split self, :check

def check_until(pattern)
scan_internal pattern, false, true, false
end
Primitive.always_split self, :check_until

def clear
warn 'StringScanner#clear is obsolete; use #terminate instead' if $VERBOSE
Expand All @@ -128,6 +130,7 @@ def eos?
def exist?(pattern)
scan_internal pattern, false, false, false
end
Primitive.always_split self, :exist?

def fixed_anchor?
@fixed_anchor
Expand Down Expand Up @@ -192,6 +195,7 @@ def inspect
def match?(pattern)
scan_internal pattern, false, false, true
end
Primitive.always_split self, :match?

def matched
@match&.to_s
Expand Down Expand Up @@ -247,6 +251,7 @@ def restsize
def scan(pattern)
scan_internal pattern, true, true, true
end
Primitive.always_split self, :scan

def scan_byte
if eos?
Expand Down Expand Up @@ -277,21 +282,24 @@ def scan_integer(base: 10)
end

if substr
Primitive.string_to_inum(substr, base, true, true)
substr.to_i(base)
end
end

def scan_until(pattern)
scan_internal pattern, true, true, false
end
Primitive.always_split self, :scan_until

def scan_full(pattern, advance_pos, getstr)
scan_internal pattern, advance_pos, getstr, true
end
Primitive.always_split self, :scan_full

def search_full(pattern, advance_pos, getstr)
scan_internal pattern, advance_pos, getstr, false
end
Primitive.always_split self, :search_full

def self.must_C_version
self
Expand All @@ -304,10 +312,12 @@ def size
def skip(pattern)
scan_internal pattern, true, false, true
end
Primitive.always_split self, :skip

def skip_until(pattern)
scan_internal pattern, true, false, false
end
Primitive.always_split self, :skip_until

def string
@original
Expand All @@ -332,7 +342,7 @@ def terminate
end

def unscan
raise ScanError if Primitive.nil?(@match)
raise ScanError unless @match
@pos = @prev_pos
@prev_pos = nil
@match = nil
Expand All @@ -358,7 +368,7 @@ def peep(len)
peek len
end

private def scan_check_args(pattern, headonly)
private def scan_check_args(pattern)
unless Primitive.is_a?(pattern, Regexp) || Primitive.is_a?(pattern, String)
raise TypeError, "bad pattern argument: #{pattern.inspect}"
end
Expand All @@ -369,15 +379,18 @@ def peep(len)
# This method is kept very small so that it should fit within 100
# AST nodes and can be split. This is done to avoid indirect calls
# to TRegex.
private def scan_internal(pattern, advance_pos, getstr, headonly)
scan_check_args(pattern, headonly)
private def scan_internal(pattern, advance_pos, getstr, only_match_at_start)
scan_check_args(pattern)

if Primitive.is_a?(pattern, String)
md = scan_internal_string_pattern(pattern, headonly)
md = scan_internal_string_pattern(pattern, only_match_at_start)
else
start = @fixed_anchor ? 0 : @pos
md = Truffle::RegexpOperations.match_in_region pattern, @string, @pos, @string.bytesize, headonly, start
Primitive.matchdata_fixup_positions(md, start) if md
if only_match_at_start
md = Primitive.regexp_match_at_start(pattern, @string, @pos, start)
else
md = Primitive.regexp_search_with_start(pattern, @string, @pos, start)
end
end

if md
Expand All @@ -387,11 +400,12 @@ def peep(len)
@match = nil
end
end
Primitive.always_split self, :scan_internal

private def scan_internal_string_pattern(pattern, headonly)
private def scan_internal_string_pattern(pattern, only_match_at_start)
pos = @pos

if headonly
if only_match_at_start
if @string.byteslice(pos..).start_with?(pattern)
Primitive.matchdata_create_single_group(pattern, @string.dup, pos, pos + pattern.bytesize)
else
Expand Down
18 changes: 9 additions & 9 deletions lib/truffle/truffle/cext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ def rb_hash_foreach(hash, func, farg)
end
end
end
Truffle::Graal.always_split instance_method(:rb_hash_foreach)
Primitive.always_split self, :rb_hash_foreach

def rb_path_to_class(path)
begin
Expand Down Expand Up @@ -1264,7 +1264,7 @@ def rb_protect(function, arg, write_status, status)
Truffle::Interop.execute_without_conversion(write_status, status, pos)
res
end
Truffle::Graal.always_split instance_method(:rb_protect)
Primitive.always_split self, :rb_protect

def rb_jump_tag(pos)
if pos > 0
Expand All @@ -1279,12 +1279,12 @@ def rb_jump_tag(pos)
def rb_yield(value)
rb_block_proc.call(value)
end
Truffle::Graal.always_split instance_method(:rb_yield)
Primitive.always_split self, :rb_yield

def rb_yield_splat(values)
rb_block_proc.call(*values)
end
Truffle::Graal.always_split instance_method(:rb_yield_splat)
Primitive.always_split self, :rb_yield_splat

def rb_ivar_lookup(object, name, default_value)
# TODO CS 24-Jul-16 races - needs a new primitive or be defined in Java?
Expand Down Expand Up @@ -1649,7 +1649,7 @@ def rb_mutex_synchronize(mutex, func, arg)
Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [func, arg])
end
end
Truffle::Graal.always_split instance_method(:rb_mutex_synchronize)
Primitive.always_split self, :rb_mutex_synchronize

def rb_gc_enable
GC.enable
Expand Down Expand Up @@ -1879,7 +1879,7 @@ def rb_ensure(b_proc, data1, e_proc, data2)
end
end
end
Truffle::Graal.always_split instance_method(:rb_ensure)
Primitive.always_split self, :rb_ensure

def rb_rescue(b_proc, data1, r_proc, data2)
begin
Expand All @@ -1898,7 +1898,7 @@ def rb_rescue(b_proc, data1, r_proc, data2)
end
end
end
Truffle::Graal.always_split instance_method(:rb_rescue)
Primitive.always_split self, :rb_rescue

def rb_rescue2(b_proc, data1, r_proc, data2, rescued)
begin
Expand All @@ -1913,7 +1913,7 @@ def rb_rescue2(b_proc, data1, r_proc, data2, rescued)
end
end
end
Truffle::Graal.always_split instance_method(:rb_rescue2)
Primitive.always_split self, :rb_rescue2

def rb_exec_recursive(func, obj, arg)
result = nil
Expand All @@ -1932,7 +1932,7 @@ def rb_exec_recursive(func, obj, arg)
result
end
end
Truffle::Graal.always_split instance_method(:rb_exec_recursive)
Primitive.always_split self, :rb_exec_recursive

def rb_catch_obj(tag, func, data)
use_cext_lock = Primitive.use_cext_lock?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,25 @@ def storage(ary)
Truffle::Debug.array_storage(ary)
end

before :each do
@array = %i[first second third]
end

guard -> { !Truffle::Boot.get_option('chaos-data') } do
it "should no-op when called on itself" do
copy = @array.dup
array = %i[first second third]
Primitive.steal_array_storage(array, array)

Primitive.steal_array_storage(@array, @array)

storage(@array).should == "Object[]"
@array.should == copy
storage(array).should == "Object[]"
array.should == %i[first second third]
end

it "should take ownership of the store" do
array = %i[first second third]
other = [1, 2, 3, 4, 5]
other_copy = other.dup

Primitive.steal_array_storage(@array, other)
Primitive.steal_array_storage(array, other)

storage(@array).should == "int[]"
@array.should == other_copy
storage(array).should == "int[]"
array.should == [1, 2, 3, 4, 5]

storage(other).should == "null"
other.empty?.should == true
storage(other).should == "empty"
other.should.empty?
end
end
end
2 changes: 0 additions & 2 deletions spec/truffle/splitting_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
Regexp.instance_method(:match?),
Truffle::RegexpOperations.method(:match),
Truffle::RegexpOperations.method(:match?),
Truffle::RegexpOperations.method(:search_region),
Truffle::RegexpOperations.method(:match_in_region),

String.instance_method(:[]),
Truffle::StringOperations.method(:subpattern),
Expand Down
2 changes: 2 additions & 0 deletions spec/truffleruby.mspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ load "#{__dir__}/ruby/default.mspec"
# Don't run ruby/spec as root on TruffleRuby
raise 'ruby/spec is not designed to be run as root on TruffleRuby' if Process.uid == 0

ENV['TRUFFLERUBY_ALLOW_PRIVATE_PRIMITIVES_IN'] = "#{__dir__}/truffle/"

class MSpecScript
def self.windows?
ENV.key?('WINDIR') || ENV.key?('windir')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@

/** Use these names in Ruby core methods stubs, ignore argument names in Java specializations. */
String[] argumentNames() default {};

/** Whether this Primitive can be used outside the TruffleRuby repository. */
boolean isPublic() default false;
}
28 changes: 27 additions & 1 deletion src/main/java/org/truffleruby/RubyLanguage.java
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ public abstract static class RubySourceOptions {
* {@link TranslatorEnvironment#newFrameDescriptorBuilderForBlock(BlockDescriptorInfo)}. */
public static final FrameDescriptor EMPTY_FRAME_DESCRIPTOR = new FrameDescriptor(nil);

public static final String INTERNAL_CORE_PREFIX = "<internal:core> ";

/** Global cache of call targets that {@code RBSprintfCompiler.compile} returns */
public static final Map<TStringWithEncoding, RootCallTarget> sprintfCompilerCallTargets = new ConcurrentHashMap<>();

Expand Down Expand Up @@ -284,6 +286,7 @@ private RubyThread getOrCreateForeignThread(RubyContext context, Thread thread)
@CompilationFinal public LanguageOptions options;
@CompilationFinal private String rubyHome;
@CompilationFinal public String cextPath;
public String[] allowPrivatePrimitivesPrefixes;

private TruffleFile rubyHomeTruffleFile;

Expand Down Expand Up @@ -777,13 +780,36 @@ private void setRubyHome(TruffleFile home) {
rubyHomeTruffleFile = home;
rubyHome = home.getPath();
cextPath = rubyHome + "/lib/truffle/truffle/cext_ruby.rb";

String allowIn = System.getenv("TRUFFLERUBY_ALLOW_PRIVATE_PRIMITIVES_IN");
if (allowIn != null) {
if (!allowIn.endsWith("/spec/truffle/") && !allowIn.endsWith("/test/truffle/compiler/") &&
!allowIn.endsWith("/bench/metrics/")) {
throw CompilerDirectives
.shouldNotReachHere("Invalid value for TRUFFLERUBY_ALLOW_PRIMITIVES_IN: " + allowIn);
}

allowPrivatePrimitivesPrefixes = new String[]{
rubyHome + "/lib/truffle/",
rubyHome + "/lib/patches/",
rubyHome + "/lib/mri/",
allowIn,
};
} else {
allowPrivatePrimitivesPrefixes = new String[]{
rubyHome + "/lib/truffle/",
rubyHome + "/lib/patches/",
rubyHome + "/lib/mri/",
};
}
}

private void resetRubyHome() {
assert Thread.holdsLock(this);
rubyHomeTruffleFile = null;
rubyHome = null;
cextPath = null;
allowPrivatePrimitivesPrefixes = null;
}

private TruffleFile findRubyHome(Env env) {
Expand Down Expand Up @@ -954,7 +980,7 @@ public static String getPath(Source source) {
public String getSourcePath(Source source) {
final String path = getPath(source);
if (path.startsWith(coreLoadPath)) {
return "<internal:core> " + path.substring(coreLoadPath.length() + 1);
return INTERNAL_CORE_PREFIX + path.substring(coreLoadPath.length() + 1);
} else {
return path;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public PrimitiveNodeConstructor getPrimitive(String name) {
}
}

throw new Error("Primitive :" + name + " not found");
throw new Error("Primitive." + name + " not found");
}

public void addLazyPrimitive(String primitive, String nodeFactoryClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public PrimitiveNodeConstructor(Primitive annotation, NodeFactory<? extends Ruby
this.factory = factory;
}

public boolean isPublic() {
return annotation.isPublic();
}

public int getPrimitiveArity() {
return factory.getExecutionSignature().size();
}
Expand Down
Loading