String.toCharArray is known to be painfully slow. Avoiding it as much as possible and dead code which was referencing it closure
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 07 May 2014 11:55:06 +0200
branchclosure
changeset 1548225ba1d7bdc9
parent 1547 7c10f6d5635c
child 1549 3f4c143ff8f0
String.toCharArray is known to be painfully slow. Avoiding it as much as possible and dead code which was referencing it
rt/emul/mini/src/main/java/java/lang/String.java
     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;