Repository: alibaba/fastjson2
Pull request #3294 (2025-01-18 15:35:47)

refactor
### What this PR does / why we need it?



### Summary of your change



#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.



Patch:
diff --git a/benchmark/pom.xml b/benchmark/pom.xml
index a7118f184..91edfe022 100644
--- a/benchmark/pom.xml
+++ b/benchmark/pom.xml
@@ -32,13 +32,6 @@
             <artifactId>fastjson2-extension</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <!--
-        <dependency>
-            <groupId>com.alibaba.fastjson2</groupId>
-            <artifactId>fastjson2-incubator-vector</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        -->
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>
@@ -217,20 +210,4 @@
             </plugin>
         </plugins>
     </build>
-
-    <profiles>
-        <profile>
-            <id>enable-incubators-for-jdk17+</id>
-            <activation>
-                <jdk>[17,)</jdk>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>com.alibaba.fastjson2</groupId>
-                    <artifactId>fastjson2-incubator-vector</artifactId>
-                    <version>${project.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
 </project>
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONFactory.java b/core/src/main/java/com/alibaba/fastjson2/JSONFactory.java
index 38c158f55..e13d3537e 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONFactory.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONFactory.java
@@ -19,11 +19,8 @@ import java.security.PrivilegedAction;
 import java.time.ZoneId;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-import java.util.function.Function;
 import java.util.function.Supplier;
 
-import static com.alibaba.fastjson2.util.JDKUtils.VECTOR_BIT_LENGTH;
-
 public final class JSONFactory {
     public static final class Conf {
         static final Properties DEFAULT_PROPERTIES;
@@ -93,11 +90,6 @@ public final class JSONFactory {
     static final NameCacheEntry[] NAME_CACHE = new NameCacheEntry[8192];
     static final NameCacheEntry2[] NAME_CACHE2 = new NameCacheEntry2[8192];
 
-    static final Function<JSONWriter.Context, JSONWriter> INCUBATOR_VECTOR_WRITER_CREATOR_UTF16;
-    static final JSONReaderUTF8Creator INCUBATOR_VECTOR_READER_CREATOR_ASCII;
-    static final JSONReaderUTF8Creator INCUBATOR_VECTOR_READER_CREATOR_UTF8;
-    static final JSONReaderUTF16Creator INCUBATOR_VECTOR_READER_CREATOR_UTF16;
-
     static int defaultDecimalMaxScale = 2048;
 
     interface JSONReaderUTF8Creator {
@@ -164,8 +156,6 @@ public final class JSONFactory {
             1.0e20, 1.0e21, 1.0e22
     };
 
-    static final Double DOUBLE_ZERO = (double) 0;
-
     static {
         Properties properties = Conf.DEFAULT_PROPERTIES;
         {
@@ -227,52 +217,6 @@ public final class JSONFactory {
         useJacksonAnnotation = getPropertyBool(properties, "fastjson2.useJacksonAnnotation", true);
         useGsonAnnotation = getPropertyBool(properties, "fastjson2.useGsonAnnotation", true);
         defaultWriterAlphabetic = getPropertyBool(properties, "fastjson2.writer.alphabetic", true);
-
-        boolean readerVector = getPropertyBool(properties, "fastjson2.readerVector", false);
-
-        Function<JSONWriter.Context, JSONWriter> incubatorVectorCreatorUTF16 = null;
-        JSONReaderUTF8Creator readerCreatorASCII = null;
-        JSONReaderUTF8Creator readerCreatorUTF8 = null;
-        JSONReaderUTF16Creator readerCreatorUTF16 = null;
-        if (JDKUtils.VECTOR_SUPPORT) {
-            if (VECTOR_BIT_LENGTH >= 64) {
-                try {
-                    Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONWriterUTF16Vector$Factory");
-                    incubatorVectorCreatorUTF16 = (Function<JSONWriter.Context, JSONWriter>) factoryClass.newInstance();
-                } catch (Throwable e) {
-                    initErrorLast = e;
-                }
-
-                if (readerVector) {
-                    try {
-                        Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONReaderASCIIVector$Factory");
-                        readerCreatorASCII = (JSONReaderUTF8Creator) factoryClass.newInstance();
-                    } catch (Throwable e) {
-                        initErrorLast = e;
-                    }
-
-                    try {
-                        Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONReaderUTF8Vector$Factory");
-                        readerCreatorUTF8 = (JSONReaderUTF8Creator) factoryClass.newInstance();
-                    } catch (Throwable e) {
-                        initErrorLast = e;
-                    }
-                }
-            }
-
-            if (VECTOR_BIT_LENGTH >= 128 && readerVector) {
-                try {
-                    Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONReaderUTF16Vector$Factory");
-                    readerCreatorUTF16 = (JSONReaderUTF16Creator) factoryClass.newInstance();
-                } catch (Throwable e) {
-                    initErrorLast = e;
-                }
-            }
-        }
-        INCUBATOR_VECTOR_WRITER_CREATOR_UTF16 = incubatorVectorCreatorUTF16;
-        INCUBATOR_VECTOR_READER_CREATOR_ASCII = readerCreatorASCII;
-        INCUBATOR_VECTOR_READER_CREATOR_UTF8 = readerCreatorUTF8;
-        INCUBATOR_VECTOR_READER_CREATOR_UTF16 = readerCreatorUTF16;
     }
 
     private static boolean getPropertyBool(Properties properties, String name, boolean defaultValue) {
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java
index 83e7e9762..efe47656e 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java
@@ -499,13 +499,6 @@ public abstract class JSONReader
                 + DIGITS2[c2]);
     }
 
-    static char char4(int c1, int c2, int c3, int c4) {
-        return (char) (DIGITS2[c1] * 0x1000
-                + DIGITS2[c2] * 0x100
-                + DIGITS2[c3] * 0x10
-                + DIGITS2[c4]);
-    }
-
     public abstract boolean nextIfObjectStart();
 
     public abstract boolean nextIfNullOrEmptyString();
@@ -3247,84 +3240,34 @@ public abstract class JSONReader
     }
 
     public static JSONReader of(byte[] utf8Bytes) {
-        boolean ascii = false;
-        if (PREDICATE_IS_ASCII != null) {
-            ascii = PREDICATE_IS_ASCII.test(utf8Bytes);
-        }
-
         Context context = createReadContext();
-        if (ascii) {
-            if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, null, utf8Bytes, 0, utf8Bytes.length);
-            }
-
+        if (PREDICATE_IS_ASCII.test(utf8Bytes)) {
             return new JSONReaderASCII(context, null, utf8Bytes, 0, utf8Bytes.length);
         }
 
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF8 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF8.create(context, null, utf8Bytes, 0, utf8Bytes.length);
-        } else {
-            return new JSONReaderUTF8(context, null, utf8Bytes, 0, utf8Bytes.length);
-        }
+        return new JSONReaderUTF8(context, null, utf8Bytes, 0, utf8Bytes.length);
     }
 
     @Deprecated
     public static JSONReader of(Context context, byte[] utf8Bytes) {
-        boolean ascii = false;
-        if (PREDICATE_IS_ASCII != null) {
-            ascii = PREDICATE_IS_ASCII.test(utf8Bytes);
-        }
-
-        if (ascii) {
-            if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, null, utf8Bytes, 0, utf8Bytes.length);
-            }
-
+        if (PREDICATE_IS_ASCII.test(utf8Bytes)) {
             return new JSONReaderASCII(context, null, utf8Bytes, 0, utf8Bytes.length);
         }
 
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF8 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF8.create(context, null, utf8Bytes, 0, utf8Bytes.length);
-        } else {
-            return new JSONReaderUTF8(context, null, utf8Bytes, 0, utf8Bytes.length);
-        }
+        return new JSONReaderUTF8(context, null, utf8Bytes, 0, utf8Bytes.length);
     }
 
     public static JSONReader of(byte[] utf8Bytes, Context context) {
-        boolean ascii = false;
-        if (PREDICATE_IS_ASCII != null) {
-            ascii = PREDICATE_IS_ASCII.test(utf8Bytes);
-        }
-
-        if (ascii) {
-            if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, null, utf8Bytes, 0, utf8Bytes.length);
-            }
-
+        if (PREDICATE_IS_ASCII.test(utf8Bytes)) {
             return new JSONReaderASCII(context, null, utf8Bytes, 0, utf8Bytes.length);
         }
 
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF8 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF8.create(context, null, utf8Bytes, 0, utf8Bytes.length);
-        } else {
-            return new JSONReaderUTF8(context, null, utf8Bytes, 0, utf8Bytes.length);
-        }
+        return new JSONReaderUTF8(context, null, utf8Bytes, 0, utf8Bytes.length);
     }
 
     public static JSONReader of(char[] chars) {
-        Context context = createReadContext();
-
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    null,
-                    chars,
-                    0,
-                    chars.length);
-        }
-
         return new JSONReaderUTF16(
-                context,
+                createReadContext(),
                 null,
                 chars,
                 0,
@@ -3333,15 +3276,6 @@ public abstract class JSONReader
 
     @Deprecated
     public static JSONReader of(Context context, char[] chars) {
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    null,
-                    chars,
-                    0,
-                    chars.length);
-        }
-
         return new JSONReaderUTF16(
                 context,
                 null,
@@ -3409,11 +3343,7 @@ public abstract class JSONReader
     }
 
     public static JSONReader ofJSONB(byte[] bytes, int offset, int length, Context context) {
-        return new JSONReaderJSONB(
-                context,
-                bytes,
-                offset,
-                length);
+        return new JSONReaderJSONB(context, bytes, offset, length);
     }
 
     public static JSONReader ofJSONB(byte[] bytes, int offset, int length, SymbolTable symbolTable) {
@@ -3428,11 +3358,7 @@ public abstract class JSONReader
         Context context = JSONFactory.createReadContext();
 
         if (charset == StandardCharsets.UTF_8) {
-            if (INCUBATOR_VECTOR_READER_CREATOR_UTF8 != null) {
-                return INCUBATOR_VECTOR_READER_CREATOR_UTF8.create(context, null, bytes, offset, length);
-            } else {
-                return new JSONReaderUTF8(context, null, bytes, offset, length);
-            }
+            return new JSONReaderUTF8(context, null, bytes, offset, length);
         }
 
         if (charset == StandardCharsets.UTF_16) {
@@ -3440,11 +3366,7 @@ public abstract class JSONReader
         }
 
         if (charset == StandardCharsets.US_ASCII || charset == StandardCharsets.ISO_8859_1) {
-            if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, null, bytes, offset, length);
-            } else {
-                return new JSONReaderASCII(context, null, bytes, offset, length);
-            }
+            return new JSONReaderASCII(context, null, bytes, offset, length);
         }
 
         throw new JSONException("not support charset " + charset);
@@ -3466,18 +3388,10 @@ public abstract class JSONReader
             }
 
             if (!hasNegative) {
-                if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                    return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, null, bytes, offset, length);
-                } else {
-                    return new JSONReaderASCII(context, null, bytes, offset, length);
-                }
+                return new JSONReaderASCII(context, null, bytes, offset, length);
             }
 
-            if (INCUBATOR_VECTOR_READER_CREATOR_UTF8 != null) {
-                return INCUBATOR_VECTOR_READER_CREATOR_UTF8.create(context, null, bytes, offset, length);
-            } else {
-                return new JSONReaderUTF8(context, null, bytes, offset, length);
-            }
+            return new JSONReaderUTF8(context, null, bytes, offset, length);
         }
 
         if (charset == StandardCharsets.UTF_16) {
@@ -3485,58 +3399,25 @@ public abstract class JSONReader
         }
 
         if (charset == StandardCharsets.US_ASCII || charset == StandardCharsets.ISO_8859_1) {
-            if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, null, bytes, offset, length);
-            } else {
-                return new JSONReaderASCII(context, null, bytes, offset, length);
-            }
+            return new JSONReaderASCII(context, null, bytes, offset, length);
         }
 
         throw new JSONException("not support charset " + charset);
     }
 
     public static JSONReader of(byte[] bytes, int offset, int length) {
-        Context context = createReadContext();
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF8 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF8.create(context, null, bytes, offset, length);
-        } else {
-            return new JSONReaderUTF8(context, null, bytes, offset, length);
-        }
+        return new JSONReaderUTF8(createReadContext(), null, bytes, offset, length);
     }
 
     public static JSONReader of(byte[] bytes, int offset, int length, Context context) {
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF8 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF8.create(context, null, bytes, offset, length);
-        } else {
-            return new JSONReaderUTF8(context, null, bytes, offset, length);
-        }
+        return new JSONReaderUTF8(context, null, bytes, offset, length);
     }
 
     public static JSONReader of(char[] chars, int offset, int length) {
-        Context context = createReadContext();
-
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    null,
-                    chars,
-                    offset,
-                    length);
-        }
-
-        return new JSONReaderUTF16(context, null, chars, offset, length);
+        return new JSONReaderUTF16(createReadContext(), null, chars, offset, length);
     }
 
     public static JSONReader of(char[] chars, int offset, int length, Context context) {
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    null,
-                    chars,
-                    offset,
-                    length);
-        }
-
         return new JSONReaderUTF16(context, null, chars, offset, length);
     }
 
@@ -3614,18 +3495,14 @@ public abstract class JSONReader
         }
 
         Context context = JSONFactory.createReadContext();
-        if (STRING_VALUE != null && STRING_CODER != null && PREDICATE_IS_ASCII != null) {
+        if (STRING_VALUE != null && STRING_CODER != null) {
             try {
                 final int LATIN1 = 0;
                 int coder = STRING_CODER.applyAsInt(str);
                 if (coder == LATIN1) {
                     byte[] bytes = STRING_VALUE.apply(str);
                     if (PREDICATE_IS_ASCII.test(bytes)) {
-                        if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                            return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, str, bytes, 0, bytes.length);
-                        } else {
-                            return new JSONReaderASCII(context, str, bytes, 0, bytes.length);
-                        }
+                        return new JSONReaderASCII(context, str, bytes, 0, bytes.length);
                     }
                 }
             } catch (Exception e) {
@@ -3639,15 +3516,6 @@ public abstract class JSONReader
             return new JSONReaderUTF16(context, str, chars, 0, length);
         }
 
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    str,
-                    null,
-                    0,
-                    length);
-        }
-
         return new JSONReaderUTF16(context, str, 0, length);
     }
 
@@ -3662,11 +3530,7 @@ public abstract class JSONReader
                 int coder = STRING_CODER.applyAsInt(str);
                 if (coder == LATIN1) {
                     byte[] bytes = STRING_VALUE.apply(str);
-                    if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                        return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, str, bytes, 0, bytes.length);
-                    } else {
-                        return new JSONReaderASCII(context, str, bytes, 0, bytes.length);
-                    }
+                    return new JSONReaderASCII(context, str, bytes, 0, bytes.length);
                 }
             } catch (Exception e) {
                 throw new JSONException("unsafe get String.coder error");
@@ -3681,15 +3545,6 @@ public abstract class JSONReader
             chars = str.toCharArray();
         }
 
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    str,
-                    chars,
-                    0,
-                    length);
-        }
-
         return new JSONReaderUTF16(context, str, chars, 0, length);
     }
 
@@ -3705,11 +3560,7 @@ public abstract class JSONReader
                 int coder = STRING_CODER.applyAsInt(str);
                 if (coder == LATIN1) {
                     byte[] bytes = STRING_VALUE.apply(str);
-                    if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                        return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, str, bytes, offset, length);
-                    } else {
-                        return new JSONReaderASCII(context, str, bytes, offset, length);
-                    }
+                    return new JSONReaderASCII(context, str, bytes, offset, length);
                 }
             } catch (Exception e) {
                 throw new JSONException("unsafe get String.coder error");
@@ -3723,15 +3574,6 @@ public abstract class JSONReader
             chars = str.toCharArray();
         }
 
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    str,
-                    chars,
-                    offset,
-                    length);
-        }
-
         return new JSONReaderUTF16(context, str, chars, offset, length);
     }
 
@@ -3746,11 +3588,7 @@ public abstract class JSONReader
                 int coder = STRING_CODER.applyAsInt(str);
                 if (coder == LATIN1) {
                     byte[] bytes = STRING_VALUE.apply(str);
-                    if (INCUBATOR_VECTOR_READER_CREATOR_ASCII != null) {
-                        return INCUBATOR_VECTOR_READER_CREATOR_ASCII.create(context, str, bytes, offset, length);
-                    } else {
-                        return new JSONReaderASCII(context, str, bytes, offset, length);
-                    }
+                    return new JSONReaderASCII(context, str, bytes, offset, length);
                 }
             } catch (Exception e) {
                 throw new JSONException("unsafe get String.coder error");
@@ -3764,15 +3602,6 @@ public abstract class JSONReader
             chars = str.toCharArray();
         }
 
-        if (INCUBATOR_VECTOR_READER_CREATOR_UTF16 != null) {
-            return INCUBATOR_VECTOR_READER_CREATOR_UTF16.create(
-                    context,
-                    str,
-                    chars,
-                    offset,
-                    length);
-        }
-
         return new JSONReaderUTF16(context, str, chars, offset, length);
     }
 
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java
index ea423aaed..a5b5cea9b 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java
@@ -10,6 +10,8 @@ import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
 import static com.alibaba.fastjson2.JSONFactory.*;
+import static com.alibaba.fastjson2.JSONReaderJSONB.check3;
+import static com.alibaba.fastjson2.util.IOUtils.hexDigit4;
 import static com.alibaba.fastjson2.util.JDKUtils.*;
 
 class JSONReaderASCII
@@ -141,7 +143,7 @@ class JSONReaderASCII
         }
 
         final int quote = ch;
-
+        final int end = this.end;
         this.nameAscii = true;
         this.nameEscape = false;
         int offset = this.nameBegin = this.offset;
@@ -169,7 +171,7 @@ class JSONReaderASCII
                 offset += 3;
             } else if ((c3 = bytes[offset + 3]) == quote
                     && c0 != '\\' && c1 != '\\' && c2 != '\\'
-                    && c0 >= 0 && c1 >= 0 && c2 > 0
+                    && (c0 | c1) >= 0 && c2 > 0
             ) {
                 nameValue
                         = (c2 << 16)
@@ -180,7 +182,7 @@ class JSONReaderASCII
                 offset += 4;
             } else if ((c4 = bytes[offset + 4]) == quote
                     && c0 != '\\' && c1 != '\\' && c2 != '\\' && c3 != '\\'
-                    && c0 >= 0 && c1 >= 0 && c2 >= 0 && c3 > 0
+                    && (c0 | c1 | c2) >= 0 && c3 > 0
             ) {
                 nameValue
                         = (c3 << 24)
@@ -192,7 +194,7 @@ class JSONReaderASCII
                 offset += 5;
             } else if ((c5 = bytes[offset + 5]) == quote
                     && c0 != '\\' && c1 != '\\' && c2 != '\\' && c3 != '\\' && c4 != '\\'
-                    && c0 >= 0 && c1 >= 0 && c2 >= 0 && c3 >= 0 && c4 > 0
+                    && (c0 | c1 | c2 | c3) >= 0 && c4 > 0
             ) {
                 nameValue
                         = (((long) c4) << 32)
@@ -205,7 +207,7 @@ class JSONReaderASCII
                 offset += 6;
             } else if ((c6 = bytes[offset + 6]) == quote
                     && c0 != '\\' && c1 != '\\' && c2 != '\\' && c3 != '\\' && c4 != '\\' && c5 != '\\'
-                    && c0 >= 0 && c1 >= 0 && c2 >= 0 && c3 >= 0 && c4 >= 0 && c5 > 0
+                    && (c0 | c1 | c2 | c3 | c4) >= 0 && c5 > 0
             ) {
                 nameValue
                         = (((long) c5) << 40)
@@ -219,7 +221,7 @@ class JSONReaderASCII
                 offset += 7;
             } else if ((c7 = bytes[offset + 7]) == quote
                     && c0 != '\\' && c1 != '\\' && c2 != '\\' && c3 != '\\' && c4 != '\\' && c5 != '\\' && c6 != '\\'
-                    && c0 >= 0 && c1 >= 0 && c2 >= 0 && c3 >= 0 && c4 >= 0 && c5 >= 0 && c6 > 0
+                    && (c0 | c1 | c2 | c3 | c4 | c5) >= 0 && c6 > 0
             ) {
                 nameValue
                         = (((long) c6) << 48)
@@ -234,7 +236,7 @@ class JSONReaderASCII
                 offset += 8;
             } else if (bytes[offset + 8] == quote
                     && c0 != '\\' && c1 != '\\' && c2 != '\\' && c3 != '\\' && c4 != '\\' && c5 != '\\' && c6 != '\\' && c7 != '\\'
-                    && c0 >= 0 && c1 >= 0 && c2 >= 0 && c3 >= 0 && c4 >= 0 && c5 >= 0 && c6 >= 0 && c7 > 0
+                    && (c0 | c1 | c2 | c3 | c4 | c5 | c6) >= 0 && c7 > 0
             ) {
                 nameValue
                         = (((long) c7) << 56)
@@ -272,7 +274,7 @@ class JSONReaderASCII
                     ch = bytes[++offset];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            ch = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -346,7 +348,7 @@ class JSONReaderASCII
                     ch = bytes[++offset];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            ch = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -453,7 +455,7 @@ class JSONReaderASCII
                 ch = (char) bytes[offset++];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
+                        ch = hexDigit4(bytes, check3(offset, end));
                         offset += 4;
                         break;
                     }
@@ -534,7 +536,7 @@ class JSONReaderASCII
                     ch = bytes[offset++];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
+                            ch = hexDigit4(bytes, check3(offset, end));
                             offset += 4;
                             break;
                         }
@@ -622,13 +624,6 @@ class JSONReaderASCII
         return hashCode;
     }
 
-    public static long getLong(byte[] bytes, int off) {
-        return UNSAFE.getLong(
-                bytes,
-                ARRAY_BYTE_BASE_OFFSET + off
-        );
-    }
-
     @Override
     public final long readValueHashCode() {
         int ch = this.ch;
@@ -665,7 +660,7 @@ class JSONReaderASCII
                 ch = bytes[++offset];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        ch = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -732,7 +727,7 @@ class JSONReaderASCII
                     ch = bytes[++offset];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            ch = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -787,7 +782,7 @@ class JSONReaderASCII
     @Override
     public final long getNameHashCodeLCase() {
         final byte[] bytes = this.bytes;
-        int offset = nameBegin;
+        int offset = nameBegin, end = this.end;
         long nameValue = 0;
         for (int i = 0; offset < end; offset++) {
             int c = bytes[offset];
@@ -796,7 +791,7 @@ class JSONReaderASCII
                 c = bytes[++offset];
                 switch (c) {
                     case 'u': {
-                        c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        c = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -875,7 +870,7 @@ class JSONReaderASCII
                 c = bytes[++offset];
                 switch (c) {
                     case 'u': {
-                        c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        c = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -930,14 +925,14 @@ class JSONReaderASCII
         if (JDKUtils.STRING_CREATOR_JDK11 != null) {
             byte[] chars = new byte[nameLength];
             forStmt:
-            for (int i = 0; offset < nameEnd; ++i) {
+            for (int i = 0, end = this.end; offset < nameEnd; ++i) {
                 byte b = bytes[offset];
 
                 if (b == '\\') {
                     b = bytes[++offset];
                     switch (b) {
                         case 'u': {
-                            char ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            int ch = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             if (ch > 0xFF) {
                                 chars = null;
@@ -994,7 +989,7 @@ class JSONReaderASCII
                 ch = (char) bytes[++offset];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        ch = (char) hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -1376,7 +1371,7 @@ class JSONReaderASCII
                     c = (char) (bytes[++offset]);
                     switch (c) {
                         case 'u': {
-                            c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            c = (char) hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -1425,7 +1420,7 @@ class JSONReaderASCII
     }
 
     @Override
-    public String readString() {
+    public final String readString() {
         if (ch == '"' || ch == '\'') {
             final byte[] bytes = this.bytes;
             final byte quote = (byte) ch;
@@ -1436,13 +1431,13 @@ class JSONReaderASCII
             int valueLength;
             boolean valueEscape = false;
 
-            int index = IOUtils.indexOfChar(bytes, quote, offset, end);
+            int index = IOUtils.indexOfQuote(bytes, quote, offset, end);
             if (index == -1) {
                 throw error("invalid escape character EOI");
             }
             int slashIndex = nextEscapeIndex;
             if (slashIndex == ESCAPE_INDEX_NOT_SET || (slashIndex != -1 && slashIndex < offset)) {
-                nextEscapeIndex = slashIndex = IOUtils.indexOfChar(bytes, '\\', offset, end);
+                nextEscapeIndex = slashIndex = IOUtils.indexOfSlash(bytes, offset, end);
             }
             if (slashIndex == -1 || slashIndex > index) {
                 valueLength = index - offset;
@@ -1525,7 +1520,7 @@ class JSONReaderASCII
                 c = (char) bytes[++offset];
                 switch (c) {
                     case 'u': {
-                        c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        c = (char) hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
index d96c6c848..9dac88e98 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
@@ -14,6 +14,7 @@ import java.time.*;
 import java.util.*;
 
 import static com.alibaba.fastjson2.JSONFactory.*;
+import static com.alibaba.fastjson2.JSONReaderJSONB.check3;
 import static com.alibaba.fastjson2.util.IOUtils.*;
 import static com.alibaba.fastjson2.util.IOUtils.INT_32_MULT_MIN_10;
 import static com.alibaba.fastjson2.util.JDKUtils.*;
@@ -962,7 +963,7 @@ class JSONReaderUTF16
                 ch = chars[offset++];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(chars[offset], chars[offset + 1], chars[offset + 2], chars[offset + 3]);
+                        ch = (char) hexDigit4(chars, check3(offset, end));
                         offset += 4;
                         break;
                     }
@@ -1043,7 +1044,7 @@ class JSONReaderUTF16
                     ch = chars[offset++];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(chars[offset], chars[offset + 1], chars[offset + 2], chars[offset + 3]);
+                            ch = (char) hexDigit4(chars, check3(offset, end));
                             offset += 4;
                             break;
                         }
@@ -1293,7 +1294,7 @@ class JSONReaderUTF16
                     c = chars[++offset];
                     switch (c) {
                         case 'u': {
-                            c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                            c = (char) hexDigit4(chars, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -1359,7 +1360,7 @@ class JSONReaderUTF16
                     c = chars[++offset];
                     switch (c) {
                         case 'u': {
-                            c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                            c = (char) hexDigit4(chars, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -1446,7 +1447,7 @@ class JSONReaderUTF16
                 ch = chars[++offset];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                        ch = (char) hexDigit4(chars, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -1511,7 +1512,7 @@ class JSONReaderUTF16
                     c = chars[++offset];
                     switch (c) {
                         case 'u': {
-                            c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                            c = (char) hexDigit4(chars, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -1590,7 +1591,7 @@ class JSONReaderUTF16
                 c = chars[++offset];
                 switch (c) {
                     case 'u': {
-                        c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                        c = (char) hexDigit4(chars, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -1669,7 +1670,7 @@ class JSONReaderUTF16
                 c = chars[++offset];
                 switch (c) {
                     case 'u': {
-                        c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                        c = (char) hexDigit4(chars, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -1726,7 +1727,7 @@ class JSONReaderUTF16
                 c = chars[++offset];
                 switch (c) {
                     case 'u': {
-                        c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                        c = (char) hexDigit4(chars, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -2932,7 +2933,7 @@ class JSONReaderUTF16
                 c = chars[++offset];
                 switch (c) {
                     case 'u': {
-                        c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                        c = (char) hexDigit4(chars, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -2991,7 +2992,7 @@ class JSONReaderUTF16
                 if (c == '\\') {
                     c = this.chars[++offset];
                     if (c == 'u') {
-                        c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                        c = (char) hexDigit4(chars, check3(offset + 1, end));
                         offset += 4;
                     } else if (c == 'x') {
                         c = char2(chars[offset + 1], chars[offset + 2]);
@@ -3045,72 +3046,49 @@ class JSONReaderUTF16
 
     @Override
     public String readString() {
+        final char[] chars = this.chars;
         if (ch == '"' || ch == '\'') {
-            char[] chars = this.chars;
             final char quote = ch;
+            final long byteVectorQuote = quote == '\'' ? 0x2727_2727_2727_2727L : 0x2222_2222_2222_2222L;
 
             int offset = this.offset;
-            final int start = offset;
+            final int start = offset, end = this.end;
             int valueLength;
             boolean valueEscape = false;
 
-            _for:
+            int upperBound = offset + ((end - offset) & ~7);
             {
                 int i = 0;
-                char c0 = 0, c1 = 0, c2 = 0, c3;
-
-                // vector optimize
-                boolean quoted = false;
-                int upperBound = offset + ((end - offset) & ~3);
                 while (offset < upperBound) {
-                    c0 = chars[offset];
-                    c1 = chars[offset + 1];
-                    c2 = chars[offset + 2];
-                    c3 = chars[offset + 3];
-                    if (c0 == '\\' || c1 == '\\' || c2 == '\\' || c3 == '\\') {
-                        break;
-                    }
-                    if (c0 == quote || c1 == quote || c2 == quote || c3 == quote) {
-                        quoted = true;
+                    long v0 = getLongLE(chars, offset);
+                    long v1 = getLongLE(chars, offset + 4);
+                    if (((v0 | v1) & 0xFF00FF00FF00FF00L) != 0
+                            || JSONReaderUTF8.containsSlashOrQuote((v0 << 8) | v1, byteVectorQuote)
+                    ) {
                         break;
                     }
-                    offset += 4;
-                    i += 4;
+
+                    offset += 8;
+                    i += 8;
                 }
 
-                if (quoted) {
-                    if (c0 == quote) {
-                        // skip
-                    } else if (c1 == quote) {
-                        offset++;
-                        i++;
-                    } else if (c2 == quote) {
-                        offset += 2;
-                        i += 2;
-                    } else {
-                        offset += 3;
-                        i += 3;
+                for (; ; ++i) {
+                    if (offset >= end) {
+                        throw new JSONException(info("invalid escape character EOI"));
+                    }
+                    char c = chars[offset];
+                    if (c == '\\') {
+                        valueEscape = true;
+                        c = chars[offset + 1];
+                        offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2));
+                        continue;
                     }
-                    valueLength = i;
-                } else {
-                    for (; ; ++i) {
-                        if (offset >= end) {
-                            throw new JSONException(info("invalid escape character EOI"));
-                        }
-                        char c = chars[offset];
-                        if (c == '\\') {
-                            valueEscape = true;
-                            c = chars[offset + 1];
-                            offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2));
-                            continue;
-                        }
 
-                        if (c == quote) {
-                            valueLength = i;
-                            break _for;
-                        }
-                        offset++;
+                    if (c == quote) {
+                        valueLength = i;
+                        break;
                     }
+                    offset++;
                 }
             }
 
@@ -3124,7 +3102,7 @@ class JSONReaderUTF16
                         c = chars[++offset];
                         switch (c) {
                             case 'u': {
-                                c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
+                                c = (char) hexDigit4(chars, check3(offset + 1, end));
                                 offset += 4;
                                 break;
                             }
@@ -3162,11 +3140,7 @@ class JSONReaderUTF16
                     offset++;
                 }
 
-                if (STRING_CREATOR_JDK8 != null) {
-                    str = STRING_CREATOR_JDK8.apply(buf, Boolean.TRUE);
-                } else {
-                    str = new String(buf);
-                }
+                str = new String(buf);
             } else {
                 char c0, c1;
                 int strlen = offset - start;
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
index 74aec9400..d2caf941d 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
@@ -7,10 +7,12 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.time.*;
 import java.util.*;
 
 import static com.alibaba.fastjson2.JSONFactory.*;
+import static com.alibaba.fastjson2.JSONReaderJSONB.check3;
 import static com.alibaba.fastjson2.util.IOUtils.*;
 import static com.alibaba.fastjson2.util.JDKUtils.*;
 import static java.lang.Long.MIN_VALUE;
@@ -528,7 +530,7 @@ class JSONReaderUTF8
                 ch = (char) bytes[offset++];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
+                        ch = hexDigit4(bytes, check3(offset, end));
                         offset += 4;
                         break;
                     }
@@ -641,7 +643,7 @@ class JSONReaderUTF8
                     ch = bytes[offset++];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
+                            ch = hexDigit4(bytes, check3(offset, end));
                             offset += 4;
                             break;
                         }
@@ -2493,7 +2495,7 @@ class JSONReaderUTF8
                     ch = bytes[++offset];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            ch = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -2567,7 +2569,7 @@ class JSONReaderUTF8
                     ch = bytes[++offset];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            ch = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -2681,7 +2683,7 @@ class JSONReaderUTF8
                 ch = bytes[++offset];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        ch = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -2748,7 +2750,7 @@ class JSONReaderUTF8
                     ch = bytes[++offset];
                     switch (ch) {
                         case 'u': {
-                            ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            ch = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -2858,7 +2860,7 @@ class JSONReaderUTF8
     @Override
     public long getNameHashCodeLCase() {
         long hashCode = Fnv.MAGIC_HASH_CODE;
-        int offset = nameBegin;
+        int offset = nameBegin, end = this.end;
         final byte[] bytes = this.bytes;
 
         long nameValue = 0;
@@ -2869,7 +2871,7 @@ class JSONReaderUTF8
                 ch = bytes[++offset];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        ch = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -2968,7 +2970,7 @@ class JSONReaderUTF8
                 ch = bytes[++offset];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        ch = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -3075,7 +3077,7 @@ class JSONReaderUTF8
 
         char[] chars = new char[nameLength];
 
-        for (int i = 0; offset < nameEnd; ++i) {
+        for (int i = 0, end = this.end; offset < nameEnd; ++i) {
             int ch = bytes[offset];
             if (ch < 0) {
                 ch &= 0xFF;
@@ -3104,7 +3106,7 @@ class JSONReaderUTF8
                 ch = (char) bytes[++offset];
                 switch (ch) {
                     case 'u': {
-                        ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                        ch = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -4068,13 +4070,13 @@ class JSONReaderUTF8
 
             char[] chars = new char[valueLength];
             offset = start;
-            for (int i = 0; ; ++i) {
+            for (int i = 0, end = this.end; ; ++i) {
                 int c = bytes[offset];
                 if (c == '\\') {
                     c = bytes[++offset];
                     switch (c) {
                         case 'u': {
-                            c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            c = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -4191,7 +4193,7 @@ class JSONReaderUTF8
         char quote = this.ch;
         int valueLength;
         int offset = this.offset;
-        int start = offset;
+        int start = offset, end = this.end;
         boolean ascii = true;
         valueEscape = false;
         final byte[] bytes = this.bytes;
@@ -4250,7 +4252,7 @@ class JSONReaderUTF8
                     c = bytes[++offset];
                     switch (c) {
                         case 'u': {
-                            c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
+                            c = hexDigit4(bytes, check3(offset + 1, end));
                             offset += 4;
                             break;
                         }
@@ -4616,7 +4618,7 @@ class JSONReaderUTF8
             return stringValue;
         }
         final byte[] bytes = this.bytes;
-        int offset = nameBegin;
+        int offset = nameBegin, end = this.end;
         int length = nameEnd - offset;
         if (!nameEscape) {
             if (ANDROID) {
@@ -4694,11 +4696,7 @@ class JSONReaderUTF8
                 c = (char) bytes[++offset];
                 switch (c) {
                     case 'u': {
-                        int c1 = bytes[offset + 1];
-                        int c2 = bytes[offset + 2];
-                        int c3 = bytes[offset + 3];
-                        int c4 = bytes[offset + 4];
-                        c = char4(c1, c2, c3, c4);
+                        c = hexDigit4(bytes, check3(offset + 1, end));
                         offset += 4;
                         break;
                     }
@@ -4735,7 +4733,6 @@ class JSONReaderUTF8
 
         final byte[] bytes = this.bytes;
         byte ch = bytes[offset++];
-        byte start = ch;
 
         boolean multi;
         if (ch == '*') {
@@ -4796,58 +4793,92 @@ class JSONReaderUTF8
         }
     }
 
+    static boolean containsSlashOrQuote(long v, long quote) {
+        /*
+          for (int i = 0; i < 8; ++i) {
+            byte c = (byte) v;
+            if (c == '"' || c == '\\') {
+                return true;
+            }
+            v >>>= 8;
+          }
+          return false;
+         */
+        long x22 = v ^ quote; // " -> 0x22
+        long x5c = v ^ 0x5C5C5C5C5C5C5C5CL; // \n -> 0x0a
+        x22 = (x22 - 0x0101010101010101L) & ~x22;
+        x5c = (x5c - 0x0101010101010101L) & ~x5c;
+        return ((x22 | x5c) & 0x8080808080808080L) != 0;
+    }
+
     @Override
     public String readString() {
-        final byte[] bytes = this.bytes;
         if (ch == '"' || ch == '\'') {
+            final byte[] bytes = this.bytes;
             char quote = this.ch;
             int valueLength;
             int offset = this.offset;
             final int start = offset, end = this.end;
+            final long byteVectorQuote = quote == '\'' ? 0x2727_2727_2727_2727L : 0x2222_2222_2222_2222L;
             boolean ascii = true;
             valueEscape = false;
 
-            for (int i = 0; ; ++i) {
-                if (offset >= end) {
-                    throw new JSONException("invalid escape character EOI");
-                }
+            {
+                int i = 0;
+                int upperBound = offset + ((end - offset) & ~7);
+                while (offset < upperBound) {
+                    long v = getLongLE(bytes, offset);
+                    if ((v & 0xFF00FF00FF00FF00L) != 0 || JSONReaderUTF8.containsSlashOrQuote(v, byteVectorQuote)) {
+                        break;
+                    }
 
-                int ch = bytes[offset];
-                if (ch == '\\') {
-                    valueEscape = true;
-                    ch = bytes[offset + 1];
-                    offset += (ch == 'u' ? 6 : (ch == 'x' ? 4 : 2));
-                    continue;
+                    offset += 8;
+                    i += 8;
                 }
+                // ...
 
-                if (ch >= 0) {
-                    if (ch == quote) {
-                        valueLength = i;
-                        break;
+                for (; ; ++i) {
+                    if (offset >= end) {
+                        throw new JSONException("invalid escape character EOI");
                     }
-                    offset++;
-                } else {
-                    ascii = false;
-                    switch ((ch & 0xFF) >> 4) {
-                        case 12:
-                        case 13: {
-                            /* 110x xxxx   10xx xxxx*/
-                            offset += 2;
-                            break;
-                        }
-                        case 14: {
-                            offset += 3;
+
+                    int c = bytes[offset];
+                    if (c == '\\') {
+                        valueEscape = true;
+                        c = bytes[offset + 1];
+                        offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2));
+                        continue;
+                    }
+
+                    if (c >= 0) {
+                        if (c == quote) {
+                            valueLength = i;
                             break;
                         }
-                        default: {
-                            /* 10xx xxxx,  1111 xxxx */
-                            if ((ch >> 3) == -2) {
-                                offset += 4;
-                                i++;
+                        offset++;
+                    } else {
+                        ascii = false;
+                        switch ((c & 0xFF) >> 4) {
+                            case 12:
+                            case 13: {
+                                /* 110x xxxx   10xx xxxx*/
+                                offset += 2;
                                 break;
                             }
+                            case 14: {
+                                offset += 3;
+                                break;
+                            }
+                            default: {
+                                /* 10xx xxxx,  1111 xxxx */
+                                if ((c >> 3) == -2) {
+                                    offset += 4;
+                                    i++;
+                                    break;
+                                }
 
-                            throw new JSONException("malformed input around byte " + offset);
+                                throw new JSONException("malformed input around byte " + offset);
+                            }
                         }
                     }
                 }
@@ -4863,15 +4894,12 @@ class JSONReaderUTF8
                         ch = bytes[++offset];
                         switch (ch) {
                             case 'u': {
-                                ch = DIGITS2[bytes[offset + 1]] * 0x1000
-                                        + DIGITS2[bytes[offset + 2]] * 0x100
-                                        + DIGITS2[bytes[offset + 3]] * 0x10
-                                        + DIGITS2[bytes[offset + 4]];
+                                ch = hexDigit4(bytes, check3(offset + 1, end));
                                 offset += 4;
                                 break;
                             }
                             case 'x': {
-                                ch = DIGITS2[bytes[offset + 1]] * 0x10 + DIGITS2[bytes[offset + 2]];
+                                ch = char2(bytes[offset + 1], bytes[offset + 2]);
                                 offset += 2;
                                 break;
                             }
@@ -4907,24 +4935,23 @@ class JSONReaderUTF8
                             offset++;
                         } else {
                             switch ((ch & 0xFF) >> 4) {
-                                case 0b1100:
-                                case 0b1101: {
+                                case 12:
+                                case 13: {
                                     /* 110x xxxx   10xx xxxx*/
-                                    int c2 = bytes[offset + 1];
-                                    chars[i] = (char) (
-                                            ((ch & 0x1F) << 6) | (c2 & 0x3F));
+                                    chars[i] = (char) (((ch & 0x1F) << 6) | (bytes[offset + 1] & 0x3F));
                                     offset += 2;
                                     break;
                                 }
-                                case 0b1110: {
+                                case 14: {
                                     chars[i] = (char)
                                             (((ch & 0x0F) << 12) |
                                                     ((bytes[offset + 1] & 0x3F) << 6) |
-                                                    ((bytes[offset + 2] & 0x3F)));
+                                                    ((bytes[offset + 2] & 0x3F) << 0));
                                     offset += 3;
                                     break;
                                 }
                                 default: {
+                                    /* 10xx xxxx,  1111 xxxx */
                                     char2_utf8(bytes, offset, ch, chars, i);
                                     offset += 4;
                                     i++;
@@ -4944,32 +4971,20 @@ class JSONReaderUTF8
                             (char) (bytes[start] & 0xff),
                             (char) (bytes[start + 1] & 0xff)
                     );
-                } else if (STRING_CREATOR_JDK8 != null) {
-                    char[] chars = new char[strlen];
-                    for (int i = 0; i < strlen; ++i) {
-                        chars[i] = (char) bytes[start + i];
-                    }
-
-                    str = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
                 } else if (STRING_CREATOR_JDK11 != null) {
-                    byte[] buf = Arrays.copyOfRange(bytes, start, offset);
-                    str = STRING_CREATOR_JDK11.apply(buf, LATIN1);
-                } else if (ANDROID) {
-                    str = getLatin1String(start, offset - start);
+                    str = STRING_CREATOR_JDK11.apply(
+                            Arrays.copyOfRange(this.bytes, this.offset, offset),
+                            LATIN1);
                 } else {
-                    str = new String(bytes, start, offset - start, ISO_8859_1);
+                    str = new String(bytes, start, offset - start, StandardCharsets.US_ASCII);
                 }
             } else {
-                str = new String(bytes, start, offset - start, UTF_8);
+                str = new String(bytes, start, offset - start, StandardCharsets.UTF_8);
             }
 
             if ((context.features & Feature.TrimString.mask) != 0) {
                 str = str.trim();
             }
-            // empty string to null
-            if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
-                str = null;
-            }
 
             int ch = ++offset == end ? EOI : bytes[offset++];
             while (ch <= ' ' && (1L << ch & SPACE) != 0) {
@@ -4988,7 +5003,39 @@ class JSONReaderUTF8
             return str;
         }
 
-        return readStringNotMatch();
+        switch (ch) {
+            case '[':
+                return toString(
+                        readArray());
+            case '{':
+                return toString(
+                        readObject());
+            case '-':
+            case '+':
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                readNumber0();
+                Number number = getNumber();
+                return number.toString();
+            case 't':
+            case 'f':
+                boolValue = readBoolValue();
+                return boolValue ? "true" : "false";
+            case 'n': {
+                readNull();
+                return null;
+            }
+            default:
+                throw new JSONException("TODO : " + ch);
+        }
     }
 
     @Override
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
index b1f8f2a81..dbc293d19 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
@@ -548,9 +548,7 @@ public abstract class JSONWriter
         } else if ((defaultWriterFeatures & OptimizedForAscii.mask) != 0) {
             jsonWriter = ofUTF8(writeContext);
         } else {
-            if (INCUBATOR_VECTOR_WRITER_CREATOR_UTF16 != null) {
-                jsonWriter = INCUBATOR_VECTOR_WRITER_CREATOR_UTF16.apply(writeContext);
-            } else if (FIELD_STRING_VALUE != null && STRING_CODER != null && STRING_VALUE != null) {
+            if (FIELD_STRING_VALUE != null && STRING_CODER != null && STRING_VALUE != null) {
                 jsonWriter = new JSONWriterUTF16JDK9UF(writeContext);
             } else {
                 jsonWriter = new JSONWriterUTF16(writeContext);
@@ -584,8 +582,8 @@ public abstract class JSONWriter
                 jsonWriter = new JSONWriterUTF8(context);
             }
         } else {
-            if (INCUBATOR_VECTOR_WRITER_CREATOR_UTF16 != null) {
-                jsonWriter = INCUBATOR_VECTOR_WRITER_CREATOR_UTF16.apply(context);
+            if (FIELD_STRING_VALUE != null && STRING_CODER != null && STRING_VALUE != null) {
+                jsonWriter = new JSONWriterUTF16JDK9UF(context);
             } else {
                 jsonWriter = new JSONWriterUTF16(context);
             }
@@ -606,8 +604,8 @@ public abstract class JSONWriter
         } else if ((writeContext.features & OptimizedForAscii.mask) != 0) {
             jsonWriter = ofUTF8(writeContext);
         } else {
-            if (INCUBATOR_VECTOR_WRITER_CREATOR_UTF16 != null) {
-                jsonWriter = INCUBATOR_VECTOR_WRITER_CREATOR_UTF16.apply(writeContext);
+            if (FIELD_STRING_VALUE != null && STRING_CODER != null && STRING_VALUE != null) {
+                jsonWriter = new JSONWriterUTF16JDK9UF(writeContext);
             } else {
                 jsonWriter = new JSONWriterUTF16(writeContext);
             }
@@ -626,8 +624,8 @@ public abstract class JSONWriter
                 jsonWriter = new JSONWriterUTF16JDK8(writeContext);
             }
         } else {
-            if (INCUBATOR_VECTOR_WRITER_CREATOR_UTF16 != null) {
-                jsonWriter = INCUBATOR_VECTOR_WRITER_CREATOR_UTF16.apply(writeContext);
+            if (FIELD_STRING_VALUE != null && STRING_CODER != null && STRING_VALUE != null) {
+                jsonWriter = new JSONWriterUTF16JDK9UF(writeContext);
             } else {
                 jsonWriter = new JSONWriterUTF16(writeContext);
             }
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
index ba0d1fa76..1c400651c 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
@@ -79,28 +79,17 @@ final class JSONWriterJSONB
 
     @Override
     public void startObject() {
-        if (level >= context.maxLevel) {
-            throw new JSONException("level too large : " + level);
+        if (++level > context.maxLevel) {
+            overflowLevel();
         }
 
-        level++;
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        bytes[off] = BC_OBJECT;
-        this.off = off + 1;
+        writeRaw(BC_OBJECT);
     }
 
     @Override
     public void endObject() {
         level--;
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        bytes[off] = BC_OBJECT_END;
-        this.off = off + 1;
+        writeRaw(BC_OBJECT_END);
     }
 
     @Override
@@ -114,216 +103,110 @@ final class JSONWriterJSONB
             writeTypeName(array.getClass().getName());
         }
 
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        boolean tinyInt = size <= ARRAY_FIX_LEN;
-        bytes[off] = tinyInt ? (byte) (BC_ARRAY_FIX_MIN + size) : BC_ARRAY;
-        this.off = off + 1;
-        if (!tinyInt) {
-            writeInt32(size);
-        }
+        startArray(size);
     }
 
     @Override
     public void startArray(int size) {
         int off = this.off;
-        if (off + 1 >= bytes.length) {
-            grow0(off + 2);
+        byte[] bytes = this.bytes;
+        if (off + 6 > bytes.length) {
+            bytes = grow(off + 6);
         }
 
         boolean tinyInt = size <= ARRAY_FIX_LEN;
-        bytes[off] = tinyInt ? (byte) (BC_ARRAY_FIX_MIN + size) : BC_ARRAY;
-        this.off = off + 1;
+        putByte(bytes, off++, tinyInt ? (byte) (BC_ARRAY_FIX_MIN + size) : BC_ARRAY);
         if (!tinyInt) {
-            writeInt32(size);
+            off = writeInt32(bytes, off, size);
         }
+        this.off = off;
     }
 
     @Override
     public void startArray0() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, BC_ARRAY_FIX_MIN);
-        this.off = off + 1;
+        writeRaw(BC_ARRAY_FIX_MIN);
     }
 
     @Override
     public void startArray1() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 1));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 1));
     }
 
     @Override
     public void startArray2() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 2));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 2));
     }
 
     @Override
     public void startArray3() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 3));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 3));
     }
 
     @Override
     public void startArray4() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 4));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 4));
     }
 
     @Override
     public void startArray5() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 5));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 5));
     }
 
     @Override
     public void startArray6() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 6));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 6));
     }
 
     @Override
     public void startArray7() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 7));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 7));
     }
 
     @Override
     public void startArray8() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 8));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 8));
     }
 
     @Override
     public void startArray9() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 9));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 9));
     }
 
     @Override
     public void startArray10() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 10));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 10));
     }
 
     @Override
     public void startArray11() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 11));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 11));
     }
 
     @Override
     public void startArray12() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 12));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 12));
     }
 
     @Override
     public void startArray13() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 13));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 13));
     }
 
     @Override
     public void startArray14() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 14));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 14));
     }
 
     @Override
     public void startArray15() {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-
-        putByte(bytes, off, (byte) (BC_ARRAY_FIX_MIN + 15));
-        this.off = off + 1;
+        writeRaw((byte) (BC_ARRAY_FIX_MIN + 15));
     }
 
     @Override
     public void writeRaw(byte b) {
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        bytes[off++] = b;
+        int off = this.off;
+        putByte(grow1(off), off, b);
+        this.off = off + 1;
     }
 
     @Override
@@ -344,18 +227,12 @@ final class JSONWriterJSONB
 
     @Override
     public void writeNull() {
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        bytes[off++] = BC_NULL;
+        writeRaw(BC_NULL);
     }
 
     @Override
     public void writeStringNull() {
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        bytes[off++] = BC_NULL;
+        writeRaw(BC_NULL);
     }
 
     @Override
@@ -515,194 +392,82 @@ final class JSONWriterJSONB
         writeString(new String(chars, coff, len));
     }
 
-    public void writeStringLatin1(final byte[] value) {
-        if (value == null) {
-            writeStringNull();
-            return;
-        }
-
+    public void writeStringLatin1(byte[] value) {
+        byte[] bytes = this.bytes;
         int off = this.off;
-        int strlen = value.length;
-        int minCapacity = value.length
-                + off
-                + 5 /*max str len*/
-                + 1;
-
+        int minCapacity = off + value.length + 6;
         if (minCapacity - bytes.length > 0) {
-            grow0(minCapacity);
+            bytes = grow(minCapacity);
         }
 
-        final byte[] bytes = this.bytes;
+        int strlen = value.length;
         if (strlen <= STR_ASCII_FIX_LEN) {
             bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
         } else if (strlen <= INT32_BYTE_MAX) {
-            putStringSizeSmall(bytes, off, strlen);
-            off += 3;
+            off = putStringSizeSmall(bytes, off, strlen);
         } else {
-            off += putStringSizeLarge(bytes, off, strlen);
+            off = putStringSizeLarge(bytes, off, strlen);
         }
         System.arraycopy(value, 0, bytes, off, value.length);
         this.off = off + strlen;
     }
 
-    private static void putStringSizeSmall(byte[] bytes, int off, int val) {
-        bytes[off] = BC_STR_ASCII;
-        bytes[off + 1] = (byte) (BC_INT32_BYTE_ZERO + (val >> 8));
-        bytes[off + 2] = (byte) (val);
+    private static int putStringSizeSmall(byte[] bytes, int off, int val) {
+        putByte(bytes, off, BC_STR_ASCII);
+        putShortBE(bytes, off + 1, (short) ((BC_INT32_BYTE_ZERO << 8) + val));
+        return off + 3;
     }
 
     private static int putStringSizeLarge(byte[] bytes, int off, int strlen) {
         if (strlen <= INT32_SHORT_MAX) {
-            bytes[off] = BC_STR_ASCII;
-            bytes[off + 1] = (byte) (BC_INT32_SHORT_ZERO + (strlen >> 16));
-            bytes[off + 2] = (byte) (strlen >> 8);
-            bytes[off + 3] = (byte) (strlen);
-            return 4;
-        }
-
-        bytes[off] = BC_STR_ASCII;
-        bytes[off + 1] = BC_INT32;
-        IOUtils.putIntBE(
-                bytes,
-                off + 2,
-                strlen
-        );
-        return 6;
+            putIntBE(bytes, off, (BC_STR_ASCII << 24) + (BC_INT32_SHORT_ZERO << 16) + strlen);
+            return off + 4;
+        }
+
+        putShortBE(bytes, off, (short) ((BC_STR_ASCII << 8) | BC_INT32));
+        putIntBE(bytes, off + 2, strlen);
+        return off + 6;
     }
 
     @Override
-    public void writeString(final char[] chars) {
+    public void writeString(char[] chars) {
         if (chars == null) {
             writeNull();
             return;
         }
 
-        int off = this.off;
-        boolean ascii = true;
-        int strlen = chars.length;
-        byte[] bytes = this.bytes;
-        if (chars.length < STR_ASCII_FIX_LEN) {
-            int minCapacity = off + 1 + strlen;
-            if (minCapacity > bytes.length) {
-                bytes = grow(minCapacity);
-            }
-
-            bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
-            for (int i = 0; i < chars.length; i++) {
-                char ch = chars[i];
-                if (ch > 0x00FF) {
-                    ascii = false;
-                    break;
-                }
-                bytes[off++] = (byte) ch;
-            }
-
-            if (ascii) {
-                this.off = off;
-                return;
-            } else {
-                off = this.off;
-            }
-        }
-
-        {
-            int i = 0;
-            int upperBound = chars.length & ~3;
-            for (; i < upperBound; i += 4) {
-                char c0 = chars[i];
-                char c1 = chars[i + 1];
-                char c2 = chars[i + 2];
-                char c3 = chars[i + 3];
-                if (c0 > 0x00FF || c1 > 0x00FF || c2 > 0x00FF || c3 > 0x00FF) {
-                    ascii = false;
-                    break;
-                }
-            }
-            if (ascii) {
-                for (; i < chars.length; ++i) {
-                    if (chars[i] > 0x00FF) {
-                        ascii = false;
-                        break;
-                    }
-                }
-            }
-        }
-
-        int minCapacity = (ascii ? strlen : strlen * 3)
-                + off
-                + 5 /*max str len*/
-                + 1;
-
-        if (minCapacity > bytes.length) {
-            bytes = grow(minCapacity);
-        }
-
-        if (ascii) {
-            if (strlen <= STR_ASCII_FIX_LEN) {
-                bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
-            } else if (strlen <= INT32_BYTE_MAX) {
-                putStringSizeSmall(bytes, off, strlen);
-                off += 3;
-            } else {
-                off += putStringSizeLarge(bytes, off, strlen);
-            }
-            for (int i = 0; i < chars.length; i++) {
-                bytes[off++] = (byte) chars[i];
-            }
-        } else {
-            int maxSize = chars.length * 3;
-            int lenByteCnt = sizeOfInt(maxSize);
-            minCapacity = off + maxSize + lenByteCnt + 1;
-            if (minCapacity > bytes.length) {
-                bytes = grow(minCapacity);
-            }
-            int result = IOUtils.encodeUTF8(chars, 0, chars.length, bytes, off + lenByteCnt + 1);
-
-            int utf8len = result - off - lenByteCnt - 1;
-            int utf8lenByteCnt = sizeOfInt(utf8len);
-            if (lenByteCnt != utf8lenByteCnt) {
-                System.arraycopy(bytes, off + lenByteCnt + 1, bytes, off + utf8lenByteCnt + 1, utf8len);
-            }
-            bytes[off++] = BC_STR_UTF8;
-            if (utf8len >= BC_INT32_NUM_MIN && utf8len <= BC_INT32_NUM_MAX) {
-                bytes[off++] = (byte) utf8len;
-            } else if (utf8len >= INT32_BYTE_MIN && utf8len <= INT32_BYTE_MAX) {
-                bytes[off] = (byte) (BC_INT32_BYTE_ZERO + (utf8len >> 8));
-                bytes[off + 1] = (byte) (utf8len);
-                off += 2;
-            } else {
-                off = writeInt32(bytes, off, utf8len);
-            }
-            off += utf8len;
-        }
-        this.off = off;
+        writeString0(chars, 0, chars.length);
     }
 
     @Override
-    public void writeString(final char[] chars, final int charsOff, final int len) {
+    public void writeString(char[] chars, int charsOff, int len) {
         if (chars == null) {
             writeNull();
             return;
         }
 
+        writeString0(chars, charsOff, len);
+    }
+
+    private void writeString0(char[] chars, int coff, int strlen) {
         int off = this.off;
         byte[] bytes = this.bytes;
         boolean ascii = true;
 
-        if (len < STR_ASCII_FIX_LEN) {
-            int minCapacity = off + 1 + len;
+        if (strlen < STR_ASCII_FIX_LEN) {
+            int minCapacity = off + 1 + strlen;
             if (minCapacity > bytes.length) {
                 bytes = grow(minCapacity);
             }
 
-            bytes[off++] = (byte) (len + BC_STR_ASCII_FIX_MIN);
-            for (int i = charsOff; i < len; i++) {
+            bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
+            for (int i = coff, end = coff + strlen; i < end; i++) {
                 char ch = chars[i];
                 if (ch > 0x00FF) {
                     ascii = false;
                     break;
                 }
-                bytes[off++] = (byte) ch;
+                putByte(bytes, off++, (byte) ch);
             }
 
             if (ascii) {
@@ -711,82 +476,53 @@ final class JSONWriterJSONB
             }
 
             off = this.off;
+        } else {
+            ascii = isASCII(chars, coff, strlen);
         }
 
-        {
-            int i = charsOff;
-            int upperBound = chars.length & ~3;
-            for (; i < upperBound; i += 4) {
-                char c0 = chars[i];
-                char c1 = chars[i + 1];
-                char c2 = chars[i + 2];
-                char c3 = chars[i + 3];
-                if (c0 > 0x00FF || c1 > 0x00FF || c2 > 0x00FF || c3 > 0x00FF) {
-                    ascii = false;
-                    break;
-                }
-            }
-            if (ascii) {
-                for (; i < chars.length; ++i) {
-                    if (chars[i] > 0x00FF) {
-                        ascii = false;
-                        break;
-                    }
-                }
-            }
-        }
-
-        int minCapacity = (ascii ? len : len * 3)
-                + off
-                + 5 /*max str len*/
-                + 1;
-
+        int minCapacity = (ascii ? strlen : strlen * 3) + off + 6;
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
 
         if (ascii) {
-            if (len <= STR_ASCII_FIX_LEN) {
-                bytes[off++] = (byte) (len + BC_STR_ASCII_FIX_MIN);
-            } else if (len <= INT32_BYTE_MAX) {
-                bytes[off] = BC_STR_ASCII;
-                bytes[off + 1] = (byte) (BC_INT32_BYTE_ZERO + (len >> 8));
-                bytes[off + 2] = (byte) (len);
-                off += 3;
-            } else {
-                bytes[off] = BC_STR_ASCII;
-                off = writeInt32(bytes, off + 1, len);
-            }
-            for (int i = 0; i < chars.length; i++) {
-                bytes[off++] = (byte) chars[i];
-            }
+            off = writeStringLatin1(bytes, off, chars, coff, strlen);
         } else {
-            int maxSize = chars.length * 3;
-            int lenByteCnt = sizeOfInt(maxSize);
-            minCapacity = off + maxSize + lenByteCnt + 1;
-            if (minCapacity > bytes.length) {
-                bytes = grow(minCapacity);
-            }
-            int result = IOUtils.encodeUTF8(chars, 0, chars.length, bytes, off + lenByteCnt + 1);
+            off = writeUTF8(bytes, off, chars, coff, strlen);
+        }
+        this.off = off;
+    }
 
-            int utf8len = result - off - lenByteCnt - 1;
-            int utf8lenByteCnt = sizeOfInt(utf8len);
-            if (lenByteCnt != utf8lenByteCnt) {
-                System.arraycopy(bytes, off + lenByteCnt + 1, bytes, off + utf8lenByteCnt + 1, utf8len);
-            }
-            bytes[off++] = BC_STR_UTF8;
-            if (utf8len >= BC_INT32_NUM_MIN && utf8len <= BC_INT32_NUM_MAX) {
-                bytes[off++] = (byte) utf8len;
-            } else if (utf8len >= INT32_BYTE_MIN && utf8len <= INT32_BYTE_MAX) {
-                bytes[off] = (byte) (BC_INT32_BYTE_ZERO + (utf8len >> 8));
-                bytes[off + 1] = (byte) (utf8len);
-                off += 2;
+    private static int writeStringLatin1(byte[] bytes, int off, char[] chars, int coff, int strlen) {
+        if (strlen <= STR_ASCII_FIX_LEN) {
+            putByte(bytes, off++, (byte) (strlen + BC_STR_ASCII_FIX_MIN));
+        } else {
+            putByte(bytes, off, BC_STR_ASCII);
+            if (strlen <= INT32_BYTE_MAX) {
+                putShortBE(bytes, off + 1, (short) ((BC_INT32_BYTE_ZERO << 8) + strlen));
+                off += 3;
             } else {
-                off = writeInt32(bytes, off, utf8len);
+                off = writeInt32(bytes, off + 1, strlen);
             }
-            off += utf8len;
         }
-        this.off = off;
+        for (int i = 0; i < strlen; i++) {
+            putByte(bytes, off++, (byte) chars[coff + i]);
+        }
+        return off;
+    }
+
+    private static int writeUTF8(byte[] bytes, int off, char[] chars, int coff, int strlen) {
+        int maxSize = strlen * 3;
+        int lenByteCnt = sizeOfInt(maxSize);
+        int result = IOUtils.encodeUTF8(chars, coff, strlen, bytes, off + lenByteCnt + 1);
+
+        int utf8len = result - off - lenByteCnt - 1;
+        int utf8lenByteCnt = sizeOfInt(utf8len);
+        if (lenByteCnt != utf8lenByteCnt) {
+            System.arraycopy(bytes, off + lenByteCnt + 1, bytes, off + utf8lenByteCnt + 1, utf8len);
+        }
+        putByte(bytes, off, BC_STR_UTF8);
+        return writeInt32(bytes, off + 1, utf8len) + utf8len;
     }
 
     public void writeString(String[] strings) {
@@ -828,10 +564,7 @@ final class JSONWriterJSONB
     @Override
     public void writeTypeName(String typeName) {
         int off = this.off;
-        byte[] bytes = this.bytes;
-        if (off == bytes.length) {
-            bytes = grow(off + 1);
-        }
+        byte[] bytes = grow1(off);
         bytes[off++] = BC_TYPED_ANY;
 
         long hash = Fnv.hashCode64(typeName);
@@ -901,18 +634,18 @@ final class JSONWriterJSONB
             return false;
         }
 
+        byte[] bytes = this.bytes;
         int off = this.off;
         int minCapacity = off + 2 + typeName.length;
         if (minCapacity > bytes.length) {
-            ensureCapacity(minCapacity);
+            bytes = grow(minCapacity);
         }
 
-        final byte[] bytes = this.bytes;
-        bytes[off++] = BC_TYPED_ANY;
-        System.arraycopy(typeName, 0, bytes, off, typeName.length);
-        off += typeName.length;
+        putByte(bytes, off, BC_TYPED_ANY);
+        System.arraycopy(typeName, 0, bytes, off + 1, typeName.length);
+        off += typeName.length + 1;
         if (symbol >= BC_INT32_NUM_MIN && symbol <= BC_INT32_NUM_MAX) {
-            bytes[off++] = (byte) symbol;
+            putByte(bytes, off++, (byte) symbol);
         } else {
             off = writeInt32(bytes, off, symbol);
         }
@@ -927,7 +660,7 @@ final class JSONWriterJSONB
             bytes = grow(off + 7);
         }
 
-        bytes[off] = BC_TYPED_ANY;
+        putByte(bytes, off, BC_TYPED_ANY);
         this.off = writeInt32(bytes, off + 1, -symbol);
         return false;
     }
@@ -962,13 +695,13 @@ final class JSONWriterJSONB
             byte[] bytes = this.bytes;
             final int LATIN = 0;
             boolean latinAll = true;
-            for (int i = 0; i < list.size(); i++) {
+            for (int i = 0; i < size; i++) {
                 String str = list.get(i);
                 if (str == null) {
                     if (off == bytes.length) {
                         bytes = grow(off + 1);
                     }
-                    bytes[off++] = BC_NULL;
+                    putByte(bytes, off++, BC_NULL);
                     continue;
                 }
                 int coder = STRING_CODER.applyAsInt(str);
@@ -981,15 +714,11 @@ final class JSONWriterJSONB
                     bytes = grow(off + strlen + 6);
                 }
                 if (strlen <= STR_ASCII_FIX_LEN) {
-                    bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
+                    putByte(bytes, off++, (byte) (strlen + BC_STR_ASCII_FIX_MIN));
                 } else if (strlen <= INT32_BYTE_MAX) {
-                    bytes[off] = BC_STR_ASCII;
-                    bytes[off + 1] = (byte) (BC_INT32_BYTE_ZERO + (strlen >> 8));
-                    bytes[off + 2] = (byte) (strlen);
-                    off += 3;
+                    off = putStringSizeSmall(bytes, off, strlen);
                 } else {
-                    bytes[off] = BC_STR_ASCII;
-                    off = writeInt32(bytes, off + 1, strlen);
+                    off = putStringSizeLarge(bytes, off, strlen);
                 }
                 byte[] value = STRING_VALUE.apply(str);
                 System.arraycopy(value, 0, bytes, off, value.length);
@@ -1001,9 +730,10 @@ final class JSONWriterJSONB
             }
         }
 
-        for (int i = 0; i < list.size(); i++) {
-            String str = list.get(i);
-            writeString(str);
+        for (int i = 0; i < size; i++) {
+            writeString(
+                    list.get(i)
+            );
         }
     }
 
@@ -1015,29 +745,9 @@ final class JSONWriterJSONB
         }
 
         if (STRING_VALUE != null) {
-            int coder = STRING_CODER.applyAsInt(str);
             byte[] value = STRING_VALUE.apply(str);
-
-            if (coder == 0) {
-                int off = this.off;
-                int strlen = value.length;
-                int minCapacity = value.length + off + 6;
-
-                if (minCapacity - bytes.length > 0) {
-                    ensureCapacity(minCapacity);
-                }
-
-                final byte[] bytes = this.bytes;
-                if (strlen <= STR_ASCII_FIX_LEN) {
-                    bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
-                } else if (strlen <= INT32_BYTE_MAX) {
-                    putStringSizeSmall(bytes, off, strlen);
-                    off += 3;
-                } else {
-                    off += putStringSizeLarge(bytes, off, strlen);
-                }
-                System.arraycopy(value, 0, bytes, off, value.length);
-                this.off = off + strlen;
+            if (STRING_CODER.applyAsInt(str) == 0) {
+                writeStringLatin1(value);
                 return;
             } else {
                 if (tryWriteStringUTF16(value)) {
@@ -1059,13 +769,13 @@ final class JSONWriterJSONB
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = JDKUtils.BIG_ENDIAN ? BC_STR_UTF16BE : BC_STR_UTF16LE;
+        putByte(bytes, off, JDKUtils.BIG_ENDIAN ? BC_STR_UTF16BE : BC_STR_UTF16LE);
         off = writeInt32(bytes, off + 1, strlen);
         System.arraycopy(value, 0, bytes, off, strlen);
         this.off = off + strlen;
     }
 
-    protected boolean tryWriteStringUTF16(byte[] value) {
+    boolean tryWriteStringUTF16(byte[] value) {
         int check_cnt = 128;
         if (check_cnt > value.length) {
             check_cnt = value.length;
@@ -1134,14 +844,14 @@ final class JSONWriterJSONB
             System.arraycopy(bytes, off + lenByteCnt + 1, bytes, off + utf8lenByteCnt + 1, utf8len);
         }
         int start = off;
-        bytes[off] = strtype;
+        putByte(bytes, off, strtype);
         off = writeInt32(bytes, off + 1, utf8len);
         return (off - start) + utf8len;
     }
 
     private static int writeUTF16(byte[] bytes, int off, byte[] value) {
         int start = off;
-        bytes[off] = JDKUtils.BIG_ENDIAN ? BC_STR_UTF16BE : BC_STR_UTF16LE;
+        putByte(bytes, off, JDKUtils.BIG_ENDIAN ? BC_STR_UTF16BE : BC_STR_UTF16LE);
         off = writeInt32(bytes, off + 1, value.length);
         System.arraycopy(value, 0, bytes, off, value.length);
         return value.length + off - start;
@@ -1153,6 +863,14 @@ final class JSONWriterJSONB
         }
     }
 
+    private byte[] grow1(int off) {
+        byte[] bytes = this.bytes;
+        if (off == bytes.length) {
+            bytes = grow(off + 1);
+        }
+        return bytes;
+    }
+
     private byte[] grow(int minCapacity) {
         grow0(minCapacity);
         return bytes;
@@ -1174,13 +892,8 @@ final class JSONWriterJSONB
             long seconds = (millis / 1000);
             if (seconds >= Integer.MIN_VALUE && seconds <= Integer.MAX_VALUE) {
                 int secondsInt = (int) seconds;
-
-                bytes[off] = BC_TIMESTAMP_SECONDS;
-                IOUtils.putIntBE(
-                        bytes,
-                        off + 1,
-                        secondsInt
-                );
+                putByte(bytes, off, BC_TIMESTAMP_SECONDS);
+                putIntBE(bytes, off + 1, secondsInt);
                 this.off = off + 5;
                 return;
             }
@@ -1189,24 +902,16 @@ final class JSONWriterJSONB
                 long minutes = seconds / 60;
                 if (minutes >= Integer.MIN_VALUE && minutes <= Integer.MAX_VALUE) {
                     int minutesInt = (int) minutes;
-                    bytes[off] = BC_TIMESTAMP_MINUTES;
-                    IOUtils.putIntBE(
-                            bytes,
-                            off + 1,
-                            minutesInt
-                    );
+                    putByte(bytes, off, BC_TIMESTAMP_MINUTES);
+                    putIntBE(bytes, off + 1, minutesInt);
                     this.off = off + 5;
                     return;
                 }
             }
         }
 
-        bytes[off] = BC_TIMESTAMP_MILLIS;
-        IOUtils.putLongBE(
-                bytes,
-                off + 1,
-                millis
-        );
+        putByte(bytes, off, BC_TIMESTAMP_MILLIS);
+        putLongBE(bytes, off + 1, millis);
         this.off = off + 9;
     }
 
@@ -1221,9 +926,10 @@ final class JSONWriterJSONB
         }
         int off = this.off;
         if (i == null) {
-            bytes[off++] = (this.context.features & WRITE_NUM_NULL_MASK) == 0
-                    ? BC_NULL
-                    : (byte) (BC_INT64_NUM_MIN - INT64_NUM_LOW_VALUE);
+            putByte(bytes, off++,
+                    (this.context.features & WRITE_NUM_NULL_MASK) == 0
+                            ? BC_NULL
+                            : (byte) (BC_INT64_NUM_MIN - INT64_NUM_LOW_VALUE));
         } else {
             off = writeInt64(bytes, off, i);
         }
@@ -1298,9 +1004,9 @@ final class JSONWriterJSONB
             bytes = grow(minCapacity);
         }
         if (size <= ARRAY_FIX_LEN) {
-            bytes[off++] = (byte) (BC_ARRAY_FIX_MIN + size);
+            putByte(bytes, off++, (byte) (BC_ARRAY_FIX_MIN + size));
         } else {
-            bytes[off] = BC_ARRAY;
+            putByte(bytes, off, BC_ARRAY);
             off = writeInt32(bytes, off + 1, size);
         }
 
@@ -1353,8 +1059,7 @@ final class JSONWriterJSONB
         }
         int i = (int) value;
         if (i == value && value >= BC_INT32_NUM_MIN && value <= BC_INT32_NUM_MAX) {
-            putByte(bytes, off, BC_FLOAT_INT);
-            putByte(bytes, off + 1, (byte) i);
+            putShortLE(bytes, off, (short) ((BC_FLOAT_INT & 0xFF) | (i << 8)));
             off += 2;
         } else {
             putByte(bytes, off, BC_FLOAT);
@@ -1385,7 +1090,7 @@ final class JSONWriterJSONB
             if (off == bytes.length) {
                 bytes = grow(off + 1);
             }
-            bytes[off] = value == 0 ? BC_DOUBLE_NUM_0 : BC_DOUBLE_NUM_1;
+            putByte(bytes, off, value == 0 ? BC_DOUBLE_NUM_0 : BC_DOUBLE_NUM_1);
             this.off = off + 1;
             return;
         }
@@ -1396,7 +1101,7 @@ final class JSONWriterJSONB
                 if (off == bytes.length) {
                     bytes = grow(off + 1);
                 }
-                bytes[off] = BC_DOUBLE_LONG;
+                putByte(bytes, off, BC_DOUBLE_LONG);
                 this.off = off + 1;
                 writeInt64(longValue);
                 return;
@@ -1406,7 +1111,7 @@ final class JSONWriterJSONB
         if (off + 9 > bytes.length) {
             bytes = grow(off + 9);
         }
-        bytes[off] = BC_DOUBLE;
+        putByte(bytes, off, BC_DOUBLE);
         IOUtils.putLongBE(bytes, off + 1, Double.doubleToLongBits(value));
         this.off = off + 9;
     }
@@ -1454,9 +1159,9 @@ final class JSONWriterJSONB
         }
 
         if (size <= ARRAY_FIX_LEN) {
-            bytes[off++] = (byte) (BC_ARRAY_FIX_MIN + size);
+            putByte(bytes, off++, (byte) (BC_ARRAY_FIX_MIN + size));
         } else {
-            bytes[off] = BC_ARRAY;
+            putByte(bytes, off, BC_ARRAY);
             off = writeInt32(bytes, off + 1, size);
         }
 
@@ -1482,17 +1187,17 @@ final class JSONWriterJSONB
         }
 
         if (size <= ARRAY_FIX_LEN) {
-            bytes[off++] = (byte) (BC_ARRAY_FIX_MIN + size);
+            putByte(bytes, off++, (byte) (BC_ARRAY_FIX_MIN + size));
         } else {
-            bytes[off] = BC_ARRAY;
+            putByte(bytes, off, BC_ARRAY);
             off = writeInt32(bytes, off + 1, size);
         }
 
         for (int val : values) {
             if (val < BC_INT32_NUM_MIN || val > BC_INT32_NUM_MAX) {
-                bytes[off++] = (byte) (BC_INT32_BYTE_ZERO + (val >> 8));
+                putByte(bytes, off++, (byte) (BC_INT32_BYTE_ZERO + (val >> 8)));
             }
-            bytes[off++] = (byte) val;
+            putByte(bytes, off++, (byte) val);
         }
         this.off = off;
     }
@@ -1504,8 +1209,7 @@ final class JSONWriterJSONB
         if (off + 2 > bytes.length) {
             bytes = grow(off + 2);
         }
-        bytes[off] = BC_INT8;
-        bytes[off + 1] = val;
+        putShortLE(bytes, off, (short) ((val << 8) | (BC_INT8 & 0xFF)));
         this.off = off + 2;
     }
 
@@ -1554,7 +1258,7 @@ final class JSONWriterJSONB
         }
         int off = this.off;
         if (i == null) {
-            bytes[off++] = (this.context.features & (Feature.NullAsDefaultValue.mask | Feature.WriteNullNumberAsZero.mask)) == 0 ? BC_NULL : 0;
+            putByte(bytes, off++, (this.context.features & (Feature.NullAsDefaultValue.mask | Feature.WriteNullNumberAsZero.mask)) == 0 ? BC_NULL : 0);
         } else {
             off = writeInt32(bytes, off, i);
         }
@@ -1588,16 +1292,16 @@ final class JSONWriterJSONB
             bytes = grow(minCapacity);
         }
         if (size <= ARRAY_FIX_LEN) {
-            bytes[off++] = (byte) (BC_ARRAY_FIX_MIN + size);
+            putByte(bytes, off++, (byte) (BC_ARRAY_FIX_MIN + size));
         } else {
-            bytes[off] = BC_ARRAY;
+            putByte(bytes, off, BC_ARRAY);
             off = writeInt32(bytes, off + 1, size);
         }
 
         for (int i = 0; i < size; i++) {
             Integer item = values.get(i);
             if (item == null) {
-                bytes[off++] = BC_NULL;
+                putByte(bytes, off++, BC_NULL);
                 continue;
             }
 
@@ -1608,14 +1312,7 @@ final class JSONWriterJSONB
 
     @Override
     public void writeArrayNull() {
-        int off = this.off;
-        byte[] bytes = this.bytes;
-        if (off == bytes.length) {
-            bytes = grow(off + 1);
-        }
-
-        bytes[off] = (this.context.features & WRITE_ARRAY_NULL_MASK) != 0 ? BC_ARRAY_FIX_MIN : BC_NULL;
-        this.off = off + 1;
+        writeRaw((this.context.features & WRITE_ARRAY_NULL_MASK) != 0 ? BC_ARRAY_FIX_MIN : BC_NULL);
     }
 
     @Override
@@ -1642,13 +1339,12 @@ final class JSONWriterJSONB
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = BC_SYMBOL;
+        putByte(bytes, off++, BC_SYMBOL);
 
         if (symbol >= BC_INT32_NUM_MIN && symbol <= BC_INT32_NUM_MAX) {
-            bytes[off++] = (byte) symbol;
+            putByte(bytes, off++, (byte) symbol);
         } else if (symbol >= INT32_BYTE_MIN && symbol <= INT32_BYTE_MAX) {
-            bytes[off] = (byte) (BC_INT32_BYTE_ZERO + (symbol >> 8));
-            bytes[off + 1] = (byte) (symbol);
+            putShortBE(bytes, off, (short) ((BC_INT32_BYTE_ZERO << 8) + symbol));
             off += 2;
         } else {
             off = writeInt32(bytes, off, symbol);
@@ -1687,12 +1383,12 @@ final class JSONWriterJSONB
             }
 
             if (!symbolExists) {
-                bytes[off++] = BC_SYMBOL;
+                putByte(bytes, off++, BC_SYMBOL);
                 System.arraycopy(name, 0, bytes, off, name.length);
                 off += name.length;
 
                 if (symbol >= BC_INT32_NUM_MIN && symbol <= BC_INT32_NUM_MAX) {
-                    bytes[off++] = (byte) symbol;
+                    putByte(bytes, off++, (byte) symbol);
                 } else {
                     off = writeInt32(bytes, off, symbol);
                 }
@@ -1705,7 +1401,7 @@ final class JSONWriterJSONB
         bytes[off++] = BC_SYMBOL;
         int intValue = -symbol;
         if (intValue >= BC_INT32_NUM_MIN && intValue <= BC_INT32_NUM_MAX) {
-            bytes[off++] = (byte) intValue;
+            putByte(bytes, off++, (byte) intValue);
         } else {
             off = writeInt32(bytes, off, intValue);
         }
@@ -1725,12 +1421,9 @@ final class JSONWriterJSONB
             bytes = grow(off + 5);
         }
 
-        bytes[off] = BC_LOCAL_DATE;
+        putByte(bytes, off, BC_LOCAL_DATE);
         int year = date.getYear();
-        bytes[off + 1] = (byte) (year >>> 8);
-        bytes[off + 2] = (byte) year;
-        bytes[off + 3] = (byte) date.getMonthValue();
-        bytes[off + 4] = (byte) date.getDayOfMonth();
+        putIntBE(bytes, off + 1, (year << 16) | (date.getMonthValue() << 8) | date.getDayOfMonth());
         this.off = off + 5;
     }
 
@@ -1747,10 +1440,9 @@ final class JSONWriterJSONB
             bytes = grow(off + 9);
         }
 
-        bytes[off] = BC_LOCAL_TIME;
-        bytes[off + 1] = (byte) time.getHour();
-        bytes[off + 2] = (byte) time.getMinute();
-        bytes[off + 3] = (byte) time.getSecond();
+        putIntBE(bytes,
+                off,
+                (BC_LOCAL_TIME << 24) | (time.getHour() << 16) | (time.getMinute() << 8) | time.getSecond());
         this.off = writeInt32(bytes, off + 4, time.getNano());
     }
 
@@ -1767,15 +1459,15 @@ final class JSONWriterJSONB
             bytes = grow(off + 13);
         }
 
-        bytes[off] = BC_LOCAL_DATETIME;
-        int year = dateTime.getYear();
-        bytes[off + 1] = (byte) (year >>> 8);
-        bytes[off + 2] = (byte) year;
-        bytes[off + 3] = (byte) dateTime.getMonthValue();
-        bytes[off + 4] = (byte) dateTime.getDayOfMonth();
-        bytes[off + 5] = (byte) dateTime.getHour();
-        bytes[off + 6] = (byte) dateTime.getMinute();
-        bytes[off + 7] = (byte) dateTime.getSecond();
+        putIntBE(bytes,
+                off,
+                (BC_LOCAL_DATETIME << 24) | (dateTime.getYear() << 8) | dateTime.getMonthValue());
+        putIntBE(bytes,
+                off + 4,
+                (dateTime.getDayOfMonth() << 24)
+                        | (dateTime.getHour() << 16)
+                        | (dateTime.getMinute() << 8)
+                        | dateTime.getSecond());
         this.off = writeInt32(bytes, off + 8, dateTime.getNano());
     }
 
@@ -1792,16 +1484,15 @@ final class JSONWriterJSONB
             bytes = grow(off + 13);
         }
 
-        bytes[off] = BC_TIMESTAMP_WITH_TIMEZONE;
-        int year = dateTime.getYear();
-        bytes[off + 1] = (byte) (year >>> 8);
-        bytes[off + 2] = (byte) year;
-        bytes[off + 3] = (byte) dateTime.getMonthValue();
-        bytes[off + 4] = (byte) dateTime.getDayOfMonth();
-        bytes[off + 5] = (byte) dateTime.getHour();
-        bytes[off + 6] = (byte) dateTime.getMinute();
-        bytes[off + 7] = (byte) dateTime.getSecond();
-
+        putIntBE(bytes,
+                off,
+                (BC_TIMESTAMP_WITH_TIMEZONE << 24) | (dateTime.getYear() << 8) | dateTime.getMonthValue());
+        putIntBE(bytes,
+                off + 4,
+                (dateTime.getDayOfMonth() << 24)
+                        | (dateTime.getHour() << 16)
+                        | (dateTime.getMinute() << 8)
+                        | dateTime.getSecond());
         this.off = writeInt32(bytes, off + 8, dateTime.getNano());
 
         ZoneId zoneId = dateTime.getZone();
@@ -1830,19 +1521,19 @@ final class JSONWriterJSONB
             bytes = grow(minCapacity);
         }
 
-        bytes[off] = BC_TIMESTAMP_WITH_TIMEZONE;
-        int year = dateTime.getYear();
-        bytes[off + 1] = (byte) (year >>> 8);
-        bytes[off + 2] = (byte) year;
-        bytes[off + 3] = (byte) dateTime.getMonthValue();
-        bytes[off + 4] = (byte) dateTime.getDayOfMonth();
-        bytes[off + 5] = (byte) dateTime.getHour();
-        bytes[off + 6] = (byte) dateTime.getMinute();
-        bytes[off + 7] = (byte) dateTime.getSecond();
+        putIntBE(bytes,
+                off,
+                (BC_TIMESTAMP_WITH_TIMEZONE << 24) | (dateTime.getYear() << 8) | dateTime.getMonthValue());
+        putIntBE(bytes,
+                off + 4,
+                (dateTime.getDayOfMonth() << 24)
+                        | (dateTime.getHour() << 16)
+                        | (dateTime.getMinute() << 8)
+                        | dateTime.getSecond());
 
         off = writeInt32(bytes, off + 8, dateTime.getNano());
 
-        bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
+        putByte(bytes, off++, (byte) (strlen + BC_STR_ASCII_FIX_MIN));
         zoneIdStr.getBytes(0, strlen, bytes, off);
         this.off = off + strlen;
     }
@@ -1872,7 +1563,7 @@ final class JSONWriterJSONB
             bytes = grow(off + 15);
         }
 
-        bytes[off] = BC_TIMESTAMP;
+        putByte(bytes, off, BC_TIMESTAMP);
         off = writeInt64(bytes, off + 1, instant.getEpochSecond());
         this.off = writeInt32(bytes, off, instant.getNano());
     }
@@ -1909,7 +1600,7 @@ final class JSONWriterJSONB
             if (off + 10 > bytes.length) {
                 bytes = grow(off + 10);
             }
-            bytes[off] = BC_BIGINT_LONG;
+            putByte(bytes, off, BC_BIGINT_LONG);
             this.off = writeInt64(bytes, off + 1, value.longValue());
             return;
         }
@@ -1920,7 +1611,7 @@ final class JSONWriterJSONB
             bytes = grow(minCapacity);
         }
 
-        bytes[off] = BC_BIGINT;
+        putByte(bytes, off, BC_BIGINT);
         off = writeInt32(bytes, off + 1, valueBytes.length);
         System.arraycopy(valueBytes, 0, bytes, off, valueBytes.length);
         this.off = off + valueBytes.length;
@@ -1940,7 +1631,7 @@ final class JSONWriterJSONB
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = BC_BINARY;
+        putByte(bytes, off, BC_BINARY);
         off = writeInt32(bytes, off + 1, len);
 
         System.arraycopy(binary, 0, bytes, off, len);
@@ -1970,7 +1661,7 @@ final class JSONWriterJSONB
                 return;
             }
 
-            bytes[off] = BC_DECIMAL;
+            putByte(bytes, off, BC_DECIMAL);
             off = writeInt32(bytes, off + 1, scale);
             if (intCompact >= Integer.MIN_VALUE && intCompact <= Integer.MAX_VALUE) {
                 off = writeInt32(bytes, off, (int) intCompact);
@@ -1984,12 +1675,12 @@ final class JSONWriterJSONB
         BigInteger unscaledValue = value.unscaledValue();
         if (scale == 0
                 && isInt64(unscaledValue)) {
-            bytes[off] = BC_DECIMAL_LONG;
+            putByte(bytes, off, BC_DECIMAL_LONG);
             this.off = writeInt64(bytes, off + 1, unscaledValue.longValue());
             return;
         }
 
-        bytes[off] = BC_DECIMAL;
+        putByte(bytes, off, BC_DECIMAL);
         off = writeInt32(bytes, off + 1, scale);
 
         if (isInt32(unscaledValue)) {
@@ -2006,12 +1697,7 @@ final class JSONWriterJSONB
 
     @Override
     public void writeBool(boolean value) {
-        int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        putByte(bytes, off, value ? BC_TRUE : BC_FALSE);
-        this.off = off + 1;
+        writeRaw(value ? BC_TRUE : BC_FALSE);
     }
 
     @Override
@@ -2031,11 +1717,7 @@ final class JSONWriterJSONB
     @Override
     public void writeReference(String path) {
         int off = this.off;
-        byte[] bytes = this.bytes;
-        if (off == bytes.length) {
-            bytes = grow(off + 1);
-        }
-        bytes[off] = BC_REFERENCE;
+        putByte(grow1(off), off, BC_REFERENCE);
         this.off = off + 1;
         writeString(path == this.lastReference ? "#-1" : path);
         this.lastReference = path;
@@ -2056,15 +1738,9 @@ final class JSONWriterJSONB
             bytes = grow(off + 9);
         }
 
-        bytes[off] = BC_LOCAL_DATETIME;
-        bytes[off + 1] = (byte) (year >>> 8);
-        bytes[off + 2] = (byte) year;
-        bytes[off + 3] = (byte) month;
-        bytes[off + 4] = (byte) dayOfMonth;
-        bytes[off + 5] = (byte) hour;
-        bytes[off + 6] = (byte) minute;
-        bytes[off + 7] = (byte) second;
-        bytes[off + 8] = BC_INT32_NUM_0;
+        putIntBE(bytes, off, (BC_LOCAL_DATETIME << 24) | ((year & 0xFFFF) << 8) | month);
+        putIntBE(bytes, off + 4, (dayOfMonth << 24) | (hour << 16) | (minute << 8) | second);
+        putByte(bytes, off + 8, BC_INT32_NUM_0);
         this.off = off + 9;
     }
 
@@ -2077,22 +1753,7 @@ final class JSONWriterJSONB
             int minute,
             int second
     ) {
-        int off = this.off;
-        byte[] bytes = this.bytes;
-        if (off + 9 > bytes.length) {
-            bytes = grow(off + 9);
-        }
-
-        bytes[off] = BC_LOCAL_DATETIME;
-        bytes[off + 1] = (byte) (year >>> 8);
-        bytes[off + 2] = (byte) year;
-        bytes[off + 3] = (byte) month;
-        bytes[off + 4] = (byte) dayOfMonth;
-        bytes[off + 5] = (byte) hour;
-        bytes[off + 6] = (byte) minute;
-        bytes[off + 7] = (byte) second;
-        bytes[off + 8] = BC_INT32_NUM_0;
-        this.off = off + 9;
+        writeDateTime14(year, month, dayOfMonth, hour, minute, second);
     }
 
     @Override
@@ -2119,10 +1780,7 @@ final class JSONWriterJSONB
         }
 
         bytes[off] = BC_LOCAL_DATE;
-        bytes[off + 1] = (byte) (year >>> 8);
-        bytes[off + 2] = (byte) year;
-        bytes[off + 3] = (byte) month;
-        bytes[off + 4] = (byte) dayOfMonth;
+        putIntBE(bytes, off + 1, (year << 16) | (month << 8) | dayOfMonth);
         this.off = off + 5;
     }
 
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
index ac2bfd56d..cb47e8f92 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
@@ -365,21 +365,21 @@ class JSONWriterUTF16
             grow(minCapacity);
         }
 
-        final long vecQuote = this.useSingleQuote ? BYTE_VEC_64_SINGLE_QUOTE : BYTE_VEC_64_DOUBLE_QUOTE;
+        final long vecQuote = this.byteVectorQuote;
         final char[] chars = this.chars;
         chars[off++] = quote;
-        int i = 0, char_len = value.length >> 1;
-
-        final int upperBound = (char_len - i) & ~3;
-        for (; i < upperBound; i += 4) {
-            long v = getLongLE(value, i << 1);
-            if (containsEscapedUTF16(v, vecQuote)) {
-                break;
+        for (int i = 0, char_len = value.length >> 1; i < char_len;) {
+            if (i + 8 < char_len) {
+                long v0 = getLongLE(value, i << 1);
+                long v1 = getLongLE(value, (i + 4) << 1);
+                if (((v0 | v1) & 0xFF00FF00FF00FF00L) == 0 && !containsEscaped((v0 << 8) | v1, vecQuote)) {
+                    putLongLE(chars, off, v0);
+                    putLongLE(chars, off + 4, v1);
+                    i += 8;
+                    off += 8;
+                    continue;
+                }
             }
-            IOUtils.putLongLE(chars, off, v);
-            off += 4;
-        }
-        for (; i < char_len;) {
             char c = getChar(value, i++);
             if (c == '\\' || c == quote || c < ' ') {
                 escape = true;
@@ -398,24 +398,43 @@ class JSONWriterUTF16
         writeStringEscapeUTF16(value);
     }
 
-    static boolean containsEscapedUTF16(long v, long quote) {
-        /*
-          for (int i = 0; i < 8; ++i) {
-            byte c = (byte) data;
-            if (c == quote || c == '\\' || c < ' ') {
-                return true;
+    final void writeStringBrowserSecure(char[] value) {
+        boolean escapeNoneAscii = (context.features & EscapeNoneAscii.mask) != 0;
+
+        boolean escape = false;
+        int off = this.off;
+        int minCapacity = off + value.length + 2;
+        if (minCapacity >= chars.length) {
+            grow(minCapacity);
+        }
+
+        final char[] chars = this.chars;
+        chars[off++] = quote;
+        for (int i = 0, char_len = value.length; i < char_len; i++) {
+            char c = getChar(value, i);
+            if (c == '\\'
+                    || c == quote
+                    || c < ' '
+                    || c == '<'
+                    || c == '>'
+                    || c == '('
+                    || c == ')'
+                    || (escapeNoneAscii && c > 0x007F)
+            ) {
+                escape = true;
+                break;
             }
-            data >>>= 8;
-          }
-          return false;
-         */
-        long x22 = v ^ quote; // " -> 0x22, ' -> 0x27
-        long x5c = v ^ 0x005C005C_005C005CL;
 
-        x22 = (x22 - 0x00010001_00010001L) & ~x22;
-        x5c = (x5c - 0x00010001_00010001L) & ~x5c;
+            chars[off++] = c;
+        }
 
-        return ((x22 | x5c | (0x007F007F_007F007FL - v + 0x00100010_00100010L) | v) & 0x00800080_00800080L) != 0;
+        if (!escape) {
+            chars[off] = quote;
+            this.off = off + 1;
+            return;
+        }
+
+        writeStringEscape(value);
     }
 
     final void writeStringUTF16BrowserSecure(byte[] value) {
@@ -2955,45 +2974,55 @@ class JSONWriterUTF16
         chars[off++] = quote;
     }
 
-    public final void writeString(final char[] str) {
-        if (str == null) {
+    public final void writeString(final char[] value) {
+        if (value == null) {
             writeStringNull();
             return;
         }
 
-        boolean browserSecure = (context.features & BrowserSecure.mask) != 0;
-        boolean special = (context.features & EscapeNoneAscii.mask) != 0;
-        for (int i = 0; i < str.length; i++) {
-            char c = str[i];
+        if ((context.features & (BrowserSecure.mask | EscapeNoneAscii.mask)) != 0) {
+            writeStringBrowserSecure(value);
+            return;
+        }
+
+        boolean escape = false;
+        int off = this.off;
+        int minCapacity = off + value.length + 2;
+        if (minCapacity >= chars.length) {
+            grow(minCapacity);
+        }
+
+        final long vecQuote = this.byteVectorQuote;
+        final char[] chars = this.chars;
+        chars[off++] = quote;
+        for (int i = 0, char_len = value.length; i < char_len;) {
+            if (i + 8 < char_len) {
+                long v0 = getLongLE(value, i);
+                long v1 = getLongLE(value, i + 4);
+                if (((v0 | v1) & 0xFF00FF00FF00FF00L) == 0 && !containsEscaped((v0 << 8) | v1, vecQuote)) {
+                    putLongLE(chars, off, v0);
+                    putLongLE(chars, off + 4, v1);
+                    i += 8;
+                    off += 8;
+                    continue;
+                }
+            }
+            char c = getChar(value, i++);
             if (c == '\\' || c == quote || c < ' ') {
-                special = true;
+                escape = true;
                 break;
             }
 
-            if (browserSecure && (c == '<' || c == '>' || c == '(' || c == ')')) {
-                special = true;
-                break;
-            }
+            chars[off++] = c;
         }
 
-        if (!special) {
-            // inline ensureCapacity
-            int off = this.off;
-            int minCapacity = off + str.length + 2;
-            char[] chars = this.chars;
-            if (minCapacity > chars.length) {
-                chars = grow(minCapacity);
-            }
-
-            chars[off++] = quote;
-            System.arraycopy(str, 0, chars, off, str.length);
-            off += str.length;
+        if (!escape) {
             chars[off] = quote;
             this.off = off + 1;
             return;
         }
 
-        writeStringEscape(str);
+        writeStringEscape(value);
     }
 
     public final void writeString(char[] str, int coff, int len) {
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK8UF.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK8UF.java
index 410ca8e96..1a1c8bbec 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK8UF.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK8UF.java
@@ -13,45 +13,9 @@ public final class JSONWriterUTF16JDK8UF
 
     @Override
     public void writeString(String str) {
-        if (str == null) {
-            writeStringNull();
-            return;
-        }
-
-        boolean browserSecure = (context.features & BrowserSecure.mask) != 0;
-        boolean escapeNoneAscii = (context.features & EscapeNoneAscii.mask) != 0;
-        char[] value = (char[]) UNSAFE.getObject(str, JDKUtils.FIELD_STRING_VALUE_OFFSET);
-        final int strlen = value.length;
-
-        boolean escape = false;
-        for (int i = 0; i < value.length; i++) {
-            char ch = value[i];
-            if (ch == quote || ch == '\\' || ch < ' '
-                    || (browserSecure && (ch == '<' || ch == '>' || ch == '(' || ch == ')'))
-                    || (escapeNoneAscii && ch > 0x007F)
-            ) {
-                escape = true;
-                break;
-            }
-        }
-
-        if (!escape) {
-            int off = this.off;
-            // inline ensureCapacity(off + strlen + 2);
-            int minCapacity = off + strlen + 2;
-            if (minCapacity >= chars.length) {
-                ensureCapacity(minCapacity);
-            }
-
-            final char[] chars = this.chars;
-            chars[off++] = quote;
-            System.arraycopy(value, 0, chars, off, value.length);
-            off += strlen;
-            chars[off] = quote;
-            this.off = off + 1;
-            return;
-        }
-
-        writeStringEscape(str);
+        writeString(
+                str == null
+                        ? null
+                        : (char[]) UNSAFE.getObject(str, JDKUtils.FIELD_STRING_VALUE_OFFSET));
     }
 }
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK9UF.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK9UF.java
index 52c4ebc8f..f8abded83 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK9UF.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16JDK9UF.java
@@ -1,9 +1,7 @@
 package com.alibaba.fastjson2;
 
 import com.alibaba.fastjson2.util.IOUtils;
-import sun.misc.Unsafe;
 
-import static com.alibaba.fastjson2.JSONWriter.Feature.BrowserSecure;
 import static com.alibaba.fastjson2.JSONWriter.Feature.WriteBooleanAsNumber;
 import static com.alibaba.fastjson2.util.JDKUtils.*;
 
@@ -20,51 +18,12 @@ final class JSONWriterUTF16JDK9UF
             return;
         }
 
-        boolean escapeNoneAscii = (context.features & Feature.EscapeNoneAscii.mask) != 0;
-        boolean browserSecure = (context.features & BrowserSecure.mask) != 0;
-        boolean escape = false;
-        final char quote = this.quote;
-
-        final int strlen = str.length();
-        int minCapacity = off + strlen + 2;
-        if (minCapacity >= chars.length) {
-            ensureCapacity(minCapacity);
-        }
-
-        final int coder = STRING_CODER.applyAsInt(str);
         final byte[] value = STRING_VALUE.apply(str);
-
-        int off = this.off;
-        final char[] chars = this.chars;
-        chars[off++] = quote;
-
-        for (int i = 0; i < strlen; ++i) {
-            int c;
-            if (coder == 0) {
-                c = value[i];
-            } else {
-                c = UNSAFE.getChar(str, (long) Unsafe.ARRAY_CHAR_BASE_OFFSET + i * 2);
-            }
-            if (c == '\\'
-                    || c == quote
-                    || c < ' '
-                    || (browserSecure && (c == '<' || c == '>' || c == '(' || c == ')'))
-                    || (escapeNoneAscii && c > 0x007F)
-            ) {
-                escape = true;
-                break;
-            }
-
-            chars[off++] = (char) c;
-        }
-
-        if (!escape) {
-            chars[off++] = quote;
-            this.off = off;
-            return;
+        if (STRING_CODER.applyAsInt(str) == 0) {
+            writeStringLatin1(value);
+        } else {
+            writeStringUTF16(value);
         }
-
-        writeStringEscape(str);
     }
 
     public void writeBool(boolean value) {
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
index d6c85fa2f..acf11b3e7 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
@@ -87,13 +87,7 @@ class JSONWriterUTF8
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, REF);
         this.off = off + 8;
         writeString(path);
-        off = this.off;
-        bytes = this.bytes;
-        if (off == bytes.length) {
-            bytes = grow(off + 1);
-        }
-        bytes[off] = '}';
-        this.off = off + 1;
+        writeRaw((byte) '}');
     }
 
     @Override
@@ -106,7 +100,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
 
         int eLen = (value.length / 3) * 3; // Length of even 24-bits.
 
@@ -115,10 +109,10 @@ class JSONWriterUTF8
             int i = (value[s++] & 0xff) << 16 | (value[s++] & 0xff) << 8 | (value[s++] & 0xff);
 
             // Encode the int into four chars
-            bytes[off] = (byte) CA[(i >>> 18) & 0x3f];
-            bytes[off + 1] = (byte) CA[(i >>> 12) & 0x3f];
-            bytes[off + 2] = (byte) CA[(i >>> 6) & 0x3f];
-            bytes[off + 3] = (byte) CA[i & 0x3f];
+            putByte(bytes, off, (byte) CA[(i >>> 18) & 0x3f]);
+            putByte(bytes, off + 1, (byte) CA[(i >>> 12) & 0x3f]);
+            putByte(bytes, off + 2, (byte) CA[(i >>> 6) & 0x3f]);
+            putByte(bytes, off + 3, (byte) CA[i & 0x3f]);
             off += 4;
         }
 
@@ -129,14 +123,14 @@ class JSONWriterUTF8
             int i = ((value[eLen] & 0xff) << 10) | (left == 2 ? ((value[value.length - 1] & 0xff) << 2) : 0);
 
             // Set last four chars
-            bytes[off] = (byte) CA[i >> 12];
-            bytes[off + 1] = (byte) CA[(i >>> 6) & 0x3f];
-            bytes[off + 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) '=';
-            bytes[off + 3] = '=';
+            putByte(bytes, off, (byte) CA[i >> 12]);
+            putByte(bytes, off + 1, (byte) CA[(i >>> 6) & 0x3f]);
+            putByte(bytes, off + 2, left == 2 ? (byte) CA[i & 0x3f] : (byte) '=');
+            putByte(bytes, off + 3, (byte) '=');
             off += 4;
         }
 
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -155,22 +149,15 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = 'x';
-        bytes[off + 1] = '\'';
+        putShortLE(bytes, off, (short) ('x' | ('\'' << 8)));
         off += 2;
 
         for (int i = 0; i < values.length; i++) {
-            byte b = values[i];
-            int a = b & 0xFF;
-            int b0 = a >> 4;
-            int b1 = a & 0xf;
-
-            bytes[off] = (byte) (b0 + (b0 < 10 ? 48 : 55));
-            bytes[off + 1] = (byte) (b1 + (b1 < 10 ? 48 : 55));
+            putShortLE(bytes, off, hex2U(values[i]));
             off += 2;
         }
 
-        bytes[off] = '\'';
+        putByte(bytes, off, (byte) '\'');
         this.off = off + 1;
     }
 
@@ -219,17 +206,14 @@ class JSONWriterUTF8
         if (off == bytes.length) {
             ensureCapacity(off + 1);
         }
-        bytes[off] = (byte) c;
+        putByte(bytes, off, (byte) c);
         this.off = off + 1;
     }
 
     @Override
     public final void writeColon() {
         int off = this.off;
-        if (off == bytes.length) {
-            ensureCapacity(off + 1);
-        }
-        bytes[off] = ':';
+        putByte(grow1(off), off, (byte) ':');
         this.off = off + 1;
     }
 
@@ -247,7 +231,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) '{';
+        putByte(bytes, off++, (byte) '{');
 
         if (pretty != PRETTY_NON) {
             off = indent(bytes, off);
@@ -268,7 +252,7 @@ class JSONWriterUTF8
             off = indent(bytes, off);
         }
 
-        bytes[off] = (byte) '}';
+        putByte(bytes, off, (byte) '}');
         this.off = off + 1;
         startObject = false;
     }
@@ -282,7 +266,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = ',';
+        putByte(bytes, off++, (byte) ',');
         if (pretty != PRETTY_NON) {
             off = indent(bytes, off);
         }
@@ -301,7 +285,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) '[';
+        putByte(bytes, off++, (byte) '[');
         if (pretty != PRETTY_NON) {
             off = indent(bytes, off);
         }
@@ -320,7 +304,7 @@ class JSONWriterUTF8
         if (pretty != PRETTY_NON) {
             off = indent(bytes, off);
         }
-        bytes[off] = (byte) ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
         startObject = false;
     }
@@ -330,21 +314,16 @@ class JSONWriterUTF8
             super.writeString(list);
             return;
         }
-        // startArray();
         int off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        bytes[off] = '[';
+        byte[] bytes = grow1(off);
+        putByte(bytes, off, (byte) '[');
         this.off = off + 1;
 
         for (int i = 0, size = list.size(); i < size; i++) {
             if (i != 0) {
                 off = this.off;
-                if (off == bytes.length) {
-                    grow0(off + 1);
-                }
-                bytes[off] = ',';
+                bytes = grow1(off);
+                putByte(bytes, off, (byte) ',');
                 this.off = off + 1;
             }
 
@@ -353,19 +332,17 @@ class JSONWriterUTF8
         }
 
         off = this.off;
-        if (off == bytes.length) {
-            grow0(off + 1);
-        }
-        bytes[off] = ']';
+        bytes = grow1(off);
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
     @Override
     public final void writeString(boolean value) {
         byte quote = (byte) this.quote;
-        bytes[off++] = quote;
+        putByte(bytes, off++, quote);
         writeBool(value);
-        bytes[off++] = quote;
+        putByte(bytes, off++, quote);
     }
 
     @Override
@@ -417,10 +394,7 @@ class JSONWriterUTF8
     }
 
     private void writeQuote() {
-        if (off == bytes.length) {
-            grow(off + 1);
-        }
-        bytes[off++] = (byte) quote;
+        writeRaw((byte) quote);
     }
 
     @Override
@@ -450,7 +424,7 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
 
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
 
         int i = 0;
         for (; i < chars.length; i++) {
@@ -464,11 +438,12 @@ class JSONWriterUTF8
             ) {
                 break;
             }
-            bytes[off++] = (byte) c0;
+
+            putByte(bytes, off++, (byte) c0);
         }
 
         if (i == chars.length) {
-            bytes[off] = (byte) quote;
+            putByte(bytes, off, (byte) quote);
             this.off = off + 1;
             return;
         }
@@ -478,7 +453,7 @@ class JSONWriterUTF8
             writeStringEscapedRest(chars, chars.length, browserSecure, escapeNoneAscii, i);
         }
 
-        this.bytes[this.off++] = (byte) quote;
+        putByte(this.bytes, this.off++, (byte) quote);
     }
 
     public void writeStringLatin1(byte[] value) {
@@ -516,10 +491,10 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = quote;
+        putByte(bytes, off, quote);
         System.arraycopy(value, 0, bytes, off + 1, value.length);
         off += value.length + 1;
-        bytes[off] = quote;
+        putByte(bytes, off, quote);
         this.off = off + 1;
     }
 
@@ -540,7 +515,7 @@ class JSONWriterUTF8
         x22 = (x22 - 0x0101010101010101L) & ~x22;
         x5c = (x5c - 0x0101010101010101L) & ~x5c;
 
-        return ((x22 | x5c | (0x7F7F7F7F7F7F7F7FL - v + 0x1010101010101010L) | v) & 0x8080808080808080L) != 0;
+        return ((x22 | x5c | (0x7F7F7F7F7F7F7F7FL - v + 0x2020202020202020L) | v) & 0x8080808080808080L) != 0;
     }
 
     protected final void writeStringLatin1BrowserSecure(byte[] values) {
@@ -569,10 +544,10 @@ class JSONWriterUTF8
             if (minCapacity > bytes.length) {
                 bytes = grow(minCapacity);
             }
-            bytes[off] = quote;
+            putByte(bytes, off, quote);
             System.arraycopy(values, 0, bytes, off + 1, values.length);
             off += values.length + 1;
-            bytes[off] = quote;
+            putByte(bytes, off, quote);
             this.off = off + 1;
             return;
         }
@@ -598,7 +573,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
 
         int coff = 0, char_len = value.length >> 1;
         while (coff < char_len) {
@@ -652,24 +627,24 @@ class JSONWriterUTF8
                             writeU4HexU(bytes, off, c);
                             off += 6;
                         } else {
-                            bytes[off++] = (byte) c;
+                            putByte(bytes, off++, (byte) c);
                         }
                         break;
                     default:
                         if (c == quote) {
-                            bytes[off] = (byte) '\\';
-                            bytes[off + 1] = (byte) quote;
+                            putByte(bytes, off, (byte) '\\');
+                            putByte(bytes, off + 1, (byte) quote);
                             off += 2;
                         } else {
-                            bytes[off++] = (byte) c;
+                            putByte(bytes, off++, (byte) c);
                         }
                         break;
                 }
             } else {
                 if (c < 0x800) {
                     // 2 bytes, 11 bits
-                    bytes[off] = (byte) (0xc0 | (c >> 6));
-                    bytes[off + 1] = (byte) (0x80 | (c & 0x3f));
+                    putByte(bytes, off, (byte) (0xc0 | (c >> 6)));
+                    putByte(bytes, off + 1, (byte) (0x80 | (c & 0x3f)));
                     off += 2;
                 } else if (escapeNoneAscii) {
                     writeU4HexU(bytes, off, c);
@@ -686,37 +661,37 @@ class JSONWriterUTF8
                                 coff++;
                                 uc = ((c << 10) + d) + (0x010000 - ('\uD800' << 10) - '\uDC00'); // Character.toCodePoint(c, d)
                             } else {
-                                bytes[off++] = '?';
+                                putByte(bytes, off++, (byte) '?');
                                 continue;
                             }
                         }
                     } else {
                         //
                         // Character.isLowSurrogate(c)
-                        bytes[off++] = '?';
+                        putByte(bytes, off++, (byte) '?');
                         continue;
                     }
 
                     if (uc < 0) {
-                        bytes[off++] = (byte) '?';
+                        putByte(bytes, off++, (byte) '?');
                     } else {
-                        bytes[off] = (byte) (0xf0 | ((uc >> 18)));
-                        bytes[off + 1] = (byte) (0x80 | ((uc >> 12) & 0x3f));
-                        bytes[off + 2] = (byte) (0x80 | ((uc >> 6) & 0x3f));
-                        bytes[off + 3] = (byte) (0x80 | (uc & 0x3f));
+                        putByte(bytes, off, (byte) (0xf0 | ((uc >> 18))));
+                        putByte(bytes, off + 1, (byte) (0x80 | ((uc >> 12) & 0x3f)));
+                        putByte(bytes, off + 2, (byte) (0x80 | ((uc >> 6) & 0x3f)));
+                        putByte(bytes, off + 3, (byte) (0x80 | (uc & 0x3f)));
                         off += 4;
                     }
                 } else {
                     // 3 bytes, 16 bits
-                    bytes[off] = (byte) (0xe0 | ((c >> 12)));
-                    bytes[off + 1] = (byte) (0x80 | ((c >> 6) & 0x3f));
-                    bytes[off + 2] = (byte) (0x80 | (c & 0x3f));
+                    putByte(bytes, off, (byte) (0xe0 | ((c >> 12))));
+                    putByte(bytes, off + 1, (byte) (0x80 | ((c >> 6) & 0x3f)));
+                    putByte(bytes, off + 2, (byte) (0x80 | (c & 0x3f)));
                     off += 3;
                 }
             }
         }
 
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -742,7 +717,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
 
         int i = 0;
         for (; i < chars.length; i++) {
@@ -756,7 +731,7 @@ class JSONWriterUTF8
             ) {
                 break;
             }
-            bytes[off++] = (byte) c;
+            putByte(bytes, off++, (byte) c);
         }
 
         this.off = off;
@@ -764,7 +739,7 @@ class JSONWriterUTF8
             writeStringEscapedRest(chars, chars.length, browserSecure, escapeNoneAscii, i);
         }
 
-        this.bytes[this.off++] = (byte) quote;
+        putByte(this.bytes, this.off++, (byte) quote);
     }
 
     public final void writeString(final char[] chars, int stroff, int strlen) {
@@ -797,7 +772,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
 
         int i = stroff;
         for (; i < end; i++) {
@@ -811,14 +786,14 @@ class JSONWriterUTF8
             ) {
                 break;
             }
-            bytes[off++] = (byte) c0;
+            putByte(bytes, off++, (byte) c0);
         }
         this.off = off;
         if (i < end) {
             writeStringEscapedRest(chars, end, browserSecure, escapeNoneAscii, i);
         }
 
-        this.bytes[this.off++] = (byte) quote;
+        putByte(this.bytes, this.off++, (byte) quote);
     }
 
     protected final void writeStringEscaped(byte[] values) {
@@ -830,7 +805,7 @@ class JSONWriterUTF8
 
         final boolean browserSecure = (context.features & BrowserSecure.mask) != 0;
         int off = this.off;
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
         for (int i = 0; i < values.length; i++) {
             byte ch = values[i];
             switch (ch) {
@@ -881,27 +856,27 @@ class JSONWriterUTF8
                         writeU4HexU(bytes, off, ch);
                         off += 6;
                     } else {
-                        bytes[off++] = ch;
+                        putByte(bytes, off++, ch);
                     }
                     break;
                 default:
                     if (ch == quote) {
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) quote;
+                        putByte(bytes, off, (byte) '\\');
+                        putByte(bytes, off + 1, (byte) quote);
                         off += 2;
                     } else if (ch < 0) {
                         // latin
                         int c = ch & 0xFF;
-                        bytes[off] = (byte) (0xc0 | (c >> 6));
-                        bytes[off + 1] = (byte) (0x80 | (c & 0x3f));
+                        putByte(bytes, off, (byte) (0xc0 | (c >> 6)));
+                        putByte(bytes, off + 1, (byte) (0x80 | (c & 0x3f)));
                         off += 2;
                     } else {
-                        bytes[off++] = ch;
+                        putByte(bytes, off++, ch);
                     }
                     break;
             }
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -925,33 +900,12 @@ class JSONWriterUTF8
             if (ch <= 0x007F) {
                 switch (ch) {
                     case '\\':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) '\\';
-                        off += 2;
-                        break;
                     case '\n':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'n';
-                        off += 2;
-                        break;
                     case '\r':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'r';
-                        off += 2;
-                        break;
                     case '\f':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'f';
-                        off += 2;
-                        break;
                     case '\b':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'b';
-                        off += 2;
-                        break;
                     case '\t':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 't';
+                        writeEscapedChar(bytes, off, ch);
                         off += 2;
                         break;
                     case 0:
@@ -992,16 +946,16 @@ class JSONWriterUTF8
                             writeU4HexU(bytes, off, ch);
                             off += 6;
                         } else {
-                            bytes[off++] = (byte) ch;
+                            putByte(bytes, off++, (byte) ch);
                         }
                         break;
                     default:
                         if (ch == quote) {
-                            bytes[off] = (byte) '\\';
-                            bytes[off + 1] = (byte) quote;
+                            putByte(bytes, off, (byte) '\\');
+                            putByte(bytes, off + 1, (byte) quote);
                             off += 2;
                         } else {
-                            bytes[off++] = (byte) ch;
+                            putByte(bytes, off++, (byte) ch);
                         }
                         break;
                 }
@@ -1020,36 +974,36 @@ class JSONWriterUTF8
                             uc = ((ch << 10) + d) + (0x010000 - ('\uD800' << 10) - '\uDC00'); // Character.toCodePoint(c, d)
                         } else {
 //                            throw new JSONException("encodeUTF8 error", new MalformedInputException(1));
-                            bytes[off++] = (byte) '?';
+                            putByte(bytes, off++, (byte) '?');
                             continue;
                         }
                     }
                 } else {
                     //
                     // Character.isLowSurrogate(c)
-                    bytes[off++] = (byte) '?';
+                    putByte(bytes, off++, (byte) '?');
                     continue;
 //                        throw new JSONException("encodeUTF8 error", new MalformedInputException(1));
                 }
 
                 if (uc < 0) {
-                    bytes[off++] = (byte) '?';
+                    putByte(bytes, off++, (byte) '?');
                 } else {
-                    bytes[off] = (byte) (0xf0 | ((uc >> 18)));
-                    bytes[off + 1] = (byte) (0x80 | ((uc >> 12) & 0x3f));
-                    bytes[off + 2] = (byte) (0x80 | ((uc >> 6) & 0x3f));
-                    bytes[off + 3] = (byte) (0x80 | (uc & 0x3f));
+                    putByte(bytes, off, (byte) (0xf0 | ((uc >> 18))));
+                    putByte(bytes, off + 1, (byte) (0x80 | ((uc >> 12) & 0x3f)));
+                    putByte(bytes, off + 2, (byte) (0x80 | ((uc >> 6) & 0x3f)));
+                    putByte(bytes, off + 3, (byte) (0x80 | (uc & 0x3f)));
                     off += 4;
                     i++; // 2 chars
                 }
             } else if (ch > 0x07FF) {
-                bytes[off] = (byte) (0xE0 | ((ch >> 12) & 0x0F));
-                bytes[off + 1] = (byte) (0x80 | ((ch >> 6) & 0x3F));
-                bytes[off + 2] = (byte) (0x80 | (ch & 0x3F));
+                putByte(bytes, off, (byte) (0xE0 | ((ch >> 12) & 0x0F)));
+                putByte(bytes, off + 1, (byte) (0x80 | ((ch >> 6) & 0x3F)));
+                putByte(bytes, off + 2, (byte) (0x80 | (ch & 0x3F)));
                 off += 3;
             } else {
-                bytes[off] = (byte) (0xC0 | ((ch >> 6) & 0x1F));
-                bytes[off + 1] = (byte) (0x80 | (ch & 0x3F));
+                putByte(bytes, off, (byte) (0xC0 | ((ch >> 6) & 0x1F)));
+                putByte(bytes, off + 1, (byte) (0x80 | (ch & 0x3F)));
                 off += 2;
             }
         }
@@ -1075,7 +1029,7 @@ class JSONWriterUTF8
         }
         int off = this.off;
         if (quoted) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
 
         int end = offset + len;
@@ -1089,12 +1043,12 @@ class JSONWriterUTF8
                     || c0 > 0x007F) {
                 break;
             }
-            bytes[off++] = (byte) c0;
+            putByte(bytes, off++, (byte) c0);
         }
 
         if (i == end) {
             if (quoted) {
-                bytes[off++] = (byte) quote;
+                putByte(bytes, off++, (byte) quote);
             }
             this.off = off;
             return;
@@ -1105,33 +1059,12 @@ class JSONWriterUTF8
             if (ch <= 0x007F) {
                 switch (ch) {
                     case '\\':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) '\\';
-                        off += 2;
-                        break;
                     case '\n':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'n';
-                        off += 2;
-                        break;
                     case '\r':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'r';
-                        off += 2;
-                        break;
                     case '\f':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'f';
-                        off += 2;
-                        break;
                     case '\b':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 'b';
-                        off += 2;
-                        break;
                     case '\t':
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) 't';
+                        writeEscapedChar(bytes, off, ch);
                         off += 2;
                         break;
                     case 0:
@@ -1166,11 +1099,11 @@ class JSONWriterUTF8
                         break;
                     default:
                         if (ch == quote) {
-                            bytes[off] = (byte) '\\';
-                            bytes[off + 1] = (byte) quote;
+                            putByte(bytes, off, (byte) '\\');
+                            putByte(bytes, off + 1, (byte) quote);
                             off += 2;
                         } else {
-                            bytes[off++] = (byte) ch;
+                            putByte(bytes, off++, (byte) ch);
                         }
                         break;
                 }
@@ -1189,42 +1122,42 @@ class JSONWriterUTF8
                             uc = ((ch << 10) + d) + (0x010000 - ('\uD800' << 10) - '\uDC00'); // Character.toCodePoint(c, d)
                         } else {
 //                            throw new JSONException("encodeUTF8 error", new MalformedInputException(1));
-                            bytes[off++] = (byte) '?';
+                            putByte(bytes, off++, (byte) '?');
                             continue;
                         }
                     }
                 } else {
                     //
                     // Character.isLowSurrogate(c)
-                    bytes[off++] = (byte) '?';
+                    putByte(bytes, off++, (byte) '?');
                     continue;
 //                        throw new JSONException("encodeUTF8 error", new MalformedInputException(1));
                 }
 
                 if (uc < 0) {
-                    bytes[off++] = (byte) '?';
+                    putByte(bytes, off++, (byte) '?');
                 } else {
-                    bytes[off] = (byte) (0xf0 | ((uc >> 18)));
-                    bytes[off + 1] = (byte) (0x80 | ((uc >> 12) & 0x3f));
-                    bytes[off + 2] = (byte) (0x80 | ((uc >> 6) & 0x3f));
-                    bytes[off + 3] = (byte) (0x80 | (uc & 0x3f));
+                    putByte(bytes, off, (byte) (0xf0 | ((uc >> 18))));
+                    putByte(bytes, off + 1, (byte) (0x80 | ((uc >> 12) & 0x3f)));
+                    putByte(bytes, off + 2, (byte) (0x80 | ((uc >> 6) & 0x3f)));
+                    putByte(bytes, off + 3, (byte) (0x80 | (uc & 0x3f)));
                     off += 4;
                     i++; // 2 chars
                 }
             } else if (ch > 0x07FF) {
-                bytes[off] = (byte) (0xE0 | ((ch >> 12) & 0x0F));
-                bytes[off + 1] = (byte) (0x80 | ((ch >> 6) & 0x3F));
-                bytes[off + 2] = (byte) (0x80 | (ch & 0x3F));
+                putByte(bytes, off, (byte) (0xE0 | ((ch >> 12) & 0x0F)));
+                putByte(bytes, off + 1, (byte) (0x80 | ((ch >> 6) & 0x3F)));
+                putByte(bytes, off + 2, (byte) (0x80 | (ch & 0x3F)));
                 off += 3;
             } else {
-                bytes[off] = (byte) (0xC0 | ((ch >> 6) & 0x1F));
-                bytes[off + 1] = (byte) (0x80 | (ch & 0x3F));
+                putByte(bytes, off, (byte) (0xC0 | ((ch >> 6) & 0x1F)));
+                putByte(bytes, off + 1, (byte) (0x80 | (ch & 0x3F)));
                 off += 2;
             }
         }
 
         if (quoted) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         this.off = off;
     }
@@ -1262,37 +1195,16 @@ class JSONWriterUTF8
         if (off + 8 > bytes.length) {
             bytes = grow(off + 8);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
         if (ch <= 0x007F) {
             switch (ch) {
                 case '\\':
-                    bytes[off] = (byte) '\\';
-                    bytes[off + 1] = (byte) '\\';
-                    off += 2;
-                    break;
                 case '\n':
-                    bytes[off] = (byte) '\\';
-                    bytes[off + 1] = (byte) 'n';
-                    off += 2;
-                    break;
                 case '\r':
-                    bytes[off] = (byte) '\\';
-                    bytes[off + 1] = (byte) 'r';
-                    off += 2;
-                    break;
                 case '\f':
-                    bytes[off] = (byte) '\\';
-                    bytes[off + 1] = (byte) 'f';
-                    off += 2;
-                    break;
                 case '\b':
-                    bytes[off] = (byte) '\\';
-                    bytes[off + 1] = (byte) 'b';
-                    off += 2;
-                    break;
                 case '\t':
-                    bytes[off] = (byte) '\\';
-                    bytes[off + 1] = (byte) 't';
+                    writeEscapedChar(bytes, off, ch);
                     off += 2;
                     break;
                 case 0:
@@ -1327,28 +1239,28 @@ class JSONWriterUTF8
                     break;
                 default:
                     if (ch == quote) {
-                        bytes[off] = (byte) '\\';
-                        bytes[off + 1] = (byte) quote;
+                        putByte(bytes, off, (byte) '\\');
+                        putByte(bytes, off + 1, (byte) quote);
                         off += 2;
                     } else {
-                        bytes[off++] = (byte) ch;
+                        putByte(bytes, off++, (byte) ch);
                     }
                     break;
             }
         } else if (ch >= '\uD800' && ch < ('\uDFFF' + 1)) { //  //Character.isSurrogate(c)
             throw new JSONException("illegal char " + ch);
         } else if (ch > 0x07FF) {
-            bytes[off] = (byte) (0xE0 | ((ch >> 12) & 0x0F));
-            bytes[off + 1] = (byte) (0x80 | ((ch >> 6) & 0x3F));
-            bytes[off + 2] = (byte) (0x80 | (ch & 0x3F));
+            putByte(bytes, off, (byte) (0xE0 | ((ch >> 12) & 0x0F)));
+            putByte(bytes, off + 1, (byte) (0x80 | ((ch >> 6) & 0x3F)));
+            putByte(bytes, off + 2, (byte) (0x80 | (ch & 0x3F)));
             off += 3;
         } else {
-            bytes[off] = (byte) (0xC0 | ((ch >> 6) & 0x1F));
-            bytes[off + 1] = (byte) (0x80 | (ch & 0x3F));
+            putByte(bytes, off, (byte) (0xC0 | ((ch >> 6) & 0x1F)));
+            putByte(bytes, off + 1, (byte) (0x80 | (ch & 0x3F)));
             off += 2;
         }
 
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -1392,7 +1304,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = '"';
+        putByte(bytes, off, (byte) '"');
 
         final long base = ARRAY_BYTE_BASE_OFFSET + off;
 
@@ -1401,22 +1313,22 @@ class JSONWriterUTF8
                 base + 1,
                 packDigits((int) (msb >> 56), (int) (msb >> 48), (int) (msb >> 40), (int) (msb >> 32))
         );
-        bytes[off + 9] = '-';
+        putByte(bytes, off + 9, (byte) '-');
         UNSAFE.putLong(
                 bytes,
                 base + 10,
                 packDigits(((int) msb) >> 24, ((int) msb) >> 16));
-        bytes[off + 14] = '-';
+        putByte(bytes, off + 14, (byte) '-');
         UNSAFE.putLong(
                 bytes,
                 base + 15,
                 packDigits(((int) msb) >> 8, (int) msb));
-        bytes[off + 19] = '-';
+        putByte(bytes, off + 19, (byte) '-');
         UNSAFE.putLong(
                 bytes,
                 base + 20,
                 packDigits((int) (lsb >> 56), (int) (lsb >> 48)));
-        bytes[off + 24] = '-';
+        putByte(bytes, off + 24, (byte) '-');
         UNSAFE.putLong(
                 bytes,
                 base + 25,
@@ -1425,7 +1337,7 @@ class JSONWriterUTF8
                 bytes,
                 base + 33,
                 packDigits(((int) lsb) >> 8, (int) lsb));
-        bytes[off + 37] = '"';
+        putByte(bytes, off + 37, (byte) '"');
         this.off += 38;
     }
 
@@ -1443,15 +1355,15 @@ class JSONWriterUTF8
         for (int i = 0; i < chars.length; i++) {
             char c = chars[i];
             if ((c >= 0x0001) && (c <= 0x007F)) {
-                bytes[off++] = (byte) c;
+                putByte(bytes, off++, (byte) c);
             } else if (c > 0x07FF) {
-                bytes[off] = (byte) (0xE0 | ((c >> 12) & 0x0F));
-                bytes[off + 1] = (byte) (0x80 | ((c >> 6) & 0x3F));
-                bytes[off + 2] = (byte) (0x80 | (c & 0x3F));
+                putByte(bytes, off, (byte) (0xE0 | ((c >> 12) & 0x0F)));
+                putByte(bytes, off + 1, (byte) (0x80 | ((c >> 6) & 0x3F)));
+                putByte(bytes, off + 2, (byte) (0x80 | (c & 0x3F)));
                 off += 3;
             } else {
-                bytes[off] = (byte) (0xC0 | ((c >> 6) & 0x1F));
-                bytes[off + 1] = (byte) (0x80 | (c & 0x3F));
+                putByte(bytes, off, (byte) (0xC0 | ((c >> 6) & 0x1F)));
+                putByte(bytes, off + 1, (byte) (0x80 | (c & 0x3F)));
                 off += 2;
             }
         }
@@ -1480,7 +1392,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1500,7 +1412,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1511,7 +1423,7 @@ class JSONWriterUTF8
     }
 
     private int indent(byte[] bytes, int off) {
-        bytes[off] = '\n';
+        putByte(bytes, off, (byte) '\n');
         int toIndex = off + 1 + pretty * level;
         Arrays.fill(bytes, off + 1, toIndex, pretty == PRETTY_TAB ? (byte) '\t' : (byte) ' ');
         return toIndex;
@@ -1528,7 +1440,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1549,7 +1461,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1570,7 +1482,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1591,14 +1503,14 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
         }
 
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
-        bytes[off + 8] = ':';
+        putByte(bytes, off + 8, (byte) ':');
         this.off = off + 9;
     }
 
@@ -1613,15 +1525,15 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
         }
 
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name);
-        bytes[off + 8] = (byte) quote;
-        bytes[off + 9] = ':';
+        putByte(bytes, off + 8, (byte) quote);
+        putByte(bytes, off + 9, (byte) ':');
         this.off = off + 10;
     }
 
@@ -1636,13 +1548,13 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
         }
 
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 1, name);
         UNSAFE.putShort(bytes, ARRAY_BYTE_BASE_OFFSET + off + 9, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 11;
@@ -1659,7 +1571,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1681,7 +1593,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1703,7 +1615,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1725,7 +1637,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1747,7 +1659,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1769,7 +1681,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1777,7 +1689,7 @@ class JSONWriterUTF8
 
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
-        bytes[off + 16] = ':';
+        putByte(bytes, off + 16, (byte) ':');
         this.off = off + 17;
     }
 
@@ -1792,7 +1704,7 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1815,19 +1727,25 @@ class JSONWriterUTF8
         if (startObject) {
             startObject = false;
         } else {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
         }
 
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
         UNSAFE.putShort(bytes, ARRAY_BYTE_BASE_OFFSET + off + 16, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 18;
     }
 
+    public final void writeRaw(byte b) {
+        int off = this.off;
+        putByte(grow1(off), off, b);
+        this.off = off + 1;
+    }
+
     @Override
     public final void writeRaw(char ch) {
         if (ch > 128) {
@@ -1837,7 +1755,7 @@ class JSONWriterUTF8
         if (off == bytes.length) {
             ensureCapacity(off + 1);
         }
-        bytes[off++] = (byte) ch;
+        putByte(bytes, off++, (byte) ch);
     }
 
     @Override
@@ -1851,8 +1769,8 @@ class JSONWriterUTF8
         if (off + 2 > bytes.length) {
             bytes = grow(off + 2);
         }
-        bytes[off] = (byte) c0;
-        bytes[off + 1] = (byte) c1;
+        putByte(bytes, off, (byte) c0);
+        putByte(bytes, off + 1, (byte) c1);
         this.off = off + 2;
     }
 
@@ -1866,7 +1784,7 @@ class JSONWriterUTF8
         }
 
         if (!startObject) {
-            bytes[off++] = ',';
+            putByte(bytes, off++, (byte) ',');
             if (pretty != PRETTY_NON) {
                 off = indent(bytes, off);
             }
@@ -1887,6 +1805,14 @@ class JSONWriterUTF8
         return bytes;
     }
 
+    private byte[] grow1(int off) {
+        byte[] bytes = this.bytes;
+        if (off == bytes.length) {
+            bytes = grow(off + 1);
+        }
+        return bytes;
+    }
+
     private void grow0(int minCapacity) {
         // minCapacity is usually close to size, so this is a win:
         bytes = Arrays.copyOf(bytes, newCapacity(minCapacity, bytes.length));
@@ -1906,22 +1832,22 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = '[';
+        putByte(bytes, off++, (byte) '[');
 
         for (int i = 0; i < values.length; i++) {
             if (i != 0) {
-                bytes[off++] = ',';
+                putByte(bytes, off++, (byte) ',');
             }
             if (writeAsString) {
-                bytes[off++] = (byte) quote;
+                putByte(bytes, off++, (byte) quote);
             }
             off = IOUtils.writeInt32(bytes, off, values[i]);
             if (writeAsString) {
-                bytes[off++] = (byte) quote;
+                putByte(bytes, off++, (byte) quote);
             }
         }
 
-        bytes[off] = ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
@@ -1936,11 +1862,11 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         off = IOUtils.writeInt8(bytes, off, i);
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         this.off = off;
     }
@@ -1960,22 +1886,22 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = '[';
+        putByte(bytes, off++, (byte) '[');
 
         for (int i = 0; i < values.length; i++) {
             if (i != 0) {
-                bytes[off++] = ',';
+                putByte(bytes, off++, (byte) ',');
             }
             if (writeAsString) {
-                bytes[off++] = (byte) quote;
+                putByte(bytes, off++, (byte) quote);
             }
             off = IOUtils.writeInt8(bytes, off, values[i]);
             if (writeAsString) {
-                bytes[off++] = (byte) quote;
+                putByte(bytes, off++, (byte) quote);
             }
         }
 
-        bytes[off] = ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
@@ -1990,11 +1916,11 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         off = IOUtils.writeInt16(bytes, off, i);
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         this.off = off;
     }
@@ -2019,11 +1945,11 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         off = IOUtils.writeInt32(bytes, off, i);
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         this.off = off;
     }
@@ -2043,11 +1969,11 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) '[';
+        putByte(bytes, off++, (byte) '[');
 
         for (int i = 0; i < size; i++) {
             if (i != 0) {
-                bytes[off++] = (byte) ',';
+                putByte(bytes, off++, (byte) ',');
             }
             Number item = values.get(i);
             if (item == null) {
@@ -2058,15 +1984,15 @@ class JSONWriterUTF8
 
             int v = item.intValue();
             if (writeAsString) {
-                bytes[off++] = (byte) quote;
+                putByte(bytes, off++, (byte) quote);
             }
             off = IOUtils.writeInt32(bytes, off, v);
             if (writeAsString) {
-                bytes[off++] = (byte) quote;
+                putByte(bytes, off++, (byte) quote);
             }
         }
 
-        bytes[off] = ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
@@ -2083,24 +2009,24 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) '[';
+        putByte(bytes, off++, (byte) '[');
 
         for (int i = 0; i < values.length; i++) {
             if (i != 0) {
-                bytes[off++] = (byte) ',';
+                putByte(bytes, off++, (byte) ',');
             }
             long v = values[i];
             boolean writeAsString = isWriteAsString(v, context.features);
             if (writeAsString) {
-                bytes[off++] = (byte) this.quote;
+                putByte(bytes, off++, (byte) quote);
             }
             off = IOUtils.writeInt64(bytes, off, v);
             if (writeAsString) {
-                bytes[off++] = (byte) this.quote;
+                putByte(bytes, off++, (byte) quote);
             }
         }
 
-        bytes[off] = ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
@@ -2118,11 +2044,11 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) '[';
+        putByte(bytes, off++, (byte) '[');
 
         for (int i = 0; i < size; i++) {
             if (i != 0) {
-                bytes[off++] = (byte) ',';
+                putByte(bytes, off++, (byte) ',');
             }
             Long item = values.get(i);
             if (item == null) {
@@ -2134,15 +2060,15 @@ class JSONWriterUTF8
             long v = item;
             boolean writeAsString = isWriteAsString(v, context.features);
             if (writeAsString) {
-                bytes[off++] = (byte) this.quote;
+                putByte(bytes, off++, (byte) quote);
             }
             off = IOUtils.writeInt64(bytes, off, v);
             if (writeAsString) {
-                bytes[off++] = (byte) this.quote;
+                putByte(bytes, off++, (byte) quote);
             }
         }
 
-        bytes[off] = ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
@@ -2157,16 +2083,16 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         }
         off = IOUtils.writeInt64(bytes, off, i);
         if (writeAsString) {
-            bytes[off++] = (byte) quote;
+            putByte(bytes, off++, (byte) quote);
         } else if ((features & WriteClassName.mask) != 0
                 && (features & NotWriteNumberClassName.mask) == 0
                 && i >= Integer.MIN_VALUE && i <= Integer.MAX_VALUE
         ) {
-            bytes[off++] = 'L';
+            putByte(bytes, off++, (byte) 'L');
         }
         this.off = off;
     }
@@ -2192,14 +2118,14 @@ class JSONWriterUTF8
         }
 
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
 
         int len = DoubleToDecimal.toString(value, bytes, off, true);
         off += len;
 
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
         this.off = off;
     }
@@ -2215,13 +2141,13 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
 
         off += DoubleToDecimal.toString(value, bytes, off, true);
 
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
         this.off = off;
     }
@@ -2241,14 +2167,15 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = '[';
+
+        putByte(bytes, off++, (byte) '[');
         for (int i = 0; i < values.length; i++) {
             if (i != 0) {
-                bytes[off++] = ',';
+                putByte(bytes, off++, (byte) ',');
             }
 
             if (writeAsString) {
-                bytes[off++] = '"';
+                putByte(bytes, off++, (byte) '"');
             }
 
             float value = values[i];
@@ -2256,10 +2183,10 @@ class JSONWriterUTF8
             off += len;
 
             if (writeAsString) {
-                bytes[off++] = '"';
+                putByte(bytes, off++, (byte) '"');
             }
         }
-        bytes[off] = ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
@@ -2278,14 +2205,14 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = '[';
+        putByte(bytes, off++, (byte) '[');
         for (int i = 0; i < values.length; i++) {
             if (i != 0) {
-                bytes[off++] = ',';
+                putByte(bytes, off++, (byte) ',');
             }
 
             if (writeAsString) {
-                bytes[off++] = '"';
+                putByte(bytes, off++, (byte) '"');
             }
 
             double value = values[i];
@@ -2293,10 +2220,10 @@ class JSONWriterUTF8
             off += len;
 
             if (writeAsString) {
-                bytes[off++] = '"';
+                putByte(bytes, off++, (byte) '"');
             }
         }
-        bytes[off] = ']';
+        putByte(bytes, off, (byte) ']');
         this.off = off + 1;
     }
 
@@ -2315,7 +2242,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         if (year < 0 || year > 9999) {
             throw illegalYear(year);
         }
@@ -2328,7 +2255,7 @@ class JSONWriterUTF8
         writeDigitPair(bytes, off + 9, hour);
         writeDigitPair(bytes, off + 11, minute);
         writeDigitPair(bytes, off + 13, second);
-        bytes[off + 15] = (byte) quote;
+        putByte(bytes, off + 15, (byte) quote);
         this.off = off + 16;
     }
 
@@ -2346,11 +2273,11 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         off = IOUtils.writeLocalDate(bytes, off + 1, year, month, dayOfMonth);
-        bytes[off] = ' ';
+        putByte(bytes, off, (byte) ' ');
         IOUtils.writeLocalTime(bytes, off + 1, hour, minute, second);
-        bytes[off + 9] = (byte) quote;
+        putByte(bytes, off + 9, (byte) quote);
         this.off = off + 10;
     }
 
@@ -2372,9 +2299,9 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
         off = IOUtils.writeLocalDate(bytes, off, date.getYear(), date.getMonthValue(), date.getDayOfMonth());
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2386,12 +2313,12 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
         LocalDate localDate = dateTime.toLocalDate();
         off = IOUtils.writeLocalDate(bytes, off, localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
-        bytes[off++] = ' ';
+        putByte(bytes, off++, (byte) ' ');
         off = IOUtils.writeLocalTime(bytes, off, dateTime.toLocalTime());
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2403,7 +2330,7 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         if (year < 0 || year > 9999) {
             throw illegalYear(year);
         }
@@ -2413,7 +2340,7 @@ class JSONWriterUTF8
         writeDigitPair(bytes, off + 3, y23);
         writeDigitPair(bytes, off + 5, month);
         writeDigitPair(bytes, off + 7, dayOfMonth);
-        bytes[off + 9] = (byte) quote;
+        putByte(bytes, off + 9, (byte) quote);
         this.off = off + 10;
     }
 
@@ -2425,9 +2352,9 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
         off = IOUtils.writeLocalDate(bytes, off, year, month, dayOfMonth);
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2439,9 +2366,9 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         IOUtils.writeLocalTime(bytes, off + 1, hour, minute, second);
-        bytes[off + 9] = (byte) quote;
+        putByte(bytes, off + 9, (byte) quote);
         this.off = off + 10;
     }
 
@@ -2453,9 +2380,9 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off++] = (byte) quote;
+        putByte(bytes, off++, (byte) quote);
         off = IOUtils.writeLocalTime(bytes, off, time);
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2486,23 +2413,23 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         LocalDate localDate = dateTime.toLocalDate();
         off = IOUtils.writeLocalDate(bytes, off + 1, localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
-        bytes[off] = 'T';
+        putByte(bytes, off, (byte) 'T');
         off = IOUtils.writeLocalTime(bytes, off + 1, dateTime.toLocalTime());
         if (zoneSize == 1) {
-            bytes[off++] = 'Z';
+            putByte(bytes, off++, (byte) 'Z');
         } else if (firstZoneChar == '+' || firstZoneChar == '-') {
             zoneId.getBytes(0, zoneIdLength, bytes, off);
             off += zoneIdLength;
         } else {
-            bytes[off++] = '[';
+            putByte(bytes, off++, (byte) '[');
             zoneId.getBytes(0, zoneIdLength, bytes, off);
             off += zoneIdLength;
-            bytes[off++] = ']';
+            putByte(bytes, off++, (byte) ']');
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2519,22 +2446,22 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         LocalDateTime ldt = dateTime.toLocalDateTime();
         LocalDate date = ldt.toLocalDate();
         off = IOUtils.writeLocalDate(bytes, off + 1, date.getYear(), date.getMonthValue(), date.getDayOfMonth());
-        bytes[off] = 'T';
+        putByte(bytes, off, (byte) 'T');
         off = IOUtils.writeLocalTime(bytes, off + 1, ldt.toLocalTime());
 
         ZoneOffset offset = dateTime.getOffset();
         if (offset.getTotalSeconds() == 0) {
-            bytes[off++] = 'Z';
+            putByte(bytes, off++, (byte) 'Z');
         } else {
             String zoneId = offset.getId();
             zoneId.getBytes(0, zoneId.length(), bytes, off);
             off += zoneId.length();
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2550,18 +2477,18 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         off = IOUtils.writeLocalTime(bytes, off + 1, time.toLocalTime());
 
         ZoneOffset offset = time.getOffset();
         if (offset.getTotalSeconds() == 0) {
-            bytes[off++] = 'Z';
+            putByte(bytes, off++, (byte) 'Z');
         } else {
             String zoneId = offset.getId();
             zoneId.getBytes(0, zoneId.length(), bytes, off);
             off += zoneId.length();
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2590,12 +2517,12 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
         str.getBytes(0, strlen, bytes, off);
         off += strlen;
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
         this.off = off;
     }
@@ -2625,9 +2552,9 @@ class JSONWriterUTF8
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         off = IOUtils.writeLocalDate(bytes, off + 1, year, month, dayOfMonth);
-        bytes[off] = (byte) (timeZone ? 'T' : ' ');
+        putByte(bytes, off, (byte) (timeZone ? 'T' : ' '));
         IOUtils.writeLocalTime(bytes, off + 1, hour, minute, second);
         off += 9;
 
@@ -2640,13 +2567,13 @@ class JSONWriterUTF8
                 putIntLE(bytes, off, DIGITS_K_32[millis & 0x3ff] & 0xffffff00 | '.');
                 off += 4;
             } else {
-                bytes[off++] = '.';
+                putByte(bytes, off++, (byte) '.');
                 final int rem2 = div - div2 * 10;
                 if (rem2 != 0) {
                     writeDigitPair(bytes, off, div);
                     off += 2;
                 } else {
-                    bytes[off++] = (byte) (div2 + '0');
+                    putByte(bytes, off++, (byte) (div2 + '0'));
                 }
             }
         }
@@ -2654,12 +2581,12 @@ class JSONWriterUTF8
         if (timeZone) {
             int offset = offsetSeconds / 3600;
             if (offsetSeconds == 0) {
-                bytes[off++] = 'Z';
+                putByte(bytes, off++, (byte) 'Z');
             } else {
                 int offsetAbs = Math.abs(offset);
-                bytes[off] = offset >= 0 ? (byte) '+' : (byte) '-';
+                putByte(bytes, off, offset >= 0 ? (byte) '+' : (byte) '-');
                 writeDigitPair(bytes, off + 1, offsetAbs);
-                bytes[off + 3] = ':';
+                putByte(bytes, off + 3, (byte) ':');
                 int offsetMinutes = (offsetSeconds - offset * 3600) / 60;
                 if (offsetMinutes < 0) {
                     offsetMinutes = -offsetMinutes;
@@ -2668,7 +2595,7 @@ class JSONWriterUTF8
                 off += 6;
             }
         }
-        bytes[off] = (byte) quote;
+        putByte(bytes, off, (byte) quote);
         this.off = off + 1;
     }
 
@@ -2697,7 +2624,7 @@ class JSONWriterUTF8
             bytes = grow(minCapacity);
         }
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
 
         boolean asPlain = (features & WriteBigDecimalAsPlain.mask) != 0;
@@ -2717,7 +2644,7 @@ class JSONWriterUTF8
         }
 
         if (writeAsString) {
-            bytes[off++] = '"';
+            putByte(bytes, off++, (byte) '"');
         }
         this.off = off;
     }
@@ -2753,7 +2680,7 @@ class JSONWriterUTF8
         if (off == bytes.length) {
             grow(off + 1);
         }
-        bytes[off++] = '{';
+        putByte(bytes, off++, (byte) '{');
 
         boolean first = true;
         for (Map.Entry entry : map.entrySet()) {
@@ -2766,7 +2693,7 @@ class JSONWriterUTF8
                 if (off == bytes.length) {
                     ensureCapacity(off + 1);
                 }
-                bytes[off++] = ',';
+                putByte(bytes, off++, (byte) ',');
             }
 
             first = false;
@@ -2780,7 +2707,7 @@ class JSONWriterUTF8
             if (off == bytes.length) {
                 ensureCapacity(off + 1);
             }
-            bytes[off++] = ':';
+            putByte(bytes, off++, (byte) ':');
 
             if (value == null) {
                 writeNull();
@@ -2830,7 +2757,7 @@ class JSONWriterUTF8
         if (off == bytes.length) {
             grow(off + 1);
         }
-        bytes[off++] = '}';
+        putByte(bytes, off++, (byte) '}');
     }
 
     @Override
@@ -2854,7 +2781,7 @@ class JSONWriterUTF8
         if (off == bytes.length) {
             grow(off + 1);
         }
-        bytes[off++] = '[';
+        putByte(bytes, off++, (byte) '[');
 
         boolean first = true;
         for (int i = 0; i < array.size(); i++) {
@@ -2863,7 +2790,7 @@ class JSONWriterUTF8
                 if (off == bytes.length) {
                     grow(off + 1);
                 }
-                bytes[off++] = ',';
+                putByte(bytes, off++, (byte) ',');
             }
             first = false;
 
@@ -2914,7 +2841,7 @@ class JSONWriterUTF8
         if (off == bytes.length) {
             grow(off + 1);
         }
-        bytes[off++] = ']';
+        putByte(bytes, off++, (byte) ']');
     }
 
     public void writeBool(boolean value) {
@@ -2925,7 +2852,7 @@ class JSONWriterUTF8
         }
         int off = this.off;
         if ((context.features & WriteBooleanAsNumber.mask) != 0) {
-            bytes[off++] = (byte) (value ? '1' : '0');
+            putByte(bytes, off++, (byte) (value ? '1' : '0'));
         } else {
             off = IOUtils.putBoolean(bytes, off, value);
         }
@@ -2996,16 +2923,16 @@ class JSONWriterUTF8
     }
 
     static void writeEscapedChar(byte[] bytes, int off, int c0) {
-        IOUtils.putShortLE(bytes, off, ESCAPED_CHARS[c0 & 0x7f]);
+        putShortLE(bytes, off, ESCAPED_CHARS[c0 & 0x7f]);
     }
 
     static void writeU4Hex2(byte[] bytes, int off, int c) {
-        IOUtils.putIntUnaligned(bytes, off, U4);
-        IOUtils.putShortLE(bytes, off + 4, hex2(c));
+        putIntUnaligned(bytes, off, U4);
+        putShortLE(bytes, off + 4, hex2(c));
     }
 
     static void writeU4HexU(byte[] bytes, int off, int c) {
-        IOUtils.putShortUnaligned(bytes, off, U2);
-        IOUtils.putIntLE(bytes, off + 2, hex4U(c));
+        putShortUnaligned(bytes, off, U2);
+        putIntLE(bytes, off + 2, hex4U(c));
     }
 }
diff --git a/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java
index 7559fc016..a4ee2854a 100644
--- a/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/support/csv/CSVWriterUTF8.java
@@ -12,6 +12,8 @@ import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 
+import static com.alibaba.fastjson2.util.IOUtils.putByte;
+
 final class CSVWriterUTF8
         extends CSVWriter {
     private static final short DOUBLE_QUOTE_2_LATIN1 = 0x22 | (0x22 << 8);
@@ -42,17 +44,17 @@ final class CSVWriterUTF8
 
     public void writeComma() {
         checkCapacity(1);
-        bytes[off++] = ',';
+        putByte(bytes, off++, (byte) ',');
     }
 
     protected void writeQuote() {
         checkCapacity(1);
-        bytes[off++] = '"';
+        putByte(bytes, off++, (byte) '"');
     }
 
     public void writeLine() {
         checkCapacity(1);
-        bytes[off++] = '\n';
+        putByte(bytes, off++, (byte) '\n');
     }
 
     public void writeBoolean(boolean v) {
@@ -83,7 +85,7 @@ final class CSVWriterUTF8
         final byte[] bytes = this.bytes;
         int off = this.off;
         off = IOUtils.writeLocalDate(bytes, off, year, month, dayOfMonth);
-        bytes[off] = ' ';
+        putByte(bytes, off, (byte) ' ');
         IOUtils.writeLocalTime(bytes, off + 1, hour, minute, second);
         this.off = off + 9;
     }
@@ -170,20 +172,20 @@ final class CSVWriterUTF8
         final int max = bytes.length - 2;
         int off = this.off;
 
-        bytes[off++] = '"';
+        putByte(bytes, off++, (byte) '"');
         for (byte ch : utf8) {
             if (ch == '"') {
                 IOUtils.putShortUnaligned(bytes, off, DOUBLE_QUOTE_2_LATIN1);
                 off += 2;
             } else {
-                bytes[off++] = ch;
+                putByte(bytes, off++, ch);
             }
             if (off >= max) {
                 flush();
                 off = this.off;
             }
         }
-        bytes[off++] = '"';
+        putByte(bytes, off++, (byte) '"');
         this.off = off;
     }
 
@@ -258,7 +260,7 @@ final class CSVWriterUTF8
             off = 0;
         }
         off = IOUtils.writeLocalDate(bytes, off, ldt.getYear(), ldt.getMonthValue(), ldt.getDayOfMonth());
-        bytes[off++] = ' ';
+        putByte(bytes, off++, (byte) ' ');
         this.off = IOUtils.writeLocalTime(bytes, off, ldt.toLocalTime());
     }
 
diff --git a/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
index 83f799147..63f7b3ae6 100644
--- a/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
+++ b/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
@@ -1621,19 +1621,23 @@ public class IOUtils {
         return d >= 0 && d <= 9 ? d : -1;
     }
 
-    public static int indexOfChar(byte[] value, int ch, int fromIndex) {
-        return indexOfChar(value, ch, fromIndex, value.length);
+    public static int indexOfQuote(byte[] value, int quote, int fromIndex, int max) {
+        int i = fromIndex;
+        int upperBound = fromIndex + ((max - fromIndex) & ~7);
+        long vectorQuote = quote == '\'' ? 0x2727_2727_2727_2727L : 0x2222_2222_2222_2222L;
+        while (i < upperBound && notContains(getLongLE(value, i), vectorQuote)) {
+            i += 8;
+        }
+        return indexOfChar0(value, quote, i, max);
     }
 
-    public static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
-        if (INDEX_OF_CHAR_LATIN1 == null) {
-            return indexOfChar0(value, ch, fromIndex, max);
-        }
-        try {
-            return (int) INDEX_OF_CHAR_LATIN1.invokeExact(value, ch, fromIndex, max);
-        } catch (Throwable e) {
-            throw new JSONException(e.getMessage());
+    public static int indexOfSlash(byte[] value, int fromIndex, int max) {
+        int i = fromIndex;
+        int upperBound = fromIndex + ((max - fromIndex) & ~7);
+        while (i < upperBound && notContains(getLongLE(value, i), 0x5C5C5C5C5C5C5C5CL)) {
+            i += 8;
         }
+        return indexOfChar0(value, '\\', i, max);
     }
 
     private static int indexOfChar0(byte[] value, int ch, int fromIndex, int max) {
@@ -1645,22 +1649,35 @@ public class IOUtils {
         return -1;
     }
 
+    private static boolean notContains(long v, long quote) {
+        /*
+          for (int i = 0; i < 8; ++i) {
+            byte c = (byte) v;
+            if (c == quote) {
+                return true;
+            }
+            v >>>= 8;
+          }
+          return false;
+         */
+        long x = v ^ quote;
+        return (((x - 0x0101010101010101L) & ~x) & 0x8080808080808080L) == 0;
+    }
+
     public static int hexDigit4(byte[] bytes, int offset) {
-        int v = Integer.reverseBytes(UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset));
+        int v = getIntLE(bytes, offset);
         v = (v & 0x0F0F0F0F) + ((((v & 0x40404040) >> 2) | ((v & 0x40404040) << 1)) >>> 4);
-        v = ((v >>> 12) & 0xF000)
-                + ((v >>> 8) & 0xF00)
-                + ((v >>> 4) & 0xF0)
-                + (v & 0xF);
-        return v;
+        return ((v & 0xF000000) >>> 24) + ((v & 0xF0000) >>> 12) + (v & 0xF00) + ((v & 0xF) << 12);
     }
 
-    public static boolean isDigit(int ch) {
-        return ch >= '0' && ch <= '9';
+    public static int hexDigit4(char[] bytes, int offset) {
+        long v = getLongLE(bytes, offset);
+        v = (v & 0x000F_000F_000F_000FL) + ((((v & 0x0004_0004_0004_00040L) >> 2) | ((v & 0x0004_0004_0004_00040L) << 1)) >>> 4);
+        return (int) (((v & 0xF_0000_0000_0000L) >>> 48) + ((v & 0xF_0000_0000L) >>> 28) + ((v & 0xF_0000) >> 8) + ((v & 0xF) << 12));
     }
 
-    public static short getShortUnaligned(byte[] bytes, int offset) {
-        return UNSAFE.getShort(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+    public static boolean isDigit(int ch) {
+        return ch >= '0' && ch <= '9';
     }
 
     public static short getShortBE(byte[] bytes, int offset) {
@@ -1726,6 +1743,13 @@ public class IOUtils {
                 + 0x30303030 + i);
     }
 
+    public static short hex2U(int i) {
+        i = ((i & 0xF0) >> 4) | ((i & 0xF) << 8);
+        int m = (i + 0x06060606) & 0x10101010;
+        return (short) (((m >> 1) - (m >> 4))
+                + 0x30303030 + i);
+    }
+
     public static int utf16Hex2(int i) {
         // 0x000F000F
         i = ((i & 0xF0) >> 4) | ((i & 0xF) << 16);
@@ -1808,4 +1832,20 @@ public class IOUtils {
     static short convEndian(boolean big, short n) {
         return big == BIG_ENDIAN ? n : Short.reverseBytes(n);
     }
+
+    public static boolean isASCII(char[] chars, int coff, int strlen) {
+        int i = coff;
+        for (int upperBound = coff + (strlen & ~3); i < upperBound; i += 4) {
+            if ((getLongLE(chars, i) & 0xFF00FF00FF00FF00L) != 0) {
+                return false;
+            }
+        }
+
+        for (; i < strlen; ++i) {
+            if (chars[i] > 0x00FF) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java
index 8d6f8db5a..c60079911 100644
--- a/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java
+++ b/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java
@@ -59,7 +59,6 @@ public class JDKUtils {
 
     public static final MethodHandle METHOD_HANDLE_HAS_NEGATIVE;
     public static final Predicate<byte[]> PREDICATE_IS_ASCII;
-    public static final MethodHandle INDEX_OF_CHAR_LATIN1;
 
     static final MethodHandles.Lookup IMPL_LOOKUP;
     static volatile MethodHandle CONSTRUCTOR_LOOKUP;
@@ -317,6 +316,9 @@ public class JDKUtils {
                     initErrorLast = e;
                 }
             }
+            if (isAscii == null) {
+                isAscii = JDKUtils::isASCII;
+            }
 
             PREDICATE_IS_ASCII = isAscii;
         }
@@ -338,21 +340,6 @@ public class JDKUtils {
             METHOD_HANDLE_HAS_NEGATIVE = handle;
         }
 
-        MethodHandle indexOfCharLatin1 = null;
-        if (JVM_VERSION > 9) {
-            try {
-                Class<?> cStringLatin1 = Class.forName("java.lang.StringLatin1");
-                MethodHandles.Lookup lookup = trustedLookup(cStringLatin1);
-                indexOfCharLatin1 = lookup.findStatic(
-                        cStringLatin1,
-                        "indexOfChar",
-                        MethodType.methodType(int.class, byte[].class, int.class, int.class, int.class));
-            } catch (Throwable ignored) {
-                // ignore
-            }
-        }
-        INDEX_OF_CHAR_LATIN1 = indexOfCharLatin1;
-
         Boolean compact_strings = null;
         try {
             if (JVM_VERSION == 8) {
@@ -522,4 +509,21 @@ public class JDKUtils {
         }
         return STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
     }
+
+    public static boolean isASCII(byte[] chars) {
+        int i = 0;
+        int strlen = chars.length;
+        for (int upperBound = (strlen & ~7); i < upperBound; i += 8) {
+            if ((UNSAFE.getLong(chars, ARRAY_BYTE_BASE_OFFSET + i) & 0x8080808080808080L) != 0) {
+                return false;
+            }
+        }
+
+        for (; i < strlen; ++i) {
+            if (UNSAFE.getByte(chars, ARRAY_BYTE_BASE_OFFSET + i) < 0) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/docs/vector_optimized.md b/docs/vector_optimized.md
index d73ace82c..4faae11c2 100644
--- a/docs/vector_optimized.md
+++ b/docs/vector_optimized.md
@@ -1,17 +1,3 @@
 JDK 17中提供了[vector api](https://openjdk.org/jeps/426)，可以用SIMD来优化性能。
 
-fastjson 2.0.51中已经支持vector api，这个优化目前处于incubator状态，需要通过如下方法打开：
-
-加上依赖
-```xml
-<dependency>
-    <groupId>com.alibaba.fastjson2</groupId>
-    <artifactId>fastjson2-incubator-vector</artifactId>
-    <version>2.0.54</version>
-</dependency>
-```
-
-JVM启动参数加上
-```shell
---add-modules=jdk.incubator.vector
-```
+fastjson 2.0.55版本开始全面使用SWAR(SIMD within a register)来做SIMD优化，不再需要使用vector api.
diff --git a/incubator-vector/pom.xml b/incubator-vector/pom.xml
deleted file mode 100644
index 3babd1e51..000000000
--- a/incubator-vector/pom.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://maven.apache.org/POM/4.0.0"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>com.alibaba.fastjson2</groupId>
-        <artifactId>fastjson2-parent</artifactId>
-        <version>2.0.55-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>fastjson2-incubator-vector</artifactId>
-    <name>fastjson2-incubator-vector</name>
-    <description>vector implementation</description>
-    <packaging>jar</packaging>
-    <url>https://github.com/alibaba/fastjson2</url>
-    <inceptionYear>2022</inceptionYear>
-
-    <licenses>
-        <license>
-            <name>Apache 2</name>
-            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
-            <distribution>repo</distribution>
-            <comments>A business-friendly OSS license</comments>
-        </license>
-    </licenses>
-    <scm>
-        <url>https://github.com/alibaba/fastjson2</url>
-        <connection>scm:git:https://git@github.com/alibaba/fastjson2.git</connection>
-    </scm>
-    <properties>
-        <maven.compiler.source>11</maven.compiler.source>
-        <maven.compiler.target>11</maven.compiler.target>
-        <add.modules.option>--add-modules=jdk.incubator.vector</add.modules.option>
-    </properties>
-
-    <organization>
-        <name>Alibaba Group</name>
-        <url>https://github.com/alibaba</url>
-    </organization>
-    <developers>
-        <developer>
-            <id>wenshao</id>
-            <name>wenshao</name>
-            <email>shaojin.wensj(at)alibaba-inc.com</email>
-            <roles>
-                <role>Developer</role>
-                <role>Tech Leader</role>
-            </roles>
-            <timezone>+8</timezone>
-            <url>https://github.com/wenshao</url>
-        </developer>
-    </developers>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.alibaba.fastjson2</groupId>
-            <artifactId>fastjson2</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-
-        <!-- test libs -->
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>11</source>
-                    <target>11</target>
-                    <compilerArgs combine.children="append">
-                        <arg>${add.modules.option}</arg>
-                    </compilerArgs>
-                </configuration>
-            </plugin>
-            <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <includes>
-                        <include>com/alibaba/fastjson2/**/*.java</include>
-                    </includes>
-                    <systemPropertyVariables>
-                        <user.timezone>Asia/Shanghai</user.timezone>
-                    </systemPropertyVariables>
-                    <argLine>${add.modules.option}</argLine>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>gen-javadoc</id>
-            <activation>
-                <property>
-                    <name>performRelease</name>
-                    <value>true</value>
-                </property>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-javadoc-plugin</artifactId>
-                        <configuration>
-                            <show>package</show>
-                            <additionalOptions>
-                                <additionalOption>${add.modules.option}</additionalOption>
-                            </additionalOptions>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
-</project>
diff --git a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderASCIIVector.java b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderASCIIVector.java
deleted file mode 100644
index fe0d86f31..000000000
--- a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderASCIIVector.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package com.alibaba.fastjson2;
-
-import com.alibaba.fastjson2.util.TypeUtils;
-import jdk.incubator.vector.ByteVector;
-import jdk.incubator.vector.Vector;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-
-import static com.alibaba.fastjson2.JSONWriterUTF16Vector.*;
-import static com.alibaba.fastjson2.util.JDKUtils.LATIN1;
-import static com.alibaba.fastjson2.util.JDKUtils.STRING_CREATOR_JDK11;
-
-final class JSONReaderASCIIVector
-        extends JSONReaderASCII {
-    public JSONReaderASCIIVector(Context ctx, String str, byte[] bytes, int offset, int length) {
-        super(ctx, str, bytes, offset, length);
-    }
-
-    @Override
-    public String readString() {
-        if (ch == '"' || ch == '\'') {
-            final byte quote = (byte) ch;
-            final byte slash = (byte) '\\';
-
-            final byte[] bytes = this.bytes;
-            int offset = this.offset;
-            final int start = offset, end = this.end;
-            int valueLength;
-            boolean valueEscape = false;
-
-            _for:
-            {
-                int i = 0;
-                Vector<Byte> v_quote = quote == '"' ? V_BYTE_64_DOUBLE_QUOTE : V_BYTE_64_SINGLE_QUOTE;
-                for (; offset + 8 < end; offset += 8, i += 8) {
-                    ByteVector v = (ByteVector) ByteVector.SPECIES_64.fromArray(bytes, offset);
-                    if (v.eq(V_BYTE_64_SLASH).or(v.eq(v_quote)).anyTrue()) {
-                        break;
-                    }
-                }
-
-                for (; ; ++i) {
-                    if (offset >= end) {
-                        throw new JSONException("invalid escape character EOI");
-                    }
-
-                    byte c = bytes[offset];
-                    if (c == slash) {
-                        valueEscape = true;
-                        c = bytes[offset + 1];
-                        offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2));
-                        continue;
-                    }
-
-                    if (c == quote) {
-                        valueLength = i;
-                        break _for;
-                    }
-                    offset++;
-                }
-            }
-
-            String str;
-            if (valueEscape) {
-                char[] chars = new char[valueLength];
-                offset = start;
-                for (int i = 0; ; ++i) {
-                    int c = bytes[offset] & 0xff;
-                    if (c == '\\') {
-                        c = bytes[++offset] & 0xff;
-                        switch (c) {
-                            case 'u': {
-                                c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
-                                offset += 4;
-                                break;
-                            }
-                            case 'x': {
-                                c = char2(bytes[offset + 1], bytes[offset + 2]);
-                                offset += 2;
-                                break;
-                            }
-                            case '\\':
-                            case '"':
-                                break;
-                            case 'b':
-                                c = '\b';
-                                break;
-                            case 't':
-                                c = '\t';
-                                break;
-                            case 'n':
-                                c = '\n';
-                                break;
-                            case 'f':
-                                c = '\f';
-                                break;
-                            case 'r':
-                                c = '\r';
-                                break;
-                            default:
-                                c = char1(c);
-                                break;
-                        }
-                    } else if (c == quote) {
-                        break;
-                    }
-                    chars[i] = (char) c;
-                    offset++;
-                }
-
-                str = new String(chars);
-            } else {
-                int strlen = offset - start;
-                if (strlen == 1) {
-                    str = TypeUtils.toString(bytes[start]);
-                } else if (strlen == 2) {
-                    str = TypeUtils.toString(
-                            bytes[start],
-                            bytes[start + 1]
-                    );
-                } else if (this.str != null) {
-                    str = this.str.substring(start, offset);
-                } else if (STRING_CREATOR_JDK11 != null) {
-                    byte[] buf = Arrays.copyOfRange(bytes, start, offset);
-                    str = STRING_CREATOR_JDK11.apply(buf, LATIN1);
-                } else {
-                    str = new String(bytes, start, offset - start, StandardCharsets.ISO_8859_1);
-                }
-            }
-
-            if ((context.features & Feature.TrimString.mask) != 0) {
-                str = str.trim();
-            }
-
-            int ch = ++offset == end ? EOI : bytes[offset++];
-            while (ch <= ' ' && (1L << ch & SPACE) != 0) {
-                ch = offset == end ? EOI : bytes[offset++];
-            }
-
-            if (comma = ch == ',') {
-                ch = offset == end ? EOI : bytes[offset++];
-                while (ch <= ' ' && (1L << ch & SPACE) != 0) {
-                    ch = offset == end ? EOI : bytes[offset++];
-                }
-            }
-
-            this.ch = (char) (ch & 0xFF);
-            this.offset = offset;
-            return str;
-        }
-
-        return readStringNotMatch();
-    }
-
-    public static class Factory
-            implements JSONFactory.JSONReaderUTF8Creator {
-        @Override
-        public JSONReader create(Context ctx, String str, byte[] bytes, int offset, int length) {
-            return new JSONReaderASCIIVector(ctx, str, bytes, offset, length);
-        }
-    }
-}
diff --git a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16Vector.java b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16Vector.java
deleted file mode 100644
index f4dad0ade..000000000
--- a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16Vector.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package com.alibaba.fastjson2;
-
-import com.alibaba.fastjson2.util.TypeUtils;
-import jdk.incubator.vector.ShortVector;
-import jdk.incubator.vector.Vector;
-
-import static com.alibaba.fastjson2.JSONWriterUTF16Vector.*;
-
-final class JSONReaderUTF16Vector
-        extends JSONReaderUTF16 {
-    JSONReaderUTF16Vector(Context ctx, String str, char[] chars, int offset, int length) {
-        super(ctx, str, chars, offset, length);
-    }
-
-    JSONReaderUTF16Vector(Context ctx, String str, int offset, int length) {
-        super(ctx, str, offset, length);
-    }
-
-    @Override
-    public String readString() {
-        char[] chars = this.chars;
-        if (ch == '"' || ch == '\'') {
-            final char quote = ch;
-
-            int offset = this.offset;
-            final int start = offset, end = this.end;
-            int valueLength;
-            boolean valueEscape = false;
-
-            {
-                int i = 0;
-                final Vector<Short> v_quote = quote == '"' ? V_SHORT_128_DOUBLE_QUOTE : V_SHORT_128_SINGLE_QUOTE;
-                for (; offset + 8 < end; offset += 8, i += 8) {
-                    ShortVector v = ShortVector.fromCharArray(ShortVector.SPECIES_128, chars, offset);
-                    if (v.eq(V_SHORT_128_SLASH).or(v.eq(v_quote)).anyTrue()) {
-                        break;
-                    }
-                }
-
-                for (; ; ++i) {
-                    if (offset >= end) {
-                        throw new JSONException(info("invalid escape character EOI"));
-                    }
-                    char c = chars[offset];
-                    if (c == '\\') {
-                        valueEscape = true;
-                        c = chars[offset + 1];
-                        offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2));
-                        continue;
-                    }
-
-                    if (c == quote) {
-                        valueLength = i;
-                        break;
-                    }
-                    offset++;
-                }
-            }
-
-            String str;
-            if (valueEscape) {
-                char[] buf = new char[valueLength];
-                offset = start;
-                for (int i = 0; ; ++i) {
-                    char c = chars[offset];
-                    if (c == '\\') {
-                        c = chars[++offset];
-                        switch (c) {
-                            case 'u': {
-                                c = char4(chars[offset + 1], chars[offset + 2], chars[offset + 3], chars[offset + 4]);
-                                offset += 4;
-                                break;
-                            }
-                            case 'x': {
-                                c = char2(chars[offset + 1], chars[offset + 2]);
-                                offset += 2;
-                                break;
-                            }
-                            case '\\':
-                            case '"':
-                                break;
-                            default:
-                                c = char1(c);
-                                break;
-                        }
-                    } else if (c == quote) {
-                        break;
-                    }
-                    buf[i] = c;
-                    offset++;
-                }
-
-                str = new String(buf);
-            } else {
-                char c0, c1;
-                int strlen = offset - start;
-                if (strlen == 1 && (c0 = chars[start]) < 128) {
-                    str = TypeUtils.toString(c0);
-                } else if (strlen == 2
-                        && (c0 = chars[start]) < 128
-                        && (c1 = chars[start + 1]) < 128
-                ) {
-                    str = TypeUtils.toString(c0, c1);
-                } else {
-                    str = this.str.substring(start, offset);
-                }
-            }
-
-            if ((context.features & Feature.TrimString.mask) != 0) {
-                str = str.trim();
-            }
-
-            int ch = ++offset == end ? EOI : chars[offset++];
-            while (ch <= ' ' && (1L << ch & SPACE) != 0) {
-                ch = offset == end ? EOI : chars[offset++];
-            }
-
-            if (comma = ch == ',') {
-                ch = offset == end ? EOI : chars[offset++];
-                while (ch <= ' ' && (1L << ch & SPACE) != 0) {
-                    ch = offset == end ? EOI : chars[offset++];
-                }
-            }
-
-            this.ch = (char) ch;
-            this.offset = offset;
-            return str;
-        }
-
-        return readStringNotMatch();
-    }
-
-    public static class Factory
-            implements JSONFactory.JSONReaderUTF16Creator {
-        @Override
-        public JSONReader create(Context ctx, String str, char[] chars, int offset, int length) {
-            if (chars == null) {
-                return new JSONReaderUTF16Vector(ctx, str, offset, length);
-            } else {
-                return new JSONReaderUTF16Vector(ctx, str, chars, offset, length);
-            }
-        }
-    }
-}
diff --git a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8Vector.java b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8Vector.java
deleted file mode 100644
index 97c243436..000000000
--- a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8Vector.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package com.alibaba.fastjson2;
-
-import com.alibaba.fastjson2.util.TypeUtils;
-import jdk.incubator.vector.ByteVector;
-import jdk.incubator.vector.Vector;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-
-import static com.alibaba.fastjson2.JSONWriterUTF16Vector.*;
-import static com.alibaba.fastjson2.util.JDKUtils.*;
-
-final class JSONReaderUTF8Vector
-        extends JSONReaderUTF8 {
-    JSONReaderUTF8Vector(Context ctx, String str, byte[] bytes, int offset, int length) {
-        super(ctx, str, bytes, offset, length);
-    }
-
-    @Override
-    public String readString() {
-        if (ch == '"' || ch == '\'') {
-            final byte[] bytes = this.bytes;
-            char quote = this.ch;
-            int valueLength;
-            int offset = this.offset;
-            final int start = offset, end = this.end;
-            boolean ascii = true;
-            valueEscape = false;
-
-            {
-                int i = 0;
-                Vector<Byte> v_quote = quote == '"' ? V_BYTE_64_DOUBLE_QUOTE : V_BYTE_64_SINGLE_QUOTE;
-                for (; offset + 8 < end; offset += 8, i += 8) {
-                    ByteVector v = (ByteVector) ByteVector.SPECIES_64.fromArray(bytes, offset);
-                    if (v.eq(V_BYTE_64_SLASH).or(v.eq(v_quote).or(v.lt(V_BYTE_64_ZERO))).anyTrue()) {
-                        break;
-                    }
-                }
-
-                for (; ; ++i) {
-                    if (offset >= end) {
-                        throw new JSONException("invalid escape character EOI");
-                    }
-
-                    int c = bytes[offset];
-                    if (c == '\\') {
-                        valueEscape = true;
-                        c = bytes[offset + 1];
-                        offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2));
-                        continue;
-                    }
-
-                    if (c >= 0) {
-                        if (c == quote) {
-                            valueLength = i;
-                            break;
-                        }
-                        offset++;
-                    } else {
-                        ascii = false;
-                        switch ((c & 0xFF) >> 4) {
-                            case 12:
-                            case 13: {
-                                /* 110x xxxx   10xx xxxx*/
-                                offset += 2;
-                                break;
-                            }
-                            case 14: {
-                                offset += 3;
-                                break;
-                            }
-                            default: {
-                                /* 10xx xxxx,  1111 xxxx */
-                                if ((c >> 3) == -2) {
-                                    offset += 4;
-                                    i++;
-                                    break;
-                                }
-
-                                throw new JSONException("malformed input around byte " + offset);
-                            }
-                        }
-                    }
-                }
-            }
-
-            String str;
-            if (valueEscape) {
-                char[] chars = new char[valueLength];
-                offset = start;
-                for (int i = 0; ; ++i) {
-                    int ch = bytes[offset];
-                    if (ch == '\\') {
-                        ch = bytes[++offset];
-                        switch (ch) {
-                            case 'u': {
-                                ch = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]);
-                                offset += 4;
-                                break;
-                            }
-                            case 'x': {
-                                ch = char2(bytes[offset + 1], bytes[offset + 2]);
-                                offset += 2;
-                                break;
-                            }
-                            case '\\':
-                            case '"':
-                                break;
-                            default:
-                                ch = char1(ch);
-                                break;
-                        }
-                        chars[i] = (char) ch;
-                        offset++;
-                    } else if (ch == '"') {
-                        break;
-                    } else {
-                        if (ch >= 0) {
-                            chars[i] = (char) ch;
-                            offset++;
-                        } else {
-                            switch ((ch & 0xFF) >> 4) {
-                                case 12:
-                                case 13: {
-                                    /* 110x xxxx   10xx xxxx*/
-                                    chars[i] = (char) (((ch & 0x1F) << 6) | (bytes[offset + 1] & 0x3F));
-                                    offset += 2;
-                                    break;
-                                }
-                                case 14: {
-                                    chars[i] = (char)
-                                            (((ch & 0x0F) << 12) |
-                                                    ((bytes[offset + 1] & 0x3F) << 6) |
-                                                    ((bytes[offset + 2] & 0x3F) << 0));
-                                    offset += 3;
-                                    break;
-                                }
-                                default: {
-                                    /* 10xx xxxx,  1111 xxxx */
-                                    char2_utf8(bytes, offset, ch, chars, i);
-                                    offset += 4;
-                                    i++;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                str = new String(chars);
-            } else if (ascii) {
-                int strlen = offset - start;
-                if (strlen == 1) {
-                    str = TypeUtils.toString((char) (bytes[start] & 0xff));
-                } else if (strlen == 2) {
-                    str = TypeUtils.toString(
-                            (char) (bytes[start] & 0xff),
-                            (char) (bytes[start + 1] & 0xff)
-                    );
-                } else if (STRING_CREATOR_JDK11 != null) {
-                    str = STRING_CREATOR_JDK11.apply(
-                            Arrays.copyOfRange(this.bytes, this.offset, offset),
-                            LATIN1);
-                } else {
-                    str = new String(bytes, start, offset - start, StandardCharsets.US_ASCII);
-                }
-            } else {
-                str = new String(bytes, start, offset - start, StandardCharsets.UTF_8);
-            }
-
-            if ((context.features & Feature.TrimString.mask) != 0) {
-                str = str.trim();
-            }
-
-            int ch = ++offset == end ? EOI : bytes[offset++];
-            while (ch <= ' ' && (1L << ch & SPACE) != 0) {
-                ch = offset == end ? EOI : bytes[offset++];
-            }
-
-            if (comma = ch == ',') {
-                ch = offset == end ? EOI : bytes[offset++];
-                while (ch <= ' ' && (1L << ch & SPACE) != 0) {
-                    ch = offset == end ? EOI : bytes[offset++];
-                }
-            }
-
-            this.ch = (char) ch;
-            this.offset = offset;
-            return str;
-        }
-
-        switch (ch) {
-            case '[':
-                return toString(
-                        readArray());
-            case '{':
-                return toString(
-                        readObject());
-            case '-':
-            case '+':
-            case '0':
-            case '1':
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7':
-            case '8':
-            case '9':
-                readNumber0();
-                Number number = getNumber();
-                return number.toString();
-            case 't':
-            case 'f':
-                boolValue = readBoolValue();
-                return boolValue ? "true" : "false";
-            case 'n': {
-                readNull();
-                return null;
-            }
-            default:
-                throw new JSONException("TODO : " + ch);
-        }
-    }
-
-    public static class Factory
-            implements JSONFactory.JSONReaderUTF8Creator {
-        @Override
-        public JSONReader create(Context ctx, String str, byte[] bytes, int offset, int length) {
-            return new JSONReaderUTF8Vector(ctx, str, bytes, offset, length);
-        }
-    }
-}
diff --git a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16Vector.java b/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16Vector.java
deleted file mode 100644
index 44b037f2e..000000000
--- a/incubator-vector/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16Vector.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package com.alibaba.fastjson2;
-
-import jdk.incubator.vector.ByteVector;
-import jdk.incubator.vector.ShortVector;
-import jdk.incubator.vector.Vector;
-import sun.misc.Unsafe;
-
-import java.util.function.Function;
-
-import static com.alibaba.fastjson2.JSONWriter.Feature.BrowserSecure;
-import static com.alibaba.fastjson2.util.JDKUtils.STRING_CODER;
-import static com.alibaba.fastjson2.util.JDKUtils.STRING_VALUE;
-import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE;
-
-final class JSONWriterUTF16Vector
-        extends JSONWriterUTF16 {
-    static final Vector<Byte> V_BYTE_64_SPACE = ByteVector.SPECIES_64.broadcast(' ');
-    static final Vector<Byte> V_BYTE_64_ZERO = ByteVector.SPECIES_64.broadcast(0);
-    static final Vector<Byte> V_BYTE_64_SLASH = ByteVector.SPECIES_64.broadcast('\\');
-    static final Vector<Byte> V_BYTE_64_DOUBLE_QUOTE = ByteVector.SPECIES_64.broadcast('"');
-    static final Vector<Byte> V_BYTE_64_SINGLE_QUOTE = ByteVector.SPECIES_64.broadcast('\'');
-
-    static final Vector<Short> V_SHORT_128_SLASH = ShortVector.SPECIES_128.broadcast('\\');
-    static final Vector<Short> V_SHORT_128_DOUBLE_QUOTE = ShortVector.SPECIES_128.broadcast('"');
-    static final Vector<Short> V_SHORT_128_SINGLE_QUOTE = ShortVector.SPECIES_128.broadcast('\'');
-    static final Vector<Short> V_SHORT_128_SPACE = ShortVector.SPECIES_128.broadcast(' ');
-    static final Vector<Short> V_SHORT_128_LT = ShortVector.SPECIES_128.broadcast('<');
-    static final Vector<Short> V_SHORT_128_GT = ShortVector.SPECIES_128.broadcast('>');
-    static final Vector<Short> V_SHORT_128_LB = ShortVector.SPECIES_128.broadcast('(');
-    static final Vector<Short> V_SHORT_128_RB = ShortVector.SPECIES_128.broadcast(')');
-    static final Vector<Short> V_SHORT_128_7F = ShortVector.SPECIES_128.broadcast(0x7F);
-
-    JSONWriterUTF16Vector(Context ctx) {
-        super(ctx);
-    }
-
-    @Override
-    public void writeString(String str) {
-        if (str == null) {
-            writeStringNull();
-            return;
-        }
-
-        int coder = STRING_CODER.applyAsInt(str);
-        byte[] value = STRING_VALUE.apply(str);
-        if (coder == 0) {
-            writeStringLatin1(value);
-        } else {
-            writeStringUTF16(value);
-        }
-    }
-
-    @Override
-    public void writeStringLatin1(byte[] value) {
-        if ((context.features & BrowserSecure.mask) != 0) {
-            writeStringLatin1BrowserSecure(value);
-            return;
-        }
-
-        boolean escape = false;
-
-        int off = this.off;
-        final int start = off;
-        int minCapacity = off + value.length + 2;
-        if (minCapacity >= chars.length) {
-            ensureCapacity(minCapacity);
-        }
-
-        char quote = this.quote;
-        final char[] chars = this.chars;
-        chars[off++] = quote;
-
-        int i = 0;
-        final int upperBound = (value.length - i) & ~7;
-        for (; i < upperBound; i += 8) {
-            ByteVector v = (ByteVector) ByteVector.SPECIES_64.fromArray(value, i);
-            if (v.eq(V_BYTE_64_DOUBLE_QUOTE)
-                    .or(v.eq(V_BYTE_64_SLASH))
-                    .or(v.lt(V_BYTE_64_SPACE))
-                    .anyTrue()
-            ) {
-                escape = true;
-                break;
-            }
-
-            ShortVector sv = (ShortVector) v.castShape(ShortVector.SPECIES_128, 0);
-            sv.intoCharArray(chars, off);
-            off += 8;
-        }
-
-        if (!escape) {
-            for (; i < value.length; i++) {
-                byte c = value[i];
-                if (c == '\\'
-                        || c == quote
-                        || c < ' ') {
-                    escape = true;
-                    break;
-                }
-                chars[off++] = (char) c;
-            }
-        }
-
-        if (!escape) {
-            chars[off] = quote;
-            this.off = off + 1;
-            return;
-        }
-
-        this.off = start;
-        writeStringEscape(value);
-    }
-
-    public void writeStringUTF16(final byte[] value) {
-        if (value == null) {
-            writeStringNull();
-            return;
-        }
-
-        boolean browserSecure = (context.features & BrowserSecure.mask) != 0;
-        boolean escapeNoneAscii = (context.features & Feature.EscapeNoneAscii.mask) != 0;
-
-        boolean escape = false;
-        int off = this.off;
-        int minCapacity = off + value.length + 2;
-        if (minCapacity >= chars.length) {
-            ensureCapacity(minCapacity);
-        }
-
-        final char[] chars = this.chars;
-        chars[off++] = quote;
-
-        int i = 0;
-        final int upperBound = (value.length - i) & ~15;
-        for (; i < upperBound; i += 16) {
-            ShortVector v = (ShortVector) ByteVector.SPECIES_128.fromArray(value, i)
-                    .castShape(ShortVector.SPECIES_128, 0);
-
-            if (v.eq(V_SHORT_128_DOUBLE_QUOTE)
-                    .or(v.eq(V_SHORT_128_SINGLE_QUOTE))
-                    .or(v.lt(V_SHORT_128_SPACE))
-                    .anyTrue()
-                    || (browserSecure
-                    && v.eq(V_SHORT_128_LT)
-                    .or(v.eq(V_SHORT_128_GT))
-                    .or(v.eq(V_SHORT_128_LB))
-                    .or(v.eq(V_SHORT_128_RB))
-                    .anyTrue())
-                    || (escapeNoneAscii && V_SHORT_128_7F.lt(v).anyTrue())
-            ) {
-                escape = true;
-                break;
-            }
-
-            v.intoCharArray(chars, off);
-            off += 8;
-        }
-
-        if (!escape) {
-            for (; i < value.length; i += 2) {
-                char c = UNSAFE.getChar(value, (long) Unsafe.ARRAY_BYTE_BASE_OFFSET + i);
-                if (c == '\\'
-                        || c == quote
-                        || c < ' '
-                        || (browserSecure && (c == '<' || c == '>' || c == '(' || c == ')'))
-                        || (escapeNoneAscii && c > 0x007F)
-                ) {
-                    escape = true;
-                    break;
-                }
-
-                chars[off++] = c;
-            }
-        }
-
-        if (!escape) {
-            chars[off] = quote;
-            this.off = off + 1;
-            return;
-        }
-
-        writeStringEscapeUTF16(value);
-    }
-
-    public static class Factory
-            implements Function {
-        @Override
-        public Object apply(Object context) {
-            return new JSONWriterUTF16Vector((Context) context);
-        }
-    }
-}
diff --git a/pom.xml b/pom.xml
index 8151d4781..a15520816 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1030,7 +1030,6 @@
                 <module>example-graalvm-native</module>
                 <module>extension-spring6</module>
                 <module>example-spring6-test</module>
-                <module>incubator-vector</module>
                 <module>test-jdk17</module>
             </modules>
         </profile>


Test patch:
diff --git a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseStringTest.java b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseStringTest.java
index 269ee43fc..309ad8cea 100644
--- a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseStringTest.java
+++ b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseStringTest.java
@@ -14,7 +14,7 @@ public class EishayParseStringTest {
             }
             long millis = System.currentTimeMillis() - start;
             System.out.println("fastjson2 millis : " + millis);
-            // zulu8.70.0.23 : 5569 5630 4435
+            // zulu8.70.0.23 : 5569 5630 4435 4199 3851
             // zulu11.64.19 : 5022 5033 3754
             // zulu17.42.19 : 5377 5193 5222 5154 5116 5083 4987 4079
         }
diff --git a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseUTF8BytesTest.java b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseUTF8BytesTest.java
index 62092da45..10c5d4760 100644
--- a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseUTF8BytesTest.java
+++ b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayParseUTF8BytesTest.java
@@ -13,7 +13,7 @@ public class EishayParseUTF8BytesTest {
             }
             long millis = System.currentTimeMillis() - start;
             System.out.println("fastjson2 millis : " + millis);
-            // zulu8.62.0.19 : 703 746 710 706 700 682 717 698 526 500 474
+            // zulu8.62.0.19 : 703 746 710 706 700 682 717 698 526 500 474 445
             // zulu11.52.13 : 579 565 552 541 554 553 554 538 420 424 434
             // zulu17.40.19 : 600 604 597 593 578 567 447 420
         }
@@ -63,8 +63,8 @@ public class EishayParseUTF8BytesTest {
     }
 
     public static void main(String[] args) throws Exception {
-//        fastjson2();
-        fastjson2_features();
+        fastjson2();
+//        fastjson2_features();
 //        dsljson();
 //        jackson();
     }
diff --git a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayWriteStringTest.java b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayWriteStringTest.java
index 544045be3..fc773515e 100644
--- a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayWriteStringTest.java
+++ b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/eishay/EishayWriteStringTest.java
@@ -16,7 +16,7 @@ public class EishayWriteStringTest {
             System.out.println("fastjson2 millis : " + millis);
             // zulu8.70.0.23 : 3001 2795
             // zulu11.62.17 : 3288 2549
-            // zulu17.32.13 : 3305 2909 2503
+            // zulu17.32.13 : 3305 2909 2503 2353
             // zulu17.40.91_vec : 2527 2536
         }
     }
diff --git a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteUTF8BytesTest.java b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteUTF8BytesTest.java
index d70ef2106..93b081e5d 100644
--- a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteUTF8BytesTest.java
+++ b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteUTF8BytesTest.java
@@ -40,7 +40,7 @@ public class ClientsWriteUTF8BytesTest {
             long millis = System.currentTimeMillis() - start;
             System.out.println("ClientsWriteUTF8Bytes-fastjson2 millis : " + millis);
             // zulu8.70.0.23 : 1533 1493 1374 1353
-            // zulu17.40.19 : 1419 1361 1356 1356 1317 1224 1212 1202 1182 979
+            // zulu17.40.19 : 1419 1361 1356 1356 1317 1224 1212 1202 1182 979 949
             // zulu17.40.19_vec : 1116
             // zulu17.40.19_reflect : 1427
         }
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java
index 8212bc6f9..4822ea084 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java
@@ -406,7 +406,40 @@ public class JSONWriterJSONBTest {
         JSONWriter jsonWriter = JSONWriter.ofJSONB();
         jsonWriter.writeString(chars, 256, 512);
         byte[] jsonbBytes = jsonWriter.getBytes();
-        assertEquals(new String(chars), JSONB.parse(jsonbBytes));
+        assertEquals(
+                new String(chars, 256, 512),
+                JSONB.parse(jsonbBytes));
+    }
+
+    @Test
+    public void writeChars2() {
+        char[] chars = new char[] {'A', 'A'};
+        Arrays.fill(chars, 'A');
+        for (int i = 128; i < 256; i++) {
+            chars[1] = (char) (i - 256);
+            JSONWriter jsonWriter = JSONWriter.ofJSONB();
+            jsonWriter.writeString(chars, 1, 1);
+            byte[] jsonbBytes = jsonWriter.getBytes();
+            assertEquals(
+                    new String(chars, 1, 1),
+                    JSONB.parse(jsonbBytes));
+        }
+    }
+
+    @Test
+    public void writeChars3() {
+        char[] chars = new char[128];
+        for (int i = 128; i < 256; i++) {
+            Arrays.fill(chars, (char) (i - 256));
+            chars[0] = 'A';
+            int strlen = chars.length - 1;
+            JSONWriter jsonWriter = JSONWriter.ofJSONB();
+            jsonWriter.writeString(chars, 1, strlen);
+            byte[] jsonbBytes = jsonWriter.getBytes();
+            assertEquals(
+                    new String(chars, 1, strlen),
+                    JSONB.parse(jsonbBytes));
+        }
     }
 
     @Test
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
index 4445bd4c5..55d8f0ef0 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
@@ -1109,6 +1109,26 @@ public class JSONWriterUTF16Test {
         assertEquals("\"" + str + "\"", jsonWriter.toString());
     }
 
+    static boolean containsEscapedUTF16(long v, long quote) {
+        /*
+          for (int i = 0; i < 8; ++i) {
+            byte c = (byte) data;
+            if (c == quote || c == '\\' || c < ' ') {
+                return true;
+            }
+            data >>>= 8;
+          }
+          return false;
+         */
+        long x22 = v ^ quote; // " -> 0x22, ' -> 0x27
+        long x5c = v ^ 0x005C005C_005C005CL;
+
+        x22 = (x22 - 0x00010001_00010001L) & ~x22;
+        x5c = (x5c - 0x00010001_00010001L) & ~x5c;
+
+        return ((x22 | x5c | (0x007F007F_007F007FL - v + 0x00100010_00100010L) | v) & 0x00800080_00800080L) != 0;
+    }
+
     @Test
     public void testEscaped_2() {
         String str = "abcd";
@@ -1117,7 +1137,7 @@ public class JSONWriterUTF16Test {
 
         long v = IOUtils.getLongLE(bytes, 0);
         assertFalse(
-                JSONWriterUTF16.containsEscapedUTF16(
+                containsEscapedUTF16(
                         v,
                         BYTE_VEC_64_DOUBLE_QUOTE));
 
@@ -1137,7 +1157,7 @@ public class JSONWriterUTF16Test {
                 long v = IOUtils.getLongLE(
                         toBytes(chars),
                         0);
-                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+                assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
             }
 
             {
@@ -1145,16 +1165,16 @@ public class JSONWriterUTF16Test {
                 long v = IOUtils.getLongLE(
                         toBytes(chars),
                         0);
-                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
-                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+                assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+                assertTrue(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
             }
             {
                 chars[0] = '\'';
                 long v = IOUtils.getLongLE(
                         toBytes(chars),
                         0);
-                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
-                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+                assertTrue(containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+                assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
             }
         }
         {
@@ -1163,7 +1183,7 @@ public class JSONWriterUTF16Test {
                 long v = IOUtils.getLongLE(
                         toBytes(chars),
                         0);
-                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+                assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
             }
         }
         {
@@ -1172,7 +1192,7 @@ public class JSONWriterUTF16Test {
                 long v = IOUtils.getLongLE(
                         toBytes(chars),
                         0);
-                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+                assertTrue(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
             }
         }
 
@@ -1183,14 +1203,14 @@ public class JSONWriterUTF16Test {
                 long v = IOUtils.getLongLE(
                         toBytes(chars),
                         0);
-                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+                assertTrue(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
             }
             for (char c : specials_single) {
                 chars[i] = c;
                 long v = IOUtils.getLongLE(
                         toBytes(chars),
                         0);
-                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+                assertTrue(containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
             }
         }
         {
@@ -1198,16 +1218,16 @@ public class JSONWriterUTF16Test {
             long v = IOUtils.getLongLE(
                     toBytes(chars),
                     0);
-            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
-            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+            assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
         }
         {
             chars = new char[]{'A', 'B', 'C', 'D'};
             long v = IOUtils.getLongLE(
                     toBytes(chars),
                     0);
-            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
-            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+            assertFalse(containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
         }
     }
 
@@ -1237,5 +1257,41 @@ public class JSONWriterUTF16Test {
 
         IOUtils.putLongUnaligned(chars, 2, IOUtils.utf16Hex4U(1));
         assertEquals("\\u0001", new String(chars));
+
+        chars = new char[] {'0', '1', '2', '3'};
+        assertEquals(0, IOUtils.getLongLE(chars, 0) & 0xFF00FF00FF00FF00L);
+
+        chars = new char[] {'中', '1', '2', '3'};
+        assertNotEquals(0, IOUtils.getLongLE(chars, 0) & 0xFF00FF00FF00FF00L);
+    }
+
+    @Test
+    public void testUTF16() {
+        char[] chars = new char[32];
+        for (int i = 0; i < chars.length; i++) {
+            {
+                Arrays.fill(chars, 'A');
+                chars[chars.length - 1] = '中';
+                String str = new String(chars);
+                String json = JSON.toJSONString(str);
+                assertEquals(str, JSON.parse(json));
+            }
+            {
+                Arrays.fill(chars, 'A');
+                chars[chars.length - 1] = '中';
+                chars[i] = '\r';
+                String str = new String(chars);
+                String json = JSON.toJSONString(str);
+                assertEquals(str, JSON.parse(json));
+            }
+
+            {
+                Arrays.fill(chars, '中');
+                chars[i] = '\r';
+                String str = new String(chars);
+                String json = JSON.toJSONString(str);
+                assertEquals(str, JSON.parse(json));
+            }
+        }
     }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java
index 82df2fe18..c31a61e9c 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java
@@ -15,8 +15,7 @@ import java.util.*;
 import static com.alibaba.fastjson2.JSONWriter.Feature.*;
 import static com.alibaba.fastjson2.util.JDKUtils.ARRAY_CHAR_BASE_OFFSET;
 import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.*;
 
 public class JSONWriterUTF8Test {
     @Test
@@ -1131,4 +1130,15 @@ public class JSONWriterUTF8Test {
         IOUtils.putIntUnaligned(bytes, 2, IOUtils.hex4U(1));
         assertEquals("\\u0001", new String(bytes));
     }
+
+    @Test
+    public void testSpecial1() {
+        byte[] buf = new byte[] {'a', 'a', 'a', 'a', 'a', 'a', 'a', 31};
+        assertEquals("\"aaaaaaa\\u001f\"", new String(JSON.toJSONBytes(new String(buf))));
+
+        for (int i = 0; i < 32; i++) {
+            buf[7] = (byte) i;
+            assertTrue(JSONWriterUTF8.containsEscaped(IOUtils.getLongUnaligned(buf, 0), 0x2222_2222_2222_2222L));
+        }
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java b/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java
index 09a234b59..2196bd494 100644
--- a/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java
+++ b/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java
@@ -6,8 +6,7 @@ import org.junit.jupiter.api.Test;
 import java.nio.charset.StandardCharsets;
 import java.util.Random;
 
-import static com.alibaba.fastjson2.util.JDKUtils.ARRAY_BYTE_BASE_OFFSET;
-import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE;
+import static com.alibaba.fastjson2.util.JDKUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 
 public class IOUtilsTest {
@@ -343,7 +342,12 @@ public class IOUtilsTest {
     @Test
     public void hexDigit4() {
         byte[] bytes = "1234ABcd".getBytes(StandardCharsets.UTF_8);
-        System.out.println(Integer.toHexString(IOUtils.hexDigit4(bytes, 0)));
+        assertEquals("1234", Integer.toHexString(IOUtils.hexDigit4(bytes, 0)));
+        assertEquals("34ab", Integer.toHexString(IOUtils.hexDigit4(bytes, 2)));
+
+        char[] chars = "1234ABcd".toCharArray();
+        assertEquals("1234", Integer.toHexString(IOUtils.hexDigit4(chars, 0)));
+        assertEquals("34ab", Integer.toHexString(IOUtils.hexDigit4(chars, 2)));
     }
 
     static int hexDigit4(byte[] bytes, int offset) {
@@ -361,17 +365,45 @@ public class IOUtilsTest {
     }
 
     @Test
-    public void indexOf() throws Throwable {
-        byte[] bytes = "abcda".getBytes(StandardCharsets.UTF_8);
+    public void indexOf() {
+        byte[] bytes = "'b'd'".getBytes(StandardCharsets.UTF_8);
+        assertEquals(2,
+                IOUtils.indexOfQuote(
+                        bytes, '\'', 1, bytes.length));
+        assertEquals(0,
+                IOUtils.indexOfQuote(
+                        bytes, '\'', 0, bytes.length));
+        assertEquals(4,
+                IOUtils.indexOfQuote(
+                        bytes, '\'', 3, bytes.length));
+    }
+
+    @Test
+    public void indexOf1() {
+        byte[] bytes = "\"b\"d\"".getBytes(StandardCharsets.UTF_8);
+        assertEquals(2,
+                IOUtils.indexOfQuote(
+                        bytes, '"', 1, bytes.length));
+        assertEquals(0,
+                IOUtils.indexOfQuote(
+                        bytes, '"', 0, bytes.length));
+        assertEquals(4,
+                IOUtils.indexOfQuote(
+                        bytes, '"', 3, bytes.length));
+    }
+
+    @Test
+    public void indexOfSlash() {
+        byte[] bytes = "\\b\\d\\".getBytes(StandardCharsets.UTF_8);
         assertEquals(2,
-                IOUtils.indexOfChar(
-                        bytes, 'c', 0));
+                IOUtils.indexOfSlash(
+                        bytes, 1, bytes.length));
         assertEquals(0,
-                IOUtils.indexOfChar(
-                        bytes, 'a', 0));
+                IOUtils.indexOfSlash(
+                        bytes, 0, bytes.length));
         assertEquals(4,
-                IOUtils.indexOfChar(
-                        bytes, 'a', 1));
+                IOUtils.indexOfSlash(
+                        bytes, 3, bytes.length));
     }
 
     @Test
@@ -390,4 +422,12 @@ public class IOUtilsTest {
         assertEquals(i16, IOUtils.convEndian(false, i16));
         assertEquals(Short.reverseBytes(i16), IOUtils.convEndian(true, i16));
     }
+
+    @Test
+    public void test_isASCII() {
+        char[] chars = new char[] {'0', '1', '2', '3', '4', '5', '6', 0x80};
+        long v = UNSAFE.getLong(chars, ARRAY_CHAR_BASE_OFFSET);
+        assertTrue(IOUtils.isASCII(chars, 0, 4));
+        assertTrue(IOUtils.isASCII(chars, 4, 4));
+    }
 }
diff --git a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderASCIIVectorTest.java b/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderASCIIVectorTest.java
deleted file mode 100644
index 180ae8f4a..000000000
--- a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderASCIIVectorTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.alibaba.fastjson2;
-
-import org.junit.jupiter.api.Test;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class JSONReaderASCIIVectorTest {
-    @Test
-    public void testJSON() {
-        for (char i = 0; i < 256; i++) {
-            String s1 = Character.toString(i);
-            String json = JSON.toJSONString(JSONObject.of(s1, s1));
-            byte[] bytes = json.getBytes(StandardCharsets.ISO_8859_1);
-            JSONReader.Context ctx = JSONFactory.createReadContext();
-            JSONReaderASCIIVector jsonReader = new JSONReaderASCIIVector(ctx, json, bytes, 0, bytes.length);
-            JSONObject object = (JSONObject) jsonReader.readObject();
-            Object v1 = object.get(s1);
-            assertEquals(s1, v1, Integer.toString(i));
-        }
-    }
-
-    @Test
-    public void testJSON2() {
-        for (char i = 0; i < 256; i++) {
-            for (char j = 0; j < 256; j++) {
-                String s2 = new String(new char[]{i, j});
-                String json = JSON.toJSONString(JSONObject.of(s2, s2));
-                byte[] bytes = json.getBytes(StandardCharsets.ISO_8859_1);
-                JSONReader.Context ctx = JSONFactory.createReadContext();
-                JSONReaderASCIIVector jsonReader = new JSONReaderASCIIVector(ctx, json, bytes, 0, bytes.length);
-                JSONObject object = (JSONObject) jsonReader.readObject();
-                Object v1 = object.get(s2);
-                assertEquals(s2, v1, ((int) i) + ", " + (int) j);
-            }
-        }
-    }
-
-    @Test
-    public void testJSON3() {
-        for (char i = 0; i < 256; i += 3) {
-            for (char j = 0; j < 256; j += 3) {
-                for (char k = 0; k < 256; k += 3) {
-                    String s3 = new String(new char[]{i, j, k});
-                    String json = JSON.toJSONString(JSONObject.of(s3, s3));
-                    byte[] bytes = json.getBytes(StandardCharsets.ISO_8859_1);
-                    JSONReader.Context ctx = JSONFactory.createReadContext();
-                    JSONReaderASCIIVector jsonReader = new JSONReaderASCIIVector(ctx, json, bytes, 0, bytes.length);
-                    JSONObject object = (JSONObject) jsonReader.readObject();
-                    Object v1 = object.get(s3);
-                    assertEquals(s3, v1, Arrays.toString(new int[]{i, j, k}));
-                }
-            }
-        }
-    }
-}
diff --git a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderUTF16VectorTest.java b/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderUTF16VectorTest.java
deleted file mode 100644
index 9df159e09..000000000
--- a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderUTF16VectorTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.alibaba.fastjson2;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class JSONReaderUTF16VectorTest {
-    @Test
-    public void testJSON() {
-        for (char i = 0; i < 512; i++) {
-            String s1 = Character.toString(i);
-            String json = JSON.toJSONString(JSONObject.of(s1, s1));
-            char[] chars = json.toCharArray();
-            JSONReader.Context ctx = JSONFactory.createReadContext();
-            JSONReaderUTF16Vector jsonReader = new JSONReaderUTF16Vector(ctx, json, chars, 0, chars.length);
-            JSONObject object = (JSONObject) jsonReader.readObject();
-            Object v1 = object.get(s1);
-            assertEquals(s1, v1, Integer.toString(i));
-        }
-
-        for (char i = 0; i < 512; i++) {
-            for (char j = 0; j < 512; j++) {
-                String s2 = new String(new char[]{i, j});
-                String json = JSON.toJSONString(JSONObject.of(s2, s2));
-                char[] chars = json.toCharArray();
-                JSONReader.Context ctx = JSONFactory.createReadContext();
-                JSONReaderUTF16Vector jsonReader = new JSONReaderUTF16Vector(ctx, json, chars, 0, chars.length);
-                JSONObject object = (JSONObject) jsonReader.readObject();
-                Object v1 = object.get(s2);
-                assertEquals(s2, v1);
-            }
-        }
-    }
-}
diff --git a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderUTF8VectorTest.java b/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderUTF8VectorTest.java
deleted file mode 100644
index 7c553ef28..000000000
--- a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONReaderUTF8VectorTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.alibaba.fastjson2;
-
-import org.junit.jupiter.api.Test;
-
-import java.nio.charset.StandardCharsets;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class JSONReaderUTF8VectorTest {
-    @Test
-    public void test() {
-        JSONReader.Context ctx = JSONFactory.createReadContext();
-        String str = "abcdef1234567890中国©®£\uD83D\uDE0D\uD83D\uDC81\uD83D\uDC4C\uD83C\uDF8D\uD83D\uDE0D";
-        String json = JSON.toJSONString(str);
-        byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
-        JSONReaderUTF8Vector jsonReader = new JSONReaderUTF8Vector(ctx, json, bytes, 0, bytes.length);
-        String parsed = jsonReader.readString();
-        assertEquals(str, parsed);
-    }
-
-    @Test
-    public void testJSON() {
-        for (char i = 0; i < 512; i++) {
-            String s1 = Character.toString(i);
-            String json = JSON.toJSONString(JSONObject.of(s1, s1));
-            byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
-            JSONReader.Context ctx = JSONFactory.createReadContext();
-            JSONReaderUTF8Vector jsonReader = new JSONReaderUTF8Vector(ctx, s1, bytes, 0, bytes.length);
-            JSONObject object = (JSONObject) jsonReader.readObject();
-            Object v1 = object.get(s1);
-            assertEquals(s1, v1);
-        }
-
-        for (char i = 0; i < 512; i++) {
-            for (char j = 0; j < 512; j++) {
-                String s2 = new String(new char[]{i, j});
-                String json = JSON.toJSONString(JSONObject.of(s2, s2));
-                byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
-                JSONReader.Context ctx = JSONFactory.createReadContext();
-                JSONReaderUTF8Vector jsonReader = new JSONReaderUTF8Vector(ctx, s2, bytes, 0, bytes.length);
-                JSONObject object = (JSONObject) jsonReader.readObject();
-                Object v1 = object.get(s2);
-                assertEquals(s2, v1);
-            }
-        }
-    }
-}
diff --git a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16VectorTest.java b/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16VectorTest.java
deleted file mode 100644
index 6018d0aec..000000000
--- a/incubator-vector/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16VectorTest.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.alibaba.fastjson2;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class JSONWriterUTF16VectorTest {
-    @Test
-    public void test() {
-        JSONWriter jsonWriter = (JSONWriter) new JSONWriterUTF16Vector.Factory().apply(JSONFactory.createWriteContext());
-        jsonWriter.writeString("01234567890012345678900123456789001234567890中国");
-        assertEquals("\"01234567890012345678900123456789001234567890中国\"", jsonWriter.toString());
-    }
-}