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

Commits on Sep 15, 2015

  1. [Truffle] allow Kernel#system and Process.spawn to be called with arr…

    …ay of arguments
    
    only :unsetenv_others is supported for now
    pitr-ch committed Sep 15, 2015
    Copy the full SHA
    e5952d1 View commit details
  2. [Truffle] code formatting

    pitr-ch committed Sep 15, 2015
    Copy the full SHA
    592098f View commit details
  3. Copy the full SHA
    181d3c9 View commit details
Original file line number Diff line number Diff line change
@@ -7,14 +7,6 @@
:file:
shims.rb: |
require 'minitest'
# mock diff, it calls not fully supported Kernel#system
module Minitest
module Assertions
def self.diff
nil
end
end
end
# mock load_plugins as it loads rubygems
def Minitest.load_plugins
end
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
:setup:
:file:
shims.rb: |
# stub methods caling #system
# stub methods calling #system
module Concurrent
module Utility
class ProcessorCounter
81 changes: 20 additions & 61 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -126,7 +126,7 @@ public DynamicObject backtick(VirtualFrame frame, DynamicObject command) {

try {
// We need to run via bash to get the variable and other expansion we expect
process = Runtime.getRuntime().exec(new String[]{"bash", "-c", command.toString()}, envp.toArray(new String[envp.size()]));
process = Runtime.getRuntime().exec(new String[]{ "bash", "-c", command.toString() }, envp.toArray(new String[envp.size()]));
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -232,14 +232,14 @@ public boolean notMatch(VirtualFrame frame, Object self, Object other) {

}

@CoreMethod(names = {"<=>"}, required = 1)
@CoreMethod(names = { "<=>" }, required = 1)
public abstract static class CompareNode extends CoreMethodArrayArgumentsNode {

@Child private SameOrEqualNode equalNode;

public CompareNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
equalNode = SameOrEqualNodeFactory.create(context, sourceSection, new RubyNode[]{null, null});
equalNode = SameOrEqualNodeFactory.create(context, sourceSection, new RubyNode[]{ null, null });
}

@Specialization
@@ -326,7 +326,7 @@ public DynamicObject calleeName() {
}
}

@CoreMethod(names = "caller_locations", isModuleFunction = true, optional = 2, lowerFixnumParameters = {0, 1})
@CoreMethod(names = "caller_locations", isModuleFunction = true, optional = 2, lowerFixnumParameters = { 0, 1 })
public abstract static class CallerLocationsNode extends CoreMethodArrayArgumentsNode {

public CallerLocationsNode(RubyContext context, SourceSection sourceSection) {
@@ -498,7 +498,8 @@ public EvalNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@CreateCast("source") public RubyNode coerceSourceToString(RubyNode source) {
@CreateCast("source")
public RubyNode coerceSourceToString(RubyNode source) {
return ToStrNodeGen.create(getContext(), getSourceSection(), source);
}

@@ -597,7 +598,7 @@ public Object evalBinding(DynamicObject source, DynamicObject binding, NotProvid
@Specialization(guards = {
"isRubyString(source)",
"isRubyBinding(binding)",
"isRubyString(filename)"})
"isRubyString(filename)" })
public Object evalBindingFilename(DynamicObject source, DynamicObject binding, DynamicObject filename,
NotProvided lineNumber) {
return getContext().eval(Layouts.STRING.getByteList(source), binding, false, filename.toString(), this);
@@ -607,7 +608,7 @@ public Object evalBindingFilename(DynamicObject source, DynamicObject binding, D
@Specialization(guards = {
"isRubyString(source)",
"isRubyBinding(binding)",
"isRubyString(filename)"})
"isRubyString(filename)" })
public Object evalBindingFilenameLine(DynamicObject source, DynamicObject binding, DynamicObject filename,
int lineNumber) {
return getContext().eval(Layouts.STRING.getByteList(source), binding, false, filename.toString(), this);
@@ -616,7 +617,7 @@ public Object evalBindingFilenameLine(DynamicObject source, DynamicObject bindin
@TruffleBoundary
@Specialization(guards = {
"isRubyString(source)",
"!isRubyBinding(badBinding)"})
"!isRubyBinding(badBinding)" })
public Object evalBadBinding(DynamicObject source, DynamicObject badBinding, NotProvided filename,
NotProvided lineNumber) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorWrongArgumentType(badBinding, "binding", this));
@@ -1044,7 +1045,7 @@ public Object instanceVariableSetSymbol(DynamicObject object, DynamicObject name

}

@CoreMethod(names = {"instance_variables", "__instance_variables__"})
@CoreMethod(names = { "instance_variables", "__instance_variables__" })
public abstract static class InstanceVariablesNode extends CoreMethodArrayArgumentsNode {

public InstanceVariablesNode(RubyContext context, SourceSection sourceSection) {
@@ -1072,7 +1073,7 @@ public DynamicObject instanceVariables(DynamicObject self) {

}

@CoreMethod(names = {"is_a?", "kind_of?"}, required = 1)
@CoreMethod(names = { "is_a?", "kind_of?" }, required = 1)
public abstract static class IsANode extends CoreMethodArrayArgumentsNode {

@Child MetaClassNode metaClassNode;
@@ -1084,14 +1085,14 @@ public IsANode(RubyContext context, SourceSection sourceSection) {

public abstract boolean executeIsA(VirtualFrame frame, Object self, DynamicObject rubyClass);

@Specialization(guards = {"isNil(nil)", "!isRubyModule(nil)"})
@Specialization(guards = { "isNil(nil)", "!isRubyModule(nil)" })
public boolean isANil(DynamicObject self, Object nil) {
return false;
}

@Specialization(
limit = "getCacheLimit()",
guards = {"isRubyModule(module)", "getMetaClass(frame, self) == cachedMetaClass", "module == cachedModule"},
guards = { "isRubyModule(module)", "getMetaClass(frame, self) == cachedMetaClass", "module == cachedModule" },
assumptions = "getUnmodifiedAssumption(cachedModule)")
public boolean isACached(VirtualFrame frame,
Object self,
@@ -1288,7 +1289,7 @@ public RubyNode coerceToBoolean(RubyNode regular) {

@Specialization(guards = "regular")
public DynamicObject methodsRegular(VirtualFrame frame, Object self, boolean regular,
@Cached("createMetaClassNode()") MetaClassNode metaClassNode) {
@Cached("createMetaClassNode()") MetaClassNode metaClassNode) {
final DynamicObject metaClass = metaClassNode.executeMetaClass(frame, self);

CompilerDirectives.transferToInterpreter();
@@ -1298,7 +1299,7 @@ public DynamicObject methodsRegular(VirtualFrame frame, Object self, boolean reg

@Specialization(guards = "!regular")
public DynamicObject methodsSingleton(VirtualFrame frame, Object self, boolean regular,
@Cached("createSingletonMethodsNode()") SingletonMethodsNode singletonMethodsNode) {
@Cached("createSingletonMethodsNode()") SingletonMethodsNode singletonMethodsNode) {
return singletonMethodsNode.executeSingletonMethods(frame, self, false);
}

@@ -1871,7 +1872,7 @@ public Long block() throws InterruptedException {

}

@CoreMethod(names = {"format", "sprintf"}, isModuleFunction = true, rest = true, required = 1, taintFromParameter = 0)
@CoreMethod(names = { "format", "sprintf" }, isModuleFunction = true, rest = true, required = 1, taintFromParameter = 0)
@ImportStatic(StringCachingGuards.class)
public abstract static class FormatNode extends CoreMethodArrayArgumentsNode {

@@ -1891,7 +1892,7 @@ public DynamicObject formatCached(
final PackResult result;

try {
result = (PackResult) callPackNode.call(frame, new Object[] { arguments, arguments.length });
result = (PackResult) callPackNode.call(frame, new Object[]{ arguments, arguments.length });
} catch (PackException e) {
CompilerDirectives.transferToInterpreter();
throw handleException(e);
@@ -1909,7 +1910,7 @@ public DynamicObject formatUncached(
final PackResult result;

try {
result = (PackResult) callPackNode.call(frame, compileFormat(format), new Object[] { arguments, arguments.length });
result = (PackResult) callPackNode.call(frame, compileFormat(format), new Object[]{ arguments, arguments.length });
} catch (PackException e) {
CompilerDirectives.transferToInterpreter();
throw handleException(e);
@@ -1983,48 +1984,6 @@ protected CallTarget compileFormat(DynamicObject format) {

}

@CoreMethod(names = "system", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class SystemNode extends CoreMethodArrayArgumentsNode {

@Child private CallDispatchHeadNode toHashNode;

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

@Specialization(guards = "isRubyString(command)")
public boolean system(VirtualFrame frame, DynamicObject command) {
if (toHashNode == null) {
CompilerDirectives.transferToInterpreter();
toHashNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

CompilerDirectives.transferToInterpreter();

// TODO(CS 5-JAN-15): very simplistic implementation

final DynamicObject env = getContext().getCoreLibrary().getENV();
final DynamicObject envAsHash = (DynamicObject) toHashNode.call(frame, env, "to_hash", null);

final List<String> envp = new ArrayList<>();

// TODO(CS): cast
for (Map.Entry<Object, Object> keyValue : HashOperations.iterableKeyValues(envAsHash)) {
envp.add(keyValue.getKey().toString() + "=" + keyValue.getValue().toString());
}

// We need to run via bash to get the variable and other expansion we expect
try {
Runtime.getRuntime().exec(new String[]{"bash", "-c", command.toString()}, envp.toArray(new String[envp.size()]));
} catch (IOException e) {
throw new RuntimeException(e);
}

return true;
}

}

@CoreMethod(names = "taint")
public abstract static class KernelTaintNode extends CoreMethodArrayArgumentsNode {

@@ -2100,8 +2059,8 @@ public abstract static class ToSNode extends CoreMethodArrayArgumentsNode {
public ToSNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
classNode = ClassNodeGen.create(context, sourceSection, null);
objectIDNode = ObjectPrimitiveNodesFactory.ObjectIDPrimitiveNodeFactory.create(context, sourceSection, new RubyNode[] { null });
toHexStringNode = KernelNodesFactory.ToHexStringNodeFactory.create(context, sourceSection, new RubyNode[]{null});
objectIDNode = ObjectPrimitiveNodesFactory.ObjectIDPrimitiveNodeFactory.create(context, sourceSection, new RubyNode[]{ null });
toHexStringNode = KernelNodesFactory.ToHexStringNodeFactory.create(context, sourceSection, new RubyNode[]{ null });
}

public abstract DynamicObject executeToS(VirtualFrame frame, Object self);
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import jnr.posix.SpawnFileAction;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.RubyGC;
@@ -35,6 +36,7 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.ArrayOperations;
import org.jruby.truffle.runtime.core.CoreLibrary;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.hash.BucketsStrategy;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.subsystems.SimpleShell;
@@ -46,6 +48,8 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Collections;
import java.util.Arrays;

@CoreClass(name = "Truffle::Primitive")
public abstract class TrufflePrimitiveNodes {
@@ -565,4 +569,60 @@ public DynamicObject printInterleavedBacktrace() {

}

@CoreMethod(names = "spawn_process", onSingleton = true, required = 3)
public abstract static class SpawnProcess extends CoreMethodArrayArgumentsNode {

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

@Specialization(guards = {
"isRubyString(command)",
"isRubyArray(arguments)",
"isRubyArray(environmentVariables)" })
public int spawn(DynamicObject command,
DynamicObject arguments,
DynamicObject environmentVariables) {

final long longPid = call(
StringOperations.getString(command),
toStringArray(arguments),
toStringArray(environmentVariables));
assert longPid <= Integer.MAX_VALUE;
// VMWaitPidPrimitiveNode accepts only int
final int pid = (int) longPid;

if (pid == -1) {
// TODO (pitr 07-Sep-2015): needs compatibility improvements
throw new RaiseException(getContext().getCoreLibrary().errnoError(getContext().getPosix().errno(), this));
}

return pid;
}

private String[] toStringArray(DynamicObject rubyStrings) {
final int size = Layouts.ARRAY.getSize(rubyStrings);
final Object[] unconvertedStrings = ArrayOperations.toObjectArray(rubyStrings);
final String[] strings = new String[size];

for (int i = 0; i < size; i++) {
assert Layouts.STRING.isString(unconvertedStrings[i]);
strings[i] = StringOperations.getString((DynamicObject) unconvertedStrings[i]);
}

return strings;
}

@TruffleBoundary
private long call(String command, String[] arguments, String[] environmentVariables) {
// TODO (pitr 04-Sep-2015): only simple implementation, does not support file actions or other options
return getContext().getPosix().posix_spawnp(
command,
Collections.<SpawnFileAction>emptyList(),
Arrays.asList(arguments),
Arrays.asList(environmentVariables));

}
}

}
Loading