Merge "Move native code of ICU4C regex usage into external/icu"
diff --git a/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java b/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java
index 4eea1a5..7b82c3c 100644
--- a/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java
+++ b/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java
@@ -79,6 +79,7 @@
*
* @hide
*/
+@libcore.api.IntraCoreApi
@Retention(RetentionPolicy.RUNTIME) // Let the GC or interpreter ask, if they need to.
// TODO(b/72332040): Reconsider retention later.
@Target({ElementType.FIELD, ElementType.METHOD})
diff --git a/luni/src/main/java/libcore/util/NativeAllocationRegistry.java b/luni/src/main/java/libcore/util/NativeAllocationRegistry.java
index 5dc1e98..e114ebe 100644
--- a/luni/src/main/java/libcore/util/NativeAllocationRegistry.java
+++ b/luni/src/main/java/libcore/util/NativeAllocationRegistry.java
@@ -41,6 +41,7 @@
* @hide
*/
@libcore.api.CorePlatformApi
+@libcore.api.IntraCoreApi
public class NativeAllocationRegistry {
private final ClassLoader classLoader;
@@ -118,6 +119,7 @@
* kind of native allocation
*/
@libcore.api.CorePlatformApi
+ @libcore.api.IntraCoreApi
public static NativeAllocationRegistry createMalloced(
ClassLoader classLoader, long freeFunction) {
return new NativeAllocationRegistry(classLoader, freeFunction, 0, true);
@@ -227,6 +229,7 @@
* thrown.
*/
@libcore.api.CorePlatformApi
+ @libcore.api.IntraCoreApi
public Runnable registerNativeAllocation(Object referent, long nativePtr) {
if (referent == null) {
throw new IllegalArgumentException("referent is null");
diff --git a/luni/src/main/native/Android.bp b/luni/src/main/native/Android.bp
index 85c6430..f94ff95 100644
--- a/luni/src/main/native/Android.bp
+++ b/luni/src/main/native/Android.bp
@@ -31,8 +31,6 @@
"java_lang_invoke_MethodHandle.cpp",
"java_lang_invoke_VarHandle.cpp",
"java_math_NativeBN.cpp",
- "java_util_regex_Matcher.cpp",
- "java_util_regex_Pattern.cpp",
"libcore_icu_ICU.cpp",
"libcore_icu_NativeConverter.cpp",
"libcore_icu_TimeZoneNames.cpp",
diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp
index bf567aa..a6b7b9e 100644
--- a/luni/src/main/native/JniConstants.cpp
+++ b/luni/src/main/native/JniConstants.cpp
@@ -61,7 +61,6 @@
jclass longClass;
jclass netlinkSocketAddressClass;
jclass packetSocketAddressClass;
-jclass patternSyntaxExceptionClass;
jclass stringClass;
jclass structAddrinfoClass;
jclass structGroupReqClass;
@@ -108,7 +107,6 @@
longClass = findClass(env, "java/lang/Long");
netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress");
packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress");
- patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException");
stringClass = findClass(env, "java/lang/String");
structAddrinfoClass = findClass(env, "android/system/StructAddrinfo");
structGroupReqClass = findClass(env, "android/system/StructGroupReq");
@@ -223,11 +221,6 @@
return packetSocketAddressClass;
}
-jclass JniConstants::GetPatternSyntaxExceptionClass(JNIEnv* env) {
- EnsureJniConstantsInitialized(env);
- return patternSyntaxExceptionClass;
-}
-
jclass JniConstants::GetStringClass(JNIEnv* env) {
EnsureJniConstantsInitialized(env);
return stringClass;
diff --git a/luni/src/main/native/JniConstants.h b/luni/src/main/native/JniConstants.h
index 021dc53..2931411 100644
--- a/luni/src/main/native/JniConstants.h
+++ b/luni/src/main/native/JniConstants.h
@@ -46,7 +46,6 @@
static jclass GetLongClass(JNIEnv* env);
static jclass GetNetlinkSocketAddressClass(JNIEnv* env);
static jclass GetPacketSocketAddressClass(JNIEnv* env);
- static jclass GetPatternSyntaxExceptionClass(JNIEnv* env);
static jclass GetStringClass(JNIEnv* env);
static jclass GetStructAddrinfoClass(JNIEnv* env);
static jclass GetStructFlockClass(JNIEnv* env);
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 0b4a94a..40e580e 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -40,8 +40,6 @@
REGISTER(register_java_lang_invoke_MethodHandle);
REGISTER(register_java_lang_invoke_VarHandle);
REGISTER(register_java_math_NativeBN);
- REGISTER(register_java_util_regex_Matcher);
- REGISTER(register_java_util_regex_Pattern);
REGISTER(register_libcore_icu_ICU);
REGISTER(register_libcore_icu_NativeConverter);
REGISTER(register_libcore_icu_TimeZoneNames);
diff --git a/luni/src/main/native/java_util_regex_Matcher.cpp b/luni/src/main/native/java_util_regex_Matcher.cpp
deleted file mode 100644
index 12fb764..0000000
--- a/luni/src/main/native/java_util_regex_Matcher.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Matcher"
-
-#include <memory>
-#include <stdlib.h>
-
-#include <android-base/logging.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedPrimitiveArray.h>
-#include <nativehelper/ScopedStringChars.h>
-#include <nativehelper/jni_macros.h>
-
-#include "IcuUtilities.h"
-#include "JniException.h"
-#include "ScopedJavaUnicodeString.h"
-#include "unicode/parseerr.h"
-#include "unicode/regex.h"
-
-// ICU documentation: http://icu-project.org/apiref/icu4c/classRegexMatcher.html
-
-/**
- * Encapsulates an instance of ICU4C's RegexMatcher class along with a copy of
- * the input it's currently operating on in the native heap.
- *
- * Rationale: We choose to make a copy here because it turns out to be a lot
- * cheaper when a moving GC and/or string compression is enabled. This is
- * because env->GetStringChars() always copies in this scenario. This becomes
- * especially bad when the String in question is long and/or contains a large
- * number of matches.
- *
- * Drawbacks: The native allocation associated with this class is no longer
- * fixed size, so we're effectively lying to the NativeAllocationRegistry about
- * the size of the object(s) we're allocating on the native heap. The peak
- * memory usage doesn't change though, given that GetStringChars would have
- * made an allocation of precisely the same size.
- */
-class MatcherState {
-public:
- MatcherState(icu::RegexMatcher* matcher) :
- mMatcher(matcher),
- mUChars(nullptr),
- mUText(nullptr),
- mStatus(U_ZERO_ERROR) {
- }
-
- bool updateInput(JNIEnv* env, jstring input) {
- // First, close the UText struct, since we're about to allocate a new one.
- if (mUText != nullptr) {
- utext_close(mUText);
- mUText = nullptr;
- }
-
- // Then delete the UChar* associated with the UText struct..
- mUChars.reset(nullptr);
-
- // TODO: We should investigate whether we can avoid an additional copy
- // in the native heap when is_copy == JNI_TRUE. The problem with doing
- // that is that we might call ReleaseStringChars with a different
- // JNIEnv* on a different downcall. This is currently safe as
- // implemented in ART, but is unlikely to be portable and the spec stays
- // silent on the matter.
- ScopedStringChars inputChars(env, input);
- if (inputChars.get() == nullptr) {
- // There will be an exception pending if we get here.
- return false;
- }
-
- // Make a copy of |input| on the native heap. This copy will be live
- // until the next call to updateInput or close.
- mUChars.reset(new (std::nothrow) UChar[inputChars.size()]);
- if (mUChars.get() == nullptr) {
- env->ThrowNew(env->FindClass("Ljava/lang/OutOfMemoryError;"), "Out of memory");
- return false;
- }
-
- static_assert(sizeof(UChar) == sizeof(jchar), "sizeof(Uchar) != sizeof(jchar)");
- memcpy(mUChars.get(), inputChars.get(), inputChars.size() * sizeof(jchar));
-
- // Reset any errors that might have occurred on previous patches.
- mStatus = U_ZERO_ERROR;
- mUText = utext_openUChars(nullptr, mUChars.get(), inputChars.size(), &mStatus);
- if (mUText == nullptr) {
- CHECK(maybeThrowIcuException(env, "utext_openUChars", mStatus));
- return false;
- }
-
- // It is an error for ICU to have returned a non-null mUText but to
- // still have indicated an error.
- CHECK(U_SUCCESS(mStatus));
-
- mMatcher->reset(mUText);
- return true;
- }
-
- ~MatcherState() {
- if (mUText != nullptr) {
- utext_close(mUText);
- }
- }
-
- icu::RegexMatcher* matcher() {
- return mMatcher.get();
- }
-
- UErrorCode& status() {
- return mStatus;
- }
-
- void updateOffsets(JNIEnv* env, jintArray javaOffsets) {
- ScopedIntArrayRW offsets(env, javaOffsets);
- if (offsets.get() == NULL) {
- return;
- }
-
- for (size_t i = 0, groupCount = mMatcher->groupCount(); i <= groupCount; ++i) {
- offsets[2*i + 0] = mMatcher->start(i, mStatus);
- offsets[2*i + 1] = mMatcher->end(i, mStatus);
- }
- }
-
-private:
- std::unique_ptr<icu::RegexMatcher> mMatcher;
- std::unique_ptr<UChar[]> mUChars;
- UText* mUText;
- UErrorCode mStatus;
-
- // Disallow copy and assignment.
- MatcherState(const MatcherState&);
- void operator=(const MatcherState&);
-};
-
-static inline MatcherState* toMatcherState(jlong address) {
- return reinterpret_cast<MatcherState*>(static_cast<uintptr_t>(address));
-}
-
-static void Matcher_free(void* address) {
- MatcherState* state = reinterpret_cast<MatcherState*>(address);
- delete state;
-}
-
-static jlong Matcher_getNativeFinalizer(JNIEnv*, jclass) {
- return reinterpret_cast<jlong>(&Matcher_free);
-}
-
-static jboolean Matcher_findImpl(JNIEnv* env, jclass, jlong addr, jint startIndex, jintArray offsets) {
- MatcherState* state = toMatcherState(addr);
- UBool result = state->matcher()->find(startIndex, state->status());
- if (result) {
- state->updateOffsets(env, offsets);
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
-}
-
-static jboolean Matcher_findNextImpl(JNIEnv* env, jclass, jlong addr, jintArray offsets) {
- MatcherState* state = toMatcherState(addr);
- UBool result = state->matcher()->find();
- if (result) {
- state->updateOffsets(env, offsets);
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
-}
-
-static jint Matcher_groupCountImpl(JNIEnv*, jclass, jlong addr) {
- MatcherState* state = toMatcherState(addr);
- return state->matcher()->groupCount();
-}
-
-static jboolean Matcher_hitEndImpl(JNIEnv*, jclass, jlong addr) {
- MatcherState* state = toMatcherState(addr);
- if (state->matcher()->hitEnd() != 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
-}
-
-static jboolean Matcher_lookingAtImpl(JNIEnv* env, jclass, jlong addr, jintArray offsets) {
- MatcherState* state = toMatcherState(addr);
- UBool result = state->matcher()->lookingAt(state->status());
- if (result) {
- state->updateOffsets(env, offsets);
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
-}
-
-static jboolean Matcher_matchesImpl(JNIEnv* env, jclass, jlong addr, jintArray offsets) {
- MatcherState* state = toMatcherState(addr);
- UBool result = state->matcher()->matches(state->status());
- if (result) {
- state->updateOffsets(env, offsets);
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
-}
-
-static jlong Matcher_openImpl(JNIEnv* env, jclass, jlong patternAddr) {
- icu::RegexPattern* pattern = reinterpret_cast<icu::RegexPattern*>(static_cast<uintptr_t>(patternAddr));
- UErrorCode status = U_ZERO_ERROR;
- icu::RegexMatcher* result = pattern->matcher(status);
- if (maybeThrowIcuException(env, "RegexPattern::matcher", status)) {
- return 0;
- }
-
- return reinterpret_cast<uintptr_t>(new MatcherState(result));
-}
-
-static jboolean Matcher_requireEndImpl(JNIEnv*, jclass, jlong addr) {
- MatcherState* state = toMatcherState(addr);
- if (state->matcher()->requireEnd() != 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
-}
-
-static void Matcher_setInputImpl(JNIEnv* env, jclass, jlong addr, jstring javaText, jint start, jint end) {
- MatcherState* state = toMatcherState(addr);
- if (state->updateInput(env, javaText)) {
- state->matcher()->region(start, end, state->status());
- }
-}
-
-static void Matcher_useAnchoringBoundsImpl(JNIEnv*, jclass, jlong addr, jboolean value) {
- MatcherState* state = toMatcherState(addr);
- state->matcher()->useAnchoringBounds(value);
-}
-
-static void Matcher_useTransparentBoundsImpl(JNIEnv*, jclass, jlong addr, jboolean value) {
- MatcherState* state = toMatcherState(addr);
- state->matcher()->useTransparentBounds(value);
-}
-
-static jint Matcher_getMatchedGroupIndex0(JNIEnv* env, jclass, jlong patternAddr, jstring javaGroupName) {
- icu::RegexPattern* pattern = reinterpret_cast<icu::RegexPattern*>(static_cast<uintptr_t>(patternAddr));
- ScopedJavaUnicodeString groupName(env, javaGroupName);
- UErrorCode status = U_ZERO_ERROR;
-
- jint result = pattern->groupNumberFromName(groupName.unicodeString(), status);
- if (U_SUCCESS(status)) {
- return result;
- }
- if (status == U_REGEX_INVALID_CAPTURE_GROUP_NAME) {
- return -1;
- }
- maybeThrowIcuException(env, "RegexPattern::groupNumberFromName", status);
- return -1;
-}
-
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Matcher, getMatchedGroupIndex0, "(JLjava/lang/String;)I"),
- NATIVE_METHOD(Matcher, findImpl, "(JI[I)Z"),
- NATIVE_METHOD(Matcher, findNextImpl, "(J[I)Z"),
- NATIVE_METHOD(Matcher, getNativeFinalizer, "()J"),
- NATIVE_METHOD(Matcher, groupCountImpl, "(J)I"),
- NATIVE_METHOD(Matcher, hitEndImpl, "(J)Z"),
- NATIVE_METHOD(Matcher, lookingAtImpl, "(J[I)Z"),
- NATIVE_METHOD(Matcher, matchesImpl, "(J[I)Z"),
- NATIVE_METHOD(Matcher, openImpl, "(J)J"),
- NATIVE_METHOD(Matcher, requireEndImpl, "(J)Z"),
- NATIVE_METHOD(Matcher, setInputImpl, "(JLjava/lang/String;II)V"),
- NATIVE_METHOD(Matcher, useAnchoringBoundsImpl, "(JZ)V"),
- NATIVE_METHOD(Matcher, useTransparentBoundsImpl, "(JZ)V"),
-};
-void register_java_util_regex_Matcher(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/util/regex/Matcher", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/java_util_regex_Pattern.cpp b/luni/src/main/native/java_util_regex_Pattern.cpp
deleted file mode 100644
index a893bab..0000000
--- a/luni/src/main/native/java_util_regex_Pattern.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Pattern"
-
-#include <stdlib.h>
-
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/jni_macros.h>
-
-#include "unicode/parseerr.h"
-#include "unicode/regex.h"
-
-#include "JniConstants.h"
-#include "ScopedJavaUnicodeString.h"
-
-// ICU documentation: http://icu-project.org/apiref/icu4c/classRegexPattern.html
-
-static const char* regexDetailMessage(UErrorCode status) {
- // These human-readable error messages were culled from "utypes.h", and then slightly tuned
- // to make more sense in context.
- // If we don't have a special-case, we'll just return the textual name of
- // the enum value (such as U_REGEX_RULE_SYNTAX), which is better than nothing.
- switch (status) {
- case U_REGEX_INTERNAL_ERROR: return "An internal error was detected";
- case U_REGEX_RULE_SYNTAX: return "Syntax error in regexp pattern";
- case U_REGEX_INVALID_STATE: return "Matcher in invalid state for requested operation";
- case U_REGEX_BAD_ESCAPE_SEQUENCE: return "Unrecognized backslash escape sequence in pattern";
- case U_REGEX_PROPERTY_SYNTAX: return "Incorrect Unicode property";
- case U_REGEX_UNIMPLEMENTED: return "Use of unimplemented feature";
- case U_REGEX_MISMATCHED_PAREN: return "Incorrectly nested parentheses in regexp pattern";
- case U_REGEX_NUMBER_TOO_BIG: return "Decimal number is too large";
- case U_REGEX_BAD_INTERVAL: return "Error in {min,max} interval";
- case U_REGEX_MAX_LT_MIN: return "In {min,max}, max is less than min";
- case U_REGEX_INVALID_BACK_REF: return "Back-reference to a non-existent capture group";
- case U_REGEX_INVALID_FLAG: return "Invalid value for match mode flags";
- case U_REGEX_LOOK_BEHIND_LIMIT: return "Look-behind pattern matches must have a bounded maximum length";
- case U_REGEX_SET_CONTAINS_STRING: return "Regular expressions cannot have UnicodeSets containing strings";
- case U_REGEX_OCTAL_TOO_BIG: return "Octal character constants must be <= 0377.";
- case U_REGEX_MISSING_CLOSE_BRACKET: return "Missing closing bracket in character class";
- case U_REGEX_INVALID_RANGE: return "In a character range [x-y], x is greater than y";
- case U_REGEX_STACK_OVERFLOW: return "Regular expression backtrack stack overflow";
- case U_REGEX_TIME_OUT: return "Maximum allowed match time exceeded";
- case U_REGEX_STOPPED_BY_CALLER: return "Matching operation aborted by user callback function";
- default:
- return u_errorName(status);
- }
-}
-
-static void throwPatternSyntaxException(JNIEnv* env, UErrorCode status, jstring pattern, UParseError error) {
- static jmethodID method = env->GetMethodID(JniConstants::GetPatternSyntaxExceptionClass(env),
- "<init>", "(Ljava/lang/String;Ljava/lang/String;I)V");
- jstring message = env->NewStringUTF(regexDetailMessage(status));
- jclass exceptionClass = JniConstants::GetPatternSyntaxExceptionClass(env);
- jobject exception = env->NewObject(exceptionClass, method, message, pattern, error.offset);
- env->Throw(reinterpret_cast<jthrowable>(exception));
-}
-
-static void Pattern_free(void* addr) {
- delete reinterpret_cast<icu::RegexPattern*>(addr);
-}
-
-static jlong Pattern_getNativeFinalizer(JNIEnv*, jclass) {
- return reinterpret_cast<jlong>(&Pattern_free);
-}
-
-static jlong Pattern_compileImpl(JNIEnv* env, jclass, jstring javaRegex, jint flags) {
- flags |= UREGEX_ERROR_ON_UNKNOWN_ESCAPES;
-
- UErrorCode status = U_ZERO_ERROR;
- UParseError error;
- error.offset = -1;
-
- ScopedJavaUnicodeString regex(env, javaRegex);
- if (!regex.valid()) {
- return 0;
- }
- icu::UnicodeString& regexString(regex.unicodeString());
- icu::RegexPattern* result = icu::RegexPattern::compile(regexString, flags, error, status);
- if (!U_SUCCESS(status)) {
- throwPatternSyntaxException(env, status, javaRegex, error);
- }
- return static_cast<jlong>(reinterpret_cast<uintptr_t>(result));
-}
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Pattern, compileImpl, "(Ljava/lang/String;I)J"),
- NATIVE_METHOD(Pattern, getNativeFinalizer, "()J"),
-};
-
-void register_java_util_regex_Pattern(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/util/regex/Pattern", gMethods, NELEM(gMethods));
-}
diff --git a/mmodules/intracoreapi/api/intra/current-api.txt b/mmodules/intracoreapi/api/intra/current-api.txt
index 02cedb4..c2024d6 100644
--- a/mmodules/intracoreapi/api/intra/current-api.txt
+++ b/mmodules/intracoreapi/api/intra/current-api.txt
@@ -48,6 +48,13 @@
}
+package dalvik.annotation.optimization {
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @libcore.api.IntraCoreApi public @interface ReachabilitySensitive {
+ }
+
+}
+
package dalvik.system {
@libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public final class BlockGuard {
@@ -120,6 +127,11 @@
package libcore.util {
+ @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public class NativeAllocationRegistry {
+ method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static libcore.util.NativeAllocationRegistry createMalloced(ClassLoader, long);
+ method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public Runnable registerNativeAllocation(Object, long);
+ }
+
@java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE_USE}) @libcore.api.IntraCoreApi public @interface NonNull {
}
diff --git a/ojluni/src/main/java/java/util/regex/Matcher.java b/ojluni/src/main/java/java/util/regex/Matcher.java
index fd60baf..eca98db 100644
--- a/ojluni/src/main/java/java/util/regex/Matcher.java
+++ b/ojluni/src/main/java/java/util/regex/Matcher.java
@@ -26,8 +26,7 @@
package java.util.regex;
-import dalvik.annotation.optimization.ReachabilitySensitive;
-import libcore.util.NativeAllocationRegistry;
+import com.android.icu.util.regex.NativeMatcher;
/**
* An engine that performs match operations on a {@linkplain java.lang.CharSequence
@@ -109,10 +108,6 @@
/**
* The Pattern object that created this Matcher.
*/
- // Patterns also contain cleanup code and a ReachabilitySensitive field.
- // This ensures that "this" and pattern remain reachable while we're using pattern.address
- // directly.
- @ReachabilitySensitive
private Pattern parentPattern;
/**
@@ -137,21 +132,7 @@
*/
private boolean matchFound;
- /**
- * The address of the native peer.
- * Uses of this must be manually synchronized to avoid native crashes.
- */
- @ReachabilitySensitive
- private long address;
-
- /**
- * If non-null, a Runnable that can be used to explicitly deallocate address.
- */
- private Runnable nativeFinalizer;
-
- private static final NativeAllocationRegistry registry =
- NativeAllocationRegistry.createMalloced(Matcher.class.getClassLoader(),
- getNativeFinalizer());
+ private NativeMatcher nativeMatcher;
/**
* The index of the last position appended in a substitution.
@@ -230,13 +211,8 @@
parentPattern = newPattern;
synchronized (this) {
- if (nativeFinalizer != null) {
- nativeFinalizer.run();
- address = 0; // In case openImpl throws.
- nativeFinalizer = null;
- }
- address = openImpl(parentPattern.address);
- nativeFinalizer = registry.registerNativeAllocation(this, address);
+ nativeMatcher = null; // In case NativeMatcher.create throws.
+ nativeMatcher = NativeMatcher.create(parentPattern.nativePattern);
}
if (text != null) {
@@ -533,7 +509,7 @@
*/
public int groupCount() {
synchronized (this) {
- return groupCountImpl(address);
+ return nativeMatcher.groupCount();
}
}
@@ -548,7 +524,7 @@
*/
public boolean matches() {
synchronized (this) {
- matchFound = matchesImpl(address, groups);
+ matchFound = nativeMatcher.matches(groups);
}
return matchFound;
}
@@ -570,7 +546,7 @@
*/
public boolean find() {
synchronized (this) {
- matchFound = findNextImpl(address, groups);
+ matchFound = nativeMatcher.findNext(groups);
}
return matchFound;
}
@@ -600,7 +576,7 @@
throw new IndexOutOfBoundsException("Illegal start index");
reset();
synchronized (this) {
- matchFound = findImpl(address, start, groups);
+ matchFound = nativeMatcher.find(start, groups);
}
return matchFound;
}
@@ -621,7 +597,7 @@
*/
public boolean lookingAt() {
synchronized (this) {
- matchFound = lookingAtImpl(address, groups);
+ matchFound = nativeMatcher.lookingAt(groups);
}
return matchFound;
}
@@ -1023,7 +999,7 @@
public Matcher useTransparentBounds(boolean b) {
synchronized (this) {
transparentBounds = b;
- useTransparentBoundsImpl(address, b);
+ nativeMatcher.useTransparentBounds(b);
}
return this;
}
@@ -1072,7 +1048,7 @@
public Matcher useAnchoringBounds(boolean b) {
synchronized (this) {
anchoringBounds = b;
- useAnchoringBoundsImpl(address, b);
+ nativeMatcher.useAnchoringBounds(b);
}
return this;
}
@@ -1112,7 +1088,7 @@
*/
public boolean hitEnd() {
synchronized (this) {
- return hitEndImpl(address);
+ return nativeMatcher.hitEnd();
}
}
@@ -1132,7 +1108,7 @@
*/
public boolean requireEnd() {
synchronized (this) {
- return requireEndImpl(address);
+ return nativeMatcher.requireEnd();
}
}
@@ -1195,9 +1171,9 @@
private void resetForInput() {
synchronized (this) {
- setInputImpl(address, text, from, to);
- useAnchoringBoundsImpl(address, anchoringBounds);
- useTransparentBoundsImpl(address, transparentBounds);
+ nativeMatcher.setInput(text, from, to);
+ nativeMatcher.useAnchoringBounds(anchoringBounds);
+ nativeMatcher.useTransparentBounds(transparentBounds);
}
}
@@ -1216,7 +1192,7 @@
private int getMatchedGroupIndex(String name) {
ensureMatch();
- int result = getMatchedGroupIndex0(parentPattern.address, name);
+ int result = nativeMatcher.getMatchedGroupIndex(name);
if (result < 0) {
throw new IllegalArgumentException("No capturing group in the pattern " +
"with the name " + name);
@@ -1224,20 +1200,6 @@
return result;
}
- private static native int getMatchedGroupIndex0(long patternAddr, String name);
- private static native boolean findImpl(long addr, int startIndex, int[] offsets);
- private static native boolean findNextImpl(long addr, int[] offsets);
- private static native long getNativeFinalizer();
- private static native int groupCountImpl(long addr);
- private static native boolean hitEndImpl(long addr);
- private static native boolean lookingAtImpl(long addr, int[] offsets);
- private static native boolean matchesImpl(long addr, int[] offsets);
- private static native long openImpl(long patternAddr);
- private static native boolean requireEndImpl(long addr);
- private static native void setInputImpl(long addr, String s, int start, int end);
- private static native void useAnchoringBoundsImpl(long addr, boolean value);
- private static native void useTransparentBoundsImpl(long addr, boolean value);
-
/**
* A trivial match result implementation that's based on an array of integers
* representing match offsets. The array is of the form
diff --git a/ojluni/src/main/java/java/util/regex/Pattern.java b/ojluni/src/main/java/java/util/regex/Pattern.java
index 55a48de..3a5ad63 100644
--- a/ojluni/src/main/java/java/util/regex/Pattern.java
+++ b/ojluni/src/main/java/java/util/regex/Pattern.java
@@ -26,11 +26,9 @@
package java.util.regex;
-import dalvik.annotation.optimization.ReachabilitySensitive;
+import com.android.icu.util.regex.NativePattern;
import dalvik.system.VMRuntime;
-import libcore.util.NativeAllocationRegistry;
-
import java.util.Iterator;
import java.util.ArrayList;
import java.util.NoSuchElementException;
@@ -945,12 +943,7 @@
// BEGIN Android-changed: reimplement matching logic natively via ICU.
// We only need some tie-ins to native memory, instead of a large number
// of fields on the .java side.
- @ReachabilitySensitive
- transient long address;
-
- private static final NativeAllocationRegistry registry =
- NativeAllocationRegistry.createMalloced(Pattern.class.getClassLoader(),
- getNativeFinalizer());
+ /* package */ transient NativePattern nativePattern;
// END Android-changed: reimplement matching logic natively via ICU.
/**
@@ -1430,12 +1423,8 @@
// These are the flags natively supported by ICU.
// They even have the same value in native code.
int icuFlags = flags & (CASE_INSENSITIVE | COMMENTS | MULTILINE | DOTALL | UNIX_LINES);
- address = compileImpl(icuPattern, icuFlags);
- registry.registerNativeAllocation(this, address);
+ nativePattern = NativePattern.create(icuPattern, icuFlags);
}
-
- private static native long compileImpl(String regex, int flags);
- private static native long getNativeFinalizer();
// END Android-changed: reimplement matching logic natively via ICU.
/**