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 4e0ca4c615d072a2535c7bdf0f508edcdde18e5b..2f45bf6836886d361715191b1a1da808950653a1 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 f2bb99d0a828ee3419c5d69c137b4a70b08741e3..069de23ca3290fa8b497893d6d2083b9b72cc8cf 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 cff6aadebf60cdce9f6b0f3aa44fd5789218a020..c963ab2ec8ff7385eb2d5eb97d09196fab53f23b 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(); }