Skip to content
Snippets Groups Projects
Commit ef07d869 authored by Lukas Stadler's avatar Lukas Stadler
Browse files

make ArgumentStatePush multithreading-safe, cleanup arg state handling

parent b49f6519
Branches
No related tags found
No related merge requests found
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -54,8 +54,6 @@ public abstract class ArgumentStatePush extends Node {
private final int index;
@Child private WriteLocalFrameVariableNode writeArgNode;
public static final int MAX_COUNTED_ARGS = 8;
public static final int INVALID_INDEX = -1;
public static final int REF_COUNT_SIZE_THRESHOLD = 64;
......
......@@ -109,7 +109,8 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
if (arg == null) {
wrappedArgs[i] = null;
} else {
wrappedArgs[i] = WrapArgumentNode.create(arg, i == 0 || modeChangeForAll ? modeChange : true, i);
boolean needsWrapping = i == 0 || modeChangeForAll ? modeChange : true;
wrappedArgs[i] = needsWrapping ? WrapArgumentNode.create(arg, i) : arg;
}
}
return new CallArgumentsNode(wrappedArgs, signature, varArgsSymbolIndicesArr);
......
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.r.nodes.function;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.nodes.RNode;
/**
* Encapsulates the nodes that increment reference count incremented when the argument node is
* wrapped.
*/
final class PreProcessArgumentsNode extends RNode {
@Children private final ArgumentStatePush[] sequence;
private PreProcessArgumentsNode(ArgumentStatePush[] sequence) {
this.sequence = sequence;
}
@Override
public Object execute(VirtualFrame frame) {
throw RInternalError.shouldNotReachHere();
}
public int getLength() {
return sequence.length;
}
static PreProcessArgumentsNode create(int length) {
ArgumentStatePush[] argStatePushNodes = new ArgumentStatePush[length];
for (int i = 0; i < length; i++) {
argStatePushNodes[i] = ArgumentStatePushNodeGen.create(i);
}
return new PreProcessArgumentsNode(argStatePushNodes);
}
@ExplodeLoop
public RNull execute(VirtualFrame frame, Object[] args) {
assert args.length == sequence.length;
for (int i = 0; i < sequence.length; i++) {
sequence[i].executeObject(frame, args[i]);
}
return RNull.instance;
}
}
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -104,7 +104,7 @@ public abstract class PromiseNode extends RNode {
RNode arg = (RNode) factory.getExpr();
RNode expr = (RNode) RASTUtils.unwrap(arg);
int wrapIndex = ArgumentStatePush.INVALID_INDEX;
if (arg instanceof WrapArgumentNode && ((WrapArgumentNode) arg).modeChange()) {
if (arg instanceof WrapArgumentNode) {
wrapIndex = ((WrapArgumentNode) arg).getIndex();
}
if (forcedEager && EvaluatedArgumentsVisitor.isSimpleArgument(expr.asRSyntaxNode())) {
......
......@@ -22,13 +22,10 @@
*/
package com.oracle.truffle.r.nodes.function;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ValueProfile;
import com.oracle.truffle.r.runtime.data.RFunction;
import com.oracle.truffle.r.runtime.data.RLanguage;
import com.oracle.truffle.r.runtime.data.RS4Object;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.runtime.data.RShareable;
import com.oracle.truffle.r.runtime.data.RVector;
import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
import com.oracle.truffle.r.runtime.nodes.RNode;
import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
......@@ -39,59 +36,33 @@ public abstract class WrapArgumentBaseNode extends RNode {
@Child protected RNode operand;
private final ValueProfile argumentValueProfile;
private final BranchProfile everSeenVector;
private final BranchProfile everSeenLanguage;
private final BranchProfile everSeenFunction;
private final BranchProfile everSeenS4Object;
private final ConditionProfile isShareable = ConditionProfile.createBinaryProfile();
protected final BranchProfile shareable;
private final BranchProfile nonShareable;
protected WrapArgumentBaseNode(RNode operand, boolean initProfiles) {
protected WrapArgumentBaseNode(RNode operand) {
this.operand = operand;
if (initProfiles) {
argumentValueProfile = ValueProfile.createClassProfile();
everSeenVector = BranchProfile.create();
everSeenLanguage = BranchProfile.create();
everSeenFunction = BranchProfile.create();
everSeenS4Object = BranchProfile.create();
shareable = BranchProfile.create();
nonShareable = BranchProfile.create();
} else {
argumentValueProfile = null;
everSeenVector = null;
everSeenLanguage = null;
everSeenFunction = null;
everSeenS4Object = null;
shareable = null;
nonShareable = null;
}
}
protected RShareable getShareable(Object initialResult) {
Object result = argumentValueProfile.profile(initialResult);
if (result instanceof RVector) {
everSeenVector.enter();
return (RVector<?>) result;
} else if (result instanceof RLanguage) {
everSeenLanguage.enter();
return (RLanguage) result;
} else if (result instanceof RFunction) {
everSeenFunction.enter();
return (RFunction) result;
} else if (result instanceof RS4Object) {
everSeenS4Object.enter();
return (RS4Object) result;
public RNode getOperand() {
return operand;
}
@Override
public final Object execute(VirtualFrame frame) {
assert operand != null;
Object result = operand.execute(frame);
return execute(frame, result);
}
public Object execute(VirtualFrame frame, Object result) {
if (isShareable.profile(result instanceof RSharingAttributeStorage)) {
return handleShareable(frame, (RSharingAttributeStorage) result);
} else {
nonShareable.enter();
return null;
assert !(result instanceof RShareable) : "unexpected RShareable that is not a subclass of RSharingAttributeStorage";
return result;
}
}
public RNode getOperand() {
return operand;
}
protected abstract Object handleShareable(VirtualFrame frame, RSharingAttributeStorage shareable);
@Override
public RSyntaxNode getRSyntaxNode() {
......
......@@ -22,13 +22,13 @@
*/
package com.oracle.truffle.r.nodes.function;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeCost;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.r.nodes.access.ConstantNode;
import com.oracle.truffle.r.runtime.data.RMissing;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RShareable;
import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
import com.oracle.truffle.r.runtime.nodes.RNode;
/**
......@@ -38,20 +38,13 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
*/
public final class WrapArgumentNode extends WrapArgumentBaseNode {
private final boolean modeChange;
private final int index;
@Child private ArgumentStatePush argPushStateNode;
private WrapArgumentNode(RNode operand, boolean modeChange, int index) {
super(operand, modeChange);
this.modeChange = modeChange;
private WrapArgumentNode(RNode operand, int index) {
super(operand);
this.index = index;
this.argPushStateNode = modeChange ? ArgumentStatePushNodeGen.create(index) : null;
}
public boolean modeChange() {
return modeChange;
}
public int getIndex() {
......@@ -59,63 +52,70 @@ public final class WrapArgumentNode extends WrapArgumentBaseNode {
}
@Override
public NodeCost getCost() {
return modeChange ? NodeCost.MONOMORPHIC : NodeCost.NONE;
}
@Override
public Object execute(VirtualFrame frame) {
assert operand != null;
Object result = operand.execute(frame);
return execute(frame, result);
}
public Object execute(VirtualFrame frame, Object result) {
if (modeChange) {
RShareable rShareable = getShareable(result);
if (rShareable != null) {
shareable.enter();
argPushStateNode.executeObject(frame, rShareable);
}
protected Object handleShareable(VirtualFrame frame, RSharingAttributeStorage shareable) {
if (argPushStateNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
argPushStateNode = insert(ArgumentStatePushNodeGen.create(index));
}
return result;
argPushStateNode.executeObject(frame, shareable);
return shareable;
}
@Override
public byte executeByte(VirtualFrame frame) throws UnexpectedResultException {
return operand.executeByte(frame);
try {
return operand.executeByte(frame);
} catch (UnexpectedResultException e) {
throw new UnexpectedResultException(execute(frame, e.getResult()));
}
}
@Override
public int executeInteger(VirtualFrame frame) throws UnexpectedResultException {
return operand.executeInteger(frame);
try {
return operand.executeInteger(frame);
} catch (UnexpectedResultException e) {
throw new UnexpectedResultException(execute(frame, e.getResult()));
}
}
@Override
public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
return operand.executeDouble(frame);
try {
return operand.executeDouble(frame);
} catch (UnexpectedResultException e) {
throw new UnexpectedResultException(execute(frame, e.getResult()));
}
}
@Override
public RMissing executeMissing(VirtualFrame frame) throws UnexpectedResultException {
return operand.executeMissing(frame);
try {
return operand.executeMissing(frame);
} catch (UnexpectedResultException e) {
throw new UnexpectedResultException(execute(frame, e.getResult()));
}
}
@Override
public RNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
return operand.executeNull(frame);
try {
return operand.executeNull(frame);
} catch (UnexpectedResultException e) {
throw new UnexpectedResultException(execute(frame, e.getResult()));
}
}
static WrapArgumentNode create(int index) {
return new WrapArgumentNode(null, true, index);
return new WrapArgumentNode(null, index);
}
static RNode create(RNode operand, boolean modeChange, int index) {
if (operand instanceof WrapArgumentNode || operand instanceof ConstantNode) {
static RNode create(RNode operand, int index) {
assert !(operand instanceof WrapArgumentNode);
if (operand instanceof ConstantNode) {
return operand;
} else {
WrapArgumentNode wan = new WrapArgumentNode(operand, modeChange, index);
return wan;
return new WrapArgumentNode(operand, index);
}
}
}
......@@ -22,10 +22,14 @@
*/
package com.oracle.truffle.r.nodes.function;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.profiles.ValueProfile;
import com.oracle.truffle.r.nodes.access.ConstantNode;
import com.oracle.truffle.r.runtime.data.RShareable;
import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
import com.oracle.truffle.r.runtime.nodes.RNode;
/**
......@@ -36,29 +40,34 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
*/
public final class WrapDefaultArgumentNode extends WrapArgumentBaseNode {
private final ConditionProfile isShared = ConditionProfile.createBinaryProfile();
@CompilationFinal private ConditionProfile isShared;
@CompilationFinal private ValueProfile copyProfile;
private WrapDefaultArgumentNode(RNode operand) {
super(operand, true);
super(operand);
}
@Override
public Object execute(VirtualFrame frame) {
Object result = operand.execute(frame);
RShareable rShareable = getShareable(result);
if (rShareable != null) {
shareable.enter();
if (isShared.profile(rShareable.isShared())) {
return rShareable.copy();
} else {
((RShareable) result).incRefCount();
protected Object handleShareable(VirtualFrame frame, RSharingAttributeStorage shareable) {
if (isShared == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
isShared = ConditionProfile.createBinaryProfile();
}
if (isShared.profile(shareable.isShared())) {
if (copyProfile == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
copyProfile = ValueProfile.createClassProfile();
}
return copyProfile.profile(shareable).copy();
} else {
shareable.incRefCount();
return shareable;
}
return result;
}
public static RNode create(RNode operand) {
if (operand instanceof WrapArgumentNode || operand instanceof ConstantNode) {
assert !(operand instanceof WrapArgumentNode);
if (operand instanceof ConstantNode) {
return operand;
} else {
return new WrapDefaultArgumentNode(operand);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment