From a892d2d120b37f8c668ba38011333440e0b1e131 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sun, 3 Jun 2007 01:40:53 +0000 Subject: Only invoke adapted properties once during encoding. --- .../carbonado/raw/GenericEncodingStrategy.java | 120 +++++++++++++++++++-- 1 file changed, 110 insertions(+), 10 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java b/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java index 1c9a4e9..d741c08 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java @@ -659,8 +659,54 @@ public class GenericEncodingStrategy { // variable length. Load each property and perform the necessary // tests to determine the exact encoding length. + // Stash of properties which are loaded and locally stored before + // entering the first loop. This avoids having to load them twice. + LocalVariable[] stashedProperties = null; + Boolean[] stashedFromInstances = null; + boolean hasStackVar = false; if (hasVariableLength) { + // Figure out which properties should be locally stashed. + stashedProperties = new LocalVariable[properties.length]; + stashedFromInstances = new Boolean[properties.length]; + + for (int i=0; i property = properties[i]; + StorablePropertyInfo info = infos[i]; + + if (info.getPropertyType() == info.getStorageType()) { + // Property won't be adapted, so loading it twice is no big deal. + continue; + } + + LocalVariable propVar = a.createLocalVariable(null, info.getStorageType()); + stashedProperties[i] = propVar; + + if (doPartial) { + // Initialize the stashed propery to null or zero to make + // the verifier happy. + switch (propVar.getType().getTypeCode()) { + case TypeDesc.OBJECT_CODE: + a.loadNull(); + break; + case TypeDesc.LONG_CODE: + a.loadConstant(0L); + break; + case TypeDesc.FLOAT_CODE: + a.loadConstant(0.0f); + break; + case TypeDesc.DOUBLE_CODE: + a.loadConstant(0.0d); + break; + case TypeDesc.INT_CODE: default: + a.loadConstant(0); + break; + } + + a.storeLocal(propVar); + } + } + Label[] entryPoints = null; if (partialStartVar != null) { @@ -752,7 +798,8 @@ public class GenericEncodingStrategy { hasStackVar = true; } else { // Load property to test for null. - loadPropertyValue(a, info, i, useReadMethods, + loadPropertyValue(stashedProperties, stashedFromInstances, + a, info, i, useReadMethods, instanceVar, adapterInstanceClass, partialStartVar); Label isNull = a.createLabel(); @@ -779,8 +826,8 @@ public class GenericEncodingStrategy { } } } else if (propType == TypeDesc.STRING) { - // Load property to test for null. - loadPropertyValue(a, info, i, useReadMethods, + loadPropertyValue(stashedProperties, stashedFromInstances, + a, info, i, useReadMethods, instanceVar, adapterInstanceClass, partialStartVar); String className = @@ -793,8 +840,8 @@ public class GenericEncodingStrategy { hasStackVar = true; } } else if (propType.toClass() == byte[].class) { - // Load property to test for null. - loadPropertyValue(a, info, i, useReadMethods, + loadPropertyValue(stashedProperties, stashedFromInstances, + a, info, i, useReadMethods, instanceVar, adapterInstanceClass, partialStartVar); String className = @@ -925,7 +972,9 @@ public class GenericEncodingStrategy { } boolean fromInstance = loadPropertyValue - (a, info, i, useReadMethods, instanceVar, adapterInstanceClass, partialStartVar); + (stashedProperties, stashedFromInstances, + a, info, i, useReadMethods, + instanceVar, adapterInstanceClass, partialStartVar); TypeDesc propType = info.getStorageType(); if (!property.isNullable() && propType.toPrimitiveType() != null) { @@ -1016,6 +1065,57 @@ public class GenericEncodingStrategy { return encodedVar; } + /** + * Generates code to load a property value onto the operand stack. + * + * @param info info for property to load + * @param ordinal zero-based property ordinal, used only if instanceVar + * refers to an object array. + * @param useReadMethod when true, access property by public read method + * instead of protected field + * @param instanceVar local variable referencing Storable instance, + * defaults to "this" if null. If variable type is an Object array, then + * property values are read from the runtime value of this array instead + * of a Storable instance. + * @param adapterInstanceClass class containing static references to + * adapter instances - defaults to instanceVar + * @param partialStartVar optional variable for supporting partial key + * generation. It must be an int, whose runtime value must be less than the + * properties array length. It marks the range start of the partial + * property range. + * @return true if property was loaded from instance, false if loaded from + * value array + */ + protected boolean loadPropertyValue(LocalVariable[] stashedProperties, + Boolean[] stashedFromInstances, + CodeAssembler a, + StorablePropertyInfo info, int ordinal, + boolean useReadMethod, + LocalVariable instanceVar, + Class adapterInstanceClass, + LocalVariable partialStartVar) + { + if (stashedFromInstances != null && stashedFromInstances[ordinal] != null) { + a.loadLocal(stashedProperties[ordinal]); + return stashedFromInstances[ordinal]; + } + + boolean fromInstance = loadPropertyValue + (a, info, ordinal, useReadMethod, instanceVar, adapterInstanceClass, partialStartVar); + + if (stashedProperties != null) { + LocalVariable propVar = stashedProperties[ordinal]; + // Stash it for the next time. + if (propVar != null) { + a.storeLocal(propVar); + a.loadLocal(propVar); + stashedFromInstances[ordinal] = fromInstance; + } + } + + return fromInstance; + } + /** * Generates code to load a property value onto the operand stack. * @@ -1044,13 +1144,13 @@ public class GenericEncodingStrategy { Class adapterInstanceClass, LocalVariable partialStartVar) { - TypeDesc type = info.getPropertyType(); - TypeDesc storageType = info.getStorageType(); + final TypeDesc type = info.getPropertyType(); + final TypeDesc storageType = info.getStorageType(); - boolean isObjectArrayInstanceVar = instanceVar != null + final boolean isObjectArrayInstanceVar = instanceVar != null && instanceVar.getType() == TypeDesc.forClass(Object[].class); - boolean useAdapterInstance = adapterInstanceClass != null + final boolean useAdapterInstance = adapterInstanceClass != null && info.getToStorageAdapter() != null && (useReadMethod || isObjectArrayInstanceVar); -- cgit v1.2.3