in java/fury-core/src/main/java/org/apache/fury/builder/BaseObjectCodecBuilder.java [1734:1831]
protected Expression deserializeForMap(
Expression buffer, TypeRef<?> typeRef, Expression serializer, InvokeHint invokeHint) {
Tuple2<TypeRef<?>, TypeRef<?>> keyValueType = TypeUtils.getMapKeyValueType(typeRef);
TypeRef<?> keyType = keyValueType.f0;
TypeRef<?> valueType = keyValueType.f1;
if (serializer == null) {
Class<?> cls = getRawType(typeRef);
if (isMonomorphic(cls)) {
serializer = getOrCreateSerializer(cls);
} else {
Expression classInfo = readClassInfo(cls, buffer);
serializer = invoke(classInfo, "getSerializer", "mapSerializer", MAP_SERIALIZER_TYPE);
}
} else {
checkArgument(
AbstractMapSerializer.class.isAssignableFrom(serializer.type().getRawType()),
"Expected AbstractMapSerializer but got %s",
serializer.type());
}
Expression mapSerializer = serializer;
Invoke supportHook = inlineInvoke(serializer, "supportCodegenHook", PRIMITIVE_BOOLEAN_TYPE);
ListExpression expressions = new ListExpression();
Expression newMap = new Invoke(serializer, "newMap", MAP_TYPE, buffer);
Expression size = new Invoke(serializer, "getAndClearNumElements", "size", PRIMITIVE_INT_TYPE);
Expression chunkHeader =
new If(
eq(size, ofInt(0)),
ofInt(0),
inlineInvoke(buffer, "readUnsignedByte", PRIMITIVE_INT_TYPE));
expressions.add(newMap, size, chunkHeader);
Class<?> keyCls = keyType.getRawType();
Class<?> valueCls = valueType.getRawType();
boolean keyMonomorphic = isMonomorphic(keyCls);
boolean valueMonomorphic = isMonomorphic(valueCls);
boolean refKey = needWriteRef(keyType);
boolean refValue = needWriteRef(valueType);
boolean inline = keyMonomorphic && valueMonomorphic && (!refKey || !refValue);
Tuple2<Expression, Expression> mapKVSerializer = getMapKVSerializer(keyCls, valueCls);
Expression keySerializer = mapKVSerializer.f0;
Expression valueSerializer = mapKVSerializer.f1;
While chunksLoop =
new While(
gt(size, ofInt(0)),
() -> {
ListExpression exprs = new ListExpression();
String method = "readJavaNullChunk";
if (keyMonomorphic && valueMonomorphic) {
if (!refKey && !refValue) {
method = "readNullChunkKVFinalNoRef";
}
}
Expression sizeAndHeader =
new Invoke(
mapSerializer,
method,
"sizeAndHeader",
PRIMITIVE_LONG_TYPE,
false,
buffer,
newMap,
chunkHeader,
size,
keySerializer,
valueSerializer);
exprs.add(
new Assign(
chunkHeader, cast(bitand(sizeAndHeader, ofInt(0xff)), PRIMITIVE_INT_TYPE)),
new Assign(size, cast(shift(">>>", sizeAndHeader, 8), PRIMITIVE_INT_TYPE)));
exprs.add(new If(eq(size, ofInt(0)), new Break()));
Expression sizeAndHeader2 =
readChunk(buffer, newMap, size, keyType, valueType, chunkHeader);
if (inline) {
exprs.add(sizeAndHeader2);
} else {
exprs.add(
new Assign(
chunkHeader, cast(bitand(sizeAndHeader2, ofInt(0xff)), PRIMITIVE_INT_TYPE)),
new Assign(size, cast(shift(">>>", sizeAndHeader2, 8), PRIMITIVE_INT_TYPE)));
}
return exprs;
});
expressions.add(chunksLoop, newMap);
// first newMap to create map, last newMap as expr value
Expression map = inlineInvoke(serializer, "onMapRead", OBJECT_TYPE, expressions);
Expression action =
new If(supportHook, map, new Invoke(serializer, "read", OBJECT_TYPE, buffer), false);
if (invokeHint != null && invokeHint.genNewMethod) {
invokeHint.add(buffer);
invokeHint.add(serializer);
return invokeGenerated(
ctx,
invokeHint.cutPoints,
new ListExpression(action, new Return(action)),
"readMap",
false);
}
return action;
}