From 52743262319bceadb3d1335db1470b52005d3198 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 12 Dec 2016 12:03:55 +0100
Subject: [PATCH] thread safety in PromiseNode

---
 .../truffle/r/nodes/function/PromiseNode.java | 28 +++++++++++++++----
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
index c46789e565..e9a2275663 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
@@ -409,8 +409,17 @@ public abstract class PromiseNode extends RNode {
         private final ConditionProfile argsValueAndNamesProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile containsVarargProfile = ConditionProfile.createBinaryProfile();
 
-        @CompilationFinal ArgumentsSignature cachedVarArgSignature;
-        @CompilationFinal ArgumentsSignature cachedResultSignature;
+        private static final class Cache {
+            private final ArgumentsSignature signature;
+            private final ArgumentsSignature result;
+
+            protected Cache(ArgumentsSignature signature, ArgumentsSignature result) {
+                this.signature = signature;
+                this.result = result;
+            }
+        }
+
+        @CompilationFinal private Cache varArgsCache;
 
         InlineVarArgsNode(RNode[] nodes, ArgumentsSignature signature) {
             this.varargs = nodes;
@@ -455,13 +464,20 @@ public abstract class PromiseNode extends RNode {
                 if (evaluatedArgs.length == 1) {
                     finalSignature = ((RArgsValuesAndNames) evaluatedArgs[0]).getSignature();
                 } else {
-                    if (cachedVarArgSignature == ArgumentsSignature.INVALID_SIGNATURE) {
+                    Cache cache = varArgsCache;
+                    if (cache == null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        finalSignature = createSignature(evaluatedArgs, flattenedArgs.length);
+                        varArgsCache = new Cache(varArgSignature, finalSignature);
+                    } else if (cache.signature == ArgumentsSignature.INVALID_SIGNATURE) {
                         finalSignature = createSignature(evaluatedArgs, flattenedArgs.length);
-                    } else if (varArgSignature == cachedVarArgSignature) {
-                        finalSignature = cachedResultSignature;
+                    } else if (varArgSignature == cache.signature) {
+                        finalSignature = cache.result;
                     } else {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        // fallback to the generic case
                         finalSignature = createSignature(evaluatedArgs, flattenedArgs.length);
-                        cachedVarArgSignature = cachedVarArgSignature == null ? finalSignature : ArgumentsSignature.INVALID_SIGNATURE;
+                        varArgsCache = new Cache(ArgumentsSignature.INVALID_SIGNATURE, null);
                     }
                 }
                 return new RArgsValuesAndNames(flattenedArgs, finalSignature);
-- 
GitLab