Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Jan 18, 2025
1 parent 18124b8 commit ee1f670
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 347 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static void fastjson2() {
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
}
}
Expand Down
11 changes: 0 additions & 11 deletions core/src/main/java/com/alibaba/fastjson2/JSONFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
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;
Expand Down Expand Up @@ -93,7 +92,6 @@ public static String getProperty(String key) {
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;
Expand Down Expand Up @@ -230,19 +228,11 @@ public NameCacheEntry2(String name, long value0, long value1) {

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");
Expand All @@ -269,7 +259,6 @@ public NameCacheEntry2(String name, long value0, long value1) {
}
}
}
INCUBATOR_VECTOR_WRITER_CREATOR_UTF16 = incubatorVectorCreatorUTF16;
INCUBATOR_VECTOR_READER_CREATOR_ASCII = readerCreatorASCII;
INCUBATOR_VECTOR_READER_CREATOR_UTF8 = readerCreatorUTF8;
INCUBATOR_VECTOR_READER_CREATOR_UTF16 = readerCreatorUTF16;
Expand Down
16 changes: 7 additions & 9 deletions core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,7 @@ public static JSONWriter of() {
} 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);
Expand Down Expand Up @@ -584,8 +582,8 @@ public static JSONWriter of(Context context) {
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);
}
Expand All @@ -606,8 +604,8 @@ public static JSONWriter of(Feature... features) {
} 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);
}
Expand All @@ -626,8 +624,8 @@ public static JSONWriter ofUTF16(Feature... features) {
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);
}
Expand Down
131 changes: 80 additions & 51 deletions core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
Original file line number Diff line number Diff line change
Expand Up @@ -365,21 +365,21 @@ public void writeStringUTF16(final byte[] value) {
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;
Expand All @@ -398,24 +398,43 @@ public void writeStringUTF16(final byte[] value) {
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) {
Expand Down Expand Up @@ -2955,45 +2974,55 @@ private void writeQuote() {
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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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.*;

Expand All @@ -20,51 +18,12 @@ public void writeString(String str) {
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) {
Expand Down
Loading

0 comments on commit ee1f670

Please sign in to comment.