Skip to content

Commit

Permalink
Showing 49 changed files with 6,616 additions and 6,923 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -49,6 +49,7 @@ lib/ruby/gems
lib/ruby/stdlib/*jopenssl*.jar
lib/ruby/stdlib/bcpkix-jdk15on-*.jar
lib/ruby/stdlib/bcprov-jdk15on-*.jar
lib/ruby/stdlib/did_you_mean*
lib/ruby/stdlib/gauntlet_rdoc.rb
lib/ruby/stdlib/jar*
lib/ruby/stdlib/jline
4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -948,7 +948,9 @@ public void setUpUseDefLocalVarMaps() {
if (i instanceof ResultInstr) {
Variable v = ((ResultInstr) i).getResult();

if (v instanceof LocalVariable) definedLocalVars.add((LocalVariable) v);
if (v instanceof LocalVariable && ((LocalVariable)v).getScopeDepth() == 0) {
definedLocalVars.add((LocalVariable) v);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -14,8 +14,7 @@ public class LiveVariablesProblem extends DataFlowProblem<LiveVariablesProblem,

public LiveVariablesProblem(IRScope scope) {
super(DataFlowProblem.DF_Direction.BACKWARD);
alwaysLiveVars = new ArrayList<LocalVariable>();
varsLiveOnScopeExit = new ArrayList<LocalVariable>(alwaysLiveVars);
varsLiveOnScopeExit = new ArrayList<LocalVariable>();
setup(scope);
}

@@ -43,18 +42,6 @@ public void addDFVar(Variable v) {

if (v instanceof LocalVariable && !v.isSelf()) {
//System.out.println("Adding df var for " + v + ":" + dfv.id);
IRScope s = getScope();
for (int n = ((LocalVariable) v).getScopeDepth(); s != null && n >= 0; n--) {
if (s instanceof IREvalScript) {
// If a variable is at the topmost scope of the eval OR crosses an eval boundary,
// it is going to be marked always live since it could be used by other evals (n = 0)
// or by enclosing scopes (n > 0)
alwaysLiveVars.add((LocalVariable) v);
break;
}

s = s.getLexicalParent();
}
localVars.add((LocalVariable) v);
}
}
@@ -125,8 +112,5 @@ public String getName() {
private HashMap<Variable, Integer> dfVarMap = new HashMap<Variable, Integer>();
private HashMap<Integer, Variable> varDfVarMap = new HashMap<Integer, Variable>();
private HashSet<LocalVariable> localVars = new HashSet<LocalVariable>(); // Local variables that can be live across dataflow barriers

// Variables that cross eval boundaries and are always live in this scope
private List<LocalVariable> alwaysLiveVars;
private Collection<LocalVariable> varsLiveOnScopeExit;
}
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.ir.transformations.inlining.InlineCloneInfo;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;

@@ -65,8 +66,8 @@ public static CheckArityInstr decode(IRReaderDecoder d) {
return new CheckArityInstr(d.decodeInt(), d.decodeInt(), d.decodeBoolean(), d.decodeBoolean(), d.decodeInt());
}

public void checkArity(ThreadContext context, Object[] args, Block.Type blockType) {
IRRuntimeHelpers.checkArity(context.runtime, context.getCurrentStaticScope(), args, required, opt, rest, receivesKeywords, restKey, blockType);
public void checkArity(ThreadContext context, StaticScope scope, Object[] args, Block.Type blockType) {
IRRuntimeHelpers.checkArity(context.runtime, scope, args, required, opt, rest, receivesKeywords, restKey, blockType);
}

@Override
Original file line number Diff line number Diff line change
@@ -384,7 +384,7 @@ protected static void processBookKeepingOp(ThreadContext context, Block block, I
context.callThreadPoll();
break;
case CHECK_ARITY:
((CheckArityInstr) instr).checkArity(context, args, block == null ? null : block.type);
((CheckArityInstr) instr).checkArity(context, currScope, args, block == null ? null : block.type);
break;
case LINE_NUM:
context.setLine(((LineNumberInstr)instr).lineNumber);
69 changes: 50 additions & 19 deletions lib/ruby/truffle/cext/ruby.h
Original file line number Diff line number Diff line change
@@ -29,30 +29,33 @@ extern "C" {
typedef void *ID;
typedef void *VALUE;

VALUE get_Qfalse();
VALUE get_Qtrue();
VALUE get_Qnil();
VALUE get_rb_cProc();
VALUE get_rb_eException();
// Constants

VALUE get_Qfalse(void);
VALUE get_Qtrue(void);
VALUE get_Qnil(void);
VALUE get_rb_cProc(void);
VALUE get_rb_eException(void);

#define Qfalse get_Qfalse()
#define Qtrue get_Qtrue()
#define Qnil get_Qnil()
#define rb_cProc get_rb_cProc();
#define rb_eException get_rb_eException();

VALUE get_rb_cObject();
VALUE get_rb_cArray();
VALUE get_rb_cHash();
VALUE get_rb_cObject(void);
VALUE get_rb_cArray(void);
VALUE get_rb_cHash(void);

#define rb_cObject get_rb_cObject()
#define rb_cArray get_rb_cArray()
#define rb_cHash get_rb_cHash()

VALUE get_rb_eRuntimeError();
VALUE get_rb_eRuntimeError(void);

#define rb_eRuntimeError get_rb_eRuntimeError()

// Conversions

int NUM2INT(VALUE value);
unsigned int NUM2UINT(VALUE value);
@@ -69,44 +72,72 @@ VALUE UINT2NUM(unsigned int value);
VALUE LONG2NUM(long value);
VALUE LONG2FIX(long value);

// Type checks

int FIXNUM_P(VALUE value);

// Float

VALUE rb_float_new(double value);

// String

char *RSTRING_PTR(VALUE string);
int RSTRING_LEN(VALUE string);
ID rb_intern(const char *string);
VALUE rb_str_new2(const char *string);
VALUE ID2SYM(ID id);
VALUE rb_intern_str(VALUE string);
VALUE rb_str_new2(const char *string);
void rb_str_cat(VALUE string, const char *to_concat, long length);

// Symbol

ID rb_intern(const char *string);
VALUE ID2SYM(ID id);

// Array

int RARRAY_LEN(VALUE array);
int RARRAY_LENINT(VALUE array);
VALUE *RARRAY_PTR(VALUE array);
VALUE RARRAY_AREF(VALUE array, long index);
VALUE rb_Array(VALUE value);
VALUE rb_ary_new(void);
VALUE rb_ary_new_capa(long capacity);
VALUE rb_ary_new2();
VALUE rb_ary_new();
void rb_ary_push(VALUE array, VALUE value);
#define rb_ary_new2 rb_ary_new_capa
VALUE rb_ary_push(VALUE array, VALUE value);
VALUE rb_ary_pop(VALUE array);
void rb_ary_store(VALUE array, long index, VALUE value);
VALUE rb_ary_entry(VALUE array, long index);
int RARRAY_LENINT(VALUE array);
VALUE rb_ary_dup(VALUE array);

VALUE rb_hash_new();
// Hash

VALUE rb_hash_new(void);
VALUE rb_hash_aref(VALUE hash, VALUE key);
void rb_hash_aset(VALUE hash, VALUE key, VALUE value);
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE value);

// Utilities

void rb_scan_args(int argc, VALUE *argv, const char *format, ...);
int rb_scan_args(int argc, VALUE *argv, const char *format, ...);

// Calls

VALUE rb_funcall(VALUE object, ID name, int argc, ...);

// Instance variables

VALUE rb_iv_get(VALUE object, const char *name);
VALUE rb_iv_set(VALUE object, const char *name, VALUE value);

// Accessing constants

VALUE rb_const_get(VALUE object, ID name);

// Raising exceptions

void rb_raise(VALUE exception, const char *format, ...);

// Defining classes, modules and methods

VALUE rb_define_class(const char *name, VALUE superclass);
VALUE rb_define_module(const char *name);
VALUE rb_define_module_under(VALUE module, const char *name);
Binary file modified lib/ruby/truffle/cext/ruby.su
Binary file not shown.
6 changes: 6 additions & 0 deletions lib/ruby/truffle/cext/version.h
Original file line number Diff line number Diff line change
@@ -11,4 +11,10 @@
#ifndef TRUFFLE_VERSION_H
#define TRUFFLE_VERSION_H

/* API version */
#define RUBY_API_VERSION_MAJOR 2
#define RUBY_API_VERSION_MINOR 3
#define RUBY_API_VERSION_TEENY 0
#define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY)

#endif
7 changes: 6 additions & 1 deletion spec/ruby/optional/capi/ext/array_spec.c
Original file line number Diff line number Diff line change
@@ -35,7 +35,9 @@ static VALUE array_spec_RARRAY_PTR_assign(VALUE self, VALUE array, VALUE value)
}
return Qnil;
}
#endif

#ifdef HAVE_RARRAY_LEN
static VALUE array_spec_RARRAY_LEN(VALUE self, VALUE array) {
return INT2FIX(RARRAY_LEN(array));
}
@@ -272,8 +274,11 @@ void Init_array_spec() {
rb_define_method(cls, "rb_Array", array_spec_rb_Array, 1);
#endif

#if defined(HAVE_RARRAY_LEN) && defined(HAVE_RARRAY_PTR)
#ifdef HAVE_RARRAY_LEN
rb_define_method(cls, "RARRAY_LEN", array_spec_RARRAY_LEN, 1);
#endif

#if defined(HAVE_RARRAY_LEN) && defined(HAVE_RARRAY_PTR)
rb_define_method(cls, "RARRAY_PTR_iterate", array_spec_RARRAY_PTR_iterate, 1);
rb_define_method(cls, "RARRAY_PTR_assign", array_spec_RARRAY_PTR_assign, 2);
#endif
11 changes: 0 additions & 11 deletions spec/ruby/optional/capi/ext/jruby_truffle.h
Original file line number Diff line number Diff line change
@@ -12,32 +12,21 @@
#undef RUBYSPEC_CAPI_JRUBY_TRUFFLE_H

/* Array */
#undef HAVE_RB_ARRAY
#ifdef RUBY_VERSION_IS_2_1
#undef HAVE_RARRAY_AREF
#endif
#undef HAVE_RARRAY_LEN
#undef HAVE_RARRAY_PTR
#undef HAVE_RB_ARY_AREF
#undef HAVE_RB_ARY_CLEAR
#undef HAVE_RB_ARY_DELETE
#undef HAVE_RB_ARY_DELETE_AT
#undef HAVE_RB_ARY_DUP
#undef HAVE_RB_ARY_ENTRY
#undef HAVE_RB_ARY_FREEZE
#undef HAVE_RB_ARY_INCLUDES
#undef HAVE_RB_ARY_JOIN
#undef HAVE_RB_ARY_NEW2
#undef HAVE_RB_ARY_NEW3
#ifdef RUBY_VERSION_IS_2_1
#undef HAVE_RB_ARY_NEW_FROM_ARGS
#endif
#undef HAVE_RB_ARY_NEW4
#undef HAVE_RB_ARY_POP
#undef HAVE_RB_ARY_PUSH
#undef HAVE_RB_ARY_REVERSE
#undef HAVE_RB_ARY_SHIFT
#undef HAVE_RB_ARY_STORE
#undef HAVE_RB_ARY_CONCAT
#undef HAVE_RB_ARY_PLUS
#undef HAVE_RB_ARY_TO_ARY
15 changes: 0 additions & 15 deletions spec/truffle/tags/optional/capi/array_tags.txt
Original file line number Diff line number Diff line change
@@ -1,34 +1,19 @@
fails:C-API Array function rb_Array returns obj if it is an array
fails:C-API Array function rb_Array tries to convert obj to an array
fails:C-API Array function rb_Array returns obj wrapped in an array if it cannot be converted to an array
fails:C-API Array function rb_ary_new2 returns an empty array
fails:C-API Array function rb_ary_new3 returns an array with the passed cardinality and varargs
fails:C-API Array function rb_ary_new_from_args returns an array with the passed cardinality and varargs
fails:C-API Array function rb_ary_new4 returns returns an array with the passed values
fails:C-API Array function rb_ary_push adds an element to the array
fails:C-API Array function rb_ary_pop removes and returns the last element in the array
fails:C-API Array function rb_ary_join joins elements of an array with a string
fails:C-API Array function rb_ary_to_s creates an Array literal representation as a String
fails:C-API Array function rb_ary_reverse reverses the order of elements in the array
fails:C-API Array function rb_ary_reverse returns the original array
fails:C-API Array function rb_ary_entry returns nil when passed an empty array
fails:C-API Array function rb_ary_entry returns elements from the end when passed a negative index
fails:C-API Array function rb_ary_entry returns nil if the index is out of range
fails:C-API Array function rb_ary_clear removes all elements from the array
fails:C-API Array function rb_ary_dup duplicates the array
fails:C-API Array function rb_ary_unshift prepends the element to the array
fails:C-API Array function rb_ary_shift removes and returns the first element
fails:C-API Array function rb_ary_shift returns nil when the array is empty
fails:C-API Array function rb_ary_store overwrites the element at the given position
fails:C-API Array function rb_ary_store writes to elements offset from the end if passed a negative index
fails:C-API Array function rb_ary_store raises on IndexError if the negative index is greater than the length
fails:C-API Array function rb_ary_store enlarges the array as needed
fails:C-API Array function rb_ary_concat concats two arrays
fails:C-API Array function rb_ary_plus adds two arrays together
fails:C-API Array function RARRAY_PTR returns a pointer to a C array of the array's elements
fails:C-API Array function RARRAY_PTR allows assigning to the elements of the C array
fails:C-API Array function RARRAY_LEN returns the size of the array
fails:C-API Array function RARRAY_AREF returns an element from the array
fails:C-API Array function rb_assoc_new returns an array containing the two elements
fails:C-API Array function rb_ary_includes returns true if the array includes the element
fails:C-API Array function rb_ary_includes returns false if the array does not include the element
80 changes: 59 additions & 21 deletions truffle/src/main/c/cext/ruby.c
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@

#define RUBY_CEXT truffle_import_cached("ruby_cext")

// Constants

VALUE get_Qfalse() {
return (VALUE) truffle_read(RUBY_CEXT, "Qfalse");
}
@@ -42,6 +44,8 @@ VALUE get_rb_eRuntimeError() {
return (VALUE) truffle_read(RUBY_CEXT, "rb_eRuntimeError");
}

// Conversions

int NUM2INT(VALUE value) {
return truffle_invoke_i(RUBY_CEXT, "NUM2INT", value);
}
@@ -86,14 +90,20 @@ VALUE LONG2FIX(long value) {
return (VALUE) truffle_invoke(RUBY_CEXT, "LONG2FIX", value);
}

// Type checks

int FIXNUM_P(VALUE value) {
return truffle_invoke_i(RUBY_CEXT, "FIXNUM_P", value);
}

// Float

VALUE rb_float_new(double value) {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_float_new", value);
}

// String

char *RSTRING_PTR(VALUE string) {
// Needs to return a fake char* which actually calls back into Ruby when read or written
return (char*) truffle_invoke(RUBY_CEXT, "RSTRING_PTR", string);
@@ -103,14 +113,6 @@ int RSTRING_LEN(VALUE string) {
return truffle_get_size(string);
}

VALUE rb_ary_dup(VALUE array) {
return (VALUE) truffle_invoke(array, "dup");
}

ID rb_intern(const char *string) {
return (ID) truffle_invoke(RUBY_CEXT, "rb_intern", string);
}

VALUE rb_str_new2(const char *string) {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_str_new2", truffle_read_string(string));
}
@@ -119,37 +121,58 @@ VALUE rb_intern_str(VALUE string) {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_intern_str", string);
}

void rb_str_cat(VALUE string, const char *to_concat, long length) {
truffle_invoke(RUBY_CEXT, "rb_str_cat", string, truffle_read_string(to_concat), length);
}

// Symbol

ID rb_intern(const char *string) {
return (ID) truffle_invoke(RUBY_CEXT, "rb_intern", string);
}

VALUE ID2SYM(ID id) {
return truffle_invoke(RUBY_CEXT, "ID2SYM", id);
}

void rb_str_cat(VALUE string, const char *to_concat, long length) {
truffle_invoke(RUBY_CEXT, "rb_str_cat", string, truffle_read_string(to_concat), length);
}
// Array

int RARRAY_LEN(VALUE array) {
return truffle_get_size(array);
}

int RARRAY_LENINT(VALUE array) {
return truffle_get_size(array);
}

VALUE *RARRAY_PTR(VALUE array) {
// Needs to return a fake VALUE* which actually calls back into Ruby when read or written
return (VALUE*) truffle_invoke(RUBY_CEXT, "RARRAY_PTR", array);
}

VALUE rb_ary_new_capa(long capacity) {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_ary_new_capa", capacity);
VALUE RARRAY_AREF(VALUE array, long index) {
return truffle_read_idx(array, (int) index);
}

VALUE rb_ary_new2() {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_ary_new2");
VALUE rb_Array(VALUE array) {
return truffle_invoke(RUBY_CEXT, "rb_Array", array);
}

VALUE rb_ary_new_capa(long capacity) {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_ary_new_capa", capacity);
}

VALUE rb_ary_new() {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_ary_new");
}

void rb_ary_push(VALUE array, VALUE value) {
VALUE rb_ary_push(VALUE array, VALUE value) {
truffle_invoke(array, "push", value);
return array;
}

VALUE rb_ary_pop(VALUE array) {
return truffle_invoke(array, "pop");
}

void rb_ary_store(VALUE array, long index, VALUE value) {
@@ -160,10 +183,12 @@ VALUE rb_ary_entry(VALUE array, long index) {
return truffle_read_idx(array, (int) index);
}

int RARRAY_LENINT(VALUE array) {
return truffle_get_size(array);
VALUE rb_ary_dup(VALUE array) {
return (VALUE) truffle_invoke(array, "dup");
}

// Hash

VALUE rb_hash_new() {
return (VALUE) truffle_invoke(RUBY_CEXT, "rb_hash_new");
}
@@ -172,18 +197,25 @@ VALUE rb_hash_aref(VALUE hash, VALUE key) {
return truffle_read(hash, key);
}

void rb_hash_aset(VALUE hash, VALUE key, VALUE value) {
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE value) {
truffle_write(hash, key, value);
return value;
}

void rb_scan_args(int argc, VALUE *argv, const char *format, ...) {
truffle_invoke(RUBY_CEXT, "rb_scan_args", argc, argv, format /*, where to get args? */);
// Utilities

int rb_scan_args(int argc, VALUE *argv, const char *format, ...) {
return truffle_invoke_i(RUBY_CEXT, "rb_scan_args", argc, argv, format /*, where to get args? */);
}

// Calls

VALUE rb_funcall(VALUE object, ID name, int argc, ...) {
return truffle_invoke(object, name /*, where to get args? */);
}

// Instance variables

VALUE rb_iv_get(VALUE object, const char *name) {
return truffle_read(object, truffle_read_string(name));
}
@@ -193,14 +225,20 @@ VALUE rb_iv_set(VALUE object, const char *name, VALUE value) {
return value;
}

// Accessing constants

VALUE rb_const_get(VALUE object, ID name) {
return truffle_invoke(object, "const_get", name);
}

// Raising exceptions

void rb_raise(VALUE exception, const char *format, ...) {
truffle_invoke(RUBY_CEXT, "rb_raise", format /*, where to get args? */);
}

// Defining classes, modules and methods

VALUE rb_define_class(const char *name, VALUE superclass) {
return truffle_invoke(RUBY_CEXT, "rb_define_class", truffle_read_string(name), superclass);
}
Original file line number Diff line number Diff line change
@@ -54,7 +54,6 @@ public class RopeOperations {

private static final ConcurrentHashMap<Encoding, Charset> encodingToCharsetMap = new ConcurrentHashMap<>();

@TruffleBoundary
public static LeafRope create(byte[] bytes, Encoding encoding, CodeRange codeRange) {
if (bytes.length == 1) {
final int index = bytes[0] & 0xff;
Original file line number Diff line number Diff line change
@@ -1291,7 +1291,7 @@ public RubyNode visitDefnNode(org.jruby.ast.DefnNode node) {
rename = methodName.equals("each") || methodName.equals("step") || methodName.equals("to_a");
} else if (path.equals(coreRubiniusPath + "integer.rb")) {
rename = methodName.equals("downto") || methodName.equals("upto");
} else if (path.equals(coreRubiniusPath + "common/string.rb")) {
} else if (path.equals(coreRubiniusPath + "string.rb")) {
rename = methodName.equals("<<");
}

@@ -1706,7 +1706,7 @@ public RubyNode visitGlobalVarNode(org.jruby.ast.GlobalVarNode node) {
RubyNode readNode = environment.findLocalVarNode(name, sourceSection);

if (name.equals("$_")) {
if (getSourcePath(sourceSection).equals(context.getCoreLibrary().getCoreLoadPath() + "/core/common/regexp.rb")) {
if (getSourcePath(sourceSection).equals(context.getCoreLibrary().getCoreLoadPath() + "/core/regexp.rb")) {
readNode = new RubiniusLastStringReadNode(context, sourceSection);
} else {
readNode = GetFromThreadLocalNodeGen.create(context, sourceSection, readNode);
@@ -1821,7 +1821,7 @@ public RubyNode visitInstAsgnNode(org.jruby.ast.InstAsgnNode node) {
setSourceSection(ret, sourceSection);
return addNewlineIfNeeded(node, ret);
}
} else if (path.equals(corePath + "bootstrap/string.rb") || path.equals(corePath + "common/string.rb")) {
} else if (path.equals(corePath + "string.rb")) {
if (name.equals("@hash")) {
ret = StringNodesFactory.ModifyBangNodeFactory.create(new RubyNode[]{});
setSourceSection(ret, sourceSection);
@@ -1841,7 +1841,7 @@ public RubyNode visitInstAsgnNode(org.jruby.ast.InstAsgnNode node) {
setSourceSection(ret, sourceSection);
return addNewlineIfNeeded(node, ret);
}
} else if (path.equals(corePath + "common/io.rb")) {
} else if (path.equals(corePath + "io.rb")) {
// TODO (pitr 08-Aug-2015): values of predefined OM properties should be casted to defined types automatically
if (name.equals("@used") || name.equals("@total") || name.equals("@lineno")) {
// Cast int-fitting longs back to int
@@ -1881,7 +1881,7 @@ public RubyNode visitInstVarNode(org.jruby.ast.InstVarNode node) {
ret = new IntegerFixnumLiteralNode(context, sourceSection, 0);
return addNewlineIfNeeded(node, ret);
}
} else if (path.equals(corePath + "common/regexp.rb")) {
} else if (path.equals(corePath + "regexp.rb")) {
if (name.equals("@source")) {
ret = MatchDataNodesFactory.RubiniusSourceNodeGen.create(self);
setSourceSection(ret, sourceSection);
67 changes: 13 additions & 54 deletions truffle/src/main/ruby/core.rb
Original file line number Diff line number Diff line change
@@ -7,17 +7,7 @@
# GNU Lesser General Public License version 2.1

Truffle::Boot.require_core 'core/pre'

# Rubinius primitives written in Ruby

Truffle::Boot.require_core 'core/primitives'

# Load alpha.rb

Truffle::Boot.require_core 'core/alpha'

# Load bootstrap

Truffle::Boot.require_core 'core/tuple'
Truffle::Boot.require_core 'core/lookuptable'
Truffle::Boot.require_core 'core/atomic'
@@ -27,46 +17,35 @@
Truffle::Boot.require_core 'core/channel'
Truffle::Boot.require_core 'core/character'
Truffle::Boot.require_core 'core/configuration'
Truffle::Boot.require_core 'core/bootstrap/dir'
Truffle::Boot.require_core 'core/false'
Truffle::Boot.require_core 'core/gc'
Truffle::Boot.require_core 'core/bootstrap/io'
Truffle::Boot.require_core 'core/nil'
Truffle::Boot.require_core 'core/bootstrap/regexp'
Truffle::Boot.require_core 'core/bootstrap/rubinius'
Truffle::Boot.require_core 'core/bootstrap/stat'
Truffle::Boot.require_core 'core/bootstrap/string'
Truffle::Boot.require_core 'core/bootstrap/thread'
Truffle::Boot.require_core 'core/rubinius'
Truffle::Boot.require_core 'core/stat'
Truffle::Boot.require_core 'core/string'
Truffle::Boot.require_core 'core/thread'
Truffle::Boot.require_core 'core/true'
Truffle::Boot.require_core 'core/bootstrap/type'
Truffle::Boot.require_core 'core/type'
Truffle::Boot.require_core 'core/weakref'

# Load platform

Truffle::Boot.require_core 'core/library'

Truffle::Boot.require_core 'core/ffi'
Truffle::Boot.require_core 'core/pointer_accessors'
Truffle::Boot.require_core 'core/pointer'
Truffle::Boot.require_core 'core/ffi_file'
Truffle::Boot.require_core 'core/ffi_struct'

# Load common

Truffle::Boot.require_core 'core/io'
Truffle::Boot.require_core 'core/immediate'
Truffle::Boot.require_core 'core/string_mirror'
Truffle::Boot.require_core 'core/common/module'
Truffle::Boot.require_core 'core/module'
Truffle::Boot.require_core 'core/proc'
Truffle::Boot.require_core 'core/enumerable_helper'
Truffle::Boot.require_core 'core/enumerable'
Truffle::Boot.require_core 'core/enumerator'
Truffle::Boot.require_core 'core/argf'
Truffle::Boot.require_core 'core/exception'
Truffle::Boot.require_core 'core/undefined'
Truffle::Boot.require_core 'core/common/type'
Truffle::Boot.require_core 'core/hash'
Truffle::Boot.require_core 'core/array'
Truffle::Boot.require_core 'core/common/kernel'
Truffle::Boot.require_core 'core/kernel'
Truffle::Boot.require_core 'core/identity_map'
Truffle::Boot.require_core 'core/comparable'
Truffle::Boot.require_core 'core/numeric_mirror'
@@ -75,64 +54,44 @@
Truffle::Boot.require_core 'core/integer'
Truffle::Boot.require_core 'core/fixnum'
Truffle::Boot.require_core 'core/lru_cache'
Truffle::Boot.require_core 'core/regexp'
Truffle::Boot.require_core 'core/encoding'
Truffle::Boot.require_core 'core/env'
Truffle::Boot.require_core 'core/errno'
Truffle::Boot.require_core 'core/common/io'
Truffle::Boot.require_core 'core/common/file'
Truffle::Boot.require_core 'core/common/dir'
Truffle::Boot.require_core 'core/file'
Truffle::Boot.require_core 'core/dir'
Truffle::Boot.require_core 'core/dir_glob'
Truffle::Boot.require_core 'core/file_test'
Truffle::Boot.require_core 'core/common/stat'
Truffle::Boot.require_core 'core/float'
Truffle::Boot.require_core 'core/marshal'
Truffle::Boot.require_core 'core/object_space'
Truffle::Boot.require_core 'core/common/string'
Truffle::Boot.require_core 'core/range_mirror'
Truffle::Boot.require_core 'core/range'
Truffle::Boot.require_core 'core/common/struct'
Truffle::Boot.require_core 'core/struct'
Truffle::Boot.require_core 'core/tms'
Truffle::Boot.require_core 'core/process'
Truffle::Boot.require_core 'core/process_mirror'
Truffle::Boot.require_core 'core/random'
Truffle::Boot.require_core 'core/common/regexp'
Truffle::Boot.require_core 'core/signal'
Truffle::Boot.require_core 'core/splitter'
Truffle::Boot.require_core 'core/symbol'
Truffle::Boot.require_core 'core/mutex'
Truffle::Boot.require_core 'core/common/thread'
Truffle::Boot.require_core 'core/throw_catch'
Truffle::Boot.require_core 'core/time'
Truffle::Boot.require_core 'core/rational'
Truffle::Boot.require_core 'core/rationalizer'
Truffle::Boot.require_core 'core/complex'
Truffle::Boot.require_core 'core/complexifier'
Truffle::Boot.require_core 'core/class'

# Load JRuby+Truffle classes

Truffle::Boot.require_core 'core/binding'
Truffle::Boot.require_core 'core/kernel'
Truffle::Boot.require_core 'core/math'
Truffle::Boot.require_core 'core/method'
Truffle::Boot.require_core 'core/module'
Truffle::Boot.require_core 'core/string'
Truffle::Boot.require_core 'core/thread'
Truffle::Boot.require_core 'core/unbound_method'
Truffle::Boot.require_core 'core/type'

# Dirty fixes we'd like to get rid of soon
Truffle::Boot.require_core 'core/shims'

# Load JRuby+Truffle specific classes

Truffle::Boot.require_core 'core/truffle/attachments'
Truffle::Boot.require_core 'core/truffle/debug'
Truffle::Boot.require_core 'core/truffle/cext'
Truffle::Boot.require_core 'core/truffle/interop'

# Start running Ruby code outside classes

Truffle::Boot.require_core 'core/rbconfig'
Truffle::Boot.require_core 'core/main'

Truffle::Boot.require_core 'core/post'
85 changes: 0 additions & 85 deletions truffle/src/main/ruby/core/alpha.rb

This file was deleted.

78 changes: 0 additions & 78 deletions truffle/src/main/ruby/core/bootstrap/dir.rb

This file was deleted.

193 changes: 0 additions & 193 deletions truffle/src/main/ruby/core/bootstrap/io.rb

This file was deleted.

92 changes: 0 additions & 92 deletions truffle/src/main/ruby/core/bootstrap/regexp.rb

This file was deleted.

129 changes: 0 additions & 129 deletions truffle/src/main/ruby/core/bootstrap/stat.rb

This file was deleted.

113 changes: 0 additions & 113 deletions truffle/src/main/ruby/core/bootstrap/string.rb

This file was deleted.

246 changes: 0 additions & 246 deletions truffle/src/main/ruby/core/bootstrap/thread.rb

This file was deleted.

289 changes: 0 additions & 289 deletions truffle/src/main/ruby/core/bootstrap/type.rb

This file was deleted.

1,059 changes: 0 additions & 1,059 deletions truffle/src/main/ruby/core/common/kernel.rb

This file was deleted.

937 changes: 0 additions & 937 deletions truffle/src/main/ruby/core/common/module.rb

This file was deleted.

252 changes: 0 additions & 252 deletions truffle/src/main/ruby/core/common/stat.rb

This file was deleted.

1,787 changes: 0 additions & 1,787 deletions truffle/src/main/ruby/core/common/string.rb

This file was deleted.

595 changes: 0 additions & 595 deletions truffle/src/main/ruby/core/common/type.rb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -41,6 +41,57 @@ class Dir

FFI = Rubinius::FFI

def self.allocate
Rubinius.primitive :dir_allocate
raise PrimitiveFailure, "Dir.allocate primitive failed"
end

def initialize(path, options=undefined)
path = Rubinius::Type.coerce_to_path path

if options.equal? undefined
enc = nil
else
options = Rubinius::Type.coerce_to options, Hash, :to_hash
enc = options[:encoding]
enc = Rubinius::Type.coerce_to_encoding enc if enc
end

Rubinius.invoke_primitive :dir_open, self, path, enc
end

private :initialize

def close
Rubinius.primitive :dir_close
raise PrimitiveFailure, "Dir#close primitive failed"
end

def closed?
Rubinius.primitive :dir_closed_p
raise PrimitiveFailure, "Dir#closed? primitive failed"
end

def read
entry = Rubinius.invoke_primitive :dir_read, self
return unless entry

if Encoding.default_external == Encoding::US_ASCII && !entry.valid_encoding?
entry.force_encoding Encoding::ASCII_8BIT
return entry
end

enc = Encoding.default_internal
enc ? entry.encode(enc) : entry
end

def control(kind, pos)
Rubinius.primitive :dir_control
raise PrimitiveFailure, "Dir#__control__ primitive failed"
end

private :control

def self.open(path, options=undefined)
dir = new path, options
if block_given?
2 changes: 1 addition & 1 deletion truffle/src/main/ruby/core/false.rb
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ def to_s

def inspect
# Call #to_s rather than alias it so that people can change #to_s if they
# wish. Yes, sounds dumb.
# wish.
to_s
end

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -37,6 +37,170 @@ class IO

include Enumerable

class InternalBuffer
def self.allocate
Rubinius.primitive :iobuffer_allocate
raise PrimitiveFailure, "IO::Buffer.allocate primitive failed"
end

##
# Returns the number of bytes that could be written to the buffer.
# If the number is less then the expected, then we need to +empty_to+
# the IO, and +unshift+ again beginning at +start_pos+.
def unshift(str, start_pos)
Rubinius.primitive :iobuffer_unshift
raise PrimitiveFailure, "IO::Buffer#unshift primitive failed"
end

def fill(io)
Rubinius.primitive :iobuffer_fill

unless io.kind_of? IO
return fill(io.to_io)
end

raise PrimitiveFailure, "IOBuffer#fill primitive failed"
end
end

def self.allocate
Rubinius.primitive :io_allocate
raise PrimitiveFailure, "IO.allocate primitive failed"
end

def self.open_with_mode(path, mode, perm)
Rubinius.primitive :io_open
raise PrimitiveFailure, "IO.open_with_mode primitive failed"
end

def self.connect_pipe(lhs, rhs)
Rubinius.primitive :io_connect_pipe
raise PrimitiveFailure, "IO.connect_pipe primitive failed"
end

def self.select_primitive(readables, writables, errorables, timeout)
Rubinius.primitive :io_select
raise IOError, "Unable to select on IO set (descriptor too big?)"
end

def self.fnmatch(pattern, path, flags)
Rubinius.primitive :io_fnmatch
raise PrimitiveFailure, "IO#fnmatch primitive failed"
end

# Instance primitive bindings

def ensure_open
Rubinius.primitive :io_ensure_open
raise PrimitiveFailure, "IO#ensure_open primitive failed"
end

def read_primitive(number_of_bytes)
Rubinius.primitive :io_sysread
raise PrimitiveFailure, "IO::sysread primitive failed"
end

def write(str)
Rubinius.primitive :io_write
raise PrimitiveFailure, "IO#write primitive failed"
end

def read_if_available(size)
Rubinius.primitive :io_read_if_available
raise PrimitiveFailure, "IO#read_if_available primitive failed"
end

def raw_write(str)
Rubinius.primitive :io_write_nonblock
raise PrimitiveFailure, "IO#write_nonblock primitive failed"
end

def reopen_io(other)
Rubinius.primitive :io_reopen
raise ArgumentError, "IO#prim_reopen only accepts an IO object"
end

def reopen_path(string, mode)
Rubinius.primitive :io_reopen_path

if mode.kind_of? Bignum
raise ArgumentError, "Bignum too big for mode"
end

reopen_path StringValue(string), Integer(mode)
end

def prim_seek(amount, whence)
Rubinius.primitive :io_seek
raise RangeError, "#{amount} is too big"
end

def self.prim_truncate(name, offset)
Rubinius.primitive :io_truncate
raise RangeError, "#{offset} is too big"
end

def prim_ftruncate(offset)
Rubinius.primitive :io_ftruncate
raise RangeError, "#{amount} is too big"
end

def query(which)
Rubinius.primitive :io_query
raise PrimitiveFailure, "IO#query primitive failed"
end

def reopen(other)
reopen_io other
end

def tty?
query :tty?
end

def ttyname
query :ttyname
end

def close
Rubinius.primitive :io_close
raise PrimitiveFailure, "IO#close primitive failed"
end

#
# Close read and/or write stream of a full-duplex descriptor.
#
# @todo More documentation. Much more. --rue
#
def shutdown(how)
Rubinius.primitive :io_shutdown
raise PrimitiveFailure, "IO#shutdown primitive failed"
end

def socket_recv(bytes, flags, type)
Rubinius.primitive :io_socket_read
raise PrimitiveFailure, "io_socket_read failed"
end

module Socketable
def accept
Rubinius.primitive :io_accept
raise PrimitiveFailure, "io_accept failed"
end
end

module TransferIO
def send_io
Rubinius.primitive :io_send_io
raise PrimitiveFailure, "IO#send_io failed"
end

def recv_fd
Rubinius.primitive :io_recv_fd
raise PrimitiveFailure, "IO#recv_fd failed"
end
end

module WaitReadable; end
module WaitWritable; end

1,052 changes: 1,050 additions & 2 deletions truffle/src/main/ruby/core/kernel.rb

Large diffs are not rendered by default.

930 changes: 928 additions & 2 deletions truffle/src/main/ruby/core/module.rb

Large diffs are not rendered by default.

823 changes: 821 additions & 2 deletions truffle/src/main/ruby/core/pointer.rb

Large diffs are not rendered by default.

864 changes: 0 additions & 864 deletions truffle/src/main/ruby/core/pointer_accessors.rb

This file was deleted.

15 changes: 14 additions & 1 deletion truffle/src/main/ruby/core/post.rb
Original file line number Diff line number Diff line change
@@ -32,6 +32,19 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

module Rubinius
module Type
def self.const_get(mod, name, inherit=true, resolve=true)
raise "unsupported" unless resolve
mod.const_get name, inherit
end

def self.const_exists?(mod, name, inherit = true)
mod.const_defined? name, inherit
end
end
end

ARGV.push *Truffle::Boot.original_argv

$LOAD_PATH.push *Truffle::Boot.original_load_path
@@ -51,7 +64,7 @@
$LOAD_PATH.push home + '/lib/ruby/truffle/rubysl/rubysl-webrick/lib'
$LOAD_PATH.push home + '/lib/ruby/truffle/shims'

# We defined Psych at the top level becuase several things depend on its name.
# We defined Psych at the top level because several things depend on its name.
# Here we fix that up and put it back into Truffle.

Truffle::Psych = Psych
28 changes: 24 additions & 4 deletions truffle/src/main/ruby/core/pre.rb
Original file line number Diff line number Diff line change
@@ -32,8 +32,32 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

class Module

# :internal:
#
# Basic version of .include used in kernel code.
#
# Redefined in kernel/delta/module.rb.
#
def include(mod)
Rubinius.privately do
mod.append_features self # Truffle: moved the append_features inside the privately
mod.included self
end
self
end

end

module Kernel

# Rubinius defines this method differently, using the :object_class primitive. The two primitives are very similar,
# so rather than introduce the new one, we'll just delegate to the existing one.
def __class__
Rubinius.invoke_primitive :vm_object_class, self
end

alias_method :eql?, :equal?

# Truffle: no extra indirection for Kernel#send.
@@ -44,10 +68,6 @@ def extend(mod)
self
end

def inspect
"#<#{self.class.name}"
end

end

class Symbol
28 changes: 28 additions & 0 deletions truffle/src/main/ruby/core/process.rb
Original file line number Diff line number Diff line change
@@ -74,6 +74,34 @@ class Rlimit < FFI::Struct
config "rbx.platform.rlimit", :rlim_cur, :rlim_max
end

# Terminate with given status code.
#
def self.exit(code=0)
case code
when true
code = 0
when false
code = 1
else
code = Rubinius::Type.coerce_to code, Integer, :to_int
end

raise SystemExit.new(code)
end

def self.exit!(code=1)
Rubinius.primitive :vm_exit

case code
when true
exit! 0
when false
exit! 1
else
exit! Rubinius::Type.coerce_to(code, Integer, :to_int)
end
end

def self.wait_pid_prim(pid, no_hang)
Rubinius.primitive :vm_wait_pid
raise PrimitiveFailure, "Process.wait_pid primitive failed"
Original file line number Diff line number Diff line change
@@ -75,6 +75,68 @@ class Regexp
ESCAPE_TABLE[124] = '\\|'
ESCAPE_TABLE[125] = '\\}'

##
# See Regexp.new. This may be overridden by subclasses.

def compile(pattern, opts)
Rubinius.primitive :regexp_initialize
raise PrimitiveFailure, "Regexp.compile(#{pattern.inspect}, #{opts}) primitive failed"
end

private :compile

def search_region(str, start, finish, forward) # equiv to MRI's re_search
Rubinius.primitive :regexp_search_region
raise PrimitiveFailure, "Regexp#search_region primitive failed"
end

def match_start(str, offset) # equiv to MRI's re_match
Rubinius.primitive :regexp_match_start
raise PrimitiveFailure, "Regexp#match_start primitive failed"
end

def search_from(str, offset) # equiv to MRI's rb_reg_search
Rubinius.primitive :regexp_search_from
raise PrimitiveFailure, "Regexp#search_from primitive failed"
end

def options
Rubinius.primitive :regexp_options
raise PrimitiveFailure, "Regexp#options primitive failed"
end

def self.last_match(field=nil)
Rubinius.primitive :regexp_last_match

return last_match(Integer(field)) if field
raise PrimitiveFailure, "Regexp#last_match primitive failed"
end

def self.last_match=(match)
Rubinius.primitive :regexp_set_last_match

unless match.kind_of? MatchData
raise TypeError, "Expected MatchData, got #{match.inspect}"
end

raise PrimitiveFailure, "Regexp#set_last_match primitive failed"
end

def self.propagate_last_match
Rubinius.primitive :regexp_propagate_last_match
raise PrimitiveFailure, "Regexp#propagate_last_match primitive failed"
end

def self.set_block_last_match
Rubinius.primitive :regexp_set_block_last_match
raise PrimitiveFailure, "Regexp#set_block_last_match primitive failed"
end

def fixed_encoding?
Rubinius.primitive :regexp_fixed_encoding_p
raise PrimitiveFailure, "Regexp.fixed_encoding? primitive failed"
end

class << self
alias_method :compile, :new
end
File renamed without changes.
352 changes: 352 additions & 0 deletions truffle/src/main/ruby/core/stat.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,352 @@
# Copyright (c) 2007-2015, Evan Phoenix and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Rubinius nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

module Rubinius
class Stat
include Comparable

def self.allocate
Rubinius.primitive :stat_allocate
raise PrimitiveFailure, "Rubinius::Stat.allocate primitive failed"
end

def setup(path)
Rubinius.primitive :stat_stat
path = Rubinius::Type.coerce_to_path(path)
setup(path)
end
private :setup

def fsetup(fd)
Rubinius.primitive :stat_fstat
fd = Rubinius::Type.coerce_to fd, Integer, :to_int
fsetup(fd)
end
private :fsetup

def lsetup(path)
Rubinius.primitive :stat_lstat
path = Rubinius::Type.coerce_to_path(path)
lsetup(path)
end
private :lsetup

def dev
Rubinius.primitive :stat_dev
raise PrimitiveFailure, "Rubinius::Stat#dev primitive failed"
end

def ino
Rubinius.primitive :stat_ino
raise PrimitiveFailure, "Rubinius::Stat#ino primitive failed"
end

def mode
Rubinius.primitive :stat_mode
raise PrimitiveFailure, "Rubinius::Stat#mode primitive failed"
end

def nlink
Rubinius.primitive :stat_nlink
raise PrimitiveFailure, "Rubinius::Stat#nlink primitive failed"
end

def uid
Rubinius.primitive :stat_uid
raise PrimitiveFailure, "Rubinius::Stat#uid primitive failed"
end

def gid
Rubinius.primitive :stat_gid
raise PrimitiveFailure, "Rubinius::Stat#gid primitive failed"
end

def rdev
Rubinius.primitive :stat_rdev
raise PrimitiveFailure, "Rubinius::Stat#rdev primitive failed"
end

def size
Rubinius.primitive :stat_size
raise PrimitiveFailure, "Rubinius::Stat#size primitive failed"
end

def blksize
Rubinius.primitive :stat_blksize
raise PrimitiveFailure, "Rubinius::Stat#blksize primitive failed"
end

def blocks
Rubinius.primitive :stat_blocks
raise PrimitiveFailure, "Rubinius::Stat#blocks primitive failed"
end

def atime
Rubinius.primitive :stat_atime
raise PrimitiveFailure, "Rubinius::Stat#atime primitive failed"
end

def mtime
Rubinius.primitive :stat_mtime
raise PrimitiveFailure, "Rubinius::Stat#mtime primitive failed"
end

def ctime
Rubinius.primitive :stat_ctime
raise PrimitiveFailure, "Rubinius::Stat#ctime primitive failed"
end

def inspect
"#<#{self.class.name} dev=0x#{self.dev.to_s(16)}, ino=#{self.ino}, " \
"mode=#{sprintf("%07d", self.mode.to_s(8).to_i)}, nlink=#{self.nlink}, " \
"uid=#{self.uid}, gid=#{self.gid}, rdev=0x#{self.rdev.to_s(16)}, " \
"size=#{self.size}, blksize=#{self.blksize}, blocks=#{self.blocks}, " \
"atime=#{self.atime}, mtime=#{self.mtime}, ctime=#{self.ctime}>"
end

S_IRUSR = Rubinius::Config['rbx.platform.file.S_IRUSR']
S_IWUSR = Rubinius::Config['rbx.platform.file.S_IWUSR']
S_IXUSR = Rubinius::Config['rbx.platform.file.S_IXUSR']
S_IRGRP = Rubinius::Config['rbx.platform.file.S_IRGRP']
S_IWGRP = Rubinius::Config['rbx.platform.file.S_IWGRP']
S_IXGRP = Rubinius::Config['rbx.platform.file.S_IXGRP']
S_IROTH = Rubinius::Config['rbx.platform.file.S_IROTH']
S_IWOTH = Rubinius::Config['rbx.platform.file.S_IWOTH']
S_IXOTH = Rubinius::Config['rbx.platform.file.S_IXOTH']

S_IRUGO = S_IRUSR | S_IRGRP | S_IROTH
S_IWUGO = S_IWUSR | S_IWGRP | S_IWOTH
S_IXUGO = S_IXUSR | S_IXGRP | S_IXOTH

S_IFMT = Rubinius::Config['rbx.platform.file.S_IFMT']
S_IFIFO = Rubinius::Config['rbx.platform.file.S_IFIFO']
S_IFCHR = Rubinius::Config['rbx.platform.file.S_IFCHR']
S_IFDIR = Rubinius::Config['rbx.platform.file.S_IFDIR']
S_IFBLK = Rubinius::Config['rbx.platform.file.S_IFBLK']
S_IFREG = Rubinius::Config['rbx.platform.file.S_IFREG']
S_IFLNK = Rubinius::Config['rbx.platform.file.S_IFLNK']
S_IFSOCK = Rubinius::Config['rbx.platform.file.S_IFSOCK']
S_IFWHT = Rubinius::Config['rbx.platform.file.S_IFWHT']
S_ISUID = Rubinius::Config['rbx.platform.file.S_ISUID']
S_ISGID = Rubinius::Config['rbx.platform.file.S_ISGID']
S_ISVTX = Rubinius::Config['rbx.platform.file.S_ISVTX']

attr_reader :path

def initialize(path)
Errno.handle path unless setup(path) == 0
end

def self.stat(path)
stat = allocate
if Rubinius.privately { stat.setup path } == 0
stat
else
nil
end
end

def self.fstat(fd)
stat = allocate
result = Rubinius.privately { stat.fsetup fd }
Errno.handle "file descriptor #{descriptor}" unless result == 0
stat
end

def self.lstat(path)
stat = allocate
result = Rubinius.privately { stat.lsetup path }
Errno.handle path unless result == 0
stat
end

def blockdev?
mode & S_IFMT == S_IFBLK
end

def chardev?
mode & S_IFMT == S_IFCHR
end

def dev_major
major = Truffle::POSIX.major dev
major < 0 ? nil : major
end

def dev_minor
minor = Truffle::POSIX.major dev
minor < 0 ? nil : minor
end

def directory?
mode & S_IFMT == S_IFDIR
end

def executable?
return true if superuser?
return mode & S_IXUSR != 0 if owned?
return mode & S_IXGRP != 0 if grpowned?
return mode & S_IXOTH != 0
end

def executable_real?
return true if rsuperuser?
return mode & S_IXUSR != 0 if rowned?
return mode & S_IXGRP != 0 if rgrpowned?
return mode & S_IXOTH != 0
end

def file?
mode & S_IFMT == S_IFREG
end

def ftype
if file?
"file"
elsif directory?
"directory"
elsif chardev?
"characterSpecial"
elsif blockdev?
"blockSpecial"
elsif pipe?
"fifo"
elsif socket?
"socket"
elsif symlink?
"link"
else
"unknown"
end
end

def owned?
uid == Truffle::POSIX.geteuid
end

def pipe?
mode & S_IFMT == S_IFIFO
end

def rdev_major
major = Truffle::POSIX.major rdev
major < 0 ? nil : major
end

def rdev_minor
minor = Truffle::POSIX.minor rdev
minor < 0 ? nil : minor
end

def readable?
return true if superuser?
return mode & S_IRUSR != 0 if owned?
return mode & S_IRGRP != 0 if grpowned?
return mode & S_IROTH != 0
end

def readable_real?
return true if rsuperuser?
return mode & S_IRUSR != 0 if rowned?
return mode & S_IRGRP != 0 if rgrpowned?
return mode & S_IROTH != 0
end

def setgid?
mode & S_ISGID != 0
end

def setuid?
mode & S_ISUID != 0
end

def sticky?
mode & S_ISVTX != 0
end

def size?
size == 0 ? nil : size
end

def socket?
mode & S_IFMT == S_IFSOCK
end

def symlink?
mode & S_IFMT == S_IFLNK
end

def writable?
return true if superuser?
return mode & S_IWUSR != 0 if owned?
return mode & S_IWGRP != 0 if grpowned?
return mode & S_IWOTH != 0
end

def writable_real?
return true if rsuperuser?
return mode & S_IWUSR != 0 if rowned?
return mode & S_IWGRP != 0 if rgrpowned?
return mode & S_IWOTH != 0
end

def zero?
size == 0
end

def <=>(other)
return nil unless other.is_a?(File::Stat)
self.mtime <=> other.mtime
end

def rgrpowned?
gid == Truffle::POSIX.getgid
end
private :rgrpowned?

def rowned?
uid == Truffle::POSIX.getuid
end
private :rowned?

def rsuperuser?
Truffle::POSIX.getuid == 0
end
private :rsuperuser?

def superuser?
Truffle::POSIX.geteuid == 0
end
private :superuser?

# Process.groups only return supplemental groups, so we need to check if gid/egid match too.
def grpowned?
gid = gid()
return true if gid == Process.gid || gid == Process.egid
Process.groups.include?(gid)
end
end
end
Loading

0 comments on commit a8a22c4

Please sign in to comment.