Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: cf0bfa94ebfc
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: fc3d39ee9366
Choose a head ref
  • 3 commits
  • 10 files changed
  • 1 contributor

Commits on May 12, 2015

  1. [Truffle] Do not allow to allocate Bignum in user code.

    * And undefine the allocator, like MRI.
    * Also makes the value final at initialization.
    eregon committed May 12, 2015
    Copy the full SHA
    fb84fbc View commit details
  2. [Truffle] Undefined Allocator for class which are only internally ins…

    …tantiated.
    
    * Following roughly the usage of rb_undef_method in MRI.
    * Make the Activation in a Thread::Bactrace::Location final.
    eregon committed May 12, 2015
    Copy the full SHA
    05eabb6 View commit details
  3. [Truffle] Make RubyBasicObject.EMPTY_SHAPE static.

    * Avoids the need for callbacks in CoreLibrary to classes with custom shapes.
    eregon committed May 12, 2015
    Copy the full SHA
    fc3d39e View commit details
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -18,6 +19,7 @@
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.truffle.nodes.cast.BooleanCastNode;
import org.jruby.truffle.nodes.cast.BooleanCastNodeGen;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
@@ -40,36 +42,17 @@ public abstract class BignumNodes {

private static final HiddenKey VALUE_IDENTIFIER = new HiddenKey("value");
public static final Property VALUE_PROPERTY;
private static final DynamicObjectFactory BIGNUM_FACTORY;

static {
Shape.Allocator allocator = RubyBasicObject.LAYOUT.createAllocator();
VALUE_PROPERTY = Property.create(VALUE_IDENTIFIER, allocator.locationForType(BigInteger.class, EnumSet.of(LocationModifier.NonNull)), 0);
}

public static Allocator createBigumAllocator(Shape emptyShape) {
Shape shape = emptyShape.addProperty(VALUE_PROPERTY);
final DynamicObjectFactory factory = shape.createFactory();

return new Allocator() {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBignum(rubyClass, factory.newInstance(BigInteger.ZERO));
}
};
VALUE_PROPERTY = Property.create(VALUE_IDENTIFIER, allocator.locationForType(BigInteger.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0);
Shape shape = RubyBasicObject.EMPTY_SHAPE.addProperty(VALUE_PROPERTY);
BIGNUM_FACTORY = shape.createFactory();
}

public static RubyBasicObject createRubyBignum(RubyClass rubyClass, BigInteger value) {
final RubyBasicObject bignum = rubyClass.getAllocator().allocate(rubyClass.getContext(), rubyClass, null);

try {
VALUE_PROPERTY.set(bignum.getDynamicObject(), value, bignum.getDynamicObject().getShape());
} catch (IncompatibleLocationException e) {
throw new UnsupportedOperationException();
} catch (FinalLocationException e) {
throw new UnsupportedOperationException();
}

return bignum;
return new RubyBignum(rubyClass, BIGNUM_FACTORY.newInstance(value));
}

public static BigInteger getBigIntegerValue(RubyBasicObject bignum) {
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@
import org.jruby.truffle.pack.runtime.PackResult;
import org.jruby.truffle.pack.runtime.exceptions.*;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.backtrace.Activation;
import org.jruby.truffle.runtime.backtrace.Backtrace;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.*;
@@ -341,12 +342,8 @@ public RubyArray callerLocations(int omit, int length) {
final Object[] locations = new Object[locationsCount];

for (int n = 0; n < locationsCount; n++) {
final RubyBasicObject location = threadBacktraceLocationClass.getAllocator().allocate(getContext(), threadBacktraceLocationClass, this);

// TODO CS 30-Apr-15 can't set set this in the allocator? How do we get it there?
ThreadBacktraceLocationNodes.setActivation(location, backtrace.getActivations().get(n));

locations[n] = location;
Activation activation = backtrace.getActivations().get(n);
locations[n] = ThreadBacktraceLocationNodes.createRubyThreadBacktraceLocation(threadBacktraceLocationClass, activation);
}

return new RubyArray(getContext().getCoreLibrary().getArrayClass(), locations, locations.length);
19 changes: 9 additions & 10 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/MutexNodes.java
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.*;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
@@ -30,22 +31,20 @@ public abstract class MutexNodes {

private static final HiddenKey LOCK_IDENTIFIER = new HiddenKey("lock");
private static final Property LOCK_PROPERTY;
private static final DynamicObjectFactory MUTEX_FACTORY;

static {
Shape.Allocator allocator = RubyBasicObject.LAYOUT.createAllocator();
LOCK_PROPERTY = Property.create(LOCK_IDENTIFIER, allocator.locationForType(ReentrantLock.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0);
Shape shape = RubyBasicObject.EMPTY_SHAPE.addProperty(LOCK_PROPERTY);
MUTEX_FACTORY = shape.createFactory();
}

public static Allocator createMutexAllocator(Shape emptyShape) {
Shape shape = emptyShape.addProperty(LOCK_PROPERTY);
final DynamicObjectFactory factory = shape.createFactory();

return new Allocator() {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBasicObject(rubyClass, factory.newInstance(new ReentrantLock()));
}
};
public static class MutexAllocator implements Allocator {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBasicObject(rubyClass, MUTEX_FACTORY.newInstance(new ReentrantLock()));
}
}

protected static ReentrantLock getLock(RubyBasicObject mutex) {
Original file line number Diff line number Diff line change
@@ -10,18 +10,22 @@
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.*;
import com.oracle.truffle.api.source.NullSourceSection;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.backtrace.Activation;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyBignum;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyString;

import java.math.BigInteger;
import java.util.EnumSet;
import java.util.concurrent.locks.ReentrantLock;

@@ -30,32 +34,17 @@ public class ThreadBacktraceLocationNodes {

private static final HiddenKey ACTIVATION_IDENTIFIER = new HiddenKey("activation");
private static final Property ACTIVATION_PROPERTY;
private static final DynamicObjectFactory THREAD_BACKTRACE_LOCATION_FACTORY;

static {
Shape.Allocator allocator = RubyBasicObject.LAYOUT.createAllocator();
ACTIVATION_PROPERTY = Property.create(ACTIVATION_IDENTIFIER, allocator.locationForType(Activation.class, EnumSet.of(LocationModifier.NonNull)), 0);
}

public static Allocator createThreadBacktraceLocationAllocator(Shape emptyShape) {
final Shape shape = emptyShape.addProperty(ACTIVATION_PROPERTY);
final DynamicObjectFactory factory = shape.createFactory();

return new Allocator() {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBasicObject(rubyClass, factory.newInstance(new ReentrantLock()));
}
};
ACTIVATION_PROPERTY = Property.create(ACTIVATION_IDENTIFIER, allocator.locationForType(Activation.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0);
final Shape shape = RubyBasicObject.EMPTY_SHAPE.addProperty(ACTIVATION_PROPERTY);
THREAD_BACKTRACE_LOCATION_FACTORY = shape.createFactory();
}

public static void setActivation(RubyBasicObject threadBacktraceLocation, Activation activation) {
assert threadBacktraceLocation.getDynamicObject().getShape().hasProperty(ACTIVATION_IDENTIFIER);

try {
ACTIVATION_PROPERTY.set(threadBacktraceLocation.getDynamicObject(), activation, threadBacktraceLocation.getDynamicObject().getShape());
} catch (IncompatibleLocationException | FinalLocationException e) {
throw new UnsupportedOperationException();
}
public static RubyBasicObject createRubyThreadBacktraceLocation(RubyClass rubyClass, Activation activation) {
return new RubyBasicObject(rubyClass, THREAD_BACKTRACE_LOCATION_FACTORY.newInstance(activation));
}

protected static Activation getActivation(RubyBasicObject threadBacktraceLocation) {
Original file line number Diff line number Diff line change
@@ -81,7 +81,6 @@ public class RubyContext extends ExecutionContext implements TruffleContextInter
private final ThreadManager threadManager;
private final AtExitManager atExitManager;
private final RubySymbol.SymbolTable symbolTable = new RubySymbol.SymbolTable(this);
private final Shape emptyShape;
private final Warnings warnings;
private final SafepointManager safepointManager;
private final Random random = new Random();
@@ -136,8 +135,6 @@ public RubyContext(Ruby runtime) {
// Object space manager needs to come early before we create any objects
objectSpaceManager = new ObjectSpaceManager(this);

emptyShape = RubyBasicObject.LAYOUT.createShape(new RubyObjectType(this));

coreLibrary = new CoreLibrary(this);
rootLexicalScope = new LexicalScope(null, coreLibrary.getObjectClass());
coreLibrary.initialize();
@@ -232,10 +229,6 @@ public RubyContext(Ruby runtime) {
}
}

public Shape getEmptyShape() {
return emptyShape;
}

public static String checkInstanceVariableName(RubyContext context, String name, Node currentNode) {
if (!name.startsWith("@")) {
throw new RaiseException(context.getCoreLibrary().nameErrorInstanceNameNotAllowable(name, currentNode));
Original file line number Diff line number Diff line change
@@ -13,7 +13,9 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.Source;

import jnr.constants.platform.Errno;

import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
import org.jcodings.transcode.EConvFlags;
@@ -149,6 +151,14 @@ private enum State {

private State state = State.INITIALIZING;

private final Allocator NO_ALLOCATOR = new Allocator() {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(typeError(String.format("allocator undefined for %s", rubyClass.getName()), currentNode));
}
};

public CoreLibrary(RubyContext context) {
this.context = context;

@@ -249,38 +259,38 @@ public CoreLibrary(RubyContext context) {

numericClass = defineClass("Numeric");
complexClass = defineClass(numericClass, "Complex");
floatClass = defineClass(numericClass, "Float");
integerClass = defineClass(numericClass, "Integer");
floatClass = defineClass(numericClass, "Float", NO_ALLOCATOR);
integerClass = defineClass(numericClass, "Integer", NO_ALLOCATOR);
fixnumClass = defineClass(integerClass, "Fixnum");
bignumClass = defineClass(integerClass, "Bignum", BignumNodes.createBigumAllocator(context.getEmptyShape()));
bignumClass = defineClass(integerClass, "Bignum");
rationalClass = defineClass(numericClass, "Rational");

// Classes defined in Object

arrayClass = defineClass("Array", new RubyArray.ArrayAllocator());
bindingClass = defineClass("Binding", new RubyBinding.BindingAllocator());
dirClass = defineClass("Dir");
encodingClass = defineClass("Encoding", new RubyEncoding.EncodingAllocator());
falseClass = defineClass("FalseClass");
encodingClass = defineClass("Encoding", NO_ALLOCATOR);
falseClass = defineClass("FalseClass", NO_ALLOCATOR);
fiberClass = defineClass("Fiber", new RubyFiber.FiberAllocator());
defineModule("FileTest");
hashClass = defineClass("Hash", new RubyHash.HashAllocator());
matchDataClass = defineClass("MatchData");
methodClass = defineClass("Method");
defineClass("Mutex", MutexNodes.createMutexAllocator(context.getEmptyShape()));
nilClass = defineClass("NilClass");
methodClass = defineClass("Method", NO_ALLOCATOR);
defineClass("Mutex", new MutexNodes.MutexAllocator());
nilClass = defineClass("NilClass", NO_ALLOCATOR);
procClass = defineClass("Proc", new RubyProc.ProcAllocator());
processModule = defineModule("Process");
rangeClass = defineClass("Range", new RubyRange.RangeAllocator());
regexpClass = defineClass("Regexp", new RubyRegexp.RegexpAllocator());
stringClass = defineClass("String", new RubyString.StringAllocator());
symbolClass = defineClass("Symbol");
symbolClass = defineClass("Symbol", NO_ALLOCATOR);
threadClass = defineClass("Thread", new RubyThread.ThreadAllocator());
threadBacktraceClass = defineClass(threadClass, objectClass, "Backtrace");
threadBacktraceLocationClass = defineClass(threadBacktraceClass, objectClass, "Location", ThreadBacktraceLocationNodes.createThreadBacktraceLocationAllocator(context.getEmptyShape()));
threadBacktraceLocationClass = defineClass(threadBacktraceClass, objectClass, "Location", NO_ALLOCATOR);
timeClass = defineClass("Time", new RubyTime.TimeAllocator());
trueClass = defineClass("TrueClass");
unboundMethodClass = defineClass("UnboundMethod");
trueClass = defineClass("TrueClass", NO_ALLOCATOR);
unboundMethodClass = defineClass("UnboundMethod", NO_ALLOCATOR);

// Modules

Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.*;

import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.DebugOperations;
import org.jruby.truffle.runtime.ModuleOperations;
@@ -34,6 +35,7 @@ public class RubyBasicObject implements TruffleObject {
public static final HiddenKey FROZEN_IDENTIFIER = new HiddenKey("frozen?");

public static final Layout LAYOUT = Layout.createLayout(Layout.INT_TO_LONG);
public static final Shape EMPTY_SHAPE = LAYOUT.createShape(new RubyObjectType());

private final DynamicObject dynamicObject;

@@ -43,14 +45,18 @@ public class RubyBasicObject implements TruffleObject {
@CompilationFinal protected RubyClass metaClass;

public RubyBasicObject(RubyClass rubyClass) {
this(rubyClass, LAYOUT.newInstance(rubyClass.getContext().getEmptyShape()));
this(rubyClass.getContext(), rubyClass);
}

public RubyBasicObject(RubyClass rubyClass, DynamicObject dynamicObject) {
this(rubyClass.getContext(), rubyClass, dynamicObject);
}

public RubyBasicObject(RubyContext context, RubyClass rubyClass, DynamicObject dynamicObject) {
protected RubyBasicObject(RubyContext context, RubyClass rubyClass) {
this(context, rubyClass, LAYOUT.newInstance(EMPTY_SHAPE));
}

private RubyBasicObject(RubyContext context, RubyClass rubyClass, DynamicObject dynamicObject) {
this.dynamicObject = dynamicObject;

if (rubyClass != null) {
Original file line number Diff line number Diff line change
@@ -91,15 +91,6 @@ public static RubyEncoding[] cloneEncodingList() {
return clone;
}

public static class EncodingAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
throw new UnsupportedOperationException();
}

}

@Override
public String toString() {
return getName().toString();
Original file line number Diff line number Diff line change
@@ -107,7 +107,7 @@ public RubyModule(RubyContext context, RubyModule lexicalParent, String name, No
}

protected RubyModule(RubyContext context, RubyClass selfClass, RubyModule lexicalParent, String name, Node currentNode) {
super(context, selfClass, LAYOUT.newInstance(context.getEmptyShape()));
super(context, selfClass);
this.context = context;

unmodifiedAssumption = new CyclicAssumption(name + " is unmodified");
Original file line number Diff line number Diff line change
@@ -23,12 +23,6 @@

public class RubyObjectType extends ObjectType {

private final RubyContext context;

public RubyObjectType(RubyContext context) {
this.context = context;
}

@CompilerDirectives.TruffleBoundary
public void setInstanceVariable(RubyBasicObject receiver, Object name, Object value) {
Shape shape = receiver.getDynamicObject().getShape();
@@ -54,7 +48,7 @@ public Object getInstanceVariable(RubyBasicObject receiver, Object name) {
if (property != null) {
return property.get(receiver.getDynamicObject(), false);
} else {
return context.getCoreLibrary().getNilObject();
return receiver.getContext().getCoreLibrary().getNilObject();
}
}