Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/truffle-head'
Browse files Browse the repository at this point in the history
  • Loading branch information
eregon committed Dec 21, 2016
2 parents fcbd3d3 + e3c2107 commit 5f5f786
Show file tree
Hide file tree
Showing 65 changed files with 820 additions and 685 deletions.
5 changes: 4 additions & 1 deletion bin/jruby-truffle-tool
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#!/usr/bin/env bash

exec `dirname $BASH_SOURCE[0]`/jruby `dirname $BASH_SOURCE[0]`/../lib/ruby/truffle/jruby-truffle-tool/bin/jruby-truffle-tool "$@"
bin="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
root="$(dirname "$bin")"

exec $bin/jruby $root/lib/ruby/truffle/jruby-truffle-tool/bin/jruby-truffle-tool "$@"
15 changes: 15 additions & 0 deletions samples/truffle/logging.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Use this configuration with -J-Djava.util.logging.config.file=samples/truffle/logging.properties

# Use the standard file logger. If we set any handlers then the default one
# will be unset. You can add it back by name -
# org.jruby.truffle.Log$RubyHandler.

org.jruby.truffle.handlers=java.util.logging.FileHandler

# Say where to send file output.

java.util.logging.FileHandler.pattern=ruby.log

# Configure the logging level.

org.jruby.truffle.level=WARNING
30 changes: 30 additions & 0 deletions spec/truffle/specs/truffle/filename_length_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

require_relative '../../../ruby/spec_helper'

describe "Truffle source files" do
it "have a small enough filename for eCryptfs" do
# For eCryptfs, see https://bugs.launchpad.net/ecryptfs/+bug/344878
max_length = 143

root = Dir.pwd
File.directory?("#{root}/.git").should be_true # Make sure we are at the root

too_long = []
Dir.chdir(root) do
Dir.glob("**/*") do |f|
if File.basename(f).size > max_length
too_long << f
end
end
end

too_long.should == []
end
end
5 changes: 0 additions & 5 deletions spec/truffle/tags/core/string/modulo_tags.txt

This file was deleted.

3 changes: 2 additions & 1 deletion tool/truffle/options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ INLINE_JS: [inline_js, boolean, false, Allow inline JavaScript]

CORE_LOAD_PATH: [core.load_path, string, 'truffle:/jruby-truffle', Location to load the Truffle core library from]
CORE_PARALLEL_LOAD: [core.parallel_load, boolean, false, Load the Truffle core library in parallel]
LAZY_TRANSLATION: [lazy_translation, boolean, false, Lazily translate from the parser AST to the Truffle AST]

ARRAY_UNINITIALIZED_SIZE: [array.uninitialized_size, integer, 32, How large an Array to allocate when we have no other information to go on]
ARRAY_SMALL: [array.small, integer, 3, Maximum size of an Array to consider small for optimisations]
HASH_PACKED_ARRAY_MAX: [hash.packed_array.max, integer, 3, Maximum size of a Hash to consider using the packed array storage strategy for]

ROPE_LAZY_SUBSTRINGS: [rope.lazy_substrings, boolean, true, Indicates whether a substring operation on a rope should be performed lazily]
ROPE_PRINT_INTERN_STATS: [rope.print_intern_stats, boolean, false, Print interned rope stats at application exit]
ROPE_DEPTH_THRESHOLD: [rope.depth_threshold, integer, 128, Threshold value at which ropes will be rebalanced (indirectly controls flattening as well)]

GLOBAL_VARIABLE_MAX_INVALIDATIONS: [global_variable.max_invalidations, integer, 10, Maximum number of times a global variable can be changed to be considered constant]

Expand Down Expand Up @@ -97,7 +99,6 @@ CALL_GRAPH_WRITE: [callgraph.write, string, null, File to write the call graph t
CHAOS: [chaos, boolean, false, Randomly modify the representation of objects]

GRAAL_WARNING_UNLESS: [graal.warn_unless, boolean, true, Warn unless the JVM has the Graal compiler]
PERF_WARNING: [perf.warn, boolean, false, Warn when using a fature which is not optimized yet]

SHARED_OBJECTS_ENABLED: [shared.objects, boolean, true, Enable shared objects]
SHARED_OBJECTS_DEBUG: [shared.objects.debug, boolean, false, Print information about shared objects]
Expand Down
81 changes: 67 additions & 14 deletions truffle/src/main/java/org/jruby/truffle/Log.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,92 @@
*/
package org.jruby.truffle;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class Log {

private static class RubyLevel extends Level {

public RubyLevel(String name, Level parent) {
super(name, parent.intValue(), parent.getResourceBundleName());
}

}

public static final Level PERFORMANCE = new RubyLevel("PERFORMANCE", Level.WARNING);

private static final Logger LOGGER = createLogger();

public static class RubyHandler extends Handler {

@Override
public void publish(LogRecord record) {
System.err.printf("[ruby] %s %s%n", record.getLevel().getName(), record.getMessage());
}

@Override
public void flush() {
}

@Override
public void close() throws SecurityException {
}

}

private static Logger createLogger() {
final Logger logger = Logger.getLogger("org.jruby.truffle");

logger.setUseParentHandlers(false);
if (LogManager.getLogManager().getProperty("org.jruby.truffle.handlers") == null) {
logger.setUseParentHandlers(false);
logger.addHandler(new RubyHandler());
}

logger.addHandler(new Handler() {
return logger;
}

@Override
public void publish(LogRecord record) {
System.err.printf("[ruby] %s %s%n", record.getLevel().getName(), record.getMessage());
}
private static final Set<String> displayedWarnings = Collections.newSetFromMap(new ConcurrentHashMap<>());

@Override
public void flush() {
}
public static final String KWARGS_NOT_OPTIMIZED_YET = "keyword arguments are not yet optimized";

@Override
public void close() throws SecurityException {
}
/**
* Warn about code that works but is not yet optimized as Truffle code normally would be. Only prints the warning
* once, and only if called from compiled code. Don't call this method from behind a boundary, as it will never
* print the warning because it will never be called from compiled code. Use {@link #performanceOnce} instead
* if you need to warn in code that is never compiled.
*/
public static void notOptimizedOnce(String message) {
if (CompilerDirectives.inCompiledCode()) {
performanceOnce(message);
}
}

});
/**
* Warn about something that has lower performance than might be expected. Only prints the warning once.
*/
@TruffleBoundary
public static void performanceOnce(String message) {
if (displayedWarnings.add(message)) {
performance(message);
}
}

return logger;
/**
* Warn about something that has lower performance than might be expected.
*/
@TruffleBoundary
public static void performance(String message) {
LOGGER.log(PERFORMANCE, message);
}

@TruffleBoundary
Expand Down
2 changes: 1 addition & 1 deletion truffle/src/main/java/org/jruby/truffle/RubyEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public RubyEngine(

public int execute(String path) {
if (!Graal.isGraal() && context.getOptions().GRAAL_WARNING_UNLESS) {
Log.warning("This JVM does not have the Graal compiler - performance will be limited - " +
Log.performanceOnce("This JVM does not have the Graal compiler - performance will be limited - " +
"see https://github.com/jruby/jruby/wiki/Truffle-FAQ#how-do-i-get-jrubytruffle");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,29 @@
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.control.ReturnException;
import org.jruby.truffle.language.control.ReturnID;

public class CallPrimitiveNode extends RubyNode {

@Child private RubyNode primitive;
private final ReturnID returnID;
@Child private RubyNode fallback;

private final ConditionProfile failedProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile successProfile = ConditionProfile.createBinaryProfile();

public CallPrimitiveNode(RubyContext context, SourceSection sourceSection, RubyNode primitive, ReturnID returnID) {
public CallPrimitiveNode(RubyContext context, SourceSection sourceSection, RubyNode primitive, RubyNode fallback) {
super(context, sourceSection);
this.primitive = primitive;
this.returnID = returnID;
this.fallback = fallback;
}

@Override
public Object execute(VirtualFrame frame) {
final Object value = primitive.execute(frame);

// Primitives fail by returning null, allowing the method to continue (the fallback)
if (failedProfile.profile(value == null)) {
return nil();
if (successProfile.profile(value != null)) {
return value;
} else {
// If the primitive didn't fail its value is returned in the calling method
throw new ReturnException(returnID, value);
return fallback.execute(frame);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public int getPrimitiveArity() {
return factory.getExecutionSignature().size();
}

public RubyNode createCallPrimitiveNode(RubyContext context, SourceSection sourceSection, ReturnID returnID) {
public RubyNode createCallPrimitiveNode(RubyContext context, SourceSection sourceSection, RubyNode fallback) {
int argumentsCount = getPrimitiveArity();
final List<RubyNode> arguments = new ArrayList<>(argumentsCount);

Expand All @@ -57,7 +57,7 @@ public RubyNode createCallPrimitiveNode(RubyContext context, SourceSection sourc
}

RubyNode primitiveNode = CoreMethodNodeManager.createNodeFromFactory(context, sourceSection, factory, arguments);
return new CallPrimitiveNode(context, sourceSection, primitiveNode, returnID);
return new CallPrimitiveNode(context, sourceSection, primitiveNode, fallback);
}

public RubyNode createInvokePrimitiveNode(RubyContext context, SourceSection sourceSection, RubyNode[] arguments) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,6 @@ public YieldingCoreMethodNode(RubyContext context, SourceSection sourceSection)
dispatchNode = new YieldNode(context);
}

private boolean booleanCast(VirtualFrame frame, Object value) {
if (booleanCastNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
booleanCastNode = insert(BooleanCastNodeGen.create(null));
}
return booleanCastNode.executeBoolean(frame, value);
}

public Object yield(VirtualFrame frame, DynamicObject block, Object... arguments) {
return dispatchNode.dispatch(frame, block, arguments);
}
Expand All @@ -49,7 +41,15 @@ public Object yieldWithBlock(VirtualFrame frame, DynamicObject block, DynamicObj
}

public boolean yieldIsTruthy(VirtualFrame frame, DynamicObject block, Object... arguments) {
return booleanCast(frame, yield(frame, block, arguments));
return booleanCast(yield(frame, block, arguments));
}

private boolean booleanCast(Object value) {
if (booleanCastNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
booleanCastNode = insert(BooleanCastNodeGen.create(null));
}
return booleanCastNode.executeToBoolean(value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,7 @@ public Object getTruffleKernelModule() {
private static final String[] coreFiles = {
"/core/pre.rb",
"/core/basic_object.rb",
"/core/array.rb",
"/core/mirror.rb",
"/core/bignum.rb",
"/core/channel.rb",
Expand Down Expand Up @@ -1720,7 +1721,6 @@ public Object getTruffleKernelModule() {
"/core/argf.rb",
"/core/exception.rb",
"/core/hash.rb",
"/core/array.rb",
"/core/kernel.rb",
"/core/comparable.rb",
"/core/numeric_mirror.rb",
Expand Down
6 changes: 2 additions & 4 deletions truffle/src/main/java/org/jruby/truffle/core/ObjectNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.language.objects.IsTaintedNode;
import org.jruby.truffle.language.objects.IsTaintedNodeGen;
import org.jruby.truffle.language.objects.ObjectIDOperations;
import org.jruby.truffle.language.objects.ObjectIVarGetNode;
import org.jruby.truffle.language.objects.ObjectIVarGetNodeGen;
Expand All @@ -30,7 +29,6 @@
import org.jruby.truffle.language.objects.ReadObjectFieldNode;
import org.jruby.truffle.language.objects.ReadObjectFieldNodeGen;
import org.jruby.truffle.language.objects.TaintNode;
import org.jruby.truffle.language.objects.TaintNodeGen;
import org.jruby.truffle.language.objects.WriteObjectFieldNode;
import org.jruby.truffle.language.objects.WriteObjectFieldNodeGen;

Expand Down Expand Up @@ -128,15 +126,15 @@ public ObjectInfectPrimitiveNode(RubyContext context, SourceSection sourceSectio
public Object objectInfect(Object host, Object source) {
if (isTaintedNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
isTaintedNode = insert(IsTaintedNodeGen.create(getContext(), null, null));
isTaintedNode = insert(IsTaintedNode.create());
}

if (isTaintedNode.executeIsTainted(source)) {
// This lazy node allocation effectively gives us a branch profile

if (taintNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
taintNode = insert(TaintNodeGen.create(getContext(), null, null));
taintNode = insert(TaintNode.create());
}

taintNode.executeTaint(host);
Expand Down

0 comments on commit 5f5f786

Please sign in to comment.