Skip to content

Commit

Permalink
Showing 50 changed files with 334 additions and 214 deletions.
14 changes: 11 additions & 3 deletions core/src/main/java/org/jruby/ir/IRClosure.java
Original file line number Diff line number Diff line change
@@ -26,18 +26,22 @@ public class IRClosure extends IRScope {

private int nestingDepth; // How many nesting levels within a method is this closure nested in?

private BlockBody body;

private boolean isBeginEndBlock;

// Block parameters
private List<Operand> blockArgs;

/** The parameter names, for Proc#parameters */
private String[] parameterList;

private Arity arity;
private int argumentType;
public boolean addedGEBForUncaughtBreaks;

/** Added for interp/JIT purposes */
private BlockBody body;

/** Added for JIT purposes */
private Handle handle;

// Used by other constructions and by IREvalScript as well
@@ -285,7 +289,11 @@ public int getNestingDepth() {

protected IRClosure cloneForInlining(CloneInfo ii, IRClosure clone) {
clone.nestingDepth = this.nestingDepth;
clone.parameterList = this.parameterList;
// FIXME: This is fragile. Untangle this state.
// Why is this being copied over to InterpretedIRBlockBody?
clone.setParameterList(this.parameterList);
clone.addedGEBForUncaughtBreaks = this.addedGEBForUncaughtBreaks;
clone.isBeginEndBlock = this.isBeginEndBlock;

SimpleCloneInfo clonedII = ii.cloneForCloningClosure(clone);

73 changes: 42 additions & 31 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -19,7 +19,9 @@
import org.jruby.ir.representations.BasicBlock;
import org.jruby.ir.representations.CFG;
import org.jruby.ir.representations.CFGLinearizer;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.ir.transformations.inlining.CFGInliner;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
@@ -111,7 +113,6 @@ public abstract class IRScope implements ParseResult {

private Instr[] linearizedInstrArray;
private List<BasicBlock> linearizedBBList;
private Map<Integer, Integer> rescueMap;
protected int temporaryVariableIndex;
protected int floatVariableIndex;
protected int fixnumVariableIndex;
@@ -475,56 +476,71 @@ private synchronized Instr[] prepareInstructions() {

setupLinearization();

// Set up IPCs
SimpleCloneInfo cloneInfo = new SimpleCloneInfo(this, false);
// Clear old set
initNestedClosures();

// FIXME: If CFG (or linearizedBBList) knew number of instrs we could end up allocing better

// Pass 1. Set up IPCs for labels and instructions and build linear instr list
List<Instr> newInstrs = new ArrayList<Instr>();
HashMap<Label, Integer> labelIPCMap = new HashMap<Label, Integer>();
int ipc = 0;
for (BasicBlock b: linearizedBBList) {
// All same-named labels must be same Java instance for this to work or we would need
// to examine all Label operands and update this as well which would be expensive.
Label l = b.getLabel();
labelIPCMap.put(l, ipc);
// This assumes if multiple equal/same labels exist which are scattered around the scope
// must be the same Java instance or only this one will get a targetPC set.
Label newL = cloneInfo.getRenamedLabel(l);
l.setTargetPC(ipc);
newL.setTargetPC(ipc);

List<Instr> bbInstrs = b.getInstrs();
int bbInstrsLength = bbInstrs.size();
for (int i = 0; i < bbInstrsLength; i++) {
Instr instr = bbInstrs.get(i);

if (instr instanceof Specializeable) {
instr = ((Specializeable) instr).specializeForInterpretation();
bbInstrs.set(i, instr);
}

if (!(instr instanceof ReceiveSelfInstr)) {
newInstrs.add(instr);
instr.setIPC(ipc);
Instr newInstr = instr.clone(cloneInfo);
// if (newInstr == instr) {
// System.out.println("Instruction " + instr.getOperation() + " returns itself on clone. Probably fragile!");
// }

if (newInstr instanceof Specializeable) {
newInstr = ((Specializeable) newInstr).specializeForInterpretation();
// Make sure debug CFG is identical to interpreted instr output
if (IRRuntimeHelpers.isDebug()) {
bbInstrs.set(i, ((Specializeable) instr).specializeForInterpretation());
}
}

newInstrs.add(newInstr);
newInstr.setIPC(ipc);
ipc++;
}
}
}

cfg().getExitBB().getLabel().setTargetPC(ipc + 1); // Exit BB ipc

// System.out.println("SCOPE: " + getName());
// System.out.println("INSTRS: " + cfg().toStringInstrs());

// Exit BB ipc
cfg().getExitBB().getLabel().setTargetPC(ipc + 1);

// Set up rescue map
setupRescueMap();

linearizedInstrArray = newInstrs.toArray(new Instr[newInstrs.size()]);
return linearizedInstrArray;
}

public void setupRescueMap() {
this.rescueMap = new HashMap<Integer, Integer>();
// Pass 2: Use ipc info from previous to mark all linearized instrs rpc
ipc = 0;
for (BasicBlock b : linearizedBBList) {
BasicBlock rescuerBB = cfg().getRescuerBBFor(b);
int rescuerPC = (rescuerBB == null) ? -1 : rescuerBB.getLabel().getTargetPC();
for (Instr i : b.getInstrs()) {
rescueMap.put(i.getIPC(), rescuerPC);
for (Instr instr : b.getInstrs()) {
// FIXME: If we did not omit instrs from previous pass we could end up just doing a
// a size and for loop this n times instead of walking an examining each instr
if (!(instr instanceof ReceiveSelfInstr)) {
linearizedInstrArray[ipc].setRPC(rescuerPC);
ipc++;
}
}
}

return linearizedInstrArray;
}

private boolean isUnsafeScope() {
@@ -1079,10 +1095,6 @@ public List<BasicBlock> buildLinearization() {
return linearizedBBList;
}

public Map<Integer, Integer> getRescueMap() {
return this.rescueMap;
}

public List<BasicBlock> linearization() {
depends(cfg());

@@ -1118,7 +1130,6 @@ public void resetState() {
flags.remove(HAS_NONLOCAL_RETURNS);
flags.remove(CAN_RECEIVE_BREAKS);
flags.remove(CAN_RECEIVE_NONLOCAL_RETURNS);
rescueMap = null;

// Invalidate compiler pass state.
//
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/instructions/BreakInstr.java
Original file line number Diff line number Diff line change
@@ -92,9 +92,9 @@ public Instr clone(CloneInfo info) {
}

return new BreakInstr(returnValue.cloneForInlining(ii), scopeName);
} else {
throw new UnsupportedOperationException("Break instructions shouldn't show up outside closures.");
}

return super.clone(ii);
}

@Override
16 changes: 12 additions & 4 deletions core/src/main/java/org/jruby/ir/instructions/Instr.java
Original file line number Diff line number Diff line change
@@ -33,7 +33,8 @@
public abstract class Instr {
public static final Operand[] EMPTY_OPERANDS = new Operand[] {};

private int ipc;
private int ipc; // Interpreter-only: instruction pointer
private int rpc; // Interpreter-only: rescue pointer
private final Operation operation;
// Is this instruction live or dead? During optimization passes, if this instruction
// causes no side-effects and the result of the instruction is not needed by anyone else,
@@ -43,6 +44,7 @@ public abstract class Instr {

public Instr(Operation operation) {
this.ipc = -1;
this.rpc = -1;
this.operation = operation;
}

@@ -56,10 +58,18 @@ public Operation getOperation() {
return operation;
}

@Interp
public int getIPC() { return ipc; }

@Interp
public void setIPC(int ipc) { this.ipc = ipc; }

@Interp
public int getRPC() { return rpc; }

@Interp
public void setRPC(int rpc) { this.rpc = rpc; }

// Does this instruction have side effects as a result of its operation
// This information is used in optimization phases to impact dead code elimination
// and other optimization passes
@@ -167,9 +177,7 @@ public void renameVars(Map<Operand, Operand> renameMap) {
* args and return values.
* @return a new instruction that can be used in the target scope.
*/
public Instr clone(CloneInfo info) {
throw new RuntimeException("clone: Not implemented for: " + this.getOperation());
}
public abstract Instr clone(CloneInfo info);

/**
* This method takes as input a map of operands to their values, and outputs
Original file line number Diff line number Diff line change
@@ -29,8 +29,8 @@ public String toString() {

@Override
public Instr clone(CloneInfo ii) {
// SSS FIXME: This is buggy! 'scope' might have changed because of cloning.
return this;
// Use original scope even if inlined -- so debugging / stack-traces are meaningful
return new LineNumberInstr(scope, lineNumber);
}

@Override
Original file line number Diff line number Diff line change
@@ -47,9 +47,9 @@ public Instr clone(CloneInfo info) {
}

return new NonlocalReturnInstr(returnValue.cloneForInlining(ii), methodName, maybeLambda);
} else {
throw new UnsupportedOperationException("Nonlocal returns shouldn't show up outside closures.");
}

return super.clone(ii);
}

@Override
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ public int getRest() {

@Override
public Instr clone(CloneInfo ii) {
return this;
return new RaiseArgumentErrorInstr(required, opt, rest, numArgs);
}

@Override
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
@@ -25,6 +26,11 @@ public Operand[] getOperands() {
return new Operand[0];
}

@Override
public Instr clone(CloneInfo ii) {
return new RaiseRequiredKeywordArgumentError(name);
}

@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
throw context.runtime.newArgumentError("missing keyword: " + name);
Original file line number Diff line number Diff line change
@@ -3,8 +3,9 @@
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.transformations.inlining.CloneInfo;

public class ReceiveExceptionBase extends Instr implements ResultInstr, FixedArityInstr {
public abstract class ReceiveExceptionBase extends Instr implements ResultInstr, FixedArityInstr {
protected Variable result;

public ReceiveExceptionBase(Operation op, Variable result) {
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package org.jruby.ir.instructions;

import org.jruby.ir.IRVisitor;
import org.jruby.ir.Interp;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

public class ReceiveSelfInstr extends Instr implements ResultInstr, FixedArityInstr {
private Variable result;
Original file line number Diff line number Diff line change
@@ -26,10 +26,10 @@ public Operand[] getOperands() {

@Override
public Instr clone(CloneInfo ii) {
if (ii instanceof SimpleCloneInfo) return this;
if (ii instanceof SimpleCloneInfo) return new ThreadPollInstr(onBackEdge);

// Get rid of non-back-edge thread-poll instructions when scopes are inlined
return onBackEdge ? this : null;
return onBackEdge ? new ThreadPollInstr(onBackEdge) : null;
}

@Override
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
import org.jruby.ir.instructions.ResultInstr;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.transformations.inlining.CloneInfo;

import java.util.Map;

@@ -44,4 +45,9 @@ public void simplifyOperands(Map<Operand, Operand> valueMap, boolean force) {
public String toString() {
return getResult() + " = " + getOperation() + "(" + val + ")";
}

@Override
public Instr clone(CloneInfo info) {
throw new UnsupportedOperationException();
}
}
7 changes: 2 additions & 5 deletions core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
Original file line number Diff line number Diff line change
@@ -510,11 +510,8 @@ private static void processOtherOp(ThreadContext context, Instr instr, Operation
}

private static IRubyObject interpret(ThreadContext context, IRubyObject self,
IRScope scope, Visibility visibility, RubyModule implClass, String name, IRubyObject[] args, Block block, Block.Type blockType)
{
IRScope scope, Visibility visibility, RubyModule implClass, String name, IRubyObject[] args, Block block, Block.Type blockType) {
Instr[] instrs = scope.getInstrsForInterpretation(blockType == Block.Type.LAMBDA);
Map<Integer, Integer> rescueMap = scope.getRescueMap();

int numTempVars = scope.getTemporaryVariablesCount();
Object[] temp = numTempVars > 0 ? new Object[numTempVars] : null;
int numFloatVars = scope.getFloatVariablesCount();
@@ -598,7 +595,7 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
extractToMethodToAvoidC2Crash(context, instr, t);

if (debug) LOG.info("in scope: " + scope + ", caught Java throwable: " + t + "; excepting instr: " + instr);
ipc = rescueMap.get(instr.getIPC());
ipc = instr.getRPC();
if (debug) LOG.info("ipc for rescuer: " + ipc);

if (ipc == -1) {
Original file line number Diff line number Diff line change
@@ -16,23 +16,20 @@ public ClosureLocalVariable(IRClosure scope, String name, int scopeDepth, int lo
this.definingScope = scope;
}

@Override
public int hashCode() {
return name.hashCode();
}

@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof ClosureLocalVariable)) return false;

return name.equals(((LocalVariable) obj).name);
return hashCode() == obj.hashCode();
}

public int compareTo(Object arg0) {
// ENEBO: what should compareTo when it is not comparable?
if (!(arg0 instanceof ClosureLocalVariable)) return 0;

return name.compareTo(((LocalVariable) arg0).name);
int a = hashCode();
int b = arg0.hashCode();
return a < b ? -1 : (a == b ? 0 : 1);
}

@Override
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ public void addUsedVariables(List<Variable> l) {
}

public Operand cloneForInlining(CloneInfo ii) {
return symbolName.cloneForInlining(ii);
return new DynamicSymbol(symbolName.cloneForInlining(ii));
}

@Override
4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/ir/operands/Label.java
Original file line number Diff line number Diff line change
@@ -50,7 +50,9 @@ public boolean equals(Object o) {
}

public Label clone() {
return new Label(prefix, id);
Label newL = new Label(prefix, id);
newL.setTargetPC(getTargetPC()); // Strictly not necessary, but, copy everything over
return newL;
}

@Override
17 changes: 11 additions & 6 deletions core/src/main/java/org/jruby/ir/operands/LocalVariable.java
Original file line number Diff line number Diff line change
@@ -16,9 +16,10 @@
* @author enebo
*/
public class LocalVariable extends Variable implements DepthCloneable {
protected String name;
protected int scopeDepth;
protected int offset;
protected final String name;
protected final int scopeDepth;
protected final int offset;
protected final int hcode;

// FIXME: We should resolve to an index into an array but localvariable has no allocator
public LocalVariable(String name, int scopeDepth, int location) {
@@ -30,6 +31,7 @@ protected LocalVariable(OperandType type, String name, int scopeDepth, int locat
this.name = name;
this.scopeDepth = scopeDepth;
this.offset = location;
this.hcode = (name + ":" + offset).hashCode();
}

public boolean isSameDepth(LocalVariable other) {
@@ -60,20 +62,23 @@ public String toString() {

@Override
public int hashCode() {
return name.hashCode();
return hcode;
}

@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof LocalVariable)) return false;

return name.equals(((LocalVariable) obj).name);
return hashCode() == obj.hashCode();
}

public int compareTo(Object arg0) {
// ENEBO: what should compareTo when it is not comparable?
if (!(arg0 instanceof LocalVariable)) return 0;

return name.compareTo(((LocalVariable) arg0).name);
int a = hashCode();
int b = arg0.hashCode();
return a < b ? -1 : (a == b ? 0 : 1);
}

@Override
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jruby.ir.operands;

import org.jruby.ir.transformations.inlining.SimpleCloneInfo;

/**
* When we optimize full local variables to be temporary ones we like to keep the name
* of what we renamed them as. This is just enough wrapper for us to maintain a nice
@@ -15,6 +17,11 @@ public TemporaryLocalReplacementVariable(String oldName, int offset) {
this.oldName = oldName;
}

@Override
public Variable clone(SimpleCloneInfo ii) {
return new TemporaryLocalReplacementVariable(oldName, offset);
}

@Override
public String getPrefix() {
return "%t_" + oldName + "_";
Original file line number Diff line number Diff line change
@@ -177,6 +177,7 @@ public void cloneInstrs(SimpleCloneInfo ii) {
for (Instr i: oldInstrs) {
Instr clonedInstr = i.clone(ii);
clonedInstr.setIPC(i.getIPC());
clonedInstr.setRPC(i.getRPC());
instrs.add(clonedInstr);
}
}
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ public RubyCallNode(RubyContext context, SourceSection section, String methodNam
this.isSplatted = isSplatted;

dispatchHead = new DispatchHeadNode(context, ignoreVisibility, rubiniusPrimitive, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
respondToMissing = new DispatchHeadNode(context, ignoreVisibility, Dispatch.MissingBehavior.RETURN_MISSING);
respondToMissing = new DispatchHeadNode(context, true, Dispatch.MissingBehavior.RETURN_MISSING);
respondToMissingCast = BooleanCastNodeFactory.create(context, section, null);

this.ignoreVisibility = ignoreVisibility;
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.dispatch.Dispatch;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
@@ -146,7 +147,7 @@ public boolean equal(Object a, Object b) {
}
}

@CoreMethod(names = "initialize", needsSelf = false, maxArgs = 0)
@CoreMethod(names = "initialize", needsSelf = false, maxArgs = 0, visibility = Visibility.PRIVATE)
public abstract static class InitializeNode extends CoreMethodNode {

public InitializeNode(RubyContext context, SourceSection sourceSection) {
@@ -199,7 +200,7 @@ public Object instanceEval(VirtualFrame frame, Object self, RubyProc block) {

}

@CoreMethod(names = "method_missing", needsBlock = true, isSplatted = true)
@CoreMethod(names = "method_missing", needsBlock = true, isSplatted = true, visibility = Visibility.PRIVATE)
public abstract static class MethodMissingNode extends CoreMethodNode {

public MethodMissingNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.truffle.nodes.dispatch.Dispatch;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyContext;
@@ -59,7 +60,7 @@ public abstract static class NewNode extends CoreMethodNode {

public NewNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
initialize = new DispatchHeadNode(context);
initialize = DispatchHeadNode.onSelf(context);
}

public NewNode(NewNode prev) {
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@

Visibility visibility() default Visibility.PUBLIC;

boolean onSingleton() default false;

boolean isModuleFunction() default false;

boolean needsSelf() default true;
Original file line number Diff line number Diff line change
@@ -72,6 +72,7 @@ public static List<MethodDetails> getMethods() {
getMethods(methods, FixnumNodesFactory.getFactories());
getMethods(methods, FloatNodesFactory.getFactories());
getMethods(methods, HashNodesFactory.getFactories());
getMethods(methods, GCNodesFactory.getFactories());
getMethods(methods, IONodesFactory.getFactories());
getMethods(methods, KernelNodesFactory.getFactories());
getMethods(methods, MainNodesFactory.getFactories());
@@ -143,33 +144,40 @@ private static void addMethod(RubyClass rubyObjectClass, MethodDetails methodDet

final Visibility visibility = anno.visibility();

if (anno.isModuleFunction() && visibility != Visibility.PUBLIC) {
System.err.println("WARNING: visibility ignored when isModuleFunction in " + methodDetails.getIndicativeName());
if (anno.isModuleFunction()) {
if (visibility != Visibility.PUBLIC) {
System.err.println("WARNING: visibility ignored when isModuleFunction in " + methodDetails.getIndicativeName());
}
if (anno.onSingleton()) {
System.err.println("WARNING: Either onSingleton or isModuleFunction for " + methodDetails.getIndicativeName());
}
}

// Do not use needsSelf=true in module functions, it is either the module/class or the instance.
final boolean needsSelf = !anno.isModuleFunction() && anno.needsSelf();
// Usage of needsSelf is quite rare for singleton methods (except constructors).
final boolean needsSelf = !anno.isModuleFunction() && !anno.onSingleton() && anno.needsSelf();

final RubyRootNode rootNode = makeGenericMethod(context, methodDetails, needsSelf);

final RubyMethod method = new RubyMethod(rootNode.getSharedMethodInfo(), canonicalName, module, visibility, false,
Truffle.getRuntime().createCallTarget(rootNode), null);

if (anno.isModuleFunction()) {
module.addMethod(null, method.withNewVisibility(Visibility.PRIVATE));
module.getSingletonClass(null).addMethod(null, method.withNewVisibility(Visibility.PUBLIC));
addMethod(module, method, aliases, Visibility.PRIVATE);
addMethod(module.getSingletonClass(null), method, aliases, Visibility.PUBLIC);
} else if (anno.onSingleton()) {
addMethod(module.getSingletonClass(null), method, aliases, visibility);
} else {
module.addMethod(null, method);
addMethod(module, method, aliases, visibility);
}
}

for (String alias : aliases) {
final RubyMethod withAlias = method.withNewName(alias);

module.addMethod(null, withAlias);
private static void addMethod(RubyModule module, RubyMethod method, List<String> aliases, Visibility visibility) {
method = method.withVisibility(visibility);

if (anno.isModuleFunction()) {
module.getSingletonClass(null).addMethod(null, withAlias.withNewVisibility(Visibility.PUBLIC));
}
module.addMethod(null, method);
for (String alias : aliases) {
module.addMethod(null, method.withNewName(alias));
}
}

9 changes: 4 additions & 5 deletions core/src/main/java/org/jruby/truffle/nodes/core/DirNodes.java
Original file line number Diff line number Diff line change
@@ -23,8 +23,7 @@

@CoreClass(name = "Dir")
public abstract class DirNodes {

@CoreMethod(names = "[]", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "[]", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class GlobNode extends CoreMethodNode {

public GlobNode(RubyContext context, SourceSection sourceSection) {
@@ -96,7 +95,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO

}

@CoreMethod(names = "chdir", isModuleFunction = true, needsBlock = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "chdir", onSingleton = true, needsBlock = true, minArgs = 1, maxArgs = 1)
public abstract static class ChdirNode extends YieldingCoreMethodNode {

public ChdirNode(RubyContext context, SourceSection sourceSection) {
@@ -129,7 +128,7 @@ public Object chdir(VirtualFrame frame, RubyString path, RubyProc block) {

}

@CoreMethod(names = {"exist?", "exists?"}, isModuleFunction = true, maxArgs = 1)
@CoreMethod(names = {"exist?", "exists?"}, onSingleton = true, maxArgs = 1)
public abstract static class ExistsNode extends CoreMethodNode {

public ExistsNode(RubyContext context, SourceSection sourceSection) {
@@ -149,7 +148,7 @@ public boolean exists(RubyString path) {

}

@CoreMethod(names = "pwd", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = {"pwd", "getwd"}, onSingleton = true, maxArgs = 0)
public abstract static class PwdNode extends CoreMethodNode {

public PwdNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ public boolean equal(RubyEncoding a, RubyEncoding b) {

}

@CoreMethod(names = "default_external", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "default_external", onSingleton = true, maxArgs = 0)
public abstract static class DefaultExternalNode extends CoreMethodNode {

public DefaultExternalNode(RubyContext context, SourceSection sourceSection) {
@@ -65,7 +65,7 @@ public RubyEncoding defaultExternal() {

}

@CoreMethod(names = "default_internal", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "default_internal", onSingleton = true, maxArgs = 0)
public abstract static class DefaultInternalNode extends CoreMethodNode {

public DefaultInternalNode(RubyContext context, SourceSection sourceSection) {
@@ -91,7 +91,7 @@ public RubyEncoding defaultInternal() {

}

@CoreMethod(names = "find", isModuleFunction = true, maxArgs = 1, minArgs = 1)
@CoreMethod(names = "find", onSingleton = true, maxArgs = 1, minArgs = 1)
public abstract static class FindNode extends CoreMethodNode {

public FindNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ public NilPlaceholder initialize(RubyFiber fiber, RubyProc block) {

}

@CoreMethod(names = "yield", isModuleFunction = true, isSplatted = true)
@CoreMethod(names = "yield", onSingleton = true, isSplatted = true)
public abstract static class YieldNode extends CoreMethodNode {

public YieldNode(RubyContext context, SourceSection sourceSection) {
50 changes: 10 additions & 40 deletions core/src/main/java/org/jruby/truffle/nodes/core/FileNodes.java
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@

@CoreClass(name = "File")
public abstract class FileNodes {
@CoreMethod(names = "absolute_path", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "absolute_path", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class AbsolutePathNode extends CoreMethodNode {

public AbsolutePathNode(RubyContext context, SourceSection sourceSection) {
@@ -62,7 +62,7 @@ public NilPlaceholder close(RubyFile file) {

}

@CoreMethod(names = "delete", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "delete", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class DeleteNode extends CoreMethodNode {

public DeleteNode(RubyContext context, SourceSection sourceSection) {
@@ -84,7 +84,7 @@ public int delete(RubyString file) {

}

@CoreMethod(names = "directory?", isModuleFunction = true, maxArgs = 1)
@CoreMethod(names = "directory?", onSingleton = true, maxArgs = 1)
public abstract static class DirectoryNode extends CoreMethodNode {

public DirectoryNode(RubyContext context, SourceSection sourceSection) {
@@ -104,7 +104,7 @@ public boolean directory(RubyString path) {

}

@CoreMethod(names = "dirname", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "dirname", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class DirnameNode extends CoreMethodNode {

public DirnameNode(RubyContext context, SourceSection sourceSection) {
@@ -172,7 +172,7 @@ public NilPlaceholder eachLine(VirtualFrame frame, RubyFile file, RubyProc block

}

@CoreMethod(names = {"exist?", "exists?"}, isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = {"exist?", "exists?"}, onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class ExistsNode extends CoreMethodNode {

public ExistsNode(RubyContext context, SourceSection sourceSection) {
@@ -192,7 +192,7 @@ public boolean exists(RubyString path) {

}

@CoreMethod(names = "executable?", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "executable?", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class ExecutableNode extends CoreMethodNode {

public ExecutableNode(RubyContext context, SourceSection sourceSection) {
@@ -212,7 +212,7 @@ public boolean executable(RubyString path) {

}

@CoreMethod(names = "expand_path", isModuleFunction = true, minArgs = 1, maxArgs = 2)
@CoreMethod(names = "expand_path", onSingleton = true, minArgs = 1, maxArgs = 2)
public abstract static class ExpandPathNode extends CoreMethodNode {

public ExpandPathNode(RubyContext context, SourceSection sourceSection) {
@@ -237,7 +237,7 @@ public RubyString expandPath(RubyString path, RubyString dir) {

}

@CoreMethod(names = "file?", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "file?", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class FileNode extends CoreMethodNode {

public FileNode(RubyContext context, SourceSection sourceSection) {
@@ -257,7 +257,7 @@ public boolean file(RubyString path) {

}

@CoreMethod(names = "join", isModuleFunction = true, isSplatted = true)
@CoreMethod(names = "join", onSingleton = true, isSplatted = true)
public abstract static class JoinNode extends CoreMethodNode {

public JoinNode(RubyContext context, SourceSection sourceSection) {
@@ -295,36 +295,6 @@ public static void join(StringBuilder builder, Object[] parts) {
}
}

@CoreMethod(names = "open", isModuleFunction = true, needsBlock = true, minArgs = 2, maxArgs = 2)
public abstract static class OpenNode extends YieldingCoreMethodNode {

public OpenNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public OpenNode(OpenNode prev) {
super(prev);
}

@Specialization
public Object open(VirtualFrame frame, RubyString fileName, RubyString mode, RubyProc block) {
notDesignedForCompilation();

final RubyFile file = RubyFile.open(getContext(), fileName.toString(), mode.toString());

if (block != null) {
try {
yield(frame, block, file);
} finally {
file.close();
}
}

return file;
}

}

@CoreMethod(names = "puts", minArgs = 1, maxArgs = 1)
public abstract static class PutsNode extends CoreMethodNode {

@@ -392,7 +362,7 @@ public RubyString read(RubyFile file) {

}

@CoreMethod(names = "size?", minArgs = 1, maxArgs = 1, isModuleFunction = true)
@CoreMethod(names = "size?", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class SizeNode extends CoreMethodNode {

public SizeNode(RubyContext context, SourceSection sourceSection) {
73 changes: 73 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/GCNodes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2013 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.core;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.NilPlaceholder;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.UndefinedPlaceholder;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyProc;

import java.math.BigInteger;

@CoreClass(name = "GC")
public abstract class GCNodes {

@CoreMethod(names = "start", onSingleton = true, maxArgs = 0)
public abstract static class StartNode extends GarbageCollectNode {
public StartNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StartNode(StartNode prev) {
super(prev);
}
}

@CoreMethod(names = "garbage_collect", needsSelf = false, maxArgs = 0)
public abstract static class GarbageCollectNode extends CoreMethodNode {

public GarbageCollectNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public GarbageCollectNode(GarbageCollectNode prev) {
super(prev);
}

public abstract NilPlaceholder executeGC();

@Specialization
public NilPlaceholder garbageCollect() {
return doGC();
}

@CompilerDirectives.SlowPath
private NilPlaceholder doGC() {
notDesignedForCompilation();

getContext().outsideGlobalLock(new Runnable() {
@Override
public void run() {
System.gc();
}
});

return NilPlaceholder.INSTANCE;
}
}

}
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ public boolean equal(RubyHash a, RubySymbol b) {

}

@CoreMethod(names = "[]", isModuleFunction = true, isSplatted = true)
@CoreMethod(names = "[]", onSingleton = true, isSplatted = true)
public abstract static class ConstructNode extends HashCoreMethodNode {

private final BranchProfile singleObject = new BranchProfile();
35 changes: 34 additions & 1 deletion core/src/main/java/org/jruby/truffle/nodes/core/IONodes.java
Original file line number Diff line number Diff line change
@@ -10,9 +10,12 @@
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyFile;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.core.RubyString;

import java.io.*;
@@ -22,7 +25,37 @@
@CoreClass(name = "IO")
public abstract class IONodes {

@CoreMethod(names = "readlines", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "open", onSingleton = true, needsBlock = true, minArgs = 2, maxArgs = 2)
public abstract static class OpenNode extends YieldingCoreMethodNode {

public OpenNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public OpenNode(OpenNode prev) {
super(prev);
}

@Specialization
public Object open(VirtualFrame frame, RubyString fileName, RubyString mode, RubyProc block) {
notDesignedForCompilation();

final RubyFile file = RubyFile.open(getContext(), fileName.toString(), mode.toString());

if (block != null) {
try {
yield(frame, block, file);
} finally {
file.close();
}
}

return file;
}

}

@CoreMethod(names = "readlines", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class ReadLinesNode extends CoreMethodNode {

public ReadLinesNode(RubyContext context, SourceSection sourceSection) {
23 changes: 16 additions & 7 deletions core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -1517,15 +1517,18 @@ public boolean require(RubyString feature) {
public abstract static class RespondToNode extends CoreMethodNode {

@Child protected DispatchHeadNode dispatch;
@Child protected DispatchHeadNode dispatchIgnoreVisibility;

public RespondToNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
dispatch = new DispatchHeadNode(context, false, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
dispatchIgnoreVisibility = new DispatchHeadNode(context, true, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
}

public RespondToNode(RespondToNode prev) {
super(prev);
dispatch = prev.dispatch;
dispatchIgnoreVisibility = prev.dispatchIgnoreVisibility;
}

@Specialization
@@ -1534,9 +1537,12 @@ public boolean doesRespondTo(VirtualFrame frame, Object object, RubyString name,
}

@Specialization
public boolean doesRespondTo(VirtualFrame frame, Object object, RubyString name, boolean dontCheckVisibility) {
// TODO(CS): check visibility flag
return dispatch.doesRespondTo(frame, name, object);
public boolean doesRespondTo(VirtualFrame frame, Object object, RubyString name, boolean ignoreVisibility) {
if (ignoreVisibility) {
return dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
} else {
return dispatch.doesRespondTo(frame, name, object);
}
}

@Specialization
@@ -1545,14 +1551,17 @@ public boolean doesRespondTo(VirtualFrame frame, Object object, RubySymbol name,
}

@Specialization
public boolean doesRespondTo(VirtualFrame frame, Object object, RubySymbol name, boolean dontCheckVisibility) {
// TODO(CS): check visibility flag
return dispatch.doesRespondTo(frame, name, object);
public boolean doesRespondTo(VirtualFrame frame, Object object, RubySymbol name, boolean ignoreVisibility) {
if (ignoreVisibility) {
return dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
} else {
return dispatch.doesRespondTo(frame, name, object);
}
}

}

@CoreMethod(names = "respond_to_missing?", minArgs = 1, maxArgs = 2)
@CoreMethod(names = "respond_to_missing?", minArgs = 1, maxArgs = 2, visibility = Visibility.PRIVATE)
public abstract static class RespondToMissingNode extends CoreMethodNode {

public RespondToMissingNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -775,7 +775,7 @@ public NilPlaceholder moduleFunction(RubyModule module, Object... args) {
throw new UnsupportedOperationException();
}

module.getSingletonClass(this).addMethod(this, method.withNewVisibility(Visibility.PUBLIC));
module.getSingletonClass(this).addMethod(this, method.withVisibility(Visibility.PUBLIC));
}
}

@@ -802,7 +802,7 @@ public RubyString name(RubyModule module) {
}
}

@CoreMethod(names = "nesting", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "nesting", onSingleton = true, maxArgs = 0)
public abstract static class NestingNode extends CoreMethodNode {

public NestingNode(RubyContext context, SourceSection sourceSection) {
@@ -886,7 +886,7 @@ public RubyModule publicClassMethod(RubyModule module, Object... args) {
throw new RuntimeException("Couldn't find method " + arg.toString());
}

moduleSingleton.addMethod(this, method.withNewVisibility(Visibility.PUBLIC));
moduleSingleton.addMethod(this, method.withVisibility(Visibility.PUBLIC));
}

return module;
@@ -945,7 +945,7 @@ public RubyModule privateClassMethod(RubyModule module, Object... args) {
throw new RuntimeException("Couldn't find method " + arg.toString());
}

moduleSingleton.addMethod(this, method.withNewVisibility(Visibility.PRIVATE));
moduleSingleton.addMethod(this, method.withVisibility(Visibility.PRIVATE));
}

return module;
Original file line number Diff line number Diff line change
@@ -115,37 +115,15 @@ public RubyProc defineFinalizer(Object object, RubyProc finalizer) {
}
}

@CoreMethod(names = {"garbage_collect", "start"}, isModuleFunction = true, maxArgs = 0)
public abstract static class GarbageCollectNode extends CoreMethodNode {

@CoreMethod(names = "garbage_collect", isModuleFunction = true, maxArgs = 0)
public abstract static class GarbageCollectNode extends GCNodes.GarbageCollectNode {
public GarbageCollectNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public GarbageCollectNode(GarbageCollectNode prev) {
super(prev);
}

@Specialization
public NilPlaceholder garbageCollect() {
return doGC();
}

@CompilerDirectives.SlowPath
private NilPlaceholder doGC() {
notDesignedForCompilation();

getContext().outsideGlobalLock(new Runnable() {

@Override
public void run() {
System.gc();
}

});

return NilPlaceholder.INSTANCE;
}
}

@CoreMethod(names = "undefine_finalizer", isModuleFunction = true, minArgs = 1, maxArgs = 1)
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ public Object match(RubyRegexp regexp, RubyString string) {

}

@CoreMethod(names = "escape", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "escape", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class EscapeNode extends CoreMethodNode {

public EscapeNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ protected boolean notSymbol(RubySymbol a, Object b) {

}

@CoreMethod(names = "all_symbols", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "all_symbols", onSingleton = true, maxArgs = 0)
public abstract static class AllSymbolsNode extends CoreMethodNode {

public AllSymbolsNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -33,12 +33,12 @@ public SubNode(SubNode prev) {

@Specialization
public double sub(RubyTime a, RubyTime b) {
return a.getSeconds() - b.getSeconds();
return a.getRealSeconds() - b.getRealSeconds();
}

}

@CoreMethod(names = "now", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "now", onSingleton = true, maxArgs = 0)
public abstract static class NowNode extends CoreMethodNode {

public NowNode(RubyContext context, SourceSection sourceSection) {
@@ -57,7 +57,7 @@ public RubyTime now() {

}

@CoreMethod(names = {"from_array", "time_s_from_array"}, isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "from_array", onSingleton = true, maxArgs = 0)
public abstract static class FromArrayNode extends CoreMethodNode {

public FromArrayNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
@CoreClass(name = "TruffleDebug")
public abstract class TruffleDebugNodes {

@CoreMethod(names = "array_storage_info", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "array_storage_info", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class ArrayStorageInfoNode extends CoreMethodNode {

public ArrayStorageInfoNode(RubyContext context, SourceSection sourceSection) {
@@ -39,7 +39,7 @@ public RubyString javaClassOf(RubyArray array) {

}

@CoreMethod(names = "dump_call_stack", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "dump_call_stack", onSingleton = true, maxArgs = 0)
public abstract static class DumpCallStackNode extends CoreMethodNode {

public DumpCallStackNode(RubyContext context, SourceSection sourceSection) {
@@ -63,7 +63,7 @@ public NilPlaceholder dumpCallStack() {

}

@CoreMethod(names = "flush_stdout", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "flush_stdout", onSingleton = true, maxArgs = 0)
public abstract static class FlushStdoutNode extends CoreMethodNode {

public FlushStdoutNode(RubyContext context, SourceSection sourceSection) {
@@ -82,7 +82,7 @@ public NilPlaceholder flush() {

}

@CoreMethod(names = "full_tree", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "full_tree", onSingleton = true, maxArgs = 0)
public abstract static class FullTreeNode extends CoreMethodNode {

public FullTreeNode(RubyContext context, SourceSection sourceSection) {
@@ -102,7 +102,7 @@ public RubyString fullTree() {

}

@CoreMethod(names = "java_class_of", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "java_class_of", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class JavaClassOfNode extends CoreMethodNode {

public JavaClassOfNode(RubyContext context, SourceSection sourceSection) {
@@ -122,7 +122,7 @@ public RubyString javaClassOf(Object value) {

}

@CoreMethod(names = "panic", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "panic", onSingleton = true, maxArgs = 0)
public abstract static class PanicNode extends CoreMethodNode {

public PanicNode(RubyContext context, SourceSection sourceSection) {
@@ -141,7 +141,7 @@ public NilPlaceholder doPanic() {

}

@CoreMethod(names = "parse_tree", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "parse_tree", onSingleton = true, maxArgs = 0)
public abstract static class ParseTreeNode extends CoreMethodNode {

public ParseTreeNode(RubyContext context, SourceSection sourceSection) {
@@ -167,7 +167,7 @@ public Object parseTree() {

}

@CoreMethod(names = "slow_path", isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = "slow_path", onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class SlowPathNode extends CoreMethodNode {

public SlowPathNode(RubyContext context, SourceSection sourceSection) {
@@ -186,7 +186,7 @@ public Object slowPath(Object value) {

}

@CoreMethod(names = "tree", isModuleFunction = true, maxArgs = 0)
@CoreMethod(names = "tree", onSingleton = true, maxArgs = 0)
public abstract static class TreeNode extends CoreMethodNode {

public TreeNode(RubyContext context, SourceSection sourceSection) {
Original file line number Diff line number Diff line change
@@ -91,7 +91,7 @@ public Object dispatch(
ignoreVisibility, dispatchAction);

if (method == null) {
final RubyMethod missingMethod = lookup(callingSelf, receiverObject, "method_missing", ignoreVisibility,
final RubyMethod missingMethod = lookup(callingSelf, receiverObject, "method_missing", true,
dispatchAction);

if (missingMethod == null) {
Original file line number Diff line number Diff line change
@@ -318,7 +318,7 @@ private DispatchNode createMethodMissingNode(
}

case CALL_METHOD_MISSING: {
final RubyMethod method = lookup(callingSelf, receiverObject, "method_missing", ignoreVisibility, dispatchAction);
final RubyMethod method = lookup(callingSelf, receiverObject, "method_missing", true, dispatchAction);

if (method == null) {
throw new RaiseException(getContext().getCoreLibrary().runtimeError(
Original file line number Diff line number Diff line change
@@ -9,10 +9,8 @@
*/
package org.jruby.truffle.nodes.methods;

import com.oracle.truffle.api.*;
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.*;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.*;
import org.jruby.truffle.runtime.*;
@@ -71,8 +69,8 @@ public Object execute(VirtualFrame frame) {
final RubyMethod methodWithDeclaringModule = methodObject.withDeclaringModule(module);

if (moduleFunctionFlag) {
module.addMethod(this, methodWithDeclaringModule.withNewVisibility(Visibility.PRIVATE));
module.getSingletonClass(this).addMethod(this, methodWithDeclaringModule.withNewVisibility(Visibility.PUBLIC));
module.addMethod(this, methodWithDeclaringModule.withVisibility(Visibility.PRIVATE));
module.getSingletonClass(this).addMethod(this, methodWithDeclaringModule.withVisibility(Visibility.PUBLIC));
} else {
module.addMethod(this, methodWithDeclaringModule);
}
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@

@CoreClass(name = "ByteArray")
public abstract class ByteArrayNodes {
@CoreMethod(names = "allocate", isModuleFunction = true)
@CoreMethod(names = "allocate", onSingleton = true)
public abstract static class AllocateNode extends CoreMethodNode {
public AllocateNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
@@ -35,8 +35,7 @@ public RubyObject allocate(RubyObject baClass, RubyObject size) {
}
}

// FIXME(eregon): this should only be defined on the singleton class, not as an instance method.
@CoreMethod(names = {"new", "allocate_sized"}, isModuleFunction = true, minArgs = 1, maxArgs = 1)
@CoreMethod(names = {"new", "allocate_sized"}, onSingleton = true, minArgs = 1, maxArgs = 1)
public abstract static class AllocateSizedNode extends CoreMethodNode {
@Child
protected DispatchHeadNode bytesToIntNode;
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@

@CoreClass(name = "Type")
public abstract class TypeNodes {
@CoreMethod(names = "object_kind_of?", isModuleFunction = true)
@CoreMethod(names = "object_kind_of?", onSingleton = true)
public abstract static class ObjKindOfPNode extends CoreMethodNode {
public ObjKindOfPNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ArrayNodes;
import org.jruby.truffle.nodes.core.MathNodes;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.NilPlaceholder;
import org.jruby.truffle.runtime.RubyCallStack;
@@ -89,6 +88,7 @@ public class CoreLibrary {
@CompilerDirectives.CompilationFinal private RubyModule configModule;
@CompilerDirectives.CompilationFinal private RubyModule enumerableModule;
@CompilerDirectives.CompilationFinal private RubyModule errnoModule;
@CompilerDirectives.CompilationFinal private RubyModule gcModule;
@CompilerDirectives.CompilationFinal private RubyModule kernelModule;
@CompilerDirectives.CompilationFinal private RubyModule mathModule;
@CompilerDirectives.CompilationFinal private RubyModule objectSpaceModule;
@@ -153,6 +153,7 @@ public void initialize() {
fileClass = new RubyClass(null, null, ioClass, "File");
fixnumClass = new RubyClass(null, null, integerClass, "Fixnum");
floatClass = new RubyClass(null, null, numericClass, "Float");
gcModule = new RubyModule(moduleClass, null, "GC");
hashClass = new RubyHash.RubyHashClass(objectClass);
kernelModule = new RubyModule(moduleClass, null, "Kernel");
loadErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "LoadError");
@@ -256,6 +257,7 @@ public void initialize() {
fileClass, //
fixnumClass, //
floatClass, //
gcModule, //
hashClass, //
integerClass, //
ioClass, //
@@ -323,7 +325,7 @@ public void initializeAfterMethodsAdded() {
// Just create a dummy object for $stdout - we can use Kernel#print and a special method TruffleDebug.flush_stdout

final RubyBasicObject stdout = new RubyBasicObject(objectClass);
stdout.getSingletonClass(null).addMethod(null, ModuleOperations.lookupMethod(stdout.getMetaClass(), "print").withNewVisibility(Visibility.PUBLIC));
stdout.getSingletonClass(null).addMethod(null, ModuleOperations.lookupMethod(stdout.getMetaClass(), "print").withVisibility(Visibility.PUBLIC));
stdout.getSingletonClass(null).addMethod(null, ModuleOperations.lookupMethod(truffleDebugModule.getSingletonClass(null), "flush_stdout").withNewName("flush"));
globalVariablesObject.setInstanceVariable("$stdout", stdout);

Original file line number Diff line number Diff line change
@@ -319,7 +319,7 @@ public void visibilityMethod(RubyNode currentNode, Object[] arguments, Visibilit
* a different visibility to this module.
*/

addMethod(currentNode, method.withNewVisibility(visibility));
addMethod(currentNode, method.withVisibility(visibility));
}
}
}
Original file line number Diff line number Diff line change
@@ -48,10 +48,14 @@ public RubyTime(RubyClass timeClass, long seconds, long nanoseconds) {
this.nanoseconds = nanoseconds;
}

public long getSeconds() {
public long getWholeSeconds() {
return seconds;
}

public double getRealSeconds() {
return seconds + nanosecondsToSecond(nanoseconds);
}

public static RubyTime fromDate(RubyClass timeClass, long timeMiliseconds) {
return new RubyTime(timeClass, milisecondsToSeconds(timeMiliseconds), milisecondsToNanoseconds(timeMiliseconds));
}
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ public RubyMethod withNewName(String newName) {
return new RubyMethod(sharedMethodInfo, newName, declaringModule, visibility, undefined, callTarget, declarationFrame);
}

public RubyMethod withNewVisibility(Visibility newVisibility) {
public RubyMethod withVisibility(Visibility newVisibility) {
if (newVisibility == visibility) {
return this;
} else {
@@ -129,18 +129,8 @@ private boolean isVisibleToX(Node currentNode, ModuleChain module) {
return false;

case PRIVATE:
if (module == declaringModule) {
return true;
}

if (module.getSingletonClass(currentNode) == declaringModule) {
return true;
}

if (module.getParentModule() != null && isVisibleToX(currentNode, module.getParentModule())) {
return true;
}

// A private method may only be called with an implicit receiver,
// in which case the visibility must not be checked.
return false;

default:
1 change: 0 additions & 1 deletion spec/truffle/tags/core/gc/garbage_collect_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/gc/start_tags.txt

This file was deleted.

1 change: 1 addition & 0 deletions spec/truffle/truffle.mspec
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ class MSpecScript
"spec/ruby/core/file",
"spec/ruby/core/fixnum",
"spec/ruby/core/float",
"spec/ruby/core/gc",
"spec/ruby/core/hash",
"spec/ruby/core/io",
"spec/ruby/core/kernel",

0 comments on commit 66a80ff

Please sign in to comment.