Skip to content

Commit

Permalink
[Truffle] Unwrap a thread local when it's returned from an assignment.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed May 25, 2015
1 parent 9e7834d commit 64e45c0
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import com.oracle.truffle.api.interop.TruffleObject;
import org.jruby.truffle.nodes.core.BigDecimalNodes;
import org.jruby.truffle.runtime.ThreadLocalObject;
import org.jruby.truffle.runtime.UndefinedPlaceholder;
import org.jruby.truffle.runtime.core.*;

Expand Down Expand Up @@ -97,7 +98,7 @@ public static boolean isRubyBasicObject(Object value) {
}

public static boolean isThreadLocal(Object value) {
return value instanceof ThreadLocal;
return value instanceof ThreadLocalObject;
}

public static boolean isForeignObject(Object object) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.globals.GetFromThreadLocalNode;
import org.jruby.truffle.nodes.globals.WrapInThreadLocalNode;
import org.jruby.truffle.nodes.locals.ReadFrameSlotNode;
import org.jruby.truffle.nodes.locals.ReadFrameSlotNodeGen;
import org.jruby.truffle.nodes.locals.WriteFrameSlotNode;
import org.jruby.truffle.nodes.locals.WriteFrameSlotNodeGen;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.ThreadLocalObject;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyBinding;
Expand Down Expand Up @@ -117,7 +116,11 @@ public Object localVariableGetLastLine(RubyBinding binding, RubySymbol symbol) {
}

final Object value = frame.getValue(frameSlot);
return GetFromThreadLocalNode.get(getContext(), value);
if (value instanceof ThreadLocalObject) {
return ((ThreadLocalObject) value).get();
} else {
return value;
}
}

protected FrameDescriptor getFrameDescriptor(RubyBinding binding) {
Expand Down Expand Up @@ -192,7 +195,7 @@ public Object localVariableSetUncached(RubyBinding binding, RubySymbol symbol, O
public Object localVariableSetLastLine(RubyBinding binding, RubySymbol symbol, Object value) {
final MaterializedFrame frame = binding.getFrame();
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbol.toString());
frame.setObject(frameSlot, WrapInThreadLocalNode.wrap(getContext(), value));
frame.setObject(frameSlot, ThreadLocalObject.wrap(getContext(), value));
return value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import org.jruby.truffle.nodes.core.KernelNodesFactory.SameOrEqualNodeFactory;
import org.jruby.truffle.nodes.core.KernelNodesFactory.SingletonMethodsNodeFactory;
import org.jruby.truffle.nodes.dispatch.*;
import org.jruby.truffle.nodes.globals.WrapInThreadLocalNode;
import org.jruby.truffle.nodes.objects.*;
import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
import org.jruby.truffle.nodes.rubinius.ObjectPrimitiveNodes;
Expand Down Expand Up @@ -708,7 +707,7 @@ public String block() throws InterruptedException {
final FrameSlot slot = caller.getFrameDescriptor().findFrameSlot("$_");

if (slot != null) {
caller.setObject(slot, WrapInThreadLocalNode.wrap(getContext(), rubyLine));
caller.setObject(slot, ThreadLocalObject.wrap(getContext(), rubyLine));
}

return rubyLine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.ThreadLocalObject;

/**
* If a child node produces a {@link ThreadLocal}, get the value from it. If the value is not a {@code ThreadLocal},
Expand All @@ -32,7 +33,7 @@ public GetFromThreadLocalNode(RubyContext context, SourceSection sourceSection)
}

@Specialization
public Object get(ThreadLocal<?> threadLocal) {
public Object get(ThreadLocalObject threadLocal) {
return threadLocal.get();
}

Expand All @@ -41,13 +42,5 @@ public Object get(Object value) {
return value;
}

public static Object get(RubyContext context, Object value) {
if (value instanceof ThreadLocal) {
return ((ThreadLocal<?>) value).get();
} else {
return value;
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.ThreadLocalObject;

/**
* Wrap a child value in a new {@link ThreadLocal} so that a value can be stored in a location such as a frame without
Expand All @@ -27,34 +28,13 @@
@NodeChild(value = "value", type = RubyNode.class)
public abstract class WrapInThreadLocalNode extends RubyNode {

public static class ThreadLocalObject extends ThreadLocal<Object> {

private final RubyContext context;

public ThreadLocalObject(RubyContext context) {
this.context = context;
}

@Override
protected Object initialValue() {
return context.getCoreLibrary().getNilObject();
}

}

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

@Specialization
public ThreadLocal<?> wrap(Object value) {
return wrap(getContext(), value);
}

public static ThreadLocal<Object> wrap(RubyContext context, Object value) {
final ThreadLocalObject threadLocal = new ThreadLocalObject(context);
threadLocal.set(value);
return threadLocal;
public ThreadLocalObject wrap(Object value) {
return ThreadLocalObject.wrap(getContext(), value);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2015 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.runtime;

public class ThreadLocalObject extends ThreadLocal<Object> {

private final RubyContext context;

public static ThreadLocalObject wrap(RubyContext context, Object value) {
final ThreadLocalObject threadLocal = new ThreadLocalObject(context);
threadLocal.set(value);
return threadLocal;
}

public ThreadLocalObject(RubyContext context) {
this.context = context;
}

@Override
protected Object initialValue() {
return context.getCoreLibrary().getNilObject();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,13 @@ public RubyNode translateGlobalAsgnNode(org.jruby.ast.GlobalAsgnNode node, RubyN
}
}

return ((ReadNode) localVarNode).makeWriteNode(rhs);
RubyNode assignment = ((ReadNode) localVarNode).makeWriteNode(rhs);

if (name.equals("$_")) {
assignment = GetFromThreadLocalNodeGen.create(context, sourceSection, assignment);
}

return assignment;
} else {
final LiteralNode globalVariablesObjectNode = new LiteralNode(context, sourceSection, context.getCoreLibrary().getGlobalVariablesObject());
return new WriteInstanceVariableNode(context, sourceSection, name, globalVariablesObjectNode, rhs, true);
Expand Down

0 comments on commit 64e45c0

Please sign in to comment.