diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java
index 70231b22c71bf5faf7cff615c51c710e72646d75..039c73841ccc5559eef108607100d3610b40ca70 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java
@@ -40,16 +40,22 @@ public class FastRComponent extends JComponent {
     private boolean shouldDraw;
     private CoordinateSystem coordinateSystem;
 
+    /**
+     * Note! Called from ED thread.
+     */
     @Override
     public void doLayout() {
         super.doLayout();
         Dimension size = getSize();
         coordinateSystem = new CoordinateSystem(0, size.getWidth(), 0, size.getHeight());
+        shouldDraw = true;
         recalculateDisplayList();
     }
 
     private void recalculateDisplayList() {
-        displayList.stream().forEach(d -> d.recalculateForDrawingIn(coordinateSystem));
+        synchronized (displayList) {
+            displayList.stream().forEach(drawableObject -> drawableObject.recalculateForDrawingIn(coordinateSystem));
+        }
     }
 
     /**
@@ -66,14 +72,14 @@ public class FastRComponent extends JComponent {
 
     private void drawDisplayListOn(Graphics2D g2) {
         synchronized (displayList) {
-            for (DrawableObject drawableObject : displayList) {
-                drawableObject.drawOn(g2);
-            }
+            displayList.stream().forEach(drawableObject -> drawableObject.drawOn(g2));
         }
     }
 
     public void addDrawableObject(DrawableObject drawableObject) {
-        displayList.add(drawableObject);
+        synchronized (displayList) {
+            displayList.add(drawableObject);
+        }
         shouldDraw = true;
         if (coordinateSystem != null) {
             drawableObject.recalculateForDrawingIn(coordinateSystem);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java
index 90f2f715e204643c0136503d941204ab48030b9b..ede0e6a824f2f102224ee14700f39d37804b3d28 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java
@@ -24,8 +24,20 @@ package com.oracle.truffle.r.library.graphics.core;
 
 public abstract class AbstractGraphicsSystem implements GraphicsSystem {
     private final GraphicsSystemParameters graphicsSystemParameters = new GraphicsSystemParameters();
+    private int id;
 
     protected GraphicsSystemParameters getGraphicsSystemParameters() {
         return graphicsSystemParameters;
     }
+
+
+    @Override
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    @Override
+    public int getId() {
+        return id;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java
index ec41210fbfa47c2a8f9d1390caaa356dc3f46be4..6749e6a89970b978c13049ad940b0fbe58023853 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java
@@ -25,10 +25,9 @@ package com.oracle.truffle.r.library.graphics.core;
 import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
 
 public interface GraphicsEngine {
-    int registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception;
+    void registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception;
 
-    // todo replace index with object ?
-    void unRegisterGraphicsSystem(int graphicsSystemId);
+    void unRegisterGraphicsSystem(GraphicsSystem graphicsSystem);
 
     void registerGraphicsDevice(GraphicsDevice newGraphicsDevice) throws Exception;
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java
index 4c3f51880260de9e8e8e6cc94a436dd68ac4fb37..2b43bdf358cc1eab8828f8ab36dfbd2ed49a69cc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java
@@ -62,19 +62,18 @@ public final class GraphicsEngineImpl implements GraphicsEngine {
         graphicsDevices[NULL_GRAPHICS_DEVICE_INDEX] = NullGraphicsDevice.getInstance();
     }
 
-    public int registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception {
+    public void registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception {
         if (newGraphicsSystem == null) {
             throw new NullPointerException("Graphics system to register is null");
         }
-        int index = findElementIndexInArray(null, graphicsSystems); // find null in the
-        // graphicsSystems
+        int index = findElementIndexInArray(null, graphicsSystems); // find null in the graphicsSystems
         if (NOT_FOUND == index) {
             throw handleErrorAndMakeException("too many graphics systems registered");
         }
+        newGraphicsSystem.setId(index);
         graphicsSystems[index] = newGraphicsSystem;
         callListenerForEachDevice(newGraphicsSystem.getGraphicsEventsListener(), GE_INIT_STATE);
         graphicsSystemsAmount++;
-        return index;
     }
 
     private void callListenerForEachDevice(AbstractGraphicsSystem.GraphicsEventsListener listener, GraphicsEvent event) {
@@ -99,13 +98,13 @@ public final class GraphicsEngineImpl implements GraphicsEngine {
         Utils.warn(warningMessage);
     }
 
-    public void unRegisterGraphicsSystem(int graphicsSystemId) {
+    public void unRegisterGraphicsSystem(GraphicsSystem graphicsSystem) {
+        int graphicsSystemId = graphicsSystem.getId();
         checkGraphicsSystemIndex(graphicsSystemId);
         if (graphicsSystemsAmount == 0) {
             issueWarning("no graphics system to unregister");
             return;
         }
-        GraphicsSystem graphicsSystem = graphicsSystems[graphicsSystemId];
         callListenerForEachDevice(graphicsSystem.getGraphicsEventsListener(), GE_FINAL_STATE);
         graphicsSystems[graphicsSystemId] = null;
         graphicsSystemsAmount--;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java
index a7990c224bba2ba8b6a7b7da76be61f9e4122e78..5fdd3467d6522f3c65fe174d3306c8aba51ab220 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java
@@ -25,6 +25,10 @@ package com.oracle.truffle.r.library.graphics.core;
 public interface GraphicsSystem {
     GraphicsEventsListener getGraphicsEventsListener();
 
+    void setId(int id);
+
+    int getId();
+
     public interface GraphicsEventsListener {
         void onEvent(GraphicsEvent graphicsEvent, GraphicsDevice graphicsDevice);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/dataframe_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/dataframe_overrides.R
deleted file mode 100644
index bbca2d76e6ba1c92a20a80a92c3dd92ae8205bfd..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/dataframe_overrides.R
+++ /dev/null
@@ -1,215 +0,0 @@
-#  File src/library/base/R/dataframe.R
-#  Part of the R package, http://www.R-project.org
-#
-#  This program is free software; you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
-#
-#  This program 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 for more details.
-#
-#  A copy of the GNU General Public License is available at
-#  http://www.r-project.org/Licenses/
-
-# Statlib code by John Chambers, Bell Labs, 1994
-# Changes Copyright (C) 1998-2013 The R Core Team
-
-
-## As from R 2.4.0, row.names can be either character or integer.
-## row.names() will always return character.
-## attr(, "row.names") will return either character or integer.
-##
-## Do not assume that the internal representation is either, since
-## 1L:n is stored as the integer vector c(NA, n) to save space (and
-## the C-level code to get/set the attribute makes the appropriate
-## translations.
-##
-## As from 2.5.0 c(NA, n > 0) indicates deliberately assigned row names,
-## and c(NA, n < 0) automatic row names.
-
-## We cannot allow long vectors as elements until we can handle
-## duplication of row names.
-
-# Until parsing problem fixed
-
-`[.data.frame` <-
-		function(x, i, j, drop = if(missing(i)) TRUE else length(cols) == 1)
-{
-
-	mdrop <- missing(drop)
-	# TODO: parsing problem?
-#	Narg <- nargs() - !mdrop  # number of arg from x,i,j that were specified
-	Narg <- nargs() - (!mdrop)  # number of arg from x,i,j that were specified
-	has.j <- !missing(j)
-	if(!all(names(sys.call()) %in% c("", "drop"))
-			&& !isS4(x)) # at least don't warn for callNextMethod!
-		warning("named arguments other than 'drop' are discouraged")
-
-	if(Narg < 3L) {  # list-like indexing or matrix indexing
-		if(!mdrop) warning("'drop' argument will be ignored")
-		if(missing(i)) return(x)
-		if(is.matrix(i))
-			return(as.matrix(x)[i])  # desperate measures
-		## zero-column data frames prior to 2.4.0 had no names.
-		nm <- names(x); if(is.null(nm)) nm <- character()
-		## if we have NA names, character indexing should always fail
-		## (for positive index length)
-		if(!is.character(i) && anyNA(nm)) { # less efficient version
-			names(nm) <- names(x) <- seq_along(x)
-			y <- NextMethod("[")
-			cols <- names(y)
-			if(anyNA(cols)) stop("undefined columns selected")
-			cols <- names(y) <- nm[cols]
-		} else {
-			y <- NextMethod("[")
-			cols <- names(y)
-			if(!is.null(cols) && anyNA(cols))
-				stop("undefined columns selected")
-		}
-		## added in 1.8.0
-		if(anyDuplicated(cols)) names(y) <- make.unique(cols)
-		## since we have not touched the rows, copy over the raw row.names
-		## Claimed at one time at least one fewer copies: PR#15274
-		attr(y, "row.names") <- .row_names_info(x, 0L)
-		attr(y, "class") <- oldClass(x)
-		return(y)
-	}
-
-	if(missing(i)) { # df[, j] or df[ , ]
-		## not quite the same as the 1/2-arg case, as 'drop' is used.
-		if(drop && !has.j && length(x) == 1L) return(.subset2(x, 1L))
-		nm <- names(x); if(is.null(nm)) nm <- character()
-		if(has.j && !is.character(j) && anyNA(nm)) {
-			## less efficient version
-			names(nm) <- names(x) <- seq_along(x)
-			y <- .subset(x, j)
-			cols <- names(y)
-			if(anyNA(cols)) stop("undefined columns selected")
-			cols <- names(y) <- nm[cols]
-		} else {
-			y <- if(has.j) .subset(x, j) else x
-			cols <- names(y)
-			if(anyNA(cols)) stop("undefined columns selected")
-		}
-		if(drop && length(y) == 1L) return(.subset2(y, 1L))
-		if(anyDuplicated(cols)) names(y) <- make.unique(cols)
-		nrow <- .row_names_info(x, 2L)
-		if(drop && !mdrop && nrow == 1L)
-			return(structure(y, class = NULL, row.names = NULL))
-		else {
-			## Claimed at one time at least one fewer copies: PR#15274
-			attr(y, "class") <- oldClass(x)
-			attr(y, "row.names") <- .row_names_info(x, 0L)
-			return(y)
-		}
-	}
-
-	### df[i, j] or df[i , ]
-	## rewritten for R 2.5.0 to avoid duplicating x.
-	xx <- x
-	cols <- names(xx)  # needed for computation of 'drop' arg
-	## make a shallow copy
-	x <- vector("list", length(x))
-	## attributes(x) <- attributes(xx) expands row names
-	x <- .Internal(copyDFattr(xx, x))
-	oldClass(x) <- attr(x, "row.names") <- NULL
-
-	if(has.j) { # df[i, j]
-		nm <- names(x); if(is.null(nm)) nm <- character()
-		if(!is.character(j) && anyNA(nm))
-			names(nm) <- names(x) <- seq_along(x)
-		x <- x[j]
-		cols <- names(x)  # needed for 'drop'
-		if(drop && length(x) == 1L) {
-			## for consistency with [, <length-1>]
-			if(is.character(i)) {
-				rows <- attr(xx, "row.names")
-				i <- pmatch(i, rows, duplicates.ok = TRUE)
-			}
-			## need to figure which col was selected:
-			## cannot use .subset2 directly as that may
-			## use recursive selection for a logical index.
-			xj <- .subset2(.subset(xx, j), 1L)
-			return(if(length(dim(xj)) != 2L) xj[i] else xj[i, , drop = FALSE])
-		}
-		if(anyNA(cols)) stop("undefined columns selected")
-		## fix up names if we altered them.
-		if(!is.null(names(nm))) cols <- names(x) <- nm[cols]
-		## sxx <- match(cols, names(xx)) fails with duplicate names
-		nxx <- structure(seq_along(xx), names=names(xx))
-		sxx <- match(nxx[j], seq_along(xx))
-	} else sxx <- seq_along(x)
-
-	rows <- NULL # placeholder: only create row names when needed
-	# as this can be expensive.
-	if(is.character(i)) {
-		rows <- attr(xx, "row.names")
-		i <- pmatch(i, rows, duplicates.ok = TRUE)
-	}
-	for(j in seq_along(x)) {
-		xj <- xx[[ sxx[j] ]]
-		## had drop = drop prior to 1.8.0
-		x[[j]] <- if(length(dim(xj)) != 2L) xj[i] else xj[i, , drop = FALSE]
-	}
-
-	if(drop) {
-		n <- length(x)
-		if(n == 1L) return(x[[1L]]) # drops attributes
-		if(n > 1L) {
-			xj <- x[[1L]]
-			nrow <- if(length(dim(xj)) == 2L) dim(xj)[1L] else length(xj)
-			## for consistency with S: don't drop (to a list)
-			## if only one row, unless explicitly asked for
-			drop <- !mdrop && nrow == 1L
-		} else drop <- FALSE ## for n == 0
-	}
-
-	if(!drop) { # not else as previous section might reset drop
-		## row names might have NAs.
-		if(is.null(rows)) rows <- attr(xx, "row.names")
-		rows <- rows[i]
-		if((ina <- anyNA(rows)) | (dup <- anyDuplicated(rows))) {
-			## both will coerce integer 'rows' to character:
-			if (!dup && is.character(rows)) dup <- "NA" %in% rows
-			if(ina)
-				rows[is.na(rows)] <- "NA"
-			if(dup)
-				rows <- make.unique(as.character(rows))
-		}
-		## new in 1.8.0  -- might have duplicate columns
-		if(has.j && anyDuplicated(nm <- names(x)))
-			names(x) <- make.unique(nm)
-		if(is.null(rows)) rows <- attr(xx, "row.names")[i]
-		attr(x, "row.names") <- rows
-		oldClass(x) <- oldClass(xx)
-	}
-	x
-}
-
-`[[.data.frame` <- function(x, ..., exact=TRUE)
-{
-	## use in-line functions to refer to the 1st and 2nd ... arguments
-	## explicitly. Also will check for wrong number or empty args
-	# TODO: parsing problem?
-#	na <- nargs() - !missing(exact)
-	na <- nargs() - (!missing(exact))
-	if(!all(names(sys.call()) %in% c("", "exact")))
-		warning("named arguments other than 'exact' are discouraged")
-
-	if(na < 3L)
-		(function(x, i, exact)
-				if(is.matrix(i)) as.matrix(x)[[i]]
-				else .subset2(x, i, exact=exact))(x, ..., exact=exact)
-	else {
-		col <- .subset2(x, ..2, exact=exact)
-		i <- if(is.character(..1))
-					pmatch(..1, row.names(x), duplicates.ok = TRUE)
-				else ..1
-		## we do want to dispatch on methods for a column.
-		## .subset2(col, i, exact=exact)
-		col[[i, exact = exact]]
-	}
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
index a66dc5e1a897082e8f05646cbdff8e1eb1cb56cd..17a9615a017289805738548e5b70dcac0d5f4f86 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
@@ -62,6 +62,7 @@ public class ParserGeneration {
         "support strings in field accesses",
         "allow NULL= in switch",
         "support NA_complex_",
-        "simplified unary and binary operations"
+        "simplified unary and binary operations",
+        "allow unary ! in normal expressions"
     };
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
index f6c95b6b2d092b3fd4473ee45e98c5672f669b71..9f4ea54006325e67c0a56fcdb2a85ab9864eb36b 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
@@ -360,7 +360,7 @@ and_expr returns [ASTNode v]
     ;
 
 not_expr returns [ASTNode v]
-    : t=NOT n_ l=not_expr { $v = UnaryOperation.create(sourceSection("not_expr", $t, $l.stop), Operator.UNARY_NOT, $l.v); }
+    : {true}? t=NOT n_ l=not_expr { $v = UnaryOperation.create(sourceSection("not_expr", $t, $l.stop), Operator.UNARY_NOT, $l.v); }
     | b=comp_expr         { $v = $b.v; }
     ;
 
@@ -440,6 +440,9 @@ unary_expression returns [ASTNode v]
       ( (number) => num=number { ((Constant) num).addNegativeSign(); $v = num; }
       | l=unary_expression     { $v = UnaryOperation.create(sourceSection("unary_expression/MINUS", $m, $l.stop), Operator.UNARY_MINUS, $l.v); }
       )
+    | m=NOT n_ { plusOrMinus = true; }
+      ( l=unary_expression     { $v = UnaryOperation.create(sourceSection("unary_expression/UNARY_NOT", $m, $l.stop), Operator.UNARY_NOT, $l.v); }
+      )
     | b=power_expr             { $v = $b.v; }
     ;
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 9c0076a1731c20960a5925bb5ec85515256d837e..1eec9399dce89af2218568cad9d2f9a50309b0f7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -22837,6 +22837,42 @@ NULL
 #/
 Error: unexpected '/' in "/"
 
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- 1; y <- 2; !(x < y)
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- 1; y <- 2; !(x) < y
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- 1; y <- 2; !x < y
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- 1; y <- TRUE; !x - !y
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- 1; y <- TRUE; (!x) - !y
+[1] 0
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- 1; y <- TRUE; x - !y
+[1] 1
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- FALSE; y <- TRUE; !x && !y
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- FALSE; y <- TRUE; !x && y
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.base.TestSimpleParsing.testUnaryNotParsing
+#x <- FALSE; y <- TRUE; (!x) && y
+[1] TRUE
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction
 #{ (1:3):(1:3) }
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleParsing.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleParsing.java
index f7b689ecbb582ec2122a67da69ea1f1174f14a94..d4b4feebc97ef7d6f49ae6a072c5b5d2b59fea83 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleParsing.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleParsing.java
@@ -36,4 +36,16 @@ public class TestSimpleParsing extends TestBase {
         assertEval("/");
     }
 
+    @Test
+    public void testUnaryNotParsing() {
+        assertEval("x <- 1; y <- TRUE; x - !y");
+        assertEval("x <- 1; y <- TRUE; !x - !y");
+        assertEval("x <- 1; y <- TRUE; (!x) - !y");
+        assertEval("x <- FALSE; y <- TRUE; !x && !y");
+        assertEval("x <- FALSE; y <- TRUE; !x && y");
+        assertEval("x <- FALSE; y <- TRUE; (!x) && y");
+        assertEval("x <- 1; y <- 2; !x < y");
+        assertEval("x <- 1; y <- 2; !(x < y)");
+        assertEval("x <- 1; y <- 2; !(x) < y");
+    }
 }