diff options
author | 2021-11-02 15:35:05 +0000 | |
---|---|---|
committer | 2021-11-05 15:21:58 +0000 | |
commit | cdf6c49112615419b0d170bac31685bd0b3dae0e (patch) | |
tree | ab64f6c58f9cd7f28319699ae13fae1af2cdff9e | |
parent | e37bacc7999bcd121bc8f7cf4be3b366799d87b4 (diff) |
Revert^2 "OpenJDK 11: Add String.repeat()"
This reverts commit 48fb9f43a81fa0cab09ed4a4f3d478c1a0ecbe9e.
Reason for revert: d8 has adopted the same behaviour as the intended
implementation so tests should no longer fail when backports are
applied.
Bug: 191859202
Bug: 202962059
Test: Treehugger
Test: cherry-pick to problem branch and run tests there.
Change-Id: I734673a2c37d04e77a76496a722db1460eaf2b49
-rw-r--r-- | runtime/mirror/string-inl.h | 4 | ||||
-rw-r--r-- | runtime/mirror/string.cc | 48 | ||||
-rw-r--r-- | runtime/mirror/string.h | 3 | ||||
-rw-r--r-- | runtime/native/java_lang_String.cc | 9 | ||||
-rw-r--r-- | test/100-reflect2/expected-stdout.txt | 2 |
5 files changed, 63 insertions, 3 deletions
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h index dd280364e1..b5b9c71de9 100644 --- a/runtime/mirror/string-inl.h +++ b/runtime/mirror/string-inl.h @@ -35,9 +35,9 @@ inline uint32_t String::ClassSize(PointerSize pointer_size) { // lambda$codePoints$1$CharSequence // which were virtual functions in standalone desugar, becomes // direct functions with D8 desugaring. - uint32_t vtable_entries = Object::kVTableLength + 54; + uint32_t vtable_entries = Object::kVTableLength + 55; #else - uint32_t vtable_entries = Object::kVTableLength + 56; + uint32_t vtable_entries = Object::kVTableLength + 57; #endif return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 1, 2, pointer_size); } diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc index 0ce45b855b..704433aca1 100644 --- a/runtime/mirror/string.cc +++ b/runtime/mirror/string.cc @@ -151,6 +151,54 @@ ObjPtr<String> String::DoConcat(Thread* self, Handle<String> h_this, Handle<Stri return Alloc(self, length_with_flag, allocator_type, visitor); } +template<typename T> +static void RepeatCharacters(ObjPtr<String> new_string, Handle<String> h_this, int32_t count) + REQUIRES_SHARED(Locks::mutator_lock_) { + T *new_value, *h_this_value; + if constexpr (std::is_same_v<T, uint8_t>) { + new_value = new_string->GetValueCompressed(); + h_this_value = h_this->GetValueCompressed(); + } else { + new_value = new_string->GetValue(); + h_this_value = h_this->GetValue(); + } + int32_t length_this = h_this->GetLength(); + if (length_this == 1) { + // compiler is smart enough to use memset for uint8_t + std::fill(new_value, new_value + count, h_this_value[0]); + } else { + memcpy(new_value, h_this_value, length_this * sizeof(T)); + int32_t copied = length_this; + int32_t limit = length_this * count; + for (; copied < limit - copied; copied <<= 1) { + memcpy(new_value + copied, new_value, copied * sizeof(T)); + } + memcpy(new_value + copied, new_value, (limit - copied) * sizeof(T)); + } +} + +ObjPtr<String> String::DoRepeat(Thread* self, Handle<String> h_this, int32_t count) { + int32_t length_this = h_this->GetLength(); + DCHECK_GT(count, 1); + DCHECK_LE(length_this, std::numeric_limits<int32_t>::max() / count); + gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator(); + const bool compressible = kUseStringCompression && (h_this->IsCompressed()); + const int32_t length_with_flag = String::GetFlaggedCount(length_this * count, compressible); + + auto visitor = [=](ObjPtr<Object> obj, size_t usable_size) REQUIRES_SHARED(Locks::mutator_lock_) { + SetStringCountVisitor set_string_count_visitor(length_with_flag); + set_string_count_visitor(obj, usable_size); + ObjPtr<String> new_string = obj->AsString(); + + if (compressible) { + RepeatCharacters<uint8_t>(new_string, h_this, count); + } else { + RepeatCharacters<uint16_t>(new_string, h_this, count); + } + }; + return Alloc(self, length_with_flag, allocator_type, visitor); +} + ObjPtr<String> String::AllocFromUtf16(Thread* self, int32_t utf16_length, const uint16_t* utf16_data_in) { diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h index 53fcf82caa..6cb560e4a2 100644 --- a/runtime/mirror/string.h +++ b/runtime/mirror/string.h @@ -160,6 +160,9 @@ class MANAGED String final : public Object { static ObjPtr<String> DoConcat(Thread* self, Handle<String> h_this, Handle<String> h_arg) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + static ObjPtr<String> DoRepeat(Thread* self, Handle<String> h_this, int32_t count) + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + static ObjPtr<String> AllocFromUtf16(Thread* self, int32_t utf16_length, const uint16_t* utf16_data_in) diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc index 86f93299d9..94ca5b53d6 100644 --- a/runtime/native/java_lang_String.cc +++ b/runtime/native/java_lang_String.cc @@ -109,10 +109,19 @@ static jcharArray String_toCharArray(JNIEnv* env, jobject java_this) { return soa.AddLocalReference<jcharArray>(mirror::String::ToCharArray(s, soa.Self())); } +static jstring String_doRepeat(JNIEnv* env, jobject java_this, jint count) { + ScopedFastNativeObjectAccess soa(env); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::String> string = hs.NewHandle(soa.Decode<mirror::String>(java_this)); + ObjPtr<mirror::String> result = mirror::String::DoRepeat(soa.Self(), string, count); + return soa.AddLocalReference<jstring>(result); +} + static JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(String, charAt, "(I)C"), FAST_NATIVE_METHOD(String, compareTo, "(Ljava/lang/String;)I"), FAST_NATIVE_METHOD(String, concat, "(Ljava/lang/String;)Ljava/lang/String;"), + FAST_NATIVE_METHOD(String, doRepeat, "(I)Ljava/lang/String;"), FAST_NATIVE_METHOD(String, doReplace, "(CC)Ljava/lang/String;"), FAST_NATIVE_METHOD(String, fastSubstring, "(II)Ljava/lang/String;"), FAST_NATIVE_METHOD(String, getCharsNoCheck, "(II[CI)V"), diff --git a/test/100-reflect2/expected-stdout.txt b/test/100-reflect2/expected-stdout.txt index 2b57824464..0d0482aac6 100644 --- a/test/100-reflect2/expected-stdout.txt +++ b/test/100-reflect2/expected-stdout.txt @@ -33,7 +33,7 @@ z (class java.lang.Character) 14 (class java.lang.Short) [java.lang.String(int,int,char[]), public java.lang.String(), public java.lang.String(byte[]), public java.lang.String(byte[],int), public java.lang.String(byte[],int,int), public java.lang.String(byte[],int,int,int), public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException, public java.lang.String(byte[],int,int,java.nio.charset.Charset), public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException, public java.lang.String(byte[],java.nio.charset.Charset), public java.lang.String(char[]), public java.lang.String(char[],int,int), public java.lang.String(int[],int,int), public java.lang.String(java.lang.String), public java.lang.String(java.lang.StringBuffer), public java.lang.String(java.lang.StringBuilder)] [private final int java.lang.String.count, private int java.lang.String.hash, private static final java.io.ObjectStreamField[] java.lang.String.serialPersistentFields, private static final long java.lang.String.serialVersionUID, public static final java.util.Comparator java.lang.String.CASE_INSENSITIVE_ORDER] -[native void java.lang.String.getCharsNoCheck(int,int,char[],int), private boolean java.lang.String.nonSyncContentEquals(java.lang.AbstractStringBuilder), private int java.lang.String.indexOfSupplementary(int,int), private int java.lang.String.lastIndexOfSupplementary(int,int), private native java.lang.String java.lang.String.doReplace(char,char), private native java.lang.String java.lang.String.fastSubstring(int,int), private static int java.lang.String.indexOf(java.lang.String,java.lang.String,int), private static int java.lang.String.lastIndexOf(java.lang.String,java.lang.String,int), public boolean java.lang.String.contains(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.StringBuffer), public boolean java.lang.String.endsWith(java.lang.String), public boolean java.lang.String.equals(java.lang.Object), public boolean java.lang.String.equalsIgnoreCase(java.lang.String), public boolean java.lang.String.isEmpty(), public boolean java.lang.String.matches(java.lang.String), public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int), public boolean java.lang.String.regionMatches(int,java.lang.String,int,int), public boolean java.lang.String.startsWith(java.lang.String), public boolean java.lang.String.startsWith(java.lang.String,int), public byte[] java.lang.String.getBytes(), public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException, public byte[] java.lang.String.getBytes(java.nio.charset.Charset), public int java.lang.String.codePointAt(int), public int java.lang.String.codePointBefore(int), public int java.lang.String.codePointCount(int,int), public int java.lang.String.compareTo(java.lang.Object), public int java.lang.String.compareToIgnoreCase(java.lang.String), public int java.lang.String.hashCode(), public int java.lang.String.indexOf(int), public int java.lang.String.indexOf(int,int), public int java.lang.String.indexOf(java.lang.String), public int java.lang.String.indexOf(java.lang.String,int), public int java.lang.String.lastIndexOf(int), public int java.lang.String.lastIndexOf(int,int), public int java.lang.String.lastIndexOf(java.lang.String), public int java.lang.String.lastIndexOf(java.lang.String,int), public int java.lang.String.length(), public int java.lang.String.offsetByCodePoints(int,int), public java.lang.CharSequence java.lang.String.subSequence(int,int), public java.lang.String java.lang.String.replace(char,char), public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence), public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String), public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String), public java.lang.String java.lang.String.substring(int), public java.lang.String java.lang.String.substring(int,int), public java.lang.String java.lang.String.toLowerCase(), public java.lang.String java.lang.String.toLowerCase(java.util.Locale), public java.lang.String java.lang.String.toString(), public java.lang.String java.lang.String.toUpperCase(), public java.lang.String java.lang.String.toUpperCase(java.util.Locale), public java.lang.String java.lang.String.trim(), public java.lang.String[] java.lang.String.split(java.lang.String), public java.lang.String[] java.lang.String.split(java.lang.String,int), public native char java.lang.String.charAt(int), public native char[] java.lang.String.toCharArray(), public native int java.lang.String.compareTo(java.lang.String), public native java.lang.String java.lang.String.concat(java.lang.String), public native java.lang.String java.lang.String.intern(), public static java.lang.String java.lang.String.copyValueOf(char[]), public static java.lang.String java.lang.String.copyValueOf(char[],int,int), public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.CharSequence[]), public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.Iterable), public static java.lang.String java.lang.String.valueOf(boolean), public static java.lang.String java.lang.String.valueOf(char), public static java.lang.String java.lang.String.valueOf(char[]), public static java.lang.String java.lang.String.valueOf(char[],int,int), public static java.lang.String java.lang.String.valueOf(double), public static java.lang.String java.lang.String.valueOf(float), public static java.lang.String java.lang.String.valueOf(int), public static java.lang.String java.lang.String.valueOf(java.lang.Object), public static java.lang.String java.lang.String.valueOf(long), public void java.lang.String.getBytes(int,int,byte[],int), public void java.lang.String.getChars(int,int,char[],int), static int java.lang.String.indexOf(char[],int,int,char[],int,int,int), static int java.lang.String.indexOf(char[],int,int,java.lang.String,int), static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int), static int java.lang.String.lastIndexOf(char[],int,int,java.lang.String,int), void java.lang.String.getChars(char[],int)] +[native void java.lang.String.getCharsNoCheck(int,int,char[],int), private boolean java.lang.String.nonSyncContentEquals(java.lang.AbstractStringBuilder), private int java.lang.String.indexOfSupplementary(int,int), private int java.lang.String.lastIndexOfSupplementary(int,int), private native java.lang.String java.lang.String.doRepeat(int), private native java.lang.String java.lang.String.doReplace(char,char), private native java.lang.String java.lang.String.fastSubstring(int,int), private static int java.lang.String.indexOf(java.lang.String,java.lang.String,int), private static int java.lang.String.lastIndexOf(java.lang.String,java.lang.String,int), public boolean java.lang.String.contains(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.StringBuffer), public boolean java.lang.String.endsWith(java.lang.String), public boolean java.lang.String.equals(java.lang.Object), public boolean java.lang.String.equalsIgnoreCase(java.lang.String), public boolean java.lang.String.isEmpty(), public boolean java.lang.String.matches(java.lang.String), public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int), public boolean java.lang.String.regionMatches(int,java.lang.String,int,int), public boolean java.lang.String.startsWith(java.lang.String), public boolean java.lang.String.startsWith(java.lang.String,int), public byte[] java.lang.String.getBytes(), public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException, public byte[] java.lang.String.getBytes(java.nio.charset.Charset), public int java.lang.String.codePointAt(int), public int java.lang.String.codePointBefore(int), public int java.lang.String.codePointCount(int,int), public int java.lang.String.compareTo(java.lang.Object), public int java.lang.String.compareToIgnoreCase(java.lang.String), public int java.lang.String.hashCode(), public int java.lang.String.indexOf(int), public int java.lang.String.indexOf(int,int), public int java.lang.String.indexOf(java.lang.String), public int java.lang.String.indexOf(java.lang.String,int), public int java.lang.String.lastIndexOf(int), public int java.lang.String.lastIndexOf(int,int), public int java.lang.String.lastIndexOf(java.lang.String), public int java.lang.String.lastIndexOf(java.lang.String,int), public int java.lang.String.length(), public int java.lang.String.offsetByCodePoints(int,int), public java.lang.CharSequence java.lang.String.subSequence(int,int), public java.lang.String java.lang.String.repeat(int), public java.lang.String java.lang.String.replace(char,char), public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence), public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String), public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String), public java.lang.String java.lang.String.substring(int), public java.lang.String java.lang.String.substring(int,int), public java.lang.String java.lang.String.toLowerCase(), public java.lang.String java.lang.String.toLowerCase(java.util.Locale), public java.lang.String java.lang.String.toString(), public java.lang.String java.lang.String.toUpperCase(), public java.lang.String java.lang.String.toUpperCase(java.util.Locale), public java.lang.String java.lang.String.trim(), public java.lang.String[] java.lang.String.split(java.lang.String), public java.lang.String[] java.lang.String.split(java.lang.String,int), public native char java.lang.String.charAt(int), public native char[] java.lang.String.toCharArray(), public native int java.lang.String.compareTo(java.lang.String), public native java.lang.String java.lang.String.concat(java.lang.String), public native java.lang.String java.lang.String.intern(), public static java.lang.String java.lang.String.copyValueOf(char[]), public static java.lang.String java.lang.String.copyValueOf(char[],int,int), public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.CharSequence[]), public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.Iterable), public static java.lang.String java.lang.String.valueOf(boolean), public static java.lang.String java.lang.String.valueOf(char), public static java.lang.String java.lang.String.valueOf(char[]), public static java.lang.String java.lang.String.valueOf(char[],int,int), public static java.lang.String java.lang.String.valueOf(double), public static java.lang.String java.lang.String.valueOf(float), public static java.lang.String java.lang.String.valueOf(int), public static java.lang.String java.lang.String.valueOf(java.lang.Object), public static java.lang.String java.lang.String.valueOf(long), public void java.lang.String.getBytes(int,int,byte[],int), public void java.lang.String.getChars(int,int,char[],int), static int java.lang.String.indexOf(char[],int,int,char[],int,int,int), static int java.lang.String.indexOf(char[],int,int,java.lang.String,int), static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int), static int java.lang.String.lastIndexOf(char[],int,int,java.lang.String,int), void java.lang.String.getChars(char[],int)] [] [interface java.io.Serializable, interface java.lang.Comparable, interface java.lang.CharSequence] 0 |