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

Commits on Apr 6, 2016

  1. 2
    Copy the full SHA
    b73d9fb View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    65eed01 View commit details
37 changes: 19 additions & 18 deletions truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -86,6 +86,7 @@
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.control.TruffleFatalException;
import org.jruby.truffle.language.globals.GlobalVariables;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.methods.DeclarationContext;
import org.jruby.truffle.language.methods.InternalMethod;
@@ -219,7 +220,7 @@ public class CoreLibrary {
private final DynamicObjectFactory handleFactory;

private final DynamicObject argv;
private final DynamicObject globalVariablesObject;
private final GlobalVariables globalVariables;
private final DynamicObject mainObject;
private final DynamicObject nilObject;
private final DynamicObject rubiniusUndefined;
@@ -552,7 +553,7 @@ public CoreLibrary(RubyContext context) {
argv = Layouts.ARRAY.createArray(Layouts.CLASS.getInstanceFactory(arrayClass), null, 0);
rubiniusUndefined = Layouts.CLASS.getInstanceFactory(objectClass).newInstance();

globalVariablesObject = Layouts.CLASS.getInstanceFactory(objectClass).newInstance();
globalVariables = new GlobalVariables(nilObject);

digestClass = defineClass(truffleModule, basicObjectClass, "Digest");
Layouts.CLASS.setInstanceFactoryUnsafe(digestClass, DigestLayoutImpl.INSTANCE.createDigestShape(digestClass, digestClass));
@@ -649,28 +650,28 @@ public void addCoreMethods() {
}

private void initializeGlobalVariables() {
DynamicObject globals = globalVariablesObject;
GlobalVariables globals = globalVariables;

globals.define("$LOAD_PATH", Layouts.ARRAY.createArray(Layouts.CLASS.getInstanceFactory(arrayClass), null, 0), 0);
globals.define("$LOADED_FEATURES", Layouts.ARRAY.createArray(Layouts.CLASS.getInstanceFactory(arrayClass), new Object[0], 0), 0);
globals.define("$:", globals.get("$LOAD_PATH", nilObject), 0);
globals.define("$\"", globals.get("$LOADED_FEATURES", nilObject), 0);
globals.define("$,", nilObject, 0);
globals.define("$*", argv, 0);
globals.define("$0", StringOperations.createString(context, StringOperations.encodeRope(context.getJRubyRuntime().getInstanceConfig().displayedFileName(), UTF8Encoding.INSTANCE)), 0);
globals.put("$LOAD_PATH", Layouts.ARRAY.createArray(Layouts.CLASS.getInstanceFactory(arrayClass), null, 0));
globals.put("$LOADED_FEATURES", Layouts.ARRAY.createArray(Layouts.CLASS.getInstanceFactory(arrayClass), new Object[0], 0));
globals.put("$:", globals.getOrDefault("$LOAD_PATH", nilObject));
globals.put("$\"", globals.getOrDefault("$LOADED_FEATURES", nilObject));
globals.put("$,", nilObject);
globals.put("$*", argv);
globals.put("$0", StringOperations.createString(context, StringOperations.encodeRope(context.getJRubyRuntime().getInstanceConfig().displayedFileName(), UTF8Encoding.INSTANCE)));

globals.define("$DEBUG", context.getJRubyRuntime().isDebug(), 0);
globals.put("$DEBUG", context.getJRubyRuntime().isDebug());

Object value = context.getJRubyRuntime().warningsEnabled() ? context.getJRubyRuntime().isVerbose() : nilObject;
globals.define("$VERBOSE", value, 0);
globals.put("$VERBOSE", value);

final DynamicObject defaultRecordSeparator = StringOperations.createString(context, StringOperations.encodeRope(CLI_RECORD_SEPARATOR, UTF8Encoding.INSTANCE));
node.freezeNode.executeFreeze(defaultRecordSeparator);

// TODO (nirvdrum 05-Feb-15) We need to support the $-0 alias as well.
globals.define("$/", defaultRecordSeparator, 0);
globals.put("$/", defaultRecordSeparator);

globals.define("$SAFE", 0, 0);
globals.put("$SAFE", 0);
}

private void initializeConstants() {
@@ -1590,16 +1591,16 @@ public DynamicObject getArgv() {
return argv;
}

public DynamicObject getGlobalVariablesObject() {
return globalVariablesObject;
public GlobalVariables getGlobalVariables() {
return globalVariables;
}

public DynamicObject getLoadPath() {
return (DynamicObject) globalVariablesObject.get("$LOAD_PATH", context.getCoreLibrary().getNilObject());
return (DynamicObject) globalVariables.getOrDefault("$LOAD_PATH", context.getCoreLibrary().getNilObject());
}

public DynamicObject getLoadedFeatures() {
return (DynamicObject) globalVariablesObject.get("$LOADED_FEATURES", context.getCoreLibrary().getNilObject());
return (DynamicObject) globalVariables.getOrDefault("$LOADED_FEATURES", context.getCoreLibrary().getNilObject());
}

public DynamicObject getMainObject() {
Original file line number Diff line number Diff line change
@@ -856,7 +856,7 @@ public RunJRubyRootNode(RubyContext context, SourceSection sourceSection) {

@Specialization
public Object runJRubyRootNode(VirtualFrame frame, @Cached("create()")IndirectCallNode callNode) {
coreLibrary().getGlobalVariablesObject().define(
coreLibrary().getGlobalVariables().put(
"$0",
StringOperations.createString(getContext(),
ByteList.create(getContext().getJRubyInterop().getArg0())));
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2015, 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
*/

package org.jruby.truffle.language.globals;

public class GlobalVariableStorage {
public volatile Object value;

GlobalVariableStorage(Object value) {
this.value = value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2015, 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
*/

package org.jruby.truffle.language.globals;

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class GlobalVariables {

private final DynamicObject defaultValue;

ConcurrentMap<String, GlobalVariableStorage> variables;

public GlobalVariables(DynamicObject defaultValue) {
this.defaultValue = defaultValue;
this.variables = new ConcurrentHashMap<>();
}

public Object getOrDefault(String key, Object defaultValue) {
final Object v;
return ((v = get(key)) != null) ? v : defaultValue;
}

public Object get(String key) {
return getStorage(key).value;
}

@TruffleBoundary
public GlobalVariableStorage getStorage(String key) {
final GlobalVariableStorage currentStorage = variables.get(key);
if (currentStorage == null) {
final GlobalVariableStorage newStorage = new GlobalVariableStorage(defaultValue);
final GlobalVariableStorage wasStorage = variables.putIfAbsent(key, newStorage);
return (wasStorage == null) ? newStorage : wasStorage;
} else {
return currentStorage;
}
}

public void put(String key, Object value) {
getStorage(key).value = value;
}

public Collection<DynamicObject> dynamicObjectValues() {
final Collection<GlobalVariableStorage> storages = variables.values();
final ArrayList<DynamicObject> values = new ArrayList<>(storages.size());
for (GlobalVariableStorage storage : storages) {
final Object value = storage.value;
if (value instanceof DynamicObject) {
values.add((DynamicObject) value);
}
}
return values;
}

}
Original file line number Diff line number Diff line change
@@ -9,46 +9,38 @@
*/
package org.jruby.truffle.language.globals;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
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.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.objects.ReadObjectFieldNode;
import org.jruby.truffle.language.objects.ReadObjectFieldNodeGen;

public class ReadGlobalVariableNode extends RubyNode {
public abstract class ReadGlobalVariableNode extends RubyNode {

private final String name;

@Child private ReadObjectFieldNode readNode;

public ReadGlobalVariableNode(RubyContext context, SourceSection sourceSection, String name) {
super(context, sourceSection);
this.name = name;
}

@Override
public Object execute(VirtualFrame frame) {
return getReadNode().execute(coreLibrary().getGlobalVariablesObject());
@Specialization
public Object read(@Cached("getStorage()") GlobalVariableStorage storage) {
return storage.value;
}

protected GlobalVariableStorage getStorage() {
return getContext().getCoreLibrary().getGlobalVariables().getStorage(name);
}

@Override
public Object isDefined(VirtualFrame frame) {
if (getReadNode().execute(coreLibrary().getGlobalVariablesObject()) != nil()) {
if (coreLibrary().getGlobalVariables().get(name) != nil()) {
return coreStrings().GLOBAL_VARIABLE.createInstance();
} else {
return nil();
}
}

private ReadObjectFieldNode getReadNode() {
if (readNode == null) {
CompilerDirectives.transferToInterpreter();
readNode = insert(ReadObjectFieldNodeGen.create(getContext(), name, nil()));
}

return readNode;
}

}
Original file line number Diff line number Diff line change
@@ -9,46 +9,36 @@
*/
package org.jruby.truffle.language.globals;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
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.RubyContext;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.objects.WriteObjectFieldNode;
import org.jruby.truffle.language.objects.WriteObjectFieldNodeGen;

public class WriteGlobalVariableNode extends RubyNode {
@NodeChild(value = "value")
public abstract class WriteGlobalVariableNode extends RubyNode {

private final String name;

@Child private RubyNode rhs;
@Child private WriteObjectFieldNode writeNode;
@Specialization
public Object write(Object value, @Cached("getStorage()") GlobalVariableStorage storage) {
return storage.value = value;
}

public WriteGlobalVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode rhs) {
super(context, sourceSection);
this.name = name;
this.rhs = rhs;
protected GlobalVariableStorage getStorage() {
return getContext().getCoreLibrary().getGlobalVariables().getStorage(name);
}

@Override
public Object execute(VirtualFrame frame) {
final Object value = rhs.execute(frame);
getWriteNode().execute(coreLibrary().getGlobalVariablesObject(), value);
return value;
public WriteGlobalVariableNode(RubyContext context, SourceSection sourceSection, String name) {
super(context, sourceSection);
this.name = name;
}

@Override
public Object isDefined(VirtualFrame frame) {
return coreStrings().ASSIGNMENT.createInstance();
}

private WriteObjectFieldNode getWriteNode() {
if (writeNode == null) {
CompilerDirectives.transferToInterpreter();
writeNode = insert(WriteObjectFieldNodeGen.create(getContext(), name));
}

return writeNode;
}

}
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ public void run(DynamicObject thread, Node currentNode) {

public static void visitContextRoots(RubyContext context, Collection<DynamicObject> stack) {
// We do not want to expose the global object
stack.addAll(ObjectGraph.getAdjacentObjects(context.getCoreLibrary().getGlobalVariablesObject()));
stack.addAll(context.getCoreLibrary().getGlobalVariables().dynamicObjectValues());
stack.addAll(context.getAtExitManager().getHandlers());
stack.addAll(context.getObjectSpaceManager().getFinalizerHandlers());
}
Original file line number Diff line number Diff line change
@@ -113,12 +113,14 @@
import org.jruby.truffle.language.globals.CheckRecordSeparatorVariableTypeNode;
import org.jruby.truffle.language.globals.CheckStdoutVariableTypeNode;
import org.jruby.truffle.language.globals.ReadGlobalVariableNode;
import org.jruby.truffle.language.globals.ReadGlobalVariableNodeGen;
import org.jruby.truffle.language.globals.ReadLastBacktraceNode;
import org.jruby.truffle.language.globals.ReadMatchReferenceNode;
import org.jruby.truffle.language.globals.ReadThreadLocalGlobalVariableNode;
import org.jruby.truffle.language.globals.UpdateLastBacktraceNode;
import org.jruby.truffle.language.globals.UpdateVerbosityNode;
import org.jruby.truffle.language.globals.WriteGlobalVariableNode;
import org.jruby.truffle.language.globals.WriteGlobalVariableNodeGen;
import org.jruby.truffle.language.globals.WriteProgramNameNodeGen;
import org.jruby.truffle.language.globals.WriteReadOnlyGlobalNode;
import org.jruby.truffle.language.literal.BooleanLiteralNode;
@@ -1658,7 +1660,7 @@ public RubyNode visitGlobalAsgnNode(org.jruby.ast.GlobalAsgnNode node) {

return addNewlineIfNeeded(node, assignment);
} else {
final RubyNode writeGlobalVariableNode = new WriteGlobalVariableNode(context, sourceSection, name, rhs);
final RubyNode writeGlobalVariableNode = WriteGlobalVariableNodeGen.create(context, sourceSection, name, rhs);

final RubyNode translated;

@@ -1706,7 +1708,7 @@ public RubyNode visitGlobalVarNode(org.jruby.ast.GlobalVarNode node) {
// Instead, it reads the backtrace field of the thread-local $! value.
ret = new ReadLastBacktraceNode(context, sourceSection);
} else {
ret = new ReadGlobalVariableNode(context, sourceSection, name);
ret = ReadGlobalVariableNodeGen.create(context, sourceSection, name);
}

return addNewlineIfNeeded(node, ret);
Loading