in core/src/main/java/com/alibaba/fastjson2/writer/ObjectWriterCreatorASM.java [4495:4794]
private FieldWriter jitFieldWriterList(
ObjectWriterProvider provider,
String fieldName,
int ordinal,
long features,
String format,
String label,
Field field,
Class<?> contentAs,
Type itemType,
Type fieldType,
Class<?> fieldClass
) {
boolean direct = false;
List<FieldWriter> fieldWriters = null;
Class<?> itemClass = TypeUtils.getClass(itemType);
if (itemClass != null && field != null && field.getDeclaringClass() != itemClass) {
ObjectWriter fieldValueWriter = provider.getObjectWriterFromCache(itemType, itemClass, FieldBased.isEnabled(features));
if (fieldValueWriter == null && itemClass != null) {
fieldValueWriter = super.createObjectWriter(itemClass, features, provider);
}
fieldWriters = fieldValueWriter.getFieldWriters();
List<FieldWriterGroup> groups = buildGroups(fieldValueWriter.getFeatures(), fieldWriters);
if (groups.size() == 1 && groups.get(0).direct) {
direct = true;
}
for (FieldWriter fieldWriter : fieldWriters) {
if (fieldWriter.method == null && fieldWriter.field == null && fieldWriter.getFunction() == null) {
direct = false;
break;
}
Class cls = fieldWriter.fieldClass;
if (cls != boolean.class && cls != Boolean.class
&& cls != byte.class && cls != Byte.class
&& cls != short.class && cls != Short.class
&& cls != int.class && cls != Integer.class
&& cls != long.class && cls != Long.class
&& cls != float.class && cls != Float.class
&& cls != double.class && cls != Double.class
&& cls != LocalDate.class && cls != LocalTime.class && cls != LocalDateTime.class
&& cls != OffsetDateTime.class && cls != OffsetTime.class
&& cls != Instant.class
&& cls != UUID.class
) {
direct = false;
break;
}
}
}
if (direct) {
int capacity = 6;
for (FieldWriter fieldWriter : fieldWriters) {
capacity = fieldCapacity(fieldWriter.fieldClass);
}
ClassWriter cw = new ClassWriter(null);
String className = "OWF_" + seed.incrementAndGet() + "_" + fieldWriters.size() + "_" + itemClass.getSimpleName();
String classNameType;
String classNameFull;
Package pkg = ObjectWriterCreatorASM.class.getPackage();
if (pkg != null) {
String packageName = pkg.getName();
int packageNameLength = packageName.length();
int charsLength = packageNameLength + 1 + className.length();
char[] chars = new char[charsLength];
packageName.getChars(0, packageName.length(), chars, 0);
chars[packageNameLength] = '.';
className.getChars(0, className.length(), chars, packageNameLength + 1);
classNameFull = new String(chars);
chars[packageNameLength] = '/';
for (int i = 0; i < packageNameLength; ++i) {
if (chars[i] == '.') {
chars[i] = '/';
}
}
classNameType = new String(chars);
} else {
classNameType = className;
classNameFull = className;
}
String supperType = type(FieldWriterListField.class);
cw.visit(Opcodes.V1_8,
Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
classNameType,
supperType,
INTERFACES
);
{
String initDesc = "(Ljava/lang/String;Ljava/lang/reflect/Type;IJLjava/lang/String;Ljava/lang/String;Ljava/lang/reflect/Type;Ljava/lang/Class;Ljava/lang/reflect/Field;Ljava/lang/Class;)V";
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"<init>",
initDesc,
64
);
mw.aload(THIS);
mw.aload(1);
mw.aload(2);
mw.iload(3);
mw.lload(4);
mw.aload(6);
mw.aload(7);
mw.aload(8);
mw.aload(9);
mw.aload(10);
mw.aload(11);
mw.invokespecial(supperType, "<init>", initDesc);
mw.return_();
mw.visitMaxs(12, 12);
}
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"writeListValueJSONB",
METHOD_DESC_WRITE_LIST_VALUE_JSONB,
fieldWriters.size() < 6 ? 512 : 1024
);
MethodWriterContext mwc = new MethodWriterContext(provider, itemClass, features, classNameType, mw, 8, false);
int LIST = 2;
int OFFSET = mwc.var("offset");
int BYTES = mwc.var("bytes");
int FEATURES = mwc.var2(CONTEXT_FEATURES);
int symbolTable = mwc.var("symbolTable");
/*
* int offset = jsonWriter.getOffset();
*/
mw.aload(JSON_WRITER);
mw.invokevirtual(TYPE_JSON_WRITER, "getOffset", "()I");
mw.istore(OFFSET);
mw.aload(JSON_WRITER);
mw.invokevirtual(TYPE_JSON_WRITER, "getFeatures", "()J");
mw.lstore(FEATURES);
Label L_SUPPER = new Label();
if (!provider.isDisableReferenceDetect()) {
/*
* if ((features & ReferenceDetection.mask) != 0) {
* goto L_SUPPER
* }
*/
mw.lload(FEATURES);
mw.visitLdcInsn(ReferenceDetection.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifne(L_SUPPER);
}
mw.aload(JSON_WRITER);
mw.getfield(TYPE_JSON_WRITER, "symbolTable", DESC_SYMBOL);
mw.astore(symbolTable);
int SIZE = mwc.var("size");
mw.aload(LIST);
mw.invokeinterface("java/util/List", "size", "()I");
mw.istore(SIZE);
/*
* byte[] bytes = (byte[]) ensureCapacity(offset + 5 + size * capacity);
*/
mw.aload(JSON_WRITER);
mw.iload(OFFSET);
mw.iconst_5();
mw.iadd();
mw.visitLdcInsn(capacity);
mw.iload(SIZE);
mw.imul();
mw.iadd();
mw.invokevirtual(TYPE_JSON_WRITER, "ensureCapacity", "(I)Ljava/lang/Object;");
mw.checkcast("[B");
mw.astore(BYTES);
/*
* offset = JSONB.IO.startArray(bytes, offset, size);
*/
mw.aload(BYTES);
mw.iload(OFFSET);
mw.iload(SIZE);
mw.invokestatic(TYPE_JSONB_IO, "startArray", "([BII)I", true);
mw.istore(OFFSET);
Label L0 = new Label(), L1 = new Label(), L3 = new Label();
int I = mwc.var("I");
mw.iconst_0();
mw.istore(I);
mw.visitLabel(L0);
mw.iload(I);
mw.iload(SIZE);
mw.if_icmpge(L3);
mw.aload(BYTES);
mw.iload(OFFSET);
mw.visitLdcInsn(fieldWriters.size());
mw.invokestatic(TYPE_JSONB_IO, "startArray", "([BII)I", true);
mw.istore(OFFSET);
int ITEM = mwc.var("ITEM");
mw.aload(LIST);
mw.iload(I);
mw.invokeinterface("java/util/List", "get", "(I)Ljava/lang/Object;");
mw.astore(ITEM);
{
/*
* if (item == null) {
* bytes[off++] = BC_NULL;
* }
*/
// bytes[off] = BC_NULL
mw.aload(ITEM);
mw.ifnonnull(L1);
mw.aload(BYTES);
mw.iload(OFFSET);
mw.bipush(BC_NULL);
mw.bastore();
mw.visitIincInsn(OFFSET, 1);
mw.goto_(L0);
mw.visitLabel(L1);
}
{
mw.aload(ITEM);
mw.invokevirtual(TYPE_OBJECT, "getClass", "()Ljava/lang/Class;");
mw.aload(THIS);
mw.getfield(TYPE_FIELD_WRITER, "fieldClass", "Ljava/lang/Class;");
mw.if_acmpeq(L_SUPPER);
}
for (int i = 0; i < fieldWriters.size(); i++) {
FieldWriter fieldWriter = fieldWriters.get(i);
writeFieldValueDirectJSONB(features, classNameType, mwc, fieldWriter, i, mw, BYTES, OFFSET, ITEM, FEATURES, symbolTable, false);
}
mw.visitIincInsn(I, 1);
mw.goto_(L0);
mw.visitLabel(L3);
mw.aload(JSON_WRITER);
mw.iload(OFFSET);
mw.invokevirtual(TYPE_JSON_WRITER, "setOffset", "(I)V");
mw.return_();
mw.visitLabel(L_SUPPER);
mw.aload(THIS);
mw.aload(JSON_WRITER);
mw.aload(LIST);
mw.invokespecial(type(FieldWriterList.class), "writeListValueJSONB", METHOD_DESC_WRITE_LIST_VALUE_JSONB);
mw.return_();
mw.visitMaxs(mwc.maxVariant + 1, mwc.maxVariant + 1);
byte[] code = cw.toByteArray();
Class<?> deserClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
try {
Constructor<?> constructor = deserClass.getConstructor(
String.class,
Type.class,
int.class,
long.class,
String.class,
String.class,
Type.class,
Class.class,
Field.class,
Class.class
);
return (FieldWriterListField) constructor.newInstance(
fieldName,
itemType,
ordinal,
features,
format,
label,
fieldType,
fieldClass,
field,
contentAs
);
} catch (Throwable e) {
throw new JSONException("create objectWriter error, objectType " + itemClass, e);
}
}
return null;
}