Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save a small amount of allocations during init #17180

Merged
merged 1 commit into from
May 13, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1103,8 +1103,8 @@ private DeferredParameter loadComplexObject(Object param, Map<Object, DeferredPa
//a list of steps that are performed on the object after it has been created
//we need to create all these first, to ensure the required objects have already
//been deserialized
List<SerialzationStep> setupSteps = new ArrayList<>();
List<SerialzationStep> ctorSetupSteps = new ArrayList<>();
List<SerializationStep> setupSteps = new ArrayList<>();
List<SerializationStep> ctorSetupSteps = new ArrayList<>();

boolean relaxedOk = false;
if (param instanceof Collection) {
Expand All @@ -1113,7 +1113,7 @@ private DeferredParameter loadComplexObject(Object param, Map<Object, DeferredPa
DeferredParameter val = i != null
? loadObjectInstance(i, existing, i.getClass(), relaxedValidation)
: loadObjectInstance(null, existing, Object.class, relaxedValidation);
setupSteps.add(new SerialzationStep() {
setupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method, DeferredArrayStoreParameter out) {
//each step can happen in a new method, so it is safe to do this
Expand All @@ -1136,7 +1136,7 @@ public void prepare(MethodContext context) {
DeferredParameter val = i.getValue() != null
? loadObjectInstance(i.getValue(), existing, i.getValue().getClass(), relaxedValidation)
: loadObjectInstance(null, existing, Object.class, relaxedValidation);
setupSteps.add(new SerialzationStep() {
setupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method, DeferredArrayStoreParameter out) {
method.invokeInterfaceMethod(MAP_PUT, context.loadDeferred(out), context.loadDeferred(key),
Expand Down Expand Up @@ -1221,7 +1221,7 @@ public void prepare(MethodContext context) {
params.add(toAdd);

}
setupSteps.add(new SerialzationStep() {
setupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method,
DeferredArrayStoreParameter out) {
Expand Down Expand Up @@ -1261,7 +1261,7 @@ public void prepare(MethodContext context) {
relaxedValidation);
def.put(key, val);
}
setupSteps.add(new SerialzationStep() {
setupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method,
DeferredArrayStoreParameter out) {
Expand Down Expand Up @@ -1337,7 +1337,7 @@ public void prepare(MethodContext context) {
i.getPropertyType(), relaxedValidation);
if (ctorParamIndex != null) {
nonDefaultConstructorHandles[ctorParamIndex] = val;
ctorSetupSteps.add(new SerialzationStep() {
ctorSetupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method, DeferredArrayStoreParameter out) {

Expand All @@ -1350,7 +1350,7 @@ public void prepare(MethodContext context) {
});
} else {
Class finalPropertyType = propertyType;
setupSteps.add(new SerialzationStep() {
setupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method, DeferredArrayStoreParameter out) {
method.invokeVirtualMethod(
Expand Down Expand Up @@ -1389,7 +1389,7 @@ public void prepare(MethodContext context) {
relaxedValidation);
if (ctorParamIndex != null) {
nonDefaultConstructorHandles[ctorParamIndex] = val;
ctorSetupSteps.add(new SerialzationStep() {
ctorSetupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method,
DeferredArrayStoreParameter out) {
Expand All @@ -1402,7 +1402,7 @@ public void prepare(MethodContext context) {
}
});
} else {
setupSteps.add(new SerialzationStep() {
setupSteps.add(new SerializationStep() {
@Override
public void handle(MethodContext context, MethodCreator method,
DeferredArrayStoreParameter out) {
Expand Down Expand Up @@ -1445,24 +1445,34 @@ ResultHandle createValue(MethodContext context, MethodCreator method, ResultHand
Arrays.stream(finalCtorHandles).map(m -> context.loadDeferred(m))
.toArray(ResultHandle[]::new));
} else {
try {
param.getClass().getDeclaredConstructor();
out = method.newInstance(ofConstructor(param.getClass()));
} catch (NoSuchMethodException e) {
//fallback for collection types, such as unmodifiableMap
if (SortedMap.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(TreeMap.class));
} else if (Map.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(LinkedHashMap.class));
} else if (List.class.isAssignableFrom(expectedType)) {
if (List.class.isAssignableFrom(param.getClass())) {
// list is a common special case, so let's handle it
List listParam = (List) param;
if (listParam.isEmpty()) {
out = method.newInstance(ofConstructor(ArrayList.class));
} else if (SortedSet.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(TreeSet.class));
} else if (Set.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(LinkedHashSet.class));
} else {
throw new RuntimeException("Unable to serialize objects of type " + param.getClass()
+ " to bytecode as it has no default constructor");
out = method.newInstance(ofConstructor(ArrayList.class, int.class), method.load(listParam.size()));
}
} else {
try {
param.getClass().getDeclaredConstructor();
out = method.newInstance(ofConstructor(param.getClass()));
} catch (NoSuchMethodException e) {
//fallback for collection types, such as unmodifiableMap
if (SortedMap.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(TreeMap.class));
} else if (Map.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(LinkedHashMap.class));
} else if (List.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(ArrayList.class));
gastaldi marked this conversation as resolved.
Show resolved Hide resolved
} else if (SortedSet.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(TreeSet.class));
} else if (Set.class.isAssignableFrom(expectedType)) {
out = method.newInstance(ofConstructor(LinkedHashSet.class));
} else {
throw new RuntimeException("Unable to serialize objects of type " + param.getClass()
+ " to bytecode as it has no default constructor");
}
}
}
}
Expand All @@ -1477,15 +1487,15 @@ ResultHandle createValue(MethodContext context, MethodCreator method, ResultHand
void doPrepare(MethodContext context) {
//this is where the object construction happens
//first create the actial object
for (SerialzationStep i : ctorSetupSteps) {
for (SerializationStep i : ctorSetupSteps) {
i.prepare(context);
}
objectValue.prepare(context);
for (SerialzationStep i : setupSteps) {
for (SerializationStep i : setupSteps) {
//then prepare the steps (i.e. creating the values to be placed into this object)
i.prepare(context);
}
for (SerialzationStep i : setupSteps) {
for (SerializationStep i : setupSteps) {
//now actually run the steps (i.e. actually stick the values into the object)
context.writeInstruction(new InstructionGroup() {
@Override
Expand Down Expand Up @@ -1792,7 +1802,7 @@ final ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHan
/**
* A step that must be executed to serialize a complex object
*/
interface SerialzationStep {
interface SerializationStep {

void handle(MethodContext context, MethodCreator method, DeferredArrayStoreParameter out);

Expand Down