Skip to content

Commit

Permalink
Showing 17 changed files with 1,038 additions and 156 deletions.
340 changes: 282 additions & 58 deletions lib/ruby/truffle/cext/ruby.h

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/exception/no_method_error_tags.txt

This file was deleted.

496 changes: 429 additions & 67 deletions truffle/src/main/c/cext/ruby.c

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions truffle/src/main/c/openssl/ossl.c
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ STACK_OF(type) * \
ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
{ \
return (STACK_OF(type)*)rb_protect( \
(VALUE(*)((VALUE)))ossl_##name##_ary2sk0, \
(VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \
ary, \
status); \
} \
@@ -136,7 +136,7 @@ ossl_buf2str(char *buf, int len)
VALUE str;
int status = 0;

str = rb_protect((VALUE(*)((VALUE)))ossl_str_new, len, &status);
str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
OPENSSL_free(buf);
if(status) rb_jump_tag(status);
3 changes: 3 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/Layouts.java
Original file line number Diff line number Diff line change
@@ -28,6 +28,8 @@
import org.jruby.truffle.core.exception.ExceptionLayoutImpl;
import org.jruby.truffle.core.exception.NameErrorLayout;
import org.jruby.truffle.core.exception.NameErrorLayoutImpl;
import org.jruby.truffle.core.exception.NoMethodErrorLayout;
import org.jruby.truffle.core.exception.NoMethodErrorLayoutImpl;
import org.jruby.truffle.core.exception.SystemCallErrorLayout;
import org.jruby.truffle.core.exception.SystemCallErrorLayoutImpl;
import org.jruby.truffle.core.fiber.FiberLayout;
@@ -124,6 +126,7 @@ public abstract class Layouts {
public static final ModuleLayout MODULE = ModuleLayoutImpl.INSTANCE;
public static final MutexLayout MUTEX = MutexLayoutImpl.INSTANCE;
public static final NameErrorLayout NAME_ERROR = NameErrorLayoutImpl.INSTANCE;
public static final NoMethodErrorLayout NO_METHOD_ERROR = NoMethodErrorLayoutImpl.INSTANCE;
public static final ObjectRangeLayout OBJECT_RANGE = ObjectRangeLayoutImpl.INSTANCE;
public static final PointerLayout POINTER = PointerLayoutImpl.INSTANCE;
public static final ProcLayout PROC = ProcLayoutImpl.INSTANCE;
4 changes: 4 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@
import org.jruby.truffle.core.encoding.EncodingNodesFactory;
import org.jruby.truffle.core.exception.ExceptionNodesFactory;
import org.jruby.truffle.core.exception.NameErrorNodesFactory;
import org.jruby.truffle.core.exception.NoMethodErrorNodesFactory;
import org.jruby.truffle.core.exception.SystemCallErrorNodesFactory;
import org.jruby.truffle.core.fiber.FiberNodesFactory;
import org.jruby.truffle.core.hash.HashNodesFactory;
@@ -397,6 +398,7 @@ public CoreLibrary(RubyContext context) {
nameErrorClass = defineClass(standardErrorClass, "NameError");
Layouts.CLASS.setInstanceFactoryUnsafe(nameErrorClass, Layouts.NAME_ERROR.createNameErrorShape(nameErrorClass, nameErrorClass));
noMethodErrorClass = defineClass(nameErrorClass, "NoMethodError");
Layouts.CLASS.setInstanceFactoryUnsafe(noMethodErrorClass, Layouts.NO_METHOD_ERROR.createNoMethodErrorShape(noMethodErrorClass, noMethodErrorClass));

// StandardError > SystemCallError
systemCallErrorClass = defineClass(standardErrorClass, "SystemCallError");
@@ -679,6 +681,7 @@ public void addPrimitives() {
primitiveManager.addPrimitiveNodes(IOBufferPrimitiveNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(ExceptionNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(NameErrorNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(NoMethodErrorNodesFactory.getFactories());
primitiveManager.addPrimitiveNodes(SystemCallErrorNodesFactory.getFactories());
return null;
}, () -> {
@@ -709,6 +712,7 @@ public void addCoreMethods() {
coreMethodNodeManager.addCoreMethodNodes(ConditionVariableNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(ExceptionNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(NameErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(NoMethodErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(SystemCallErrorNodesFactory.getFactories());
coreMethodNodeManager.addCoreMethodNodes(FalseClassNodesFactory.getFactories());
return null;
Original file line number Diff line number Diff line change
@@ -280,13 +280,13 @@ private DynamicObject buildMethodMissingException(Object self, DynamicObject nam
final String name = nameObject.toString();

if (lastCallWasSuper()) {
return coreExceptions().noSuperMethodError(name, self, this);
return coreExceptions().noSuperMethodError(name, self, args, this);
} else if (lastCallWasCallingPrivateMethod(self, name)) {
return coreExceptions().privateMethodError(name, self, this);
return coreExceptions().privateMethodError(name, self, args, this);
} else if (lastCallWasVCall()) {
return coreExceptions().nameErrorUndefinedLocalVariableOrMethod(name, self, this);
} else {
return coreExceptions().noMethodErrorOnReceiver(name, self, this);
return coreExceptions().noMethodErrorOnReceiver(name, self, args, this);
}
}

Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;

import static org.jruby.truffle.core.array.ArrayHelpers.createArray;

public class CoreExceptions {

private final RubyContext context;
@@ -502,9 +504,10 @@ public DynamicObject nameError(String message, Object receiver, String name, Nod
// NoMethodError

@TruffleBoundary
public DynamicObject noMethodError(String message, Object receiver, String name, Node currentNode) {
public DynamicObject noMethodError(String message, Object receiver, String name, Object[] args, Node currentNode) {
final DynamicObject messageString = StringOperations.createString(context, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE));
DynamicObject noMethodError = ExceptionOperations.createNameError(context.getCoreLibrary().getNoMethodErrorClass(), messageString, context.getCallStack().getBacktrace(currentNode), receiver, context.getSymbolTable().getSymbol(name));
final DynamicObject argsArray = createArray(context, args, args.length);
final DynamicObject noMethodError = ExceptionOperations.createNoMethodError(context.getCoreLibrary().getNoMethodErrorClass(), messageString, context.getCallStack().getBacktrace(currentNode), receiver, context.getSymbolTable().getSymbol(name), argsArray);
return noMethodError;
}

@@ -518,26 +521,26 @@ public DynamicObject noSuperMethodOutsideMethodError(Node currentNode) {
}

@TruffleBoundary
public DynamicObject noSuperMethodError(String name, Object self, Node currentNode) {
return noMethodError(String.format("super: no superclass method `%s'", name), self, name, currentNode);
public DynamicObject noSuperMethodError(String name, Object self, Object[] args, Node currentNode) {
return noMethodError(String.format("super: no superclass method `%s'", name), self, name, args, currentNode);
}

@TruffleBoundary
public DynamicObject noMethodErrorOnReceiver(String name, Object receiver, Node currentNode) {
public DynamicObject noMethodErrorOnReceiver(String name, Object receiver, Object[] args, Node currentNode) {
final DynamicObject logicalClass = context.getCoreLibrary().getLogicalClass(receiver);
final String moduleName = Layouts.MODULE.getFields(logicalClass).getName();

// e.g. BasicObject does not have inspect
final boolean hasInspect = ModuleOperations.lookupMethod(logicalClass, "inspect", Visibility.PUBLIC) != null;
final Object stringRepresentation = hasInspect ? context.send(receiver, "inspect", null) : context.getCoreLibrary().getNilObject();

return noMethodError(String.format("undefined method `%s' for %s:%s", name, stringRepresentation, moduleName), receiver, name, currentNode);
return noMethodError(String.format("undefined method `%s' for %s:%s", name, stringRepresentation, moduleName), receiver, name, args, currentNode);
}

@TruffleBoundary
public DynamicObject privateMethodError(String name, Object self, Node currentNode) {
public DynamicObject privateMethodError(String name, Object self, Object[] args, Node currentNode) {
String className = Layouts.MODULE.getFields(context.getCoreLibrary().getLogicalClass(self)).getName();
return noMethodError(String.format("private method `%s' called for %s", name, className), self, name, currentNode);
return noMethodError(String.format("private method `%s' called for %s", name, className), self, name, args, currentNode);
}

// LoadError
@@ -652,6 +655,21 @@ public DynamicObject rangeError(DynamicObject range, Node currentNode) {
Layouts.INT_RANGE.getEnd(range)), currentNode);
}

@TruffleBoundary
public DynamicObject rangeErrorConvertToInt(long value, Node currentNode) {
final String direction;

if (value < Integer.MIN_VALUE) {
direction = "small";
} else if (value > Integer.MAX_VALUE) {
direction = "big";
} else {
throw new IllegalArgumentException();
}

return rangeError(String.format("integer %d too %s to convert to `int'", value, direction), currentNode);
}

@TruffleBoundary
public DynamicObject rangeError(String message, Node currentNode) {
return ExceptionOperations.createRubyException(
Original file line number Diff line number Diff line change
@@ -54,4 +54,8 @@ public static DynamicObject createNameError(DynamicObject rubyClass, Object mess
return Layouts.NAME_ERROR.createNameError(Layouts.CLASS.getInstanceFactory(rubyClass), message, backtrace, receiver, name);
}

public static DynamicObject createNoMethodError(DynamicObject rubyClass, Object message, Backtrace backtrace, Object receiver, Object name, DynamicObject args) {
return Layouts.NO_METHOD_ERROR.createNoMethodError(Layouts.CLASS.getInstanceFactory(rubyClass), message, backtrace, receiver, name, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.core.exception;

import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectFactory;
import com.oracle.truffle.api.object.dsl.Layout;
import com.oracle.truffle.api.object.dsl.Nullable;
import org.jruby.truffle.language.backtrace.Backtrace;

@Layout
public interface NoMethodErrorLayout extends NameErrorLayout {

DynamicObjectFactory createNoMethodErrorShape(
DynamicObject logicalClass,
DynamicObject metaClass);

DynamicObject createNoMethodError(
DynamicObjectFactory factory,
Object message,
@Nullable Backtrace backtrace,
@Nullable Object receiver,
Object name,
Object args);

Object getArgs(DynamicObject object);
void setArgs(DynamicObject object, Object value);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.core.exception;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.builtins.CoreClass;
import org.jruby.truffle.builtins.CoreMethod;
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.language.objects.AllocateObjectNode;
import org.jruby.truffle.language.objects.AllocateObjectNodeGen;

@CoreClass("NoMethodError")
public abstract class NoMethodErrorNodes {

@CoreMethod(names = "allocate", constructor = true)
public abstract static class AllocateNode extends CoreMethodArrayArgumentsNode {

@Child private AllocateObjectNode allocateObjectNode;

public AllocateNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, null, null);
}

@Specialization
public DynamicObject allocateNoMethodError(DynamicObject rubyClass) {
return allocateObjectNode.allocate(rubyClass, nil(), null, null, nil(), nil());
}

}

@CoreMethod(names = "args")
public abstract static class ArgsNode extends CoreMethodArrayArgumentsNode {

@Specialization
public Object args(DynamicObject self) {
return Layouts.NO_METHOD_ERROR.getArgs(self);
}

}

@Primitive(name = "no_method_error_set_args")
public abstract static class ArgsSetNode extends PrimitiveArrayArgumentsNode {

@Specialization
public Object setArgs(DynamicObject error, Object args) {
Layouts.NO_METHOD_ERROR.setArgs(error, args);
return args;
}

}


}
Original file line number Diff line number Diff line change
@@ -87,12 +87,16 @@ private void doWait(
Object condition) {

final long start = System.currentTimeMillis();
boolean doLock = false;

try {
// First lock the condition so we only release the Mutex when we are in wait()
// and ready to be notified
// First acquire the condition monitor, so we only release the Mutex
// when we own the condition monitor blocking notify/notifyAll calls until
// we are in wait(), ready to be notified.
synchronized (condition) {
MutexOperations.unlock(lock, thread, this);
// successfully unlocked, do lock later
doLock = true;
getContext().getThreadManager().
runUntilResult(this, new BlockingAction<Boolean>() {
@Override
@@ -112,8 +116,10 @@ public Boolean block() throws InterruptedException {
} finally {
// Has to lock again *after* condition lock is released, otherwise it would be
// locked in reverse order condition > mutex opposed to normal locking order
// mutex > condition, which would lead to deadlock.
MutexOperations.lock(lock, thread, this);
// mutex > condition (as in signal, broadcast), which would lead to deadlock.
if (doLock) {
MutexOperations.lock(lock, thread, this);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -31,6 +31,8 @@ DynamicObject createIO(DynamicObjectFactory factory,
int descriptor,
int mode);

boolean isIO(DynamicObject object);

DynamicObject getIBuffer(DynamicObject object);

int getLineNo(DynamicObject object);
Original file line number Diff line number Diff line change
@@ -24,17 +24,20 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.builtins.CoreClass;
import org.jruby.truffle.builtins.CoreMethod;
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.builtins.CoreMethodNode;
import org.jruby.truffle.core.CoreLibrary;
import org.jruby.truffle.core.cast.NameToJavaStringNodeGen;
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.language.RubyConstant;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.constants.GetConstantNode;
import org.jruby.truffle.language.constants.LookupConstantNode;
import org.jruby.truffle.language.control.RaiseException;

@CoreClass("Truffle::CExt")
public class CExtNodes {
@@ -70,6 +73,27 @@ public long num2long(int num) {

}

@CoreMethod(names = "NUM2ULONG", isModuleFunction = true, required = 1)
public abstract static class NUM2ULONGNode extends CoreMethodArrayArgumentsNode {

@Specialization
public long num2ulong(int num) {
// TODO CS 2-May-16 what to do about the fact it's unsigned?
return num;
}

}

@CoreMethod(names = "NUM2DBL", isModuleFunction = true, required = 1)
public abstract static class NUM2DBLNode extends CoreMethodArrayArgumentsNode {

@Specialization
public double num2dbl(int num) {
return num;
}

}

@CoreMethod(names = "FIX2INT", isModuleFunction = true, required = 1)
public abstract static class FIX2INTNode extends CoreMethodArrayArgumentsNode {

@@ -158,6 +182,17 @@ public int long2num(int num) {

}

@CoreMethod(names = "ULONG2NUM", isModuleFunction = true, required = 1)
public abstract static class ULONG2NUMNode extends CoreMethodArrayArgumentsNode {

@Specialization
public int ulong2num(int num) {
// TODO CS 2-May-16 what to do about the fact it's unsigned?
return num;
}

}

@CoreMethod(names = "LONG2FIX", isModuleFunction = true, required = 1)
public abstract static class LONG2FIXNode extends CoreMethodArrayArgumentsNode {

@@ -168,6 +203,30 @@ public int long2fix(int num) {

}

@CoreMethod(names = "rb_long2int", isModuleFunction = true, required = 1)
public abstract static class Long2Int extends CoreMethodArrayArgumentsNode {

@Specialization
public int long2fix(int num) {
return num;
}

@Specialization(guards = "fitsIntoInteger(num)")
public int long2fixInRange(long num) {
return (int) num;
}

@Specialization(guards = "!fitsIntoInteger(num)")
public int long2fixOutOfRange(long num) {
throw new RaiseException(coreExceptions().rangeErrorConvertToInt(num, this));
}

protected boolean fitsIntoInteger(long num) {
return CoreLibrary.fitsIntoInteger(num);
}

}

@CoreMethod(names = "CExtString", isModuleFunction = true, required = 1)
public abstract static class CExtStringNode extends CoreMethodArrayArgumentsNode {

@@ -197,15 +256,15 @@ public DynamicObject toRubyString(DynamicObject string) {
public abstract static class BlockGivenNode extends CoreMethodArrayArgumentsNode {

@Specialization
public boolean blockGiven(MaterializedFrame callerFrame,
public int blockGiven(MaterializedFrame callerFrame,
@Cached("createBinaryProfile()") ConditionProfile blockProfile) {
return blockProfile.profile(RubyArguments.getBlock(callerFrame) != null);
return blockProfile.profile(RubyArguments.getBlock(callerFrame) != null) ? 1 : 0;
}

@TruffleBoundary
@Specialization
public boolean blockGiven(NotProvided noCallerFrame) {
return RubyArguments.getBlock(Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_ONLY, false)) != null;
public int blockGiven(NotProvided noCallerFrame) {
return RubyArguments.getBlock(Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_ONLY, false)) != null ? 1 : 0;
}

}
@@ -250,4 +309,14 @@ public Object constGetFrom(VirtualFrame frame, DynamicObject module, String name

}

@CoreMethod(names = "rb_jt_io_handle", isModuleFunction = true)
public abstract static class IOHandleNode extends CoreMethodArrayArgumentsNode {

@Specialization(guards = "isRubyIO(io)")
public int ioHandle(DynamicObject io) {
return Layouts.IO.getDescriptor(io);
}

}

}
Original file line number Diff line number Diff line change
@@ -241,6 +241,10 @@ public static boolean isTracePoint(DynamicObject object) {
return Layouts.TRACE_POINT.isTracePoint(object);
}

public static boolean isRubyIO(DynamicObject object) {
return Layouts.IO.isIO(object);
}

public static boolean isNullPointer(DynamicObject pointer) {
return Layouts.POINTER.getPointer(pointer) == PointerPrimitiveNodes.NULL_POINTER;
}
12 changes: 6 additions & 6 deletions truffle/src/main/ruby/core/exception.rb
Original file line number Diff line number Diff line change
@@ -183,18 +183,18 @@ class LocalJumpError < StandardError
class NameError < StandardError

def initialize(*args)
super(args.shift)
Truffle.invoke_primitive :name_error_set_name, self, args.shift
name = args.size > 1 ? args.pop : nil
super(*args)
Truffle.invoke_primitive :name_error_set_name, self, name
end
end

class NoMethodError < NameError
attr_reader :args

def initialize(*arguments)
super(arguments.shift)
@name = arguments.shift
@args = arguments.shift
args = arguments.size > 2 ? arguments.pop : nil
super(*arguments) # TODO BJF Jul 24, 2016 Need to handle NoMethodError.new(1,2,3,4)
Truffle.invoke_primitive :no_method_error_set_args, self, args
end
end

89 changes: 87 additions & 2 deletions truffle/src/main/ruby/core/truffle/cext.rb
Original file line number Diff line number Diff line change
@@ -96,6 +96,9 @@ def rb_type(value)
end

def RB_TYPE_P(value, type)
# TODO CS 23-Jul-16 we could do with making this a kind of specialising case
# that puts never seen cases behind a transfer

case type
when T_STRING
value.is_a?(String)
@@ -111,6 +114,18 @@ def rb_check_type(value, type)
end
end

def rb_obj_is_instance_of(object, ruby_class)
object.class == ruby_class
end

def SYMBOL_P(value)
value.is_a?(Symbol)
end

def Qundef
Rubinius::UNDEFINED
end

def Qfalse
false
end
@@ -139,10 +154,30 @@ def rb_cProc
Proc
end

def rb_cTime
Time
end

def rb_mKernel
Kernel
end

def rb_mEnumerable
Enumerable
end

def rb_mWaitReadable
WaitReadable
end

def rb_mWaitWritable
WaitWritable
end

def rb_eException
Exception
end

def rb_eRuntimeError
RuntimeError
end
@@ -155,6 +190,22 @@ def rb_eNoMemError
NoMemError
end

def rb_eTypeError
TypeError
end

def rb_eArgError
ArgError
end

def rb_eRangeError
RangeError
end

def rb_eNotImpError
NotImplementedError
end

def rb_fix2int(value)
if value.nil?
raise TypeError
@@ -175,11 +226,11 @@ def rb_fix2uint(value)
end
end

def NIL_P(value)
def RB_NIL_P(value)
nil.equal?(value)
end

def FIXNUM_P(value)
def RB_FIXNUM_P(value)
value.is_a?(Fixnum)
end

@@ -191,6 +242,10 @@ def rb_float_new(value)
value.to_f
end

def rb_Integer(value)
Integer(value)
end

def rb_Float(value)
Float(value)
end
@@ -203,6 +258,15 @@ def RSTRING_PTR(string)
Truffle::Interop.to_java_string(string)
end

def rb_str_new_frozen(value)
if value.frozen?
value
else
# There's more to rb_str_new_frozen than this
String(value).freeze
end
end

def rb_intern(str)
str.intern
end
@@ -223,6 +287,10 @@ def rb_str_cat(string, to_concat, length)
raise 'not implemented'
end

def rb_String(value)
String(value)
end

def RARRAY_PTR(array)
array
end
@@ -243,6 +311,10 @@ def rb_hash_new
{}
end

def rb_class_real(ruby_class)
raise 'not implemented'
end

def rb_proc_new(function, value)
proc { |*args|
Truffle::Interop.execute(function, *args)
@@ -262,6 +334,15 @@ def rb_yield(value)
block.call(value)
end

def rb_ivar_lookup(object, name, default_value)
# TODO CS 24-Jul-16 races - needs a new primitive or be defined in Java?
if object.instance_variable_defined?(name)
object.instance_variable_get(name)
else
default_value
end
end

def rb_exc_raise(exception)
raise exception
end
@@ -427,6 +508,10 @@ def rb_nativethread_lock_initialize
Mutex.new
end

def rb_data_typed_object_wrap(ruby_class, data, data_type)
raise 'not implemented'
end

end

Truffle::Interop.export(:ruby_cext, Truffle::CExt)

0 comments on commit 4f8c02f

Please sign in to comment.