From acdc6ed7e257356175c54358de28038fa028db02 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 10 Feb 2017 11:55:02 -0800
Subject: [PATCH] Convert PCRERFFI to one node per method.

---
 .../r/nodes/builtin/base/GrepFunctions.java   | 30 +++++----
 .../truffle/r/runtime/ffi/jni/JNI_PCRE.java   | 54 +++++++++++++---
 .../truffle/r/runtime/ffi/PCRERFFI.java       | 64 ++++++++++++++++---
 3 files changed, 119 insertions(+), 29 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 4e0ca4c615..2f45bf6836 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -63,7 +63,8 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  */
 public class GrepFunctions {
     public abstract static class CommonCodeAdapter extends RBuiltinNode {
-        @Child protected PCRERFFI.PCRERFFINode pcreRFFINode = RFFIFactory.getRFFI().getPCRERFFI().createPCRERFFINode();
+        @Child protected PCRERFFI.MaketablesNode maketablesNode = RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode();
+        @Child protected PCRERFFI.CompileNode compileNode = RFFIFactory.getRFFI().getPCRERFFI().createCompileNode();
 
         protected static void castPattern(Casts casts) {
             // with default error message, NO_CALLER does not work
@@ -201,8 +202,8 @@ public class GrepFunctions {
 
         protected PCRERFFI.Result compilePerlPattern(String pattern, boolean ignoreCase) {
             int cflags = ignoreCase ? PCRERFFI.CASELESS : 0;
-            long tables = pcreRFFINode.maketables();
-            PCRERFFI.Result pcre = pcreRFFINode.compile(pattern, cflags, tables);
+            long tables = maketablesNode.execute();
+            PCRERFFI.Result pcre = compileNode.execute(pattern, cflags, tables);
             if (pcre.result == 0) {
                 // TODO output warning if pcre.errorMessage not NULL
                 throw RError.error(this, RError.Message.INVALID_REGEXP, pattern);
@@ -212,6 +213,8 @@ public class GrepFunctions {
     }
 
     private abstract static class GrepAdapter extends CommonCodeAdapter {
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+
         protected Object doGrep(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical,
                         @SuppressWarnings("unused") byte useBytes, byte invertLogical, boolean grepl) {
             boolean value = RRuntime.fromLogical(valueLogical);
@@ -241,7 +244,7 @@ public class GrepFunctions {
                 for (int i = 0; i < len; i++) {
                     String text = vector.getDataAt(i);
                     if (!RRuntime.isNA(text)) {
-                        if (pcreRFFINode.exec(pcre.result, 0, text, 0, 0, ovector) >= 0) {
+                        if (execNode.execute(pcre.result, 0, text, 0, 0, ovector) >= 0) {
                             matches[i] = true;
                         }
                     }
@@ -363,6 +366,7 @@ public class GrepFunctions {
     }
 
     protected abstract static class SubAdapter extends CommonCodeAdapter {
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
 
         protected static void castReplacement(Casts casts) {
             // with default error message, NO_CALLER does not work
@@ -432,7 +436,7 @@ public class GrepFunctions {
                                                                            // necessary
 
                         StringBuffer sb = new StringBuffer();
-                        while (pcreRFFINode.exec(pcre.result, 0, input, lastEndOffset, eflag, ovector) >= 0) {
+                        while (execNode.execute(pcre.result, 0, input, lastEndOffset, eflag, ovector) >= 0) {
                             nmatch++;
 
                             // offset == byte position
@@ -690,6 +694,9 @@ public class GrepFunctions {
         @Child SetFixedAttributeNode setCaptureLengthAttrNode = SetFixedAttributeNode.create("capture.length");
         @Child SetFixedAttributeNode setCaptureNamesAttrNode = SetFixedAttributeNode.create("capture.names");
         @Child SetFixedAttributeNode setDimNamesAttrNode = SetFixedAttributeNode.createDimNames();
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+        @Child PCRERFFI.GetCaptureNamesNode getCaptureNamesNode = RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureNamesNode();
+        @Child PCRERFFI.GetCaptureCountNode getCaptureCountNode = RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureCountNode();
 
         static {
             Casts casts = new Casts(Regexp.class);
@@ -817,13 +824,13 @@ public class GrepFunctions {
                 }
             } else if (perl) {
                 PCRERFFI.Result pcre = compilePerlPattern(pattern, ignoreCase);
-                int maxCaptureCount = pcreRFFINode.getCaptureCount(pcre.result, 0);
+                int maxCaptureCount = getCaptureCountNode.execute(pcre.result, 0);
                 int[] ovector = new int[(maxCaptureCount + 1) * 3];
                 int offset = 0;
                 while (true) {
-                    int captureCount = pcreRFFINode.exec(pcre.result, 0, text, offset, 0, ovector);
+                    int captureCount = execNode.execute(pcre.result, 0, text, offset, 0, ovector);
                     if (captureCount >= 0) {
-                        String[] captureNames = pcreRFFINode.getCaptureNames(pcre.result, 0, maxCaptureCount);
+                        String[] captureNames = getCaptureNamesNode.execute(pcre.result, 0, maxCaptureCount);
                         for (int i = 0; i < captureNames.length; i++) {
                             if (captureNames[i] == null) {
                                 captureNames[i] = "";
@@ -1164,6 +1171,7 @@ public class GrepFunctions {
 
     @RBuiltin(name = "strsplit", kind = INTERNAL, parameterNames = {"x", "split", "fixed", "perl", "useBytes"}, behavior = PURE)
     public abstract static class Strsplit extends CommonCodeAdapter {
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
 
         static {
             Casts casts = new Casts(Strsplit.class);
@@ -1185,7 +1193,7 @@ public class GrepFunctions {
             // treat split = NULL as split = ""
             RAbstractStringVector split = splitArg.getLength() == 0 ? RDataFactory.createStringVectorFromScalar("") : splitArg;
             String[] splits = new String[split.getLength()];
-            long pcreTables = perl ? pcreRFFINode.maketables() : 0;
+            long pcreTables = perl ? maketablesNode.execute() : 0;
             PCRERFFI.Result[] pcreSplits = perl ? new PCRERFFI.Result[splits.length] : null;
 
             na.enable(x);
@@ -1194,7 +1202,7 @@ public class GrepFunctions {
                 splits[i] = fixed || perl ? split.getDataAt(i) : RegExp.checkPreDefinedClasses(split.getDataAt(i));
                 if (perl) {
                     if (!currentSplit.isEmpty()) {
-                        pcreSplits[i] = pcreRFFINode.compile(currentSplit, 0, pcreTables);
+                        pcreSplits[i] = compileNode.execute(currentSplit, 0, pcreTables);
                         if (pcreSplits[i].result == 0) {
                             // TODO output warning if pcre.errorMessage not NULL
                             throw RError.error(this, RError.Message.INVALID_REGEXP, currentSplit);
@@ -1298,7 +1306,7 @@ public class GrepFunctions {
             int[] ovector = new int[30];
             int[] fromByteMapping = getFromByteMapping(data); // non-null if it's necessary
 
-            while (pcreRFFINode.exec(pcre.result, 0, data, lastEndOffset, 0, ovector) >= 0) {
+            while (execNode.execute(pcre.result, 0, data, lastEndOffset, 0, ovector) >= 0) {
                 // offset == byte position
                 // index == character position
                 int startOffset = ovector[0];
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java
index f2bb99d0a8..069de23ca3 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java
@@ -28,19 +28,23 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 
 public class JNI_PCRE implements PCRERFFI {
-    private static class JNI_PCRERFFINode extends PCRERFFINode {
+    private static class JNI_MaketablesNode extends MaketablesNode {
         @Override
-        public long maketables() {
+        public long execute() {
             return nativeMaketables();
         }
+    }
 
+    private static class JNI_CompileNode extends CompileNode {
         @Override
-        public Result compile(String pattern, int options, long tables) {
+        public Result execute(String pattern, int options, long tables) {
             return nativeCompile(pattern, options, tables);
         }
+    }
 
+    private static class JNI_GetCaptureCountNode extends GetCaptureCountNode {
         @Override
-        public int getCaptureCount(long code, long extra) {
+        public int execute(long code, long extra) {
             int res = nativeGetCaptureCount(code, extra);
             if (res < 0) {
                 CompilerDirectives.transferToInterpreter();
@@ -48,9 +52,11 @@ public class JNI_PCRE implements PCRERFFI {
             }
             return res;
         }
+    }
 
+    private static class JNI_GetCaptureNamesNode extends GetCaptureNamesNode {
         @Override
-        public String[] getCaptureNames(long code, long extra, int captureCount) {
+        public String[] execute(long code, long extra, int captureCount) {
             String[] ret = new String[captureCount];
             int res = nativeGetCaptureNames(code, extra, ret);
             if (res < 0) {
@@ -59,14 +65,18 @@ public class JNI_PCRE implements PCRERFFI {
             }
             return ret;
         }
+    }
 
+    private static class JNI_StudyNode extends StudyNode {
         @Override
-        public Result study(long code, int options) {
+        public Result execute(long code, int options) {
             throw RInternalError.unimplemented("pcre_study");
         }
+    }
 
+    private static class JNI_ExecNode extends ExecNode {
         @Override
-        public int exec(long code, long extra, String subject, int offset, int options, int[] ovector) {
+        public int execute(long code, long extra, String subject, int offset, int options, int[] ovector) {
             return nativeExec(code, extra, subject, offset, options, ovector, ovector.length);
         }
     }
@@ -83,7 +93,33 @@ public class JNI_PCRE implements PCRERFFI {
                     int options, int[] ovector, int ovectorLen);
 
     @Override
-    public PCRERFFINode createPCRERFFINode() {
-        return new JNI_PCRERFFINode();
+    public MaketablesNode createMaketablesNode() {
+        return new JNI_MaketablesNode();
+    }
+
+    @Override
+    public CompileNode createCompileNode() {
+        return new JNI_CompileNode();
+    }
+
+    @Override
+    public GetCaptureCountNode createGetCaptureCountNode() {
+        return new JNI_GetCaptureCountNode();
     }
+
+    @Override
+    public GetCaptureNamesNode createGetCaptureNamesNode() {
+        return new JNI_GetCaptureNamesNode();
+    }
+
+    @Override
+    public StudyNode createStudyNode() {
+        return new JNI_StudyNode();
+    }
+
+    @Override
+    public ExecNode createExecNode() {
+        return new JNI_ExecNode();
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java
index cff6aadebf..c963ab2ec8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -49,21 +49,67 @@ public interface PCRERFFI {
         }
     }
 
-    abstract class PCRERFFINode extends Node {
+    abstract class MaketablesNode extends Node {
 
-        public abstract long maketables();
+        public abstract long execute();
 
-        public abstract Result compile(String pattern, int options, long tables);
+        public static MaketablesNode create() {
+            return RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode();
+        }
+    }
+
+    abstract class CompileNode extends Node {
+
+        public abstract Result execute(String pattern, int options, long tables);
+
+        public static CompileNode create() {
+            return RFFIFactory.getRFFI().getPCRERFFI().createCompileNode();
+        }
+    }
+
+    abstract class GetCaptureCountNode extends Node {
+
+        public abstract int execute(long code, long extra);
+
+        public static GetCaptureCountNode create() {
+            return RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureCountNode();
+        }
+    }
 
-        public abstract int getCaptureCount(long code, long extra);
+    abstract class GetCaptureNamesNode extends Node {
+        public abstract String[] execute(long code, long extra, int captureCount);
 
-        public abstract String[] getCaptureNames(long code, long extra, int captureCount);
+        public static GetCaptureNamesNode create() {
+            return RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureNamesNode();
+        }
+    }
+
+    abstract class StudyNode extends Node {
+        public abstract Result execute(long code, int options);
+
+        public static StudyNode create() {
+            return RFFIFactory.getRFFI().getPCRERFFI().createStudyNode();
+        }
+    }
 
-        public abstract Result study(long code, int options);
+    abstract class ExecNode extends Node {
+        public abstract int execute(long code, long extra, String subject, int offset, int options, int[] ovector);
 
-        public abstract int exec(long code, long extra, String subject, int offset, int options, int[] ovector);
+        public static ExecNode create() {
+            return RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+        }
     }
 
-    PCRERFFINode createPCRERFFINode();
+    MaketablesNode createMaketablesNode();
+
+    CompileNode createCompileNode();
+
+    GetCaptureCountNode createGetCaptureCountNode();
+
+    GetCaptureNamesNode createGetCaptureNamesNode();
+
+    StudyNode createStudyNode();
+
+    ExecNode createExecNode();
 
 }
-- 
GitLab