Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

Intern Property instances so reference equality is guaranteed #22

Open
wants to merge 9 commits into
base: 1.16.x
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package me.jellysquid.mods.hydrogen.common.state.property;

import net.minecraft.state.property.Property;

import java.lang.ref.WeakReference;
import java.util.WeakHashMap;

public class WeakPropertyCache {

/**
* Values are {@link WeakReference} because values in {@link WeakHashMap} are strongly-referenced by default.
*/
private static final WeakHashMap<Property<?>, WeakReference<Property<?>>> CACHE = new WeakHashMap<>();

/**
* Caches properties passed into it in a {@link WeakHashMap}.
*
* @param newProperty the property to cache
* @param <T> the property type (checked by the property's equals method)
* @return the cached property
*/
@SuppressWarnings("unchecked")
public static <T extends Property<?>> T tryCacheProperty(T newProperty) {
// Synchronized to prevent interleaving of separated contains-put pattern
synchronized (CACHE) {
T cachedProperty = (T) CACHE.computeIfAbsent(newProperty, WeakReference::new).get();

// Check if the reference was cleared by GC before WeakReference::get() was called.
if (cachedProperty == null) {
CACHE.put(newProperty, new WeakReference<>(newProperty));
return newProperty;
} else {
return cachedProperty;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.jellysquid.mods.hydrogen.mixin.state.property;

import me.jellysquid.mods.hydrogen.common.state.property.WeakPropertyCache;
import net.minecraft.state.property.BooleanProperty;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(BooleanProperty.class)
public class MixinBooleanProperty {
@Inject(method = "of", at = @At("TAIL"), cancellable = true)
private static void internOf(CallbackInfoReturnable<BooleanProperty> cir) {
cir.setReturnValue(WeakPropertyCache.tryCacheProperty(cir.getReturnValue()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.jellysquid.mods.hydrogen.mixin.state.property;

import me.jellysquid.mods.hydrogen.common.state.property.WeakPropertyCache;
import net.minecraft.state.property.DirectionProperty;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(DirectionProperty.class)
public class MixinDirectionProperty {
@Inject(method = "of(Ljava/lang/String;Ljava/util/Collection;)Lnet/minecraft/state/property/DirectionProperty;", at = @At("TAIL"), cancellable = true)
private static void internOf(CallbackInfoReturnable<DirectionProperty> cir) {
cir.setReturnValue(WeakPropertyCache.tryCacheProperty(cir.getReturnValue()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.jellysquid.mods.hydrogen.mixin.state.property;

import me.jellysquid.mods.hydrogen.common.state.property.WeakPropertyCache;
import net.minecraft.state.property.EnumProperty;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(EnumProperty.class)
public class MixinEnumProperty {
@Inject(method = "of(Ljava/lang/String;Ljava/lang/Class;Ljava/util/Collection;)Lnet/minecraft/state/property/EnumProperty;", at = @At("TAIL"), cancellable = true)
private static void internOf(CallbackInfoReturnable<EnumProperty<?>> cir) {
cir.setReturnValue(WeakPropertyCache.tryCacheProperty(cir.getReturnValue()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.jellysquid.mods.hydrogen.mixin.state.property;

import me.jellysquid.mods.hydrogen.common.state.property.WeakPropertyCache;
import net.minecraft.state.property.IntProperty;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(IntProperty.class)
public class MixinIntProperty {
@Inject(method = "of", at = @At("TAIL"), cancellable = true)
private static void internOf(CallbackInfoReturnable<IntProperty> cir) {
cir.setReturnValue(WeakPropertyCache.tryCacheProperty(cir.getReturnValue()));
}
}
8 changes: 6 additions & 2 deletions src/main/resources/hydrogen.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
"chunk.MixinChunkSerializer",
"chunk.MixinWorldChunk",
"nbt.MixinCompoundTag",
"state.MixinState"
"state.MixinState",
"state.property.MixinBooleanProperty",
"state.property.MixinDirectionProperty",
"state.property.MixinEnumProperty",
"state.property.MixinIntProperty"
]
}
}