Skip to content

Commit d4d3f90

Browse files
committed
Refactor eval/exec
1 parent 3e43d0a commit d4d3f90

File tree

1 file changed

+81
-160
lines changed

1 file changed

+81
-160
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 81 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@
159159
import com.oracle.graal.python.builtins.objects.list.PList;
160160
import com.oracle.graal.python.builtins.objects.module.PythonModule;
161161
import com.oracle.graal.python.builtins.objects.object.ObjectNodes;
162-
import com.oracle.graal.python.builtins.objects.object.PythonObject;
163162
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
164163
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
165164
import com.oracle.graal.python.builtins.objects.type.TpSlots;
@@ -785,194 +784,116 @@ static Object doObject(VirtualFrame frame, Object a, Object b,
785784
}
786785
}
787786

788-
// eval(expression, globals=None, locals=None)
789-
@Builtin(name = J_EVAL, minNumOfPositionalArgs = 1, parameterNames = {"expression", "globals", "locals"})
790-
@GenerateNodeFactory
791-
public abstract static class EvalNode extends PythonBuiltinNode {
792-
@Child protected CompileNode compileNode;
793-
@Child private GetOrCreateDictNode getOrCreateDictNode;
794-
795-
final void assertNoFreeVars(Node inliningTarget, PCode code, PRaiseNode raiseNode) {
796-
Object[] freeVars = code.getFreeVars();
797-
if (freeVars.length > 0) {
798-
throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.CODE_OBJ_NO_FREE_VARIABLES, getMode());
799-
}
800-
}
801-
802-
protected TruffleString getMode() {
803-
return T_EVAL;
804-
}
805-
806-
static boolean isMapping(Node inliningTarget, PyMappingCheckNode mappingCheckNode, Object object) {
807-
return mappingCheckNode.execute(inliningTarget, object);
808-
}
809-
810-
static boolean isAnyNone(Object object) {
811-
return object instanceof PNone;
812-
}
813-
814-
final PCode createAndCheckCode(VirtualFrame frame, Node inliningTarget, Object source, PRaiseNode raiseNode) {
815-
PCode code = getCompileNode().compile(frame, source, T_STRING_SOURCE, getMode(), -1, -1);
816-
assertNoFreeVars(inliningTarget, code, raiseNode);
817-
return code;
818-
}
819-
820-
private static void inheritGlobals(PFrame callerFrame, Object[] args) {
821-
PArguments.setGlobals(args, callerFrame.getGlobals());
822-
}
823-
824-
private static void inheritLocals(Node inliningTarget, PFrame callerFrame, Object[] args, GetFrameLocalsNode getFrameLocalsNode) {
825-
Object callerLocals = getFrameLocalsNode.execute(inliningTarget, callerFrame);
826-
setCustomLocals(args, callerLocals);
827-
}
828-
829-
private static void setCustomLocals(Object[] args, Object locals) {
830-
PArguments.setSpecialArgument(args, locals);
831-
}
832-
833-
private void setBuiltinsInGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, HashingCollectionNodes.SetItemNode setBuiltins, PythonModule builtins) {
834-
if (builtins != null) {
835-
PDict builtinsDict = getOrCreateDictNode(builtins);
836-
setBuiltins.execute(frame, inliningTarget, globals, T___BUILTINS__, builtinsDict);
837-
} else {
838-
// This happens during context initialization
839-
return;
840-
}
841-
}
842-
843-
private void setCustomGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, HashingCollectionNodes.SetItemNode setBuiltins, Object[] args) {
844-
PythonModule builtins = getContext().getBuiltins();
845-
setBuiltinsInGlobals(frame, inliningTarget, globals, setBuiltins, builtins);
846-
PArguments.setGlobals(args, globals);
847-
}
787+
@GenerateInline
788+
@GenerateCached(false)
789+
abstract static class CreateEvalExecArgumentsNode extends Node {
790+
public abstract Object[] execute(VirtualFrame frame, Node inliningTarget, Object globals, Object locals, TruffleString mode);
848791

849792
@Specialization
850-
@SuppressWarnings("truffle-static-method")
851-
Object execInheritGlobalsInheritLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, @SuppressWarnings("unused") PNone locals,
852-
@Bind("this") Node inliningTarget,
793+
static Object[] inheritGlobals(VirtualFrame frame, Node inliningTarget, @SuppressWarnings("unused") PNone globals, Object locals, TruffleString mode,
853794
@Exclusive @Cached ReadCallerFrameNode readCallerFrameNode,
854-
@Exclusive @Cached CodeNodes.GetCodeCallTargetNode getCt,
855-
@Cached GetFrameLocalsNode getFrameLocalsNode,
856-
@Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke,
795+
@Exclusive @Cached InlinedConditionProfile haveLocals,
796+
@Exclusive @Cached PyMappingCheckNode mappingCheckNode,
797+
@Exclusive @Cached GetFrameLocalsNode getFrameLocalsNode,
857798
@Exclusive @Cached PRaiseNode raiseNode) {
858-
PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode);
859799
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
860800
Object[] args = PArguments.create();
861-
inheritGlobals(callerFrame, args);
862-
inheritLocals(inliningTarget, callerFrame, args, getFrameLocalsNode);
863-
864-
return invoke.execute(frame, inliningTarget, getCt.execute(inliningTarget, code), args);
801+
PArguments.setGlobals(args, callerFrame.getGlobals());
802+
if (haveLocals.profile(inliningTarget, locals instanceof PNone)) {
803+
Object callerLocals = getFrameLocalsNode.execute(inliningTarget, callerFrame);
804+
setCustomLocals(args, callerLocals);
805+
} else {
806+
if (!mappingCheckNode.execute(inliningTarget, locals)) {
807+
throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.LOCALS_MUST_BE_MAPPING, mode, locals);
808+
}
809+
setCustomLocals(args, locals);
810+
}
811+
return args;
865812
}
866813

867814
@Specialization
868-
Object execCustomGlobalsGlobalLocals(VirtualFrame frame, Object source, PDict globals, @SuppressWarnings("unused") PNone locals,
869-
@Bind("this") Node inliningTarget,
870-
@Shared @Cached HashingCollectionNodes.SetItemNode setBuiltins,
871-
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt,
872-
@Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke,
873-
@Shared @Cached PRaiseNode raiseNode) {
874-
PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode);
815+
static Object[] customGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, Object locals, TruffleString mode,
816+
@Bind PythonContext context,
817+
@Exclusive @Cached InlinedConditionProfile haveLocals,
818+
@Exclusive @Cached PyMappingCheckNode mappingCheckNode,
819+
@Exclusive @Cached GetOrCreateDictNode getOrCreateDictNode,
820+
@Exclusive @Cached HashingCollectionNodes.SetItemNode setBuiltins,
821+
@Exclusive @Cached PRaiseNode raiseNode) {
875822
Object[] args = PArguments.create();
876-
setCustomGlobals(frame, inliningTarget, globals, setBuiltins, args);
877-
setCustomLocals(args, globals);
878-
RootCallTarget rootCallTarget = getCt.execute(inliningTarget, code);
879-
if (rootCallTarget == null) {
880-
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.CANNOT_CREATE_CALL_TARGET, code);
823+
PythonModule builtins = context.getBuiltins();
824+
// Builtins may be null during context initialization
825+
if (builtins != null) {
826+
PDict builtinsDict = getOrCreateDictNode.execute(inliningTarget, builtins);
827+
setBuiltins.execute(frame, inliningTarget, globals, T___BUILTINS__, builtinsDict);
828+
}
829+
PArguments.setGlobals(args, globals);
830+
if (haveLocals.profile(inliningTarget, locals instanceof PNone)) {
831+
setCustomLocals(args, globals);
832+
} else {
833+
if (!mappingCheckNode.execute(inliningTarget, locals)) {
834+
throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.LOCALS_MUST_BE_MAPPING, mode, locals);
835+
}
836+
setCustomLocals(args, locals);
881837
}
882838

883-
return invoke.execute(frame, inliningTarget, rootCallTarget, args);
884-
}
885-
886-
@Specialization(guards = {"isMapping(inliningTarget, mappingCheckNode, locals)"})
887-
@SuppressWarnings("truffle-static-method")
888-
Object execInheritGlobalsCustomLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, Object locals,
889-
@Bind("this") Node inliningTarget,
890-
@SuppressWarnings("unused") @Shared @Cached PyMappingCheckNode mappingCheckNode,
891-
@Exclusive @Cached ReadCallerFrameNode readCallerFrameNode,
892-
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt,
893-
@Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke,
894-
@Shared @Cached PRaiseNode raiseNode) {
895-
PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode);
896-
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
897-
Object[] args = PArguments.create();
898-
inheritGlobals(callerFrame, args);
899-
setCustomLocals(args, locals);
900-
901-
return invoke.execute(frame, inliningTarget, getCt.execute(inliningTarget, code), args);
839+
return args;
902840
}
903841

904-
@Specialization(guards = {"isMapping(inliningTarget, mappingCheckNode, locals)"})
905-
@SuppressWarnings("truffle-static-method")
906-
Object execCustomGlobalsCustomLocals(VirtualFrame frame, Object source, PDict globals, Object locals,
907-
@Bind("this") Node inliningTarget,
908-
@SuppressWarnings("unused") @Shared @Cached PyMappingCheckNode mappingCheckNode,
909-
@Shared @Cached HashingCollectionNodes.SetItemNode setBuiltins,
910-
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt,
911-
@Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke,
912-
@Shared @Cached PRaiseNode raiseNode) {
913-
PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode);
914-
Object[] args = PArguments.create();
915-
setCustomGlobals(frame, inliningTarget, globals, setBuiltins, args);
916-
setCustomLocals(args, locals);
917-
918-
return invoke.execute(frame, inliningTarget, getCt.execute(inliningTarget, code), args);
842+
@Fallback
843+
static Object[] badGlobals(Node inliningTarget, Object globals, @SuppressWarnings("unused") Object locals, TruffleString mode) {
844+
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.GLOBALS_MUST_BE_DICT, mode, globals);
919845
}
920846

921-
@Specialization(guards = {"!isAnyNone(globals)", "!isDict(globals)"})
922-
@SuppressWarnings({"unused", "truffle-static-method"})
923-
PNone badGlobals(Object source, Object globals, Object locals,
924-
@Bind("this") Node inliningTarget) {
925-
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.GLOBALS_MUST_BE_DICT, getMode(), globals);
847+
private static void setCustomLocals(Object[] args, Object locals) {
848+
PArguments.setSpecialArgument(args, locals);
926849
}
850+
}
927851

928-
@Specialization(guards = {"isAnyNone(globals) || isDict(globals)", "!isAnyNone(locals)", "!isMapping(inliningTarget, mappingCheckNode, locals)"})
929-
@SuppressWarnings({"unused", "truffle-static-method"})
930-
PNone badLocals(Object source, PDict globals, Object locals,
931-
@Bind("this") Node inliningTarget,
932-
@Shared @Cached PyMappingCheckNode mappingCheckNode) {
933-
throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.LOCALS_MUST_BE_MAPPING, getMode(), locals);
934-
}
852+
@GenerateInline
853+
@GenerateCached(false)
854+
abstract static class EvalExecNode extends Node {
855+
abstract Object execute(VirtualFrame frame, Node inliningTarget, Object source, Object globals, Object locals, TruffleString mode, boolean shouldStripLeadingWhitespace);
935856

936-
private CompileNode getCompileNode() {
937-
if (compileNode == null) {
938-
CompilerDirectives.transferToInterpreterAndInvalidate();
939-
compileNode = insert(CompileNode.create(false, shouldStripLeadingWhitespace()));
857+
@Specialization
858+
static Object eval(VirtualFrame frame, Node inliningTarget, Object source, Object globals, Object locals, TruffleString mode, @SuppressWarnings("unused") boolean shouldStripLeadingWhitespace,
859+
@Cached("create(false, shouldStripLeadingWhitespace)") CompileNode compileNode,
860+
@Cached CreateEvalExecArgumentsNode createArguments,
861+
@Cached CodeNodes.GetCodeCallTargetNode getCallTarget,
862+
@Cached CallDispatchers.CallTargetCachedInvokeNode invoke,
863+
@Cached PRaiseNode raiseNode) {
864+
PCode code = compileNode.compile(frame, source, T_STRING_SOURCE, mode, -1, -1);
865+
if (code.getFreeVars().length > 0) {
866+
throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.CODE_OBJ_NO_FREE_VARIABLES, mode);
940867
}
941-
return compileNode;
868+
Object[] args = createArguments.execute(frame, inliningTarget, globals, locals, mode);
869+
RootCallTarget callTarget = getCallTarget.execute(inliningTarget, code);
870+
return invoke.execute(frame, inliningTarget, callTarget, args);
942871
}
872+
}
943873

944-
private PDict getOrCreateDictNode(PythonObject object) {
945-
if (getOrCreateDictNode == null) {
946-
CompilerDirectives.transferToInterpreterAndInvalidate();
947-
getOrCreateDictNode = insert(GetOrCreateDictNode.create());
948-
}
949-
return getOrCreateDictNode.executeCached(object);
950-
}
874+
// eval(expression, globals=None, locals=None)
875+
@Builtin(name = J_EVAL, minNumOfPositionalArgs = 1, parameterNames = {"expression", "globals", "locals"})
876+
@GenerateNodeFactory
877+
public abstract static class EvalNode extends PythonBuiltinNode {
951878

952-
protected boolean shouldStripLeadingWhitespace() {
953-
return true;
879+
@Specialization
880+
static Object eval(VirtualFrame frame, Object source, Object globals, Object locals,
881+
@Bind Node inliningTarget,
882+
@Cached EvalExecNode evalNode) {
883+
return evalNode.execute(frame, inliningTarget, source, globals, locals, T_EVAL, true);
954884
}
955885
}
956886

957887
@Builtin(name = J_EXEC, minNumOfPositionalArgs = 1, parameterNames = {"source", "globals", "locals"})
958888
@GenerateNodeFactory
959-
abstract static class ExecNode extends EvalNode {
960-
protected abstract Object executeInternal(VirtualFrame frame);
961-
962-
@Override
963-
protected TruffleString getMode() {
964-
return T_EXEC;
965-
}
966-
967-
@Override
968-
public final Object execute(VirtualFrame frame) {
969-
executeInternal(frame);
970-
return PNone.NONE;
971-
}
889+
public abstract static class ExecNode extends PythonBuiltinNode {
972890

973-
@Override
974-
protected boolean shouldStripLeadingWhitespace() {
975-
return false;
891+
@Specialization
892+
static Object exec(VirtualFrame frame, Object source, Object globals, Object locals,
893+
@Bind Node inliningTarget,
894+
@Cached EvalExecNode evalNode) {
895+
evalNode.execute(frame, inliningTarget, source, globals, locals, T_EXEC, false);
896+
return NONE;
976897
}
977898
}
978899

0 commit comments

Comments
 (0)