String.toCharArray is known to be painfully slow. Avoiding it as much as possible and dead code which was referencing it
1.1 --- a/rt/emul/mini/src/main/java/java/lang/String.java Wed May 07 11:41:41 2014 +0200
1.2 +++ b/rt/emul/mini/src/main/java/java/lang/String.java Wed May 07 11:55:06 2014 +0200
1.3 @@ -794,9 +794,7 @@
1.4 " arr[to++] = s[i];\n" +
1.5 "}"
1.6 )
1.7 - void getChars(char dst[], int dstBegin) {
1.8 - System.arraycopy(toCharArray(), offset(), dst, dstBegin, length());
1.9 - }
1.10 + native void getChars(char dst[], int dstBegin);
1.11
1.12 /**
1.13 * Copies characters from this string into the destination character
1.14 @@ -834,19 +832,7 @@
1.15 " arr[dst++] = s.charCodeAt(beg++);\n" +
1.16 "}\n"
1.17 )
1.18 - public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
1.19 - if (srcBegin < 0) {
1.20 - throw new StringIndexOutOfBoundsException(srcBegin);
1.21 - }
1.22 - if (srcEnd > length()) {
1.23 - throw new StringIndexOutOfBoundsException(srcEnd);
1.24 - }
1.25 - if (srcBegin > srcEnd) {
1.26 - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
1.27 - }
1.28 - System.arraycopy(toCharArray(), offset() + srcBegin, dst, dstBegin,
1.29 - srcEnd - srcBegin);
1.30 - }
1.31 + public native void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin);
1.32
1.33 /**
1.34 * Copies characters from this string into the destination byte array. Each
1.35 @@ -905,10 +891,9 @@
1.36 int j = dstBegin;
1.37 int n = offset() + srcEnd;
1.38 int i = offset() + srcBegin;
1.39 - char[] val = toCharArray(); /* avoid getfield opcode */
1.40
1.41 while (i < n) {
1.42 - dst[j++] = (byte)val[i++];
1.43 + dst[j++] = (byte)charAt(i++);
1.44 }
1.45 }
1.46
1.47 @@ -1016,30 +1001,10 @@
1.48 * @see #equalsIgnoreCase(String)
1.49 */
1.50 @JavaScriptBody(args = { "obj" }, body =
1.51 - "return obj != null && obj['$instOf_java_lang_String'] && "
1.52 + "return obj !== null && obj['$instOf_java_lang_String'] && "
1.53 + "this.toString() === obj.toString();"
1.54 )
1.55 - public boolean equals(Object anObject) {
1.56 - if (this == anObject) {
1.57 - return true;
1.58 - }
1.59 - if (anObject instanceof String) {
1.60 - String anotherString = (String)anObject;
1.61 - int n = length();
1.62 - if (n == anotherString.length()) {
1.63 - char v1[] = toCharArray();
1.64 - char v2[] = anotherString.toCharArray();
1.65 - int i = offset();
1.66 - int j = anotherString.offset();
1.67 - while (n-- != 0) {
1.68 - if (v1[i++] != v2[j++])
1.69 - return false;
1.70 - }
1.71 - return true;
1.72 - }
1.73 - }
1.74 - return false;
1.75 - }
1.76 + public native boolean equals(Object anObject);
1.77
1.78 /**
1.79 * Compares this string to the specified {@code StringBuffer}. The result
1.80 @@ -1080,13 +1045,12 @@
1.81 return false;
1.82 // Argument is a StringBuffer, StringBuilder
1.83 if (cs instanceof AbstractStringBuilder) {
1.84 - char v1[] = toCharArray();
1.85 char v2[] = ((AbstractStringBuilder)cs).getValue();
1.86 int i = offset();
1.87 int j = 0;
1.88 int n = length();
1.89 while (n-- != 0) {
1.90 - if (v1[i++] != v2[j++])
1.91 + if (this.charAt(i++) != v2[j++])
1.92 return false;
1.93 }
1.94 return true;
1.95 @@ -1095,12 +1059,11 @@
1.96 if (cs.equals(this))
1.97 return true;
1.98 // Argument is a generic CharSequence
1.99 - char v1[] = toCharArray();
1.100 int i = offset();
1.101 int j = 0;
1.102 int n = length();
1.103 while (n-- != 0) {
1.104 - if (v1[i++] != cs.charAt(j++))
1.105 + if (this.charAt(i++) != cs.charAt(j++))
1.106 return false;
1.107 }
1.108 return true;
1.109 @@ -1444,23 +1407,7 @@
1.110 "find = find.toString();\n" +
1.111 "return this.toString().substring(from, from + find.length) === find;\n"
1.112 )
1.113 - public boolean startsWith(String prefix, int toffset) {
1.114 - char ta[] = toCharArray();
1.115 - int to = offset() + toffset;
1.116 - char pa[] = prefix.toCharArray();
1.117 - int po = prefix.offset();
1.118 - int pc = prefix.length();
1.119 - // Note: toffset might be near -1>>>1.
1.120 - if ((toffset < 0) || (toffset > length() - pc)) {
1.121 - return false;
1.122 - }
1.123 - while (--pc >= 0) {
1.124 - if (ta[to++] != pa[po++]) {
1.125 - return false;
1.126 - }
1.127 - }
1.128 - return true;
1.129 - }
1.130 + public native boolean startsWith(String prefix, int toffset);
1.131
1.132 /**
1.133 * Tests if this string starts with the specified prefix.
1.134 @@ -1594,49 +1541,7 @@
1.135 "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
1.136 "return this.toString().indexOf(ch, from);\n"
1.137 )
1.138 - public int indexOf(int ch, int fromIndex) {
1.139 - if (fromIndex < 0) {
1.140 - fromIndex = 0;
1.141 - } else if (fromIndex >= length()) {
1.142 - // Note: fromIndex might be near -1>>>1.
1.143 - return -1;
1.144 - }
1.145 -
1.146 - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
1.147 - // handle most cases here (ch is a BMP code point or a
1.148 - // negative value (invalid code point))
1.149 - final char[] value = this.toCharArray();
1.150 - final int offset = this.offset();
1.151 - final int max = offset + length();
1.152 - for (int i = offset + fromIndex; i < max ; i++) {
1.153 - if (value[i] == ch) {
1.154 - return i - offset;
1.155 - }
1.156 - }
1.157 - return -1;
1.158 - } else {
1.159 - return indexOfSupplementary(ch, fromIndex);
1.160 - }
1.161 - }
1.162 -
1.163 - /**
1.164 - * Handles (rare) calls of indexOf with a supplementary character.
1.165 - */
1.166 - private int indexOfSupplementary(int ch, int fromIndex) {
1.167 - if (Character.isValidCodePoint(ch)) {
1.168 - final char[] value = this.toCharArray();
1.169 - final int offset = this.offset();
1.170 - final char hi = Character.highSurrogate(ch);
1.171 - final char lo = Character.lowSurrogate(ch);
1.172 - final int max = offset + length() - 1;
1.173 - for (int i = offset + fromIndex; i < max; i++) {
1.174 - if (value[i] == hi && value[i+1] == lo) {
1.175 - return i - offset;
1.176 - }
1.177 - }
1.178 - }
1.179 - return -1;
1.180 - }
1.181 + public native int indexOf(int ch, int fromIndex);
1.182
1.183 /**
1.184 * Returns the index within this string of the last occurrence of
1.185 @@ -1703,42 +1608,7 @@
1.186 "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
1.187 "return this.toString().lastIndexOf(ch, from);"
1.188 )
1.189 - public int lastIndexOf(int ch, int fromIndex) {
1.190 - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
1.191 - // handle most cases here (ch is a BMP code point or a
1.192 - // negative value (invalid code point))
1.193 - final char[] value = this.toCharArray();
1.194 - final int offset = this.offset();
1.195 - int i = offset + Math.min(fromIndex, length() - 1);
1.196 - for (; i >= offset ; i--) {
1.197 - if (value[i] == ch) {
1.198 - return i - offset;
1.199 - }
1.200 - }
1.201 - return -1;
1.202 - } else {
1.203 - return lastIndexOfSupplementary(ch, fromIndex);
1.204 - }
1.205 - }
1.206 -
1.207 - /**
1.208 - * Handles (rare) calls of lastIndexOf with a supplementary character.
1.209 - */
1.210 - private int lastIndexOfSupplementary(int ch, int fromIndex) {
1.211 - if (Character.isValidCodePoint(ch)) {
1.212 - final char[] value = this.toCharArray();
1.213 - final int offset = this.offset();
1.214 - char hi = Character.highSurrogate(ch);
1.215 - char lo = Character.lowSurrogate(ch);
1.216 - int i = offset + Math.min(fromIndex, length() - 2);
1.217 - for (; i >= offset; i--) {
1.218 - if (value[i] == hi && value[i+1] == lo) {
1.219 - return i - offset;
1.220 - }
1.221 - }
1.222 - }
1.223 - return -1;
1.224 - }
1.225 + public native int lastIndexOf(int ch, int fromIndex);
1.226
1.227 /**
1.228 * Returns the index within this string of the first occurrence of the
1.229 @@ -1817,9 +1687,7 @@
1.230 @JavaScriptBody(args = { "s", "from" }, body =
1.231 "return this.toString().lastIndexOf(s.toString(), from);"
1.232 )
1.233 - public int lastIndexOf(String str, int fromIndex) {
1.234 - return lastIndexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex);
1.235 - }
1.236 + public native int lastIndexOf(String str, int fromIndex);
1.237
1.238 /**
1.239 * Code shared by String and StringBuffer to do searches. The
1.240 @@ -1926,19 +1794,7 @@
1.241 @JavaScriptBody(args = { "beginIndex", "endIndex" }, body =
1.242 "return this.toString().substring(beginIndex, endIndex);"
1.243 )
1.244 - public String substring(int beginIndex, int endIndex) {
1.245 - if (beginIndex < 0) {
1.246 - throw new StringIndexOutOfBoundsException(beginIndex);
1.247 - }
1.248 - if (endIndex > length()) {
1.249 - throw new StringIndexOutOfBoundsException(endIndex);
1.250 - }
1.251 - if (beginIndex > endIndex) {
1.252 - throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
1.253 - }
1.254 - return ((beginIndex == 0) && (endIndex == length())) ? this :
1.255 - new String(toCharArray(), offset() + beginIndex, endIndex - beginIndex);
1.256 - }
1.257 + public native String substring(int beginIndex, int endIndex);
1.258
1.259 /**
1.260 * Returns a new character sequence that is a subsequence of this sequence.
1.261 @@ -2044,33 +1900,7 @@
1.262 " s = ret;\n" +
1.263 "}"
1.264 )
1.265 - public String replace(char oldChar, char newChar) {
1.266 - if (oldChar != newChar) {
1.267 - int len = length();
1.268 - int i = -1;
1.269 - char[] val = toCharArray(); /* avoid getfield opcode */
1.270 - int off = offset(); /* avoid getfield opcode */
1.271 -
1.272 - while (++i < len) {
1.273 - if (val[off + i] == oldChar) {
1.274 - break;
1.275 - }
1.276 - }
1.277 - if (i < len) {
1.278 - char buf[] = new char[len];
1.279 - for (int j = 0 ; j < i ; j++) {
1.280 - buf[j] = val[off+j];
1.281 - }
1.282 - while (i < len) {
1.283 - char c = val[off + i];
1.284 - buf[i] = (c == oldChar) ? newChar : c;
1.285 - i++;
1.286 - }
1.287 - return new String(buf, 0, len);
1.288 - }
1.289 - }
1.290 - return this;
1.291 - }
1.292 + public native String replace(char oldChar, char newChar);
1.293
1.294 /**
1.295 * Tells whether or not this string matches the given <a
1.296 @@ -2798,12 +2628,11 @@
1.297 int len = length();
1.298 int st = 0;
1.299 int off = offset(); /* avoid getfield opcode */
1.300 - char[] val = toCharArray(); /* avoid getfield opcode */
1.301
1.302 - while ((st < len) && (val[off + st] <= ' ')) {
1.303 + while ((st < len) && (this.charAt(off + st) <= ' ')) {
1.304 st++;
1.305 }
1.306 - while ((st < len) && (val[off + len - 1] <= ' ')) {
1.307 + while ((st < len) && (this.charAt(off + len - 1) <= ' ')) {
1.308 len--;
1.309 }
1.310 return ((st > 0) || (len < length())) ? substring(st, len) : this;