< prev index next >

src/java.base/share/classes/java/lang/StringCoding.java

Print this page
rev 56460 : 8231717: Improve performance of charset decoding when charset is always compactable
   1 /*
   2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 174             return cs.name();
 175         }
 176 
 177         final String requestedCharsetName() {
 178             return requestedCharsetName;
 179         }
 180 
 181         Result decode(byte[] ba, int off, int len) {
 182             if (len == 0) {
 183                 return result.with();
 184             }
 185             // fastpath for ascii compatible
 186             if (isASCIICompatible && !hasNegatives(ba, off, len)) {
 187                 if (COMPACT_STRINGS) {
 188                     return result.with(Arrays.copyOfRange(ba, off, off + len),
 189                                       LATIN1);
 190                 } else {
 191                     return result.with(StringLatin1.inflate(ba, off, len), UTF16);
 192                 }
 193             }






 194             int en = scale(len, cd.maxCharsPerByte());
 195             char[] ca = new char[en];
 196             if (cd instanceof ArrayDecoder) {
 197                 int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
 198                 return result.with(ca, 0, clen);
 199             }
 200             cd.reset();
 201             ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
 202             CharBuffer cb = CharBuffer.wrap(ca);
 203             try {
 204                 CoderResult cr = cd.decode(bb, cb, true);
 205                 if (!cr.isUnderflow())
 206                     cr.throwException();
 207                 cr = cd.flush(cb);
 208                 if (!cr.isUnderflow())
 209                     cr.throwException();
 210             } catch (CharacterCodingException x) {
 211                 // Substitution is always enabled,
 212                 // so this shouldn't happen
 213                 throw new Error(x);


 261         // an additional StringDe/Encoder object to wrap it is to share the
 262         // de/encode() method. These SD/E objects are short-lived, the young-gen
 263         // gc should be able to take care of them well. But the best approach
 264         // is still not to generate them if not really necessary.
 265         // (2)The defensive copy of the input byte/char[] has a big performance
 266         // impact, as well as the outgoing result byte/char[]. Need to do the
 267         // optimization check of (sm==null && classLoader0==null) for both.
 268         // (3)There might be a timing gap in isTrusted setting. getClassLoader0()
 269         // is only checked (and then isTrusted gets set) when (SM==null). It is
 270         // possible that the SM==null for now but then SM is NOT null later
 271         // when safeTrim() is invoked...the "safe" way to do is to redundant
 272         // check (... && (isTrusted || SM == null || getClassLoader0())) in trim
 273         // but it then can be argued that the SM is null when the operation
 274         // is started...
 275         CharsetDecoder cd = cs.newDecoder();
 276         // ascii fastpath
 277         if ((cd instanceof ArrayDecoder) &&
 278             ((ArrayDecoder)cd).isASCIICompatible() && !hasNegatives(ba, off, len)) {
 279             return decodeLatin1(ba, off, len);
 280         }







 281         int en = scale(len, cd.maxCharsPerByte());
 282         if (len == 0) {
 283             return new Result().with();
 284         }
 285         cd.onMalformedInput(CodingErrorAction.REPLACE)
 286           .onUnmappableCharacter(CodingErrorAction.REPLACE)
 287           .reset();
 288         char[] ca = new char[en];
 289         if (cd instanceof ArrayDecoder) {
 290             int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
 291             return new Result().with(ca, 0, clen);
 292         }
 293         if (cs.getClass().getClassLoader0() != null &&
 294             System.getSecurityManager() != null) {
 295             ba = Arrays.copyOfRange(ba, off, off + len);
 296             off = 0;
 297         }
 298         ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
 299         CharBuffer cb = CharBuffer.wrap(ca);
 300         try {


   1 /*
   2  * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 174             return cs.name();
 175         }
 176 
 177         final String requestedCharsetName() {
 178             return requestedCharsetName;
 179         }
 180 
 181         Result decode(byte[] ba, int off, int len) {
 182             if (len == 0) {
 183                 return result.with();
 184             }
 185             // fastpath for ascii compatible
 186             if (isASCIICompatible && !hasNegatives(ba, off, len)) {
 187                 if (COMPACT_STRINGS) {
 188                     return result.with(Arrays.copyOfRange(ba, off, off + len),
 189                                       LATIN1);
 190                 } else {
 191                     return result.with(StringLatin1.inflate(ba, off, len), UTF16);
 192                 }
 193             }
 194             // fastpath for always compactable single byte
 195             if (COMPACT_STRINGS && cd instanceof ArrayDecoder && ((ArrayDecoder)cd).isAlwaysCompactable()) {
 196                 byte[] dst = new byte[len];
 197                 ((ArrayDecoder)cd).decodeToLatin1(ba, off, len, dst);
 198                 return result.with(dst, LATIN1);
 199             }
 200             int en = scale(len, cd.maxCharsPerByte());
 201             char[] ca = new char[en];
 202             if (cd instanceof ArrayDecoder) {
 203                 int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
 204                 return result.with(ca, 0, clen);
 205             }
 206             cd.reset();
 207             ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
 208             CharBuffer cb = CharBuffer.wrap(ca);
 209             try {
 210                 CoderResult cr = cd.decode(bb, cb, true);
 211                 if (!cr.isUnderflow())
 212                     cr.throwException();
 213                 cr = cd.flush(cb);
 214                 if (!cr.isUnderflow())
 215                     cr.throwException();
 216             } catch (CharacterCodingException x) {
 217                 // Substitution is always enabled,
 218                 // so this shouldn't happen
 219                 throw new Error(x);


 267         // an additional StringDe/Encoder object to wrap it is to share the
 268         // de/encode() method. These SD/E objects are short-lived, the young-gen
 269         // gc should be able to take care of them well. But the best approach
 270         // is still not to generate them if not really necessary.
 271         // (2)The defensive copy of the input byte/char[] has a big performance
 272         // impact, as well as the outgoing result byte/char[]. Need to do the
 273         // optimization check of (sm==null && classLoader0==null) for both.
 274         // (3)There might be a timing gap in isTrusted setting. getClassLoader0()
 275         // is only checked (and then isTrusted gets set) when (SM==null). It is
 276         // possible that the SM==null for now but then SM is NOT null later
 277         // when safeTrim() is invoked...the "safe" way to do is to redundant
 278         // check (... && (isTrusted || SM == null || getClassLoader0())) in trim
 279         // but it then can be argued that the SM is null when the operation
 280         // is started...
 281         CharsetDecoder cd = cs.newDecoder();
 282         // ascii fastpath
 283         if ((cd instanceof ArrayDecoder) &&
 284             ((ArrayDecoder)cd).isASCIICompatible() && !hasNegatives(ba, off, len)) {
 285             return decodeLatin1(ba, off, len);
 286         }
 287         // fastpath for always compactable single byte
 288         if (COMPACT_STRINGS && cd instanceof ArrayDecoder && ((ArrayDecoder)cd).isAlwaysCompactable()) {
 289             byte[] dst = new byte[len];
 290             ((ArrayDecoder)cd).decodeToLatin1(ba, off, len, dst);
 291             return new Result().with(dst, LATIN1);
 292         }
 293 
 294         int en = scale(len, cd.maxCharsPerByte());
 295         if (len == 0) {
 296             return new Result().with();
 297         }
 298         cd.onMalformedInput(CodingErrorAction.REPLACE)
 299           .onUnmappableCharacter(CodingErrorAction.REPLACE)
 300           .reset();
 301         char[] ca = new char[en];
 302         if (cd instanceof ArrayDecoder) {
 303             int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
 304             return new Result().with(ca, 0, clen);
 305         }
 306         if (cs.getClass().getClassLoader0() != null &&
 307             System.getSecurityManager() != null) {
 308             ba = Arrays.copyOfRange(ba, off, off + len);
 309             off = 0;
 310         }
 311         ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
 312         CharBuffer cb = CharBuffer.wrap(ca);
 313         try {


< prev index next >