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: ae1d35e6c722
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ff30b4088075
Choose a head ref
  • 2 commits
  • 23 files changed
  • 1 contributor

Commits on Dec 25, 2014

  1. [Truffle] We used to have the object allocator in complicated subclas…

    …ses of RubyClass - now we have an interface that we can attach to any class.
    chrisseaton committed Dec 25, 2014
    Copy the full SHA
    a4ea0ce View commit details
  2. Copy the full SHA
    ff30b40 View commit details
Showing with 289 additions and 294 deletions.
  1. +1 −1 core/src/main/java/org/jruby/truffle/nodes/core/ClassNodes.java
  2. +7 −6 core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  3. +5 −4 core/src/main/java/org/jruby/truffle/nodes/core/ThreadNodes.java
  4. +22 −0 core/src/main/java/org/jruby/truffle/nodes/objects/Allocator.java
  5. +2 −7 core/src/main/java/org/jruby/truffle/nodes/objects/DefineOrGetClassNode.java
  6. +83 −39 core/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
  7. +9 −13 core/src/main/java/org/jruby/truffle/runtime/core/RubyArray.java
  8. +13 −0 core/src/main/java/org/jruby/truffle/runtime/core/RubyBasicObject.java
  9. +10 −13 core/src/main/java/org/jruby/truffle/runtime/core/RubyBignum.java
  10. +25 −21 core/src/main/java/org/jruby/truffle/runtime/core/RubyClass.java
  11. +11 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyEncoding.java
  12. +10 −13 core/src/main/java/org/jruby/truffle/runtime/core/RubyEncodingConverter.java
  13. +10 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyException.java
  14. +10 −13 core/src/main/java/org/jruby/truffle/runtime/core/RubyFiber.java
  15. +10 −13 core/src/main/java/org/jruby/truffle/runtime/core/RubyHash.java
  16. +10 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyModule.java
  17. +10 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyProc.java
  18. +11 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
  19. +10 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyString.java
  20. +10 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyThread.java
  21. +10 −18 core/src/main/java/org/jruby/truffle/runtime/core/RubyTime.java
  22. +0 −1 spec/truffle/tags/language/send_tags.txt
  23. +0 −6 spec/truffle/tags/language/variables_tags.txt
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ public RubyBasicObject allocate(RubyClass rubyClass) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError("can't create instance of singleton class", this));
}
return rubyClass.newInstance(this);
return rubyClass.allocate(this);
}

}
13 changes: 7 additions & 6 deletions core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -427,7 +427,7 @@ public CloneNode(CloneNode prev) {
public Object clone(VirtualFrame frame, RubyBasicObject self) {
notDesignedForCompilation();

final RubyBasicObject newObject = self.getLogicalClass().newInstance(this);
final RubyBasicObject newObject = self.getLogicalClass().allocate(this);

// Copy the singleton class if any.
if (self.getMetaClass().isSingleton()) {
@@ -462,7 +462,7 @@ public DupNode(DupNode prev) {
public Object dup(VirtualFrame frame, RubyBasicObject self) {
// This method is pretty crappy for compilation - it should improve with the OM

final RubyBasicObject newObject = self.getLogicalClass().newInstance(this);
final RubyBasicObject newObject = self.getLogicalClass().allocate(this);
newObject.getOperations().setInstanceVariables(newObject, self.getOperations().getInstanceVariables(self));
initializeDupNode.call(frame, newObject, "initialize_dup", null, self);

@@ -1517,14 +1517,15 @@ public Object raise(VirtualFrame frame, RubyClass exceptionClass, UndefinedPlace
public Object raise(VirtualFrame frame, RubyClass exceptionClass, RubyString message, Object undefined1) {
notDesignedForCompilation();

if (!(exceptionClass instanceof RubyException.RubyExceptionClass)) {
final Object exception = exceptionClass.allocate(this);
initialize.call(frame, exception, "initialize", null, message);

if (!(exception instanceof RubyException)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError("exception class/object expected", this));
}

final RubyException exception = ((RubyException.RubyExceptionClass) exceptionClass).newInstance(this);
initialize.call(frame, exception, "initialize", null, message);
throw new RaiseException(exception);
throw new RaiseException((RubyException) exception);
}

@Specialization
Original file line number Diff line number Diff line change
@@ -220,14 +220,15 @@ public RubyNilClass raise(VirtualFrame frame, RubyThread thread, RubyString mess

@Specialization
public RubyNilClass raise(VirtualFrame frame, final RubyThread thread, RubyClass exceptionClass, RubyString message) {
if (!(exceptionClass instanceof RubyException.RubyExceptionClass)) {
final Object exception = exceptionClass.allocate(this);
initialize.call(frame, exception, "initialize", null, message);

if (!(exception instanceof RubyException)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError("exception class/object expected", this));
}

final RubyException exception = ((RubyException.RubyExceptionClass) exceptionClass).newInstance(this);
initialize.call(frame, exception, "initialize", null, message);
final RaiseException exceptionWrapper = new RaiseException(exception);
final RaiseException exceptionWrapper = new RaiseException((RubyException) exception);

getContext().getSafepointManager().pauseAllThreadsAndExecute(new Consumer<Boolean>() {

22 changes: 22 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/objects/Allocator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2014 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.nodes.objects;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;

public interface Allocator {

// TODO(CS): do we need all these parameters?
RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode);

}
Original file line number Diff line number Diff line change
@@ -54,13 +54,8 @@ public Object execute(VirtualFrame frame) {
RubyClass superClassObject = getRubySuperClass(frame, context);

if (constant == null) {
if (superClassObject instanceof RubyException.RubyExceptionClass) {
definingClass = new RubyException.RubyExceptionClass(context, lexicalParent, superClassObject, name);
} else if (superClassObject instanceof RubyString.RubyStringClass) {
definingClass = new RubyString.RubyStringClass(context, lexicalParent, superClassObject, name);
} else {
definingClass = new RubyClass(context, lexicalParent, superClassObject, name);
}
definingClass = new RubyClass(context, lexicalParent, superClassObject, name);
definingClass.setAllocator(superClassObject.getAllocator());
callInherited(frame, superClassObject, definingClass);
} else {
if (constant.getValue() instanceof RubyClass) {
122 changes: 83 additions & 39 deletions core/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -151,10 +151,14 @@ public static boolean fitsIntoInteger(long value) {
public void initialize() {
// Create the cyclic classes and modules

classClass = new RubyClass.RubyClassClass(context);
classClass = new RubyClass(context, null, null, "Class", false);
classClass.setAllocator(new RubyClass.ClassAllocator());

basicObjectClass = RubyClass.createBootClass(context, "BasicObject");
objectClass = RubyClass.createBootClass(context, "Object");
moduleClass = new RubyModule.RubyModuleClass(context);

moduleClass = new RubyClass(context, null, null, "Module", false);
moduleClass.setAllocator(new RubyModule.ModuleAllocator());

// Close the cycles
classClass.unsafeSetLogicalClass(classClass);
@@ -177,63 +181,93 @@ public void initialize() {
numericClass = new RubyClass(context, objectClass, objectClass, "Numeric");
integerClass = new RubyClass(context, objectClass, numericClass, "Integer");

exceptionClass = new RubyException.RubyExceptionClass(context, objectClass, objectClass, "Exception");
standardErrorClass = new RubyException.RubyExceptionClass(context, objectClass, exceptionClass, "StandardError");
exceptionClass = new RubyClass(context, objectClass, objectClass, "Exception");
exceptionClass.setAllocator(new RubyException.ExceptionAllocator());

standardErrorClass = new RubyClass(context, objectClass, exceptionClass, "StandardError");
standardErrorClass.setAllocator(new RubyException.ExceptionAllocator());

ioClass = new RubyClass(context, objectClass, objectClass, "IO");

argumentErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "ArgumentError");
arrayClass = new RubyArray.RubyArrayClass(context, objectClass);
bignumClass = new RubyBignum.RubyBignumClass(context, objectClass, integerClass, "Bignum");
argumentErrorClass = new RubyClass(context, objectClass, standardErrorClass, "ArgumentError");
argumentErrorClass.setAllocator(new RubyException.ExceptionAllocator());
arrayClass = new RubyClass(context, objectClass, objectClass, "Array");
arrayClass.setAllocator(new RubyArray.ArrayAllocator());
bignumClass = new RubyClass(context, objectClass, integerClass, "Bignum");
bignumClass.setAllocator(new RubyBignum.BignumAllocator());
bindingClass = new RubyClass(context, objectClass, objectClass, "Binding");
comparableModule = new RubyModule(context, objectClass, "Comparable");
configModule = new RubyModule(context, objectClass, "Config");
continuationClass = new RubyClass(context, objectClass, objectClass, "Continuation");
dirClass = new RubyClass(context, objectClass, objectClass, "Dir");
encodingClass = new RubyEncoding.RubyEncodingClass(context, objectClass);
encodingClass = new RubyClass(context, objectClass, objectClass, "Encoding");
encodingClass.setAllocator(new RubyEncoding.EncodingAllocator());
errnoModule = new RubyModule(context, objectClass, "Errno");
enumerableModule = new RubyModule(context, objectClass, "Enumerable");
falseClass = new RubyClass(context, objectClass, objectClass, "FalseClass");
fiberClass = new RubyFiber.RubyFiberClass(context, objectClass);
fiberClass = new RubyClass(context, objectClass, objectClass, "Fiber");
fileClass = new RubyClass(context, objectClass, ioClass, "File");
fixnumClass = new RubyClass(context, objectClass, integerClass, "Fixnum");
floatClass = new RubyClass(context, objectClass, numericClass, "Float");
floatDomainErrorClass = new RubyException.RubyExceptionClass(context, objectClass, rangeErrorClass, "FloatDomainError");
floatDomainErrorClass = new RubyClass(context, objectClass, rangeErrorClass, "FloatDomainError");
floatDomainErrorClass.setAllocator(new RubyException.ExceptionAllocator());
gcModule = new RubyModule(context, objectClass, "GC");
hashClass = new RubyHash.RubyHashClass(context, objectClass);
indexErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "IndexError");
hashClass = new RubyClass(context, objectClass, objectClass, "Hash");
hashClass.setAllocator(new RubyHash.HashAllocator());
indexErrorClass = new RubyClass(context, objectClass, standardErrorClass, "IndexError");
indexErrorClass.setAllocator(new RubyException.ExceptionAllocator());
kernelModule = new RubyModule(context, objectClass, "Kernel");
keyErrorClass = new RubyException.RubyExceptionClass(context, objectClass, indexErrorClass, "KeyError");
loadErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "LoadError");
localJumpErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "LocalJumpError");
keyErrorClass = new RubyClass(context, objectClass, indexErrorClass, "KeyError");
keyErrorClass.setAllocator(new RubyException.ExceptionAllocator());
loadErrorClass = new RubyClass(context, objectClass, standardErrorClass, "LoadError");
loadErrorClass.setAllocator(new RubyException.ExceptionAllocator());
localJumpErrorClass = new RubyClass(context, objectClass, standardErrorClass, "LocalJumpError");
localJumpErrorClass.setAllocator(new RubyException.ExceptionAllocator());
matchDataClass = new RubyClass(context, objectClass, objectClass, "MatchData");
mathModule = new RubyModule(context, objectClass, "Math");
nameErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "NameError");
nameErrorClass = new RubyClass(context, objectClass, standardErrorClass, "NameError");
nameErrorClass.setAllocator(new RubyException.ExceptionAllocator());
nilClass = new RubyClass(context, objectClass, objectClass, "NilClass");
noMethodErrorClass = new RubyException.RubyExceptionClass(context, objectClass, nameErrorClass, "NoMethodError");
noMethodErrorClass = new RubyClass(context, objectClass, nameErrorClass, "NoMethodError");
noMethodErrorClass.setAllocator(new RubyException.ExceptionAllocator());
objectSpaceModule = new RubyModule(context, objectClass, "ObjectSpace");
procClass = new RubyProc.RubyProcClass(context, objectClass);
procClass = new RubyClass(context, objectClass, objectClass, "Proc");
procClass.setAllocator(new RubyProc.ProcAllocator());
processClass = new RubyClass(context, objectClass, objectClass, "Process");
rangeClass = new RubyClass(context, objectClass, objectClass, "Range");
rangeErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "RangeError");
regexpClass = new RubyRegexp.RubyRegexpClass(context, objectClass);
regexpErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "RegexpError");
rubyTruffleErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "RubyTruffleError");
runtimeErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "RuntimeError");
rangeErrorClass = new RubyClass(context, objectClass, standardErrorClass, "RangeError");
rangeErrorClass.setAllocator(new RubyException.ExceptionAllocator());
regexpClass = new RubyClass(context, objectClass, objectClass, "Regexp");
regexpClass.setAllocator(new RubyRegexp.RegexpAllocator());
regexpErrorClass = new RubyClass(context, objectClass, standardErrorClass, "RegexpError");
regexpErrorClass.setAllocator(new RubyException.ExceptionAllocator());
rubyTruffleErrorClass = new RubyClass(context, objectClass, standardErrorClass, "RubyTruffleError");
rubyTruffleErrorClass.setAllocator(new RubyException.ExceptionAllocator());
runtimeErrorClass = new RubyClass(context, objectClass, standardErrorClass, "RuntimeError");
runtimeErrorClass.setAllocator(new RubyException.ExceptionAllocator());
signalModule = new RubyModule(context, objectClass, "Signal");
stringClass = new RubyString.RubyStringClass(context, objectClass, objectClass, "String");
stringClass = new RubyClass(context, objectClass, objectClass, "String");
stringClass.setAllocator(new RubyString.StringAllocator());
symbolClass = new RubyClass(context, objectClass, objectClass, "Symbol");
syntaxErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "SyntaxError");
systemCallErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "SystemCallError");
systemExitClass = new RubyException.RubyExceptionClass(context, objectClass, exceptionClass, "SystemExit");
threadClass = new RubyThread.RubyThreadClass(context, objectClass);
timeClass = new RubyTime.RubyTimeClass(context, objectClass);
syntaxErrorClass = new RubyClass(context, objectClass, standardErrorClass, "SyntaxError");
syntaxErrorClass.setAllocator(new RubyException.ExceptionAllocator());
systemCallErrorClass = new RubyClass(context, objectClass, standardErrorClass, "SystemCallError");
systemCallErrorClass.setAllocator(new RubyException.ExceptionAllocator());
systemExitClass = new RubyClass(context, objectClass, exceptionClass, "SystemExit");
systemExitClass.setAllocator(new RubyException.ExceptionAllocator());
threadClass = new RubyClass(context, objectClass, objectClass, "Thread");
threadClass.setAllocator(new RubyThread.ThreadAllocator());
timeClass = new RubyClass(context, objectClass, objectClass, "Time");
timeClass.setAllocator(new RubyTime.TimeAllocator());
trueClass = new RubyClass(context, objectClass, objectClass, "TrueClass");
truffleModule = new RubyModule(context, objectClass, "Truffle");
truffleDebugModule = new RubyModule(context, truffleModule, "Debug");
typeErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "TypeError");
zeroDivisionErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "ZeroDivisionError");
encodingConverterClass = new RubyEncodingConverter.RubyEncodingConverterClass(context, encodingClass, objectClass);
typeErrorClass = new RubyClass(context, objectClass, standardErrorClass, "TypeError");
typeErrorClass.setAllocator(new RubyException.ExceptionAllocator());
zeroDivisionErrorClass = new RubyClass(context, objectClass, standardErrorClass, "ZeroDivisionError");
zeroDivisionErrorClass.setAllocator(new RubyException.ExceptionAllocator());
encodingConverterClass = new RubyClass(context, encodingClass, objectClass, "Converter");
encodingConverterClass.setAllocator(new RubyEncodingConverter.EncodingConverterAllocator());

// Includes

@@ -248,13 +282,23 @@ public void initialize() {
objectClass.setConstant(null, "RUBY_ENGINE", RubyString.fromJavaString(stringClass, Constants.ENGINE + "+truffle"));
objectClass.setConstant(null, "RUBY_PLATFORM", RubyString.fromJavaString(stringClass, Constants.PLATFORM));

edomClass = new RubyException.RubyExceptionClass(context, errnoModule, systemCallErrorClass, "EDOM");
new RubyClass(context, errnoModule, systemCallErrorClass, "ENOENT");
new RubyClass(context, errnoModule, systemCallErrorClass, "EPERM");
new RubyClass(context, errnoModule, systemCallErrorClass, "ENOTEMPTY");
new RubyClass(context, errnoModule, systemCallErrorClass, "EEXIST");
new RubyClass(context, errnoModule, systemCallErrorClass, "EXDEV");
new RubyClass(context, errnoModule, systemCallErrorClass, "EACCES");
edomClass = new RubyClass(context, errnoModule, systemCallErrorClass, "EDOM");
edomClass.setAllocator(new RubyException.ExceptionAllocator());

RubyClass tempClass;

tempClass = new RubyClass(context, errnoModule, systemCallErrorClass, "ENOENT");
tempClass.setAllocator(new RubyException.ExceptionAllocator());
tempClass = new RubyClass(context, errnoModule, systemCallErrorClass, "EPERM");
tempClass.setAllocator(new RubyException.ExceptionAllocator());
tempClass = new RubyClass(context, errnoModule, systemCallErrorClass, "ENOTEMPTY");
tempClass.setAllocator(new RubyException.ExceptionAllocator());
tempClass = new RubyClass(context, errnoModule, systemCallErrorClass, "EEXIST");
tempClass.setAllocator(new RubyException.ExceptionAllocator());
tempClass = new RubyClass(context, errnoModule, systemCallErrorClass, "EXDEV");
tempClass.setAllocator(new RubyException.ExceptionAllocator());
tempClass = new RubyClass(context, errnoModule, systemCallErrorClass, "EACCES");
tempClass.setAllocator(new RubyException.ExceptionAllocator());

// TODO(cs): this should be a separate exception
mathModule.setConstant(null, "DomainError", edomClass);
22 changes: 9 additions & 13 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyArray.java
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import com.oracle.truffle.api.CompilerDirectives;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ArrayAllocationSite;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.subsystems.ObjectSpaceManager;
import org.jruby.truffle.runtime.util.ArrayUtils;
@@ -27,19 +28,6 @@ public final class RubyArray extends RubyBasicObject {

public static final int ARRAYS_SMALL = Options.TRUFFLE_ARRAYS_SMALL.load();

public static class RubyArrayClass extends RubyClass {

public RubyArrayClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Array");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyArray(this);
}

}

private final ArrayAllocationSite allocationSite;
private Object store;
private int size;
@@ -283,5 +271,13 @@ public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visit
}
}

public static class ArrayAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyArray(rubyClass);
}

}

}
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
import com.oracle.truffle.api.object.Property;
import com.oracle.truffle.api.object.Shape;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.InternalName;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyContext;
@@ -195,4 +196,16 @@ public RubyClass getLogicalClass() {
public DynamicObject getDynamicObject() {
return dynamicObject;
}

public static class BasicObjectAllocator implements Allocator {

// TODO(CS): why on earth is this a boundary? Seems like a really bad thing.
@CompilerDirectives.TruffleBoundary
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyBasicObject(rubyClass);
}

}

}
23 changes: 10 additions & 13 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -11,25 +11,13 @@

import com.oracle.truffle.api.CompilerDirectives;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;

import java.math.BigInteger;

public class RubyBignum extends RubyBasicObject {

public static class RubyBignumClass extends RubyClass {

public RubyBignumClass(RubyContext context, RubyModule lexicalParent, RubyClass superclass, String name) {
super(context, lexicalParent, superclass, name);
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyBignum(this, BigInteger.ZERO);
}

}

private BigInteger value;

public RubyBignum(RubyClass rubyClass, BigInteger value) {
@@ -227,4 +215,13 @@ public int hashCode() {
return value.hashCode();
}

public static class BignumAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyBignum(rubyClass, BigInteger.ZERO);
}

}

}
46 changes: 25 additions & 21 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyClass.java
Original file line number Diff line number Diff line change
@@ -12,9 +12,11 @@
import java.util.*;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.*;
import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.*;

/**
@@ -23,27 +25,12 @@
*/
public class RubyClass extends RubyModule {

// TODO(CS): is this compilation final needed? Is it a problem for correctness?
@CompilationFinal Allocator allocator = new RubyBasicObject.BasicObjectAllocator();

private boolean isSingleton;
private final Set<RubyClass> subClasses = Collections.newSetFromMap(new WeakHashMap<RubyClass, Boolean>());

/**
* The class from which we create the object that is {@code Class}. A subclass of
* {@link RubyClass} so that we can override {@link #newInstance} and allocate a
* {@link RubyClass} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyClassClass extends RubyClass {

public RubyClassClass(RubyContext context) {
super(context, null, null, "Class", false);
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyClass(getContext(), null, null, null, false);
}

}

/**
* This constructor supports initialization and solves boot-order problems and should not
* normally be used from outside this class.
@@ -73,9 +60,14 @@ protected RubyClass(RubyContext context, RubyModule lexicalParent, RubyClass sup
}
}

public void setAllocator(Allocator allocator) {
this.allocator = allocator;
}

public void initialize(RubyClass superclass) {
unsafeSetSuperclass(superclass);
ensureSingletonConsistency();
allocator = superclass.allocator;
}

@Override
@@ -133,9 +125,8 @@ public void unsafeSetSuperclass(RubyClass newSuperclass) {
newVersion();
}

@TruffleBoundary
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyBasicObject(this);
public RubyBasicObject allocate(RubyNode currentNode) {
return allocator.allocate(getContext(), this, currentNode);
}

public boolean isSingleton() {
@@ -154,4 +145,17 @@ public RubyClass getSuperClass() {
return null;
}

public Allocator getAllocator() {
return allocator;
}

public static class ClassAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyClass(context, null, null, null, false);
}

}

}
29 changes: 11 additions & 18 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyEncoding.java
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.util.ByteList;

@@ -30,24 +31,6 @@ public class RubyEncoding extends RubyBasicObject {
private final ByteList name;
private final boolean dummy;

/**
* The class from which we create the object that is {@code Encoding}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance} and allocate a
* {@link RubyEncoding} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyEncodingClass extends RubyClass {

public RubyEncodingClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Encoding");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
throw new UnsupportedOperationException();
}

}

public static synchronized RubyEncoding getEncoding(RubyContext context, Encoding encoding) {
return lookup.get(new String(encoding.getName()).toLowerCase());
}
@@ -99,4 +82,14 @@ public static RubyEncoding[] cloneEncodingList() {

return clone;
}

public static class EncodingAllocator implements Allocator {

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

}

}
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@

import org.jcodings.transcode.EConv;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;

public class RubyEncodingConverter extends RubyBasicObject {
@@ -19,19 +20,6 @@ public EConv getEConv() {
return econv;
}

public static class RubyEncodingConverterClass extends RubyClass {

public RubyEncodingConverterClass(RubyContext context, RubyClass encodingClass, RubyClass objectClass) {
super(context, encodingClass, objectClass, "Converter");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyEncodingConverter(this, null);
}

}

private EConv econv;

public RubyEncodingConverter(RubyClass rubyClass, EConv econv) {
@@ -43,4 +31,13 @@ public void setEConv(EConv econv) {
this.econv = econv;
}

public static class EncodingConverterAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyEncodingConverter(rubyClass, null);
}

}

}
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.runtime.core;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.backtrace.Backtrace;

@@ -18,24 +19,6 @@
*/
public class RubyException extends RubyBasicObject {

/**
* The class from which we create the object that is {@code Exception}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance} and allocate a
* {@link RubyException} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyExceptionClass extends RubyClass {

public RubyExceptionClass(RubyContext context, RubyModule lexicalParent, RubyClass superClass, String name) {
super(context, lexicalParent, superClass, name);
}

@Override
public RubyException newInstance(RubyNode currentNode) {
return new RubyException(this);
}

}

private RubyString message;
private Backtrace backtrace;

@@ -77,4 +60,13 @@ public RubyArray asRubyStringArray() {
return RubyArray.fromObjects(getContext().getCoreLibrary().getArrayClass(), array);
}

public static class ExceptionAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyException(rubyClass);
}

}

}
23 changes: 10 additions & 13 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyFiber.java
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@

import com.oracle.truffle.api.nodes.*;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.subsystems.*;

@@ -25,19 +26,6 @@
*/
public class RubyFiber extends RubyBasicObject {

public static class RubyFiberClass extends RubyClass {

public RubyFiberClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Fiber");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyFiber(this, getContext().getFiberManager(), getContext().getThreadManager());
}

}

private interface FiberMessage {
}

@@ -177,4 +165,13 @@ public void shutdown() {
messageQueue.add(new FiberExitMessage());
}

public static class FiberAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyFiber(rubyClass, context.getFiberManager(), context.getThreadManager());
}

}

}
23 changes: 10 additions & 13 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyHash.java
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.runtime.core;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.hash.Entry;
import org.jruby.truffle.runtime.hash.KeyValue;
@@ -18,19 +19,6 @@

public class RubyHash extends RubyBasicObject {

public static class RubyHashClass extends RubyClass {

public RubyHashClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Hash");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyHash(this, null, null, null, 0, null);
}

}

private RubyProc defaultBlock;
private Object defaultValue;
private Object store;
@@ -111,4 +99,13 @@ public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visit
}
}

public static class HashAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyHash(rubyClass, null, null, null, 0, null);
}

}

}
28 changes: 10 additions & 18 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyModule.java
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
import com.oracle.truffle.api.utilities.CyclicAssumption;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.methods.RubyMethod;
@@ -108,24 +109,6 @@ public static void debugModuleChain(RubyModule module) {
*/
private final Set<RubyModule> lexicalDependents = Collections.newSetFromMap(new WeakHashMap<RubyModule, Boolean>());

/**
* The class from which we create the object that is {@code Module}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance(org.jruby.truffle.nodes.RubyNode)}} and allocate a
* {@link RubyModule} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyModuleClass extends RubyClass {

public RubyModuleClass(RubyContext context) {
super(context, null, null, "Module", false);
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyModule(getContext(), null, null);
}

}

public RubyModule(RubyContext context, RubyModule lexicalParent, String name) {
this(context, lexicalParent, name, null);
}
@@ -538,4 +521,13 @@ public LexicalScope getLexicalScope() {
return lexicalScope;
}

public static class ModuleAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyModule(context, null, null);
}

}

}
28 changes: 10 additions & 18 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyProc.java
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.frame.MaterializedFrame;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.methods.*;
@@ -27,24 +28,6 @@ public class RubyProc extends RubyBasicObject implements MethodLike {

public static final boolean PROC_BINDING = Options.TRUFFLE_PROC_BINDING.load();

/**
* The class from which we create the object that is {@code Proc}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance} and allocate a
* {@link RubyProc} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyProcClass extends RubyClass {

public RubyProcClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Proc");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyProc(this, Type.PROC);
}

}

public static enum Type {
PROC, LAMBDA
}
@@ -145,4 +128,13 @@ public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visit
getContext().getObjectSpaceManager().visitFrame(declarationFrame, visitor);
}

public static class ProcAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyProc(rubyClass, Type.PROC);
}

}

}
29 changes: 11 additions & 18 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
import org.joni.exception.SyntaxException;
import org.joni.exception.ValueException;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.util.ByteList;
@@ -36,24 +37,7 @@
*/
public class RubyRegexp extends RubyBasicObject {

/**
* The class from which we create the object that is {@code Regexp}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance} and allocate a
* {@link RubyRegexp} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyRegexpClass extends RubyClass {

public RubyRegexpClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Regexp");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyRegexp(getContext().getCoreLibrary().getRegexpClass());
}

}

// TODO(CS): not sure these compilation finals are correct - are they needed anyway?
@CompilationFinal private Regex regex;
@CompilationFinal private ByteList source;

@@ -471,4 +455,13 @@ public RubyEncoding getEncoding() {
return encoding;
}

public static class RegexpAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyRegexp(context.getCoreLibrary().getRegexpClass());
}

}

}
28 changes: 10 additions & 18 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyString.java
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import org.jcodings.specific.UTF8Encoding;
import org.jruby.runtime.Helpers;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;
@@ -23,24 +24,6 @@
*/
public class RubyString extends RubyBasicObject {

/**
* The class from which we create the object that is {@code String}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance} and allocate a
* {@link RubyString} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyStringClass extends RubyClass {

public RubyStringClass(RubyContext context, RubyModule lexicalParent, RubyClass superclass, String name) {
super(context, lexicalParent, superclass, name);
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyString(this, new ByteList());
}

}

private ByteList bytes;

public RubyString(RubyClass stringClass, ByteList bytes) {
@@ -175,4 +158,13 @@ public int clampExclusiveIndex(int index) {
return RubyArray.clampExclusiveIndex(bytes.length(), index);
}

public static class StringAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyString(rubyClass, new ByteList());
}

}

}
28 changes: 10 additions & 18 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyThread.java
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
import org.jcodings.util.Hash;
import org.jruby.RubyThread.Status;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.control.ReturnException;
@@ -40,24 +41,6 @@ public RubyException getException() {
public void shutdown() {
}

/**
* The class from which we create the object that is {@code Thread}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance} and allocate a
* {@link RubyThread} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyThreadClass extends RubyClass {

public RubyThreadClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Thread");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyThread(this, getContext().getThreadManager());
}

}

private final ThreadManager manager;

private final CountDownLatch finished = new CountDownLatch(1);
@@ -149,4 +132,13 @@ public RubyBasicObject getThreadLocals() {
return threadLocals;
}

public static class ThreadAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyThread(rubyClass, context.getThreadManager());
}

}

}
28 changes: 10 additions & 18 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyTime.java
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.runtime.core;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import java.util.Date;

@@ -20,24 +21,6 @@

public class RubyTime extends RubyBasicObject {

/**
* The class from which we create the object that is {@code Time}. A subclass of
* {@link RubyClass} so that we can override {@link RubyClass#newInstance} and allocate a
* {@link RubyTime} rather than a normal {@link RubyBasicObject}.
*/
public static class RubyTimeClass extends RubyClass {

public RubyTimeClass(RubyContext context, RubyClass objectClass) {
super(context, objectClass, objectClass, "Time");
}

@Override
public RubyBasicObject newInstance(RubyNode currentNode) {
return new RubyTime(this, milisecondsToSeconds(System.currentTimeMillis()), milisecondsToNanoseconds(System.currentTimeMillis()));
}

}

private long seconds;
private long nanoseconds;
private boolean isdst;
@@ -99,4 +82,13 @@ public static long secondsToMiliseconds(long seconds) {
return seconds * 1000;
}

public static class TimeAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyTime(rubyClass, milisecondsToSeconds(System.currentTimeMillis()), milisecondsToNanoseconds(System.currentTimeMillis()));
}

}

}
1 change: 0 additions & 1 deletion spec/truffle/tags/language/send_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:Invoking a method expands an array to arguments grouped in parentheses which in turn takes rest arguments
fails:Invoking a method converts a final splatted explicit Hash to an Array
6 changes: 0 additions & 6 deletions spec/truffle/tags/language/variables_tags.txt
Original file line number Diff line number Diff line change
@@ -4,12 +4,9 @@ fails:Multiple assignment with a single RHS value does not call #to_ary if #resp
fails:Multiple assignment with a single RHS value wraps the Object in an Array if #to_ary returns nil
fails:Multiple assignment with a single RHS value raises a TypeError of #to_ary does not return an Array
fails:Multiple assignment with a single RHS value does not call #to_a to convert an Object RHS when assigning a simple MLHS
fails:Multiple assignment with a single RHS value does not call #to_ary on an Array subclass instance
fails:Multiple assignment with a single RHS value does not call #to_a on an Array subclass instance
fails:Multiple assignment with a single RHS value assigns a single LHS splat
fails:Multiple assignment with a single RHS value calls #to_ary to convert an Object RHS
fails:Multiple assignment with a single RHS value raises a TypeError if #to_ary does not return an Array
fails:Multiple assignment with a single RHS value does not call #to_ary on an Array subclass
fails:Multiple assignment with a single RHS value assigns an Array when the RHS is an Array subclass
fails:Multiple assignment with a single RHS value calls #to_ary to convert an Object RHS with MLHS
fails:Multiple assignment with a single RHS value does not call #to_a to convert an Object RHS with a MLHS
@@ -21,7 +18,6 @@ fails:Multiple assignment with a single RHS value calls #to_ary on the value ret
fails:Multiple assignment with a single RHS value assigns global variables
fails:Multiple assignment with a single RHS value assigns indexed elements
fails:Multiple assignment with a single splatted RHS value calls #to_a to convert nil to an empty Array
fails:Multiple assignment with a single splatted RHS value returns an Array when the splatted object is an Array subclass
fails:Multiple assignment with a single splatted RHS value does not call #to_a if #respond_to? returns false
fails:Multiple assignment with a single splatted RHS value assigns a MLHS with leading splat
fails:Multiple assignment with a single splatted RHS value calls #to_a to convert an Object RHS with MLHS
@@ -38,5 +34,3 @@ fails:Multiple assignment with a MRHS value calls #to_ary to convert a splatted
fails:Multiple assignment with a MRHS value does not call #to_ary to convert an Object when the position receiving the value is a rest variable
fails:Multiple assignment with a MRHS value does not call #to_ary to convert a splatted Object when the position receiving the value is a simple variable
fails:Multiple assignment with a RHS assignment value does not mutate a RHS Array
fails:Multiple assignment with a single splatted RHS value does not call #to_a on an Array subclass
fails:Multiple assignment with a single RHS value returns the RHS when it is an Array subclass