diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java
similarity index 83%
rename from com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java
index 656d5fd698afc7c7b872abfd924a2e166ffa4007..c2cd454c0010b03af51eaba66b890515234f70b1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java
@@ -15,15 +15,13 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContain
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asInt;
 
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
-final class DrawArrowsNode extends Node {
+final class Arrows {
     // Structure of an arrow description
     private static final int ARROWANGLE = 0;
     private static final int ARROWLENGTH = 1;
@@ -33,8 +31,6 @@ final class DrawArrowsNode extends Node {
     private static final int ARROWTYPE_LINES = 1;
     private static final int ARROWTYPE_POLYGON = 2;
 
-    @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
-
     /**
      * Draws arrows at the start and end of given lines.
      *
@@ -49,7 +45,7 @@ final class DrawArrowsNode extends Node {
      * @param end should we draw end arrow if the arrow list says so. Otherwise never draw it.
      * @param conversionCtx needed for unit conversions.
      */
-    public void drawArrows(double[] x, double[] y, int startIndex, int length, int parentIndex, RList arrow, boolean start, boolean end, UnitConversionContext conversionCtx) {
+    public static void drawArrows(double[] x, double[] y, int startIndex, int length, int parentIndex, RList arrow, boolean start, boolean end, UnitConversionContext conversionCtx) {
         assert x.length == y.length;
         int endsVal = asInt(arrow.getDataAt(ARROWENDS), parentIndex);
         boolean first = endsVal != 2;
@@ -62,8 +58,8 @@ final class DrawArrowsNode extends Node {
         double angle = asDouble(arrow.getDataAt(ARROWANGLE), parentIndex);
         int arrowType = asInt(arrow.getDataAt(ARROWTYPE), parentIndex);
         RAbstractContainer lengthVec = asAbstractContainer(arrow.getDataAt(ARROWLENGTH));
-        double arrowLength = unitToInches.convertHeight(lengthVec, parentIndex, conversionCtx);
-        arrowLength = Math.max(arrowLength, unitToInches.convertWidth(lengthVec, parentIndex, conversionCtx));
+        double arrowLength = Unit.convertHeight(lengthVec, parentIndex, conversionCtx);
+        arrowLength = Math.max(arrowLength, Unit.convertWidth(lengthVec, parentIndex, conversionCtx));
         // draw the arrows
         GridDevice device = conversionCtx.device;
         DrawingContext drawingCtx = conversionCtx.gpar.getDrawingContext(parentIndex);
@@ -76,7 +72,7 @@ final class DrawArrowsNode extends Node {
         }
     }
 
-    private void drawArrow(DrawingContext drawingCtx, GridDevice device, int arrowType, double x0, double y0, double x1, double y1, double angle, double length) {
+    private static void drawArrow(DrawingContext drawingCtx, GridDevice device, int arrowType, double x0, double y0, double x1, double y1, double angle, double length) {
         double a = Math.toRadians(angle);
         double xc = x1 - x0;
         double yc = y1 - y0;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index a70e2cfa41df72278ac3b7c8eecd3607edd23801..f2d1290c6e10fd3c4f50de1f5d7aa8f74d3e51c4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -22,43 +22,44 @@ import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.rotation;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-final class DoSetViewPort extends RBaseNode {
-    @Child private CastNode castScalarDouble = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
-    @Child private CastNode castDoubleVector = newCastBuilder().asDoubleVector().buildCastNode();
-    @Child private CastNode castChildrenEnv = newCastBuilder().mustBe(REnvironment.class).buildCastNode();
-    @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
+final class DoSetViewPort {
 
+    private DoSetViewPort() {
+        // only static members
+    }
+
+    /**
+     * Prepares the given view-port to be set as the current view-port, calculates necessary
+     * information for the new current view-port.
+     *
+     * @see #calcViewportTransform(RList, Object, boolean, GridDevice, GPar)
+     */
     @TruffleBoundary
-    public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
+    public static RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
         GridState gridState = GridContext.getContext().getGridState();
         Object[] pushedVPData = pushedViewPort.getDataWithoutCopying();
         if (hasParent && pushing) {
             RList parent = gridState.getViewPort();
             pushedVPData[ViewPort.PVP_PARENT] = parent;
-            REnvironment children = (REnvironment) castChildrenEnv.execute(parent.getDataAt(ViewPort.PVP_CHILDREN));
-            safePutToEnv(pushedViewPort, pushedVPData[ViewPort.VP_NAME], children);
+            REnvironment children = GridUtils.asEnvironment(parent.getDataAt(ViewPort.PVP_CHILDREN));
+            children.safePut(RRuntime.asString(pushedVPData[ViewPort.VP_NAME]), pushedViewPort);
         }
 
         GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
@@ -90,7 +91,7 @@ final class DoSetViewPort extends RBaseNode {
      *            order to convert units for the top level view port
      */
     @TruffleBoundary
-    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, GPar deviceTopLevelGpar) {
+    public static void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, GPar deviceTopLevelGpar) {
         double[][] parentTransform;
         ViewPortContext parentContext;
         ViewPortLocation vpl;
@@ -111,8 +112,8 @@ final class DoSetViewPort extends RBaseNode {
             if (!incremental) {
                 calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceTopLevelGpar);
             }
-            parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
-            parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
+            parentSize = new Size(Unit.cmToInches(GridUtils.asDouble(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(GridUtils.asDouble(parentData[ViewPort.PVP_HEIGHTCM])));
+            parentTransform = fromFlat(GridUtils.asDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
             parentContext = ViewPortContext.fromViewPort(parentVPList);
             parentAngle = asDouble(parentData[ViewPort.PVP_ROTATION]);
 
@@ -126,13 +127,13 @@ final class DoSetViewPort extends RBaseNode {
         }
 
         UnitConversionContext conversionCtx = new UnitConversionContext(parentSize, parentContext, device, drawingContext);
-        double xInches = unitsToInches.convertX(vpl.x, 0, conversionCtx);
-        double yInches = unitsToInches.convertY(vpl.y, 0, conversionCtx);
-        double width = unitsToInches.convertWidth(vpl.width, 0, conversionCtx);
-        double height = unitsToInches.convertHeight(vpl.height, 0, conversionCtx);
+        double xInches = Unit.convertX(vpl.x, 0, conversionCtx);
+        double yInches = Unit.convertY(vpl.y, 0, conversionCtx);
+        double width = Unit.convertWidth(vpl.width, 0, conversionCtx);
+        double height = Unit.convertHeight(vpl.height, 0, conversionCtx);
 
         if (!Double.isFinite(xInches) || !Double.isFinite(yInches) || !Double.isFinite(width) || !Double.isFinite(height)) {
-            throw error(Message.GENERIC, "non-finite location and/or size for viewport");
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "non-finite location and/or size for viewport");
         }
 
         double xadj = GridUtils.justification(width, vpl.hjust);
@@ -166,7 +167,7 @@ final class DoSetViewPort extends RBaseNode {
         viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3});
     }
 
-    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, GPar gpar) {
+    private static void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, GPar gpar) {
         LayoutSize layoutSize = LayoutSize.fromViewPort(viewPort);
         double[] npcWidths = new double[layoutSize.ncol];
         double[] npcHeights = new double[layoutSize.nrow];
@@ -257,7 +258,7 @@ final class DoSetViewPort extends RBaseNode {
         vpData[ViewPort.PVP_HEIGHTS] = RDataFactory.createDoubleVector(npcHeights, RDataFactory.COMPLETE_VECTOR);
     }
 
-    private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
+    private static void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
                     GridDevice device, GPar gpar, ViewPortContext parentVPCtx, boolean isWidth) {
         assert relativeItems.length == npcItems.length;
         UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
@@ -265,7 +266,7 @@ final class DoSetViewPort extends RBaseNode {
         if (reducedDim > 0) {
             for (int i = 0; i < relativeItems.length; i++) {
                 if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
-                    totalUnrespectedSize += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
+                    totalUnrespectedSize += Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
                 }
             }
         }
@@ -275,17 +276,17 @@ final class DoSetViewPort extends RBaseNode {
                 npcItems[i] = 0;
                 if (totalUnrespectedSize > 0) {
                     // if there was some with left, then totalUnrespectedSize contains sum of it
-                    npcItems[i] = reducedDim * unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth) / totalUnrespectedSize;
+                    npcItems[i] = reducedDim * Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth) / totalUnrespectedSize;
                 }
             }
         }
     }
 
-    private boolean rowColRespected(int respected, int rowOrCol, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
+    private static boolean rowColRespected(int respected, int rowOrCol, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
         return isColumn ? colRespected(respected, rowOrCol, layoutRespectMat, layoutSize) : rowRespected(respected, rowOrCol, layoutRespectMat, layoutSize);
     }
 
-    private boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) {
+    private static boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) {
         if (respected == 1) {
             return true;
         }
@@ -297,7 +298,7 @@ final class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private boolean colRespected(int respected, int col, int[] layoutRespectMat, LayoutSize layoutSize) {
+    private static boolean colRespected(int respected, int col, int[] layoutRespectMat, LayoutSize layoutSize) {
         if (respected == 1) {
             return true;
         }
@@ -309,58 +310,42 @@ final class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, GPar gpar,
+    private static double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, GPar gpar,
                     boolean isWidth) {
         UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
         double totalWidth = 0;
         for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i]) {
-                totalWidth += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
+                totalWidth += Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
             }
         }
         return totalWidth;
     }
 
-    private double getReducedDimension(RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double initialSize, UnitConversionContext conversionCtx,
+    private static double getReducedDimension(RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double initialSize, UnitConversionContext conversionCtx,
                     boolean isWidth) {
         double reducedSize = initialSize;
         for (int i = 0; i < npcItems.length; i++) {
             boolean currIsRel = Unit.isRelativeUnit(GridContext.getContext(), layoutItems, i);
             relativeItems[i] = currIsRel;
             if (!currIsRel) {
-                npcItems[i] = unitsToInches.convertDimension(layoutItems, i, conversionCtx, isWidth);
+                npcItems[i] = Unit.convertDimension(layoutItems, i, conversionCtx, isWidth);
                 reducedSize -= npcItems[i];
             }
         }
         return reducedSize;
     }
 
-    private RAbstractDoubleVector castDoubleVector(Object obj) {
-        return (RAbstractDoubleVector) castDoubleVector.execute(obj);
-    }
-
-    private double castScalar(Object obj) {
-        return (double) castScalarDouble.execute(obj);
-    }
-
     private static RDoubleVector scalar(double val) {
         return RDataFactory.createDoubleVectorFromScalar(val);
     }
 
-    private static void safePutToEnv(RList pushedViewPort, Object pushedVPDatum, REnvironment children) {
-        try {
-            children.put(RRuntime.asString(pushedVPDatum), pushedViewPort);
-        } catch (PutException e) {
-            throw RInternalError.shouldNotReachHere("Cannot update children environment in a view port list");
-        }
-    }
-
     // Note: unlike the GnuR counterpart of this method, we expect the LayoutPos to have the NULL
     // positions replaced with nrow/ncol already.
-    private ViewPortLocation calcViewportLocationFromLayout(LayoutPos pos, RList parentVP, Size parentSize) {
+    private static ViewPortLocation calcViewportLocationFromLayout(LayoutPos pos, RList parentVP, Size parentSize) {
         // unlike in GnuR, we maintain parent viewport widths/heights in inches like anything else
-        double[] widths = castDoubleVector(parentVP.getDataAt(ViewPort.PVP_WIDTHS)).materialize().getDataWithoutCopying();
-        double[] heights = castDoubleVector(parentVP.getDataAt(ViewPort.PVP_HEIGHTS)).materialize().getDataWithoutCopying();
+        double[] widths = GridUtils.asDoubleVector(parentVP.getDataAt(ViewPort.PVP_WIDTHS)).materialize().getDataWithoutCopying();
+        double[] heights = GridUtils.asDoubleVector(parentVP.getDataAt(ViewPort.PVP_HEIGHTS)).materialize().getDataWithoutCopying();
         double totalWidth = sum(widths, 0, pos.layoutSize.ncol);
         double totalHeight = sum(heights, 0, pos.layoutSize.nrow);
         double width = sum(widths, pos.colMin, pos.colMax - pos.colMin + 1);
@@ -376,7 +361,7 @@ final class DoSetViewPort extends RBaseNode {
         return result;
     }
 
-    private LayoutPos getLayoutPos(RList vp, RList parent) {
+    private static LayoutPos getLayoutPos(RList vp, RList parent) {
         LayoutSize size = LayoutSize.fromViewPort(parent);
         Object rowObj = vp.getDataAt(ViewPort.VP_VALIDLPOSROW);
         int rowMin = 1;
@@ -385,7 +370,7 @@ final class DoSetViewPort extends RBaseNode {
             rowMin = ((RAbstractIntVector) rowObj).getDataAt(0);
             rowMax = ((RAbstractIntVector) rowObj).getDataAt(1);
             if (rowMin < 1 || rowMax > size.nrow) {
-                throw error(Message.GENERIC, "invalid 'layout.pos.row'");
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "invalid 'layout.pos.row'");
             }
         }
         Object colObj = vp.getDataAt(ViewPort.VP_VALIDLPOSCOL);
@@ -395,7 +380,7 @@ final class DoSetViewPort extends RBaseNode {
             colMin = ((RAbstractIntVector) colObj).getDataAt(0);
             colMax = ((RAbstractIntVector) colObj).getDataAt(1);
             if (colMin < 1 || colMax > size.ncol) {
-                throw error(Message.GENERIC, "invalid 'layout.pos.row'");
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "invalid 'layout.pos.row'");
             }
         }
         // the indexes in LayoutPos are to be interpreted as 0-based
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
index d8b2359414dd6ac40bab72f1e23d2375f8f3d421..60ce02957ff14524dedbc3be55bb6ca915e6bf8b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.DoSetViewPort.doSetViewPort;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
@@ -29,7 +30,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
  */
 @RBuiltin(name = ".fastr.grid.doSetViewPort", parameterNames = {"vp", "hasParent", "pushing"}, kind = RBuiltinKind.INTERNAL, behavior = RBehavior.COMPLEX)
 public abstract class DoSetViewPortBuiltin extends RBuiltinNode {
-    @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
 
     static {
         Casts casts = new Casts(DoSetViewPortBuiltin.class);
@@ -40,7 +40,7 @@ public abstract class DoSetViewPortBuiltin extends RBuiltinNode {
 
     @Specialization
     RNull doIt(RList pushedVP, boolean hasParent, boolean pushing) {
-        RList vp = doSetViewPort.doSetViewPort(pushedVP, hasParent, pushing);
+        RList vp = doSetViewPort(pushedVP, hasParent, pushing);
         GridContext.getContext().getGridState().setViewPort(vp);
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index e70b56cf70651c42b1ebe3b57d456fda2942f016..1287407d6e52f3293e7faa8d46ffa062f23af8a0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -43,10 +42,6 @@ public abstract class GridLinesNode extends Node {
         return new GridLinesPolygon();
     }
 
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
-
     @TruffleBoundary
     void execute(RAbstractVector x, RAbstractVector y, RList lengths, RList arrow) {
         GridContext ctx = GridContext.getContext();
@@ -54,7 +49,7 @@ public abstract class GridLinesNode extends Node {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -79,7 +74,7 @@ public abstract class GridLinesNode extends Node {
             // such series as a polyline
             for (int i = 0; i < unitIndexesLen; i++) {
                 int unitIndex = unitIndexes.getDataAt(i) - 1;   // converting R's 1-based index
-                Point origLoc = Point.fromUnits(unitToInches, x, y, unitIndex, conversionCtx);
+                Point origLoc = Point.fromUnits(x, y, unitIndex, conversionCtx);
                 Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
                 xx[i] = loc.x;
                 yy[i] = loc.y;
@@ -102,7 +97,7 @@ public abstract class GridLinesNode extends Node {
                         if (arrow != null) {
                             // Can draw an arrow at the start if the points include the first point.
                             // Draw an arrow at the end only if this is the last series
-                            drawArrowsNode.drawArrows(xx, yy, start, length, unitIndex, arrow, start == 0, lastIter, conversionCtx);
+                            Arrows.drawArrows(xx, yy, start, length, unitIndex, arrow, start == 0, lastIter, conversionCtx);
                         }
                     }
                 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 3916bba868a13df6cfd6fe74747cd5990cecd8b1..76ccd7660bc91192096e874bdd7b4e111ce98696 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Rectangle;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
@@ -57,8 +56,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)}.
  */
 public final class GridTextNode extends RBaseNode {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     private final ConditionProfile checkOverlapProfile = ConditionProfile.createBinaryProfile();
     private final boolean draw;
@@ -97,7 +94,7 @@ public final class GridTextNode extends RBaseNode {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -117,7 +114,7 @@ public final class GridTextNode extends RBaseNode {
         }
 
         for (int i = 0; i < length; i++) {
-            Point loc = Point.fromUnits(unitToInches, x, y, i, conversionCtx);
+            Point loc = Point.fromUnits(x, y, i, conversionCtx);
             if (draw) {
                 // transformation not necessary for bounds calculation
                 loc = transLocation(loc, vpTransform.transform);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index b6aac6f088123d075aee8d2b3b134b1aa89d8c70..284a98450523ea60c5e2c57de3a91fd81070ab25 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 
 final class GridUtils {
     private GridUtils() {
@@ -207,6 +208,13 @@ final class GridUtils {
         throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non abstract container type " + value.getClass().getSimpleName());
     }
 
+    static REnvironment asEnvironment(Object value) {
+        if (value instanceof REnvironment) {
+            return (REnvironment) value;
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected: value is not environment " + value.getClass().getSimpleName());
+    }
+
     static double sum(double[] values) {
         return sum(values, 0, values.length);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 441a703d2a2a835cfd366df94edfbcf0dcd9974d..cacc0eec422c77b599c52a664d562f3de9b30abe 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -25,8 +24,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nmath.RMath;
 
 public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LCircle.class);
@@ -51,15 +48,15 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(xVec, yVec, radiusVec);
         for (int i = 0; i < length; i++) {
-            Size radiusSizes = Size.fromUnits(unitToInches, radiusVec, radiusVec, i, conversionCtx);
+            Size radiusSizes = Size.fromUnits(radiusVec, radiusVec, i, conversionCtx);
             double radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
-            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             dev.drawCircle(gpar.getDrawingContext(i), loc.x, loc.y, radius);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
index 36e207aa10d7db7c37ca4a13ad325da0cb524d83..bab570f2e8f38d12b1c18a07637ad57f1aae9179 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
@@ -17,7 +17,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -26,8 +25,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nmath.RMath;
 
 public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LCircleBounds.class);
@@ -47,7 +44,7 @@ public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -57,9 +54,9 @@ public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
         Point loc = null;  // we remember the last position and radius
         double radius = -1;
         for (int i = 0; i < length; i++) {
-            Size radiusSizes = Size.fromUnits(unitToInches, radiusVec, radiusVec, i, conversionCtx);
+            Size radiusSizes = Size.fromUnits(radiusVec, radiusVec, i, conversionCtx);
             radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
-            loc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            loc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(radius)) {
                 bounds.updateX(loc.x - radius, loc.x + radius);
                 bounds.updateY(loc.y - radius, loc.y + radius);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index e99d0b36f9efa1981d7fa79f543e7c76be9024dd..a66bbdb689aed171f31a89dc433496f2d1d0aa28 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -33,8 +32,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LConvert.class);
@@ -57,7 +54,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -110,15 +107,15 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         double inches;
         if (axisFrom.isHorizontal()) {
             if (axisFrom.isDimension()) {
-                inches = unitToInches.convertWidth(units, index, conversionCtx);
+                inches = Unit.convertWidth(units, index, conversionCtx);
             } else {
-                inches = unitToInches.convertX(units, index, conversionCtx);
+                inches = Unit.convertX(units, index, conversionCtx);
             }
         } else {
             if (axisFrom.isDimension()) {
-                inches = unitToInches.convertHeight(units, index, conversionCtx);
+                inches = Unit.convertHeight(units, index, conversionCtx);
             } else {
-                inches = unitToInches.convertY(units, index, conversionCtx);
+                inches = Unit.convertY(units, index, conversionCtx);
             }
         }
         return inches;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
index efcdc7d8db91a092e7b47344bfed34dfc98d9100..97536e3dd007dde16e8e70b620871acbeed8d62a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
@@ -18,7 +18,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -26,8 +25,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LLocnBounds.class);
@@ -48,7 +45,7 @@ public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -62,7 +59,7 @@ public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
         Bounds bounds = new Bounds();
         int count = 0;
         for (int i = 0; i < length; i++) {
-            Point loc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Point loc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             xx[i] = loc.x;
             yy[i] = loc.y;
             if (loc.isFinite()) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 2f491ea4ccfaa8a626abc1e65684460dffc179df..95c5e9bcfd0767a0731a6920f4a06256552c4f16 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -33,7 +33,7 @@ final class LNewPage extends RExternalBuiltinNode {
             return RNull.instance;
         }
         // There are some exceptions to the rule that any external call from grid R code is
-        // preceeded by L_gridDirty call, L_newpage is one of them.
+        // preceded by L_gridDirty call, L_newpage is one of them.
         CompilerDirectives.transferToInterpreter();
         return gridDirty.call(frame, RArgsValuesAndNames.EMPTY);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index f92e35e49401215e7f6fba4ce94dfee07a878e0c..02d7c1b47f5aa8c05d30e490a58b3ec267fceeb4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -17,8 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -39,10 +37,6 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
     private static final double TRC1 = 1.34677368708859836060; /* TRC0 * sqrt(3) / 2 */
     private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */
 
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-
-    @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
-
     static {
         Casts casts = new Casts(LPoints.class);
         casts.arg(0).mustBe(abstractVectorValue());
@@ -65,7 +59,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         RList gparList = ctx.getGridState().getGpar();
         GPar gpar = GPar.create(gparList);
         double cex = GPar.getCex(gparList);
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -74,8 +68,8 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         DrawingContext initialDrawingCtx = gpar.getDrawingContext(0);
         PointDrawingContext pointDrawingCtx = new PointDrawingContext(initialDrawingCtx, initialDrawingCtx.getFillColor(), initialDrawingCtx.getFillColor());
         for (int i = 0; i < length; i++) {
-            Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx), vpTransform.transform);
-            double size = unitToInches.convertWidth(sizeVec, i, conversionCtx);
+            Point loc = TransformMatrix.transLocation(Point.fromUnits(xVec, yVec, i, conversionCtx), vpTransform.transform);
+            double size = Unit.convertWidth(sizeVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(size)) {
                 pointDrawingCtx = pointDrawingCtx.update(gpar.getDrawingContext(i));
                 pointDrawingCtx = drawSymbol(pointDrawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index c99f7401c11b689d1c735513f188226674f2bb9b..1d2ce1bdb67b9d8213ca2a9a7481feddbaf14e0f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -18,7 +18,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -27,8 +26,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LRect extends RExternalBuiltinNode.Arg6 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LRect.class);
@@ -56,14 +53,14 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
-            Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
-            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Size size = Size.fromUnits(wVec, hVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
             dev.drawRect(gpar.getDrawingContext(i), loc.x, loc.y, size.getWidth(), size.getHeight(), Math.toRadians(vpTransform.rotationAngle));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
index 9eebc15292906bed275fceaac8ca4364f65fb467..2aff9d698f78f0ef53b1e3359ea9d483212146ce 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
@@ -19,7 +19,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -29,8 +28,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LRectBounds.class);
@@ -50,7 +47,7 @@ public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -58,8 +55,8 @@ public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
         Bounds bounds = new Bounds();
         int nrect = 0;
         for (int i = 0; i < length; i++) {
-            Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
-            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Size size = Size.fromUnits(wVec, hVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             // just calculate the bounds, no transformation necessary
             Point loc = origLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
             if (size.isFinite() && loc.isFinite()) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index e3fa28dd480f9072e14ee7499c63233b7ffdce61..2c384f0488e7801d38ebc4baa8c0c9d309bc5289 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -28,10 +27,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  * which gets a vector of points and connects them all.
  */
 public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
-
     static {
         Casts casts = new Casts(LSegments.class);
         casts.arg(0).mustBe(abstractVectorValue());
@@ -58,7 +53,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -66,8 +61,8 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         double[] xx = new double[2];
         double[] yy = new double[2];
         for (int i = 0; i < length; i++) {
-            Point loc1 = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x0, y0, i, conversionCtx), vpTransform.transform);
-            Point loc2 = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x1, y1, i, conversionCtx), vpTransform.transform);
+            Point loc1 = TransformMatrix.transLocation(Point.fromUnits(x0, y0, i, conversionCtx), vpTransform.transform);
+            Point loc2 = TransformMatrix.transLocation(Point.fromUnits(x1, y1, i, conversionCtx), vpTransform.transform);
             if (!loc1.isFinite() || !loc2.isFinite()) {
                 continue;
             }
@@ -77,7 +72,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
             yy[1] = loc2.y;
             dev.drawPolyLines(gpar.getDrawingContext(i), xx, yy, 0, 2);
             if (arrow != null) {
-                drawArrowsNode.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
+                Arrows.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
             }
         }
         return RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
index f23564cd261e1d0fcd634de7c4a43a9252753bbb..f8fb9b0e6da3f6c0989ea781ed35fca95360d790 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
@@ -28,8 +28,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 
 public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
-    @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
-
     static {
         Casts casts = new Casts(LUnsetViewPort.class);
         casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst();
@@ -67,7 +65,7 @@ public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
         if (ViewPort.updateDeviceSizeInVP(newVp, device)) {
             // Note: like in other places calling this, why incremental == true, given that the
             // device has changed? Don't we want to recalculate the whole tree?
-            doSetViewPort.calcViewportTransform(newVp, newVp.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
+            DoSetViewPort.calcViewportTransform(newVp, newVp.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
         }
 
         gridState.setGpar(asList(newVp.getDataAt(ViewPort.PVP_GPAR)));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
index a4080e1ae7d1e2d94707fb7da562bade0c778e64..e2b1505d667b9a7ee279f14d5061e4a0e27ed762 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
@@ -47,7 +47,7 @@ public abstract class LValidUnit extends RExternalBuiltinNode.Arg1 {
         return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR);
     }
 
-    protected int convertSingle(String name) {
+    private int convertSingle(String name) {
         if (name.equals("npc")) {
             // seems to be by far the most common unit
             return Unit.NPC;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
index ba2c5135203ec29e6c547b259fdfa90c2a97de14..bd5311e91630160f3cbb555a00ac429e672e6f8e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public final class Point {
@@ -35,10 +34,8 @@ public final class Point {
         this.y = y;
     }
 
-    public static Point fromUnits(UnitToInchesNode unitToInches, RAbstractVector x, RAbstractVector y, int index, UnitConversionContext ctx) {
-        double newX = unitToInches.convertX(x, index, ctx);
-        double newY = unitToInches.convertY(y, index, ctx);
-        return new Point(newX, newY);
+    public static Point fromUnits(RAbstractVector x, RAbstractVector y, int index, UnitConversionContext ctx) {
+        return new Point(Unit.convertX(x, index, ctx), Unit.convertY(y, index, ctx));
     }
 
     public Point justify(Size size, double hjust, double vjust) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
deleted file mode 100644
index 6ff0c0c5f23b2a02672db844e9197e884de53f08..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2017, 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.library.fastrGrid;
-
-import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.frame.FrameDescriptor;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
-import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.RInternalCode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
-
-/**
- * Allows to call arbitrary R function from {@code fastrGrid.R} source.
- */
-final class RGridCodeCall extends Node {
-    private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("<fastrGrid.R tmp frame>");
-    @Child private RInternalCodeBuiltinNode child;
-
-    RGridCodeCall(String functionName) {
-        child = new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(GPar.class, "fastrGrid.R"), functionName);
-    }
-
-    static {
-        FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<fastrGrid.R tmp frame>", emptyFrameDescriptor);
-    }
-
-    public Object call(Object arg1) {
-        return execute(new RArgsValuesAndNames(new Object[]{arg1}, ArgumentsSignature.empty(1)));
-    }
-
-    public Object execute(RArgsValuesAndNames args) {
-        Object[] dummyFrameArgs = RArguments.createUnitialized();
-        VirtualFrame dummyFrame = Truffle.getRuntime().createVirtualFrame(dummyFrameArgs, emptyFrameDescriptor);
-        return child.call(dummyFrame, args);
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
index 5ab5ed637301e950b718f983d85a6afb86795f16..1dd7e55ce6ac7998b9adf1f3189e91dfdd289a12 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public final class Size {
@@ -35,9 +34,9 @@ public final class Size {
         this.height = height;
     }
 
-    public static Size fromUnits(UnitToInchesNode unitToInches, RAbstractVector wVec, RAbstractVector hVec, int index, UnitConversionContext conversionCtx) {
-        double w = unitToInches.convertWidth(wVec, index, conversionCtx);
-        double h = unitToInches.convertHeight(hVec, index, conversionCtx);
+    public static Size fromUnits(RAbstractVector wVec, RAbstractVector hVec, int index, UnitConversionContext conversionCtx) {
+        double w = Unit.convertWidth(wVec, index, conversionCtx);
+        double h = Unit.convertHeight(hVec, index, conversionCtx);
         return new Size(w, h);
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index eca26778b920c609a65d9b8c40f7aaa414f3ebbf..1d6405efaf78e1942d91018099ea19e6c5df9c42 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -27,21 +27,12 @@ import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_
 
 import java.util.function.BiFunction;
 
-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.nodes.Node;
-import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
-import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
@@ -51,7 +42,6 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Note: internally in FastR Grid everything is in inches. However, some lists that are exposed to
@@ -139,10 +129,6 @@ public final class Unit {
         return result;
     }
 
-    public static UnitToInchesNode createToInchesNode() {
-        return UnitToInchesNode.create();
-    }
-
     static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
         switch (unitId) {
             case NATIVE:
@@ -228,16 +214,16 @@ public final class Unit {
             case MYSTRINGWIDTH:
                 str = RRuntime.asString(data.getDataAt(0));
                 lines = str.split("\n");
-                for (int i = 0; i < lines.length; i++) {
-                    result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), lines[i]));
+                for (String line1 : lines) {
+                    result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), line1));
                 }
                 return value * result;
             case STRINGHEIGHT:
             case MYSTRINGHEIGHT:
                 str = RRuntime.asString(data.getDataAt(0));
                 lines = str.split("\n");
-                for (int i = 0; i < lines.length; i++) {
-                    result += ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), lines[i]);
+                for (String line : lines) {
+                    result += ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), line);
                 }
                 return value * result;
             case NULL:
@@ -451,23 +437,6 @@ public final class Unit {
         return UnitLengthVisitor.INSTANCE.visit(unit);
     }
 
-    abstract static class UnitNodeBase extends RBaseNode {
-        @Child private InheritsCheckNode inheritsArithmeticCheckNode = new InheritsCheckNode(UNIT_ARITHMETIC_CLASS);
-        @Child private InheritsCheckNode inheritsUnitListCheckNode = new InheritsCheckNode(UNIT_LIST_CLASS);
-
-        boolean isSimple(Object obj) {
-            return !inheritsArithmeticCheckNode.execute(obj) && !inheritsUnitListCheckNode.execute(obj);
-        }
-
-        boolean isArithmetic(Object obj) {
-            return inheritsArithmeticCheckNode.execute(obj);
-        }
-
-        boolean isUnitList(Object obj) {
-            return inheritsUnitListCheckNode.execute(obj);
-        }
-    }
-
     /**
      * Returns {@code true} if the given unit object represents a unit without actual unit type,
      * i.e. the unit type is {@link #NULL}. Such units are used internally for layouting, and the
@@ -548,65 +517,41 @@ public final class Unit {
         }
     }
 
-    /**
-     * Normalizes grid unit object to a double value in inches. For convenience the index is
-     * interpreted as cyclic.
-     */
-    public abstract static class UnitToInchesNode extends UnitNodeBase {
-        @Child GrobUnitToInches grobUnitToInches;
+    private static final class UnitConversionArgs {
+        public final UnitConversionContext ctx;
+        public final AxisOrDimension axisOrDim;
+        public final int index;
 
-        public static UnitToInchesNode create() {
-            return UnitToInchesNodeGen.create();
-        }
-
-        public double convertX(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.X);
-        }
-
-        public double convertY(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.Y);
-        }
-
-        public double convertWidth(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.WIDTH);
-        }
-
-        public double convertHeight(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.HEIGHT);
-        }
-
-        public double convertDimension(RAbstractContainer vector, int index, UnitConversionContext ctx, boolean isWidth) {
-            return isWidth ? convertWidth(vector, index, ctx) : convertHeight(vector, index, ctx);
+        UnitConversionArgs(int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+            this.ctx = ctx;
+            this.axisOrDim = axisOrDim;
+            this.index = index;
         }
+    }
 
-        public abstract double execute(RAbstractContainer vector, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim);
+    private static final class UnitConvertVisitor extends UnitVisitor<Double, UnitConversionArgs> {
+        private static final UnitConvertVisitor INSTANCE = new UnitConvertVisitor();
 
-        @Specialization(guards = "isSimple(value)")
-        double doNormal(RAbstractVector value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
-            int unitId = getDataAtMod(asIntVector(value.getAttr(UNIT_ATTR_UNIT_ID)), index);
-            double scalarValue = getDoubleAt(value, index % value.getLength());
+        @Override
+        protected Double visitSimpleUnit(RAbstractVector value, UnitConversionArgs args) {
+            int unitId = getDataAtMod(asIntVector(value.getAttr(UNIT_ATTR_UNIT_ID)), args.index);
+            double scalarValue = getDoubleAt(value, args.index % value.getLength());
             if (isGrobUnit(unitId)) {
                 RList grobList = asList(value.getAttr(UNIT_ATTR_DATA));
-                return getGrobUnitToInchesNode().execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), ctx);
+                return grobUnitToInches(scalarValue, unitId, grobList.getDataAt(args.index % grobList.getLength()), args.ctx);
             }
-            return convertToInches(scalarValue, index, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), ctx, axisOrDim);
+            return convertToInches(scalarValue, args.index, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), args.ctx, args.axisOrDim);
         }
 
-        @Specialization(guards = "isUnitList(value)")
-        double doList(RList value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
-                        @Cached("create()") UnitToInchesNode recursiveNode) {
-            Object unwrapped = value.getDataAt(index % value.getLength());
-            if (unwrapped instanceof RAbstractVector) {
-                return recursiveNode.execute((RAbstractContainer) unwrapped, 0, ctx, axisOrDim);
-            }
-            throw error(Message.GENERIC, "Unexpected unit list with non-vector like element at index " + index);
+        @Override
+        protected Double visitListUnit(RList unit, UnitConversionArgs args) {
+            return visit(asAbstractContainer(unit.getDataAt(args.index % unit.getLength())), new UnitConversionArgs(0, args.ctx, args.axisOrDim));
         }
 
-        @Specialization(guards = "isArithmetic(list)")
-        double doArithmetic(RList list, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
-                        @Cached("create()") UnitToInchesNode recursiveNode) {
-            ArithmeticUnit expr = ArithmeticUnit.asArithmeticUnit(list);
-            BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> recursiveNode.execute(x, index, getNewCtx(ctx, axisOrDim, newNullAMode), axisOrDim);
+        @Override
+        protected Double visitArithmeticUnit(ArithmeticUnit expr, UnitConversionArgs args) {
+            BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> visit(x,
+                            new UnitConversionArgs(args.index, getNewCtx(args.ctx, args.axisOrDim, newNullAMode), args.axisOrDim));
             switch (expr.op) {
                 case "+":
                     return recursive.apply(expr.arg1, L_adding) + recursive.apply(expr.arg2, L_adding);
@@ -614,17 +559,17 @@ public final class Unit {
                     return recursive.apply(expr.arg1, L_subtracting) - recursive.apply(expr.arg2, L_subtracting);
                 case "*":
                     RAbstractDoubleVector left = asDoubleVector(expr.arg1);
-                    return left.getDataAt(index % left.getLength()) * recursive.apply(expr.arg2, L_multiplying);
+                    return left.getDataAt(args.index % left.getLength()) * recursive.apply(expr.arg2, L_multiplying);
                 default:
                     break;
             }
 
             // must be aggregate operation
-            UnitConversionContext newCtx = getNewCtx(ctx, axisOrDim, getNullAMode(expr.op));
+            UnitConversionContext newCtx = getNewCtx(args.ctx, args.axisOrDim, getNullAMode(expr.op));
             int len = getLength(expr.arg1);
             double[] values = new double[len];
             for (int i = 0; i < len; i++) {
-                values[i] = recursiveNode.execute(expr.arg1, i, newCtx, axisOrDim);
+                values[i] = visit(expr.arg1, new UnitConversionArgs(i, newCtx, args.axisOrDim));
             }
 
             switch (expr.op) {
@@ -656,105 +601,100 @@ public final class Unit {
             }
             return L_plain;
         }
+    }
 
-        private GrobUnitToInches getGrobUnitToInchesNode() {
-            if (grobUnitToInches == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                grobUnitToInches = insert(new GrobUnitToInches());
-            }
-            return grobUnitToInches;
-        }
+    public static double convert(RAbstractContainer unit, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+        return UnitConvertVisitor.INSTANCE.visit(unit, new UnitConversionArgs(index, ctx, axisOrDim));
     }
 
-    public static final class GrobUnitToInches extends Node {
-        @Child private RGridCodeCall preDrawCode = new RGridCodeCall("grobConversionPreDraw");
-        @Child private RGridCodeCall getUnitXY = new RGridCodeCall("grobConversionGetUnitXY");
-        @Child private RGridCodeCall postDrawCode = new RGridCodeCall("grobConversionPostDraw");
-        @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-        @Child private UnitToInchesNode unitToInches = createToInchesNode();
-
-        @Child private UnitToInchesNode unitToInchesNode;
-
-        // transcribed from unit.c function evaluateGrobUnit
-
-        public double execute(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
-            GridState gridState = GridContext.getContext().getGridState();
-            return gridState.runWithoutRecording(() -> executeImpl(value, unitId, grob, conversionCtx));
-        }
-
-        private double executeImpl(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
-            GridContext ctx = GridContext.getContext();
-            RList currentVP = ctx.getGridState().getViewPort();
-            getViewPortTransform.execute(currentVP, conversionCtx.device);
-
-            RList savedGPar = ctx.getGridState().getGpar();
-            Object savedGrob = ctx.getGridState().getCurrentGrob();
-
-            Object updatedGrob = preDrawCode.call(grob);
-
-            /*
-             * The call to preDraw may have pushed viewports and/or enforced gpar settings, SO we
-             * need to re-establish the current viewport and gpar settings before evaluating the
-             * width unit.
-             */
-            currentVP = ctx.getGridState().getViewPort();
-            RList currentGP = ctx.getGridState().getGpar();
-            ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, conversionCtx.device);
-            ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-
-            // getUnitXY returns a list with either one or two items
-            RList unitxy = (RList) getUnitXY.execute(new RArgsValuesAndNames(new Object[]{updatedGrob, unitId, value}, ArgumentsSignature.empty(3)));
-            double result;
-            switch (unitId) {
-                case GROBX:
-                case GROBY:
-                    if (unitId == GROBY && isRelativeUnit(ctx, unitxy.getDataAt(1), 0)) {
-                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
-                    } else if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
-                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
-                    } else {
-                        double[][] inversed = TransformMatrix.inversion(vpTransform.transform);
-                        Point loc = Point.fromUnits(unitToInches, (RAbstractVector) unitxy.getDataAt(0), (RAbstractVector) unitxy.getDataAt(1), 0, conversionCtx);
-                        Point transLoc = TransformMatrix.transLocation(loc, vpTransform.transform);
-                        Point p = TransformMatrix.transLocation(transLoc, inversed);
-                        result = unitId == GROBX ? p.x : p.y;
-                    }
-                    break;
-                default:
-                    // should still be GROB_SOMETHING unit: width, height, ascent, descent
-                    if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
-                        // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
-                        // GROBHEIGHT, bug?
-                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+    public static double convertX(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.X);
+    }
+
+    public static double convertY(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.Y);
+    }
+
+    public static double convertWidth(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.WIDTH);
+    }
+
+    public static double convertHeight(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.HEIGHT);
+    }
+
+    public static double convertDimension(RAbstractContainer unit, int index, UnitConversionContext ctx, boolean isWidth) {
+        return convert(unit, index, ctx, isWidth ? AxisOrDimension.WIDTH : AxisOrDimension.HEIGHT);
+    }
+
+    private static double grobUnitToInches(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
+        return GridContext.getContext().getGridState().runWithoutRecording(() -> grobUnitToInchesImpl(value, unitId, grob, conversionCtx));
+    }
+
+    private static double grobUnitToInchesImpl(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
+        GridContext ctx = GridContext.getContext();
+        RList currentVP = ctx.getGridState().getViewPort();
+        // This may update the VP if the device size has changed
+        ViewPortTransform.get(currentVP, conversionCtx.device);
+
+        RList savedGPar = ctx.getGridState().getGpar();
+        Object savedGrob = ctx.getGridState().getCurrentGrob();
+
+        Object updatedGrob = ctx.evalInternalRFunction("grobConversionPreDraw", grob);
+
+        /*
+         * The call to preDraw may have pushed viewports and/or enforced gpar settings, SO we need
+         * to re-establish the current viewport and gpar settings before evaluating the width unit.
+         */
+        currentVP = ctx.getGridState().getViewPort();
+        RList currentGP = ctx.getGridState().getGpar();
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, conversionCtx.device);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
+
+        // getUnitXY returns a list with either one or two items
+        RList unitxy = (RList) ctx.evalInternalRFunction("grobConversionGetUnitXY", updatedGrob, unitId, value);
+        double result;
+        switch (unitId) {
+            case GROBX:
+            case GROBY:
+                if (unitId == GROBY && isRelativeUnit(ctx, unitxy.getDataAt(1), 0)) {
+                    double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0);
+                    result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+                } else if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
+                    double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
+                    result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+                } else {
+                    double[][] inversed = TransformMatrix.inversion(vpTransform.transform);
+                    Point loc = Point.fromUnits((RAbstractVector) unitxy.getDataAt(0), (RAbstractVector) unitxy.getDataAt(1), 0, conversionCtx);
+                    Point transLoc = TransformMatrix.transLocation(loc, vpTransform.transform);
+                    Point p = TransformMatrix.transLocation(transLoc, inversed);
+                    result = unitId == GROBX ? p.x : p.y;
+                }
+                break;
+            default:
+                // should still be GROB_SOMETHING unit: width, height, ascent, descent
+                if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
+                    // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
+                    // GROBHEIGHT, bug?
+                    double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
+                    result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+                } else {
+                    UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.create(currentGP));
+                    if (unitId == GROBWIDTH) {
+                        result = convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
                     } else {
-                        UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.create(currentGP));
-                        initUnitToInchesNode();
-                        if (unitId == GROBWIDTH) {
-                            result = unitToInchesNode.convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
-                        } else {
-                            // Note: GnuR uses height transform for both grobascent, grobdescent and
-                            // for height
-                            result = unitToInchesNode.convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
-                        }
+                        // Note: GnuR uses height transform for both grobascent, grobdescent and
+                        // for height
+                        result = convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
                     }
-                    result *= value;
-                    break;
-            }
-
-            postDrawCode.call(updatedGrob);
-            ctx.getGridState().setGpar(savedGPar);
-            ctx.getGridState().setCurrentGrob(savedGrob);
-            return result;
+                }
+                result *= value;
+                break;
         }
 
-        private void initUnitToInchesNode() {
-            if (unitToInchesNode == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                unitToInchesNode = UnitToInchesNode.create();
-            }
-        }
+        ctx.evalInternalRFunction("grobConversionPostDraw", updatedGrob);
+        ctx.getGridState().setGpar(savedGPar);
+        ctx.getGridState().setCurrentGrob(savedGrob);
+        return result;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
index 80e93f6270d712ec482957010c2dde21dce72014..6bd2592e1610cafb8fd09614d33457f6387881da 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -148,7 +148,6 @@ final class ViewPort {
     public static final class InitViewPortNode extends Node {
         @Child private ReadVariableNode readGridTopLevel = ReadVariableNode.create("grid.top.level.vp");
         @Child private RExplicitCallNode callNode = RExplicitCallNode.create();
-        @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
 
         public RList execute(VirtualFrame frame) {
             RFunction gridTopLevel = (RFunction) readGridTopLevel.execute(frame);
@@ -161,7 +160,7 @@ final class ViewPort {
             data[ViewPort.VP_XSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getWidth()}, RDataFactory.COMPLETE_VECTOR);
             data[ViewPort.VP_YSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getHeight()}, RDataFactory.COMPLETE_VECTOR);
             data[ViewPort.PVP_GPAR] = GridContext.getContext().getGridState().getGpar();
-            return doSetViewPort.doSetViewPort(topVP, false, true);
+            return DoSetViewPort.doSetViewPort(topVP, false, true);
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
index bed955d7f2988fb4a85d773cb1c452d7b4016484..179ec60d185947d6dbffb883dca04063d8b9b92f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
@@ -11,13 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
@@ -38,35 +32,17 @@ public final class ViewPortTransform {
         this.transform = transform;
     }
 
-    public static final class GetViewPortTransformNode extends Node {
-        @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
-        @Child private CastNode castScalarDouble = newCastBuilder().mustBe(numericValue()).asDoubleVector().findFirst().buildCastNode();
-        @Child private DoSetViewPort doSetViewPort;
-
-        public ViewPortTransform execute(RList viewPort, GridDevice device) {
-            if (ViewPort.updateDeviceSizeInVP(viewPort, device)) {
-                // Note: GnuR sets incremental parameter to true, but don't we need to recalculate
-                // the parent(s) as well?
-                initDoSetViewportNode();
-                doSetViewPort.calcViewportTransform(viewPort, viewPort.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
-            }
-            double width = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
-            double height = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
-            double rotationAngle = getScalar(viewPort.getDataAt(ViewPort.VP_ANGLE));
-            RAbstractDoubleVector trans = (RAbstractDoubleVector) castDoubleVector.execute(viewPort.getDataAt(ViewPort.PVP_TRANS));
-            double[][] transform = TransformMatrix.fromFlat(trans.materialize().getDataWithoutCopying());
-            return new ViewPortTransform(width, height, rotationAngle, transform);
-        }
-
-        private void initDoSetViewportNode() {
-            if (doSetViewPort == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                doSetViewPort = new DoSetViewPort();
-            }
-        }
-
-        private double getScalar(Object value) {
-            return (double) castScalarDouble.execute(value);
+    public static ViewPortTransform get(RList viewPort, GridDevice device) {
+        if (ViewPort.updateDeviceSizeInVP(viewPort, device)) {
+            // Note: GnuR sets incremental parameter to true, but don't we need to recalculate
+            // the parent(s) as well?
+            DoSetViewPort.calcViewportTransform(viewPort, viewPort.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
         }
+        double width = Unit.cmToInches(GridUtils.asDouble(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
+        double height = Unit.cmToInches(GridUtils.asDouble(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
+        double rotationAngle = GridUtils.asDouble(viewPort.getDataAt(ViewPort.VP_ANGLE));
+        RAbstractDoubleVector trans = GridUtils.asDoubleVector(viewPort.getDataAt(ViewPort.PVP_TRANS));
+        double[][] transform = TransformMatrix.fromFlat(trans.materialize().getDataWithoutCopying());
+        return new ViewPortTransform(width, height, rotationAngle, transform);
     }
 }
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index a72c103a9a0f35fe0d2e62be3dd50fb1c660ff2d..e5dac23416de2bb12398e2780659a48933b47eb3 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -747,7 +747,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.ja
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright