Index: fop
===================================================================
--- fop	(revision 479586)
+++ fop	(working copy)
@@ -243,7 +243,11 @@
 
 # Execute FOP using eval/exec to preserve spaces in paths,
 # java options, and FOP args
-fop_exec_command="exec \"$JAVACMD\" $LOGCHOICE $LOGLEVEL -classpath \"$LOCALCLASSPATH\" $FOP_OPTS org.apache.fop.cli.Main $fop_exec_args"
+
+# JMP: -Xrunjmp
+# Hat: -Xrunhprof:file=dump.hprof,format=b
+
+fop_exec_command="exec \"$JAVACMD\" -Xrunhprof:file=dump.hprof,format=b $LOGCHOICE $LOGLEVEL -classpath \"$LOCALCLASSPATH\" $FOP_OPTS org.apache.fop.cli.Main $fop_exec_args"
 if $fop_exec_debug ; then
     echo $fop_exec_command
 fi
Index: src/java/org/apache/fop/fo/properties/EnumProperty.java
===================================================================
--- src/java/org/apache/fop/fo/properties/EnumProperty.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/EnumProperty.java	(working copy)
@@ -23,6 +23,9 @@
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.expr.PropertyException;
 
+import java.util.Map;
+import java.util.WeakHashMap;
+
 /**
  * Superclass for properties that wrap an enumeration value
  */
@@ -62,18 +65,31 @@
         }
     }
 
-    private int value;
-    private String text;
+    private static final Map propertyCache = new WeakHashMap();
 
+    private final int value;
+    private final String text;
+
     /**
      * @param explicitValue enumerated value to be set for this property
      * @param text the string value of the enum.
      */
-    public EnumProperty(int explicitValue, String text) {
+    private EnumProperty(int explicitValue, String text) {
         this.value = explicitValue;
         this.text = text;
     }
 
+    public static EnumProperty getInstance(int explicitValue, String text) {
+        EnumProperty ep = new EnumProperty(explicitValue, text);
+        EnumProperty cacheEntry = (EnumProperty)propertyCache.get(ep);
+        if (cacheEntry == null) {
+            propertyCache.put(ep, ep);
+            return ep;
+        } else {
+            return cacheEntry;
+        }
+    }
+
     /**
      * @return this.value
      */
@@ -88,5 +104,19 @@
         return text;
     }
 
+    public boolean equals(Object obj) {
+        if (obj instanceof EnumProperty) {
+            EnumProperty ep = (EnumProperty)obj;
+            return ep.value == this.value &&
+                ((ep.text == null && this.text == null)
+                 || ep.text.equals(this.text));
+        } else {
+            return false;
+        }
+    }
+
+    public int hashCode() {
+        return value + text.hashCode();
+    }
 }
 
Index: src/java/org/apache/fop/fo/properties/PageBreakShorthandParser.java
===================================================================
--- src/java/org/apache/fop/fo/properties/PageBreakShorthandParser.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/PageBreakShorthandParser.java	(working copy)
@@ -49,11 +49,11 @@
                 || propId == Constants.PR_BREAK_AFTER) {
             switch (property.getEnum()) {
             case Constants.EN_ALWAYS:
-                return new EnumProperty(Constants.EN_PAGE, "PAGE");
+                return EnumProperty.getInstance(Constants.EN_PAGE, "PAGE");
             case Constants.EN_LEFT:
-                return new EnumProperty(Constants.EN_EVEN_PAGE, "EVEN_PAGE");
+                return EnumProperty.getInstance(Constants.EN_EVEN_PAGE, "EVEN_PAGE");
             case Constants.EN_RIGHT:
-                return new EnumProperty(Constants.EN_ODD_PAGE, "ODD_PAGE");
+                return EnumProperty.getInstance(Constants.EN_ODD_PAGE, "ODD_PAGE");
             case Constants.EN_AVOID:
             default:
                 //nop;
Index: src/java/org/apache/fop/fo/properties/VerticalAlignShorthandParser.java
===================================================================
--- src/java/org/apache/fop/fo/properties/VerticalAlignShorthandParser.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/VerticalAlignShorthandParser.java	(working copy)
@@ -40,101 +40,101 @@
             case EN_BASELINE:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_BASELINE, "BASELINE");
+                        return EnumProperty.getInstance(EN_BASELINE, "BASELINE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_BASELINE, "BASELINE"));
+                        return new EnumLength(EnumProperty.getInstance(EN_BASELINE, "BASELINE"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             case EN_TOP:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_BEFORE_EDGE, "BEFORE_EDGE");
+                        return EnumProperty.getInstance(EN_BEFORE_EDGE, "BEFORE_EDGE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_BASELINE, "BASELINE"));
+                        return new EnumLength(EnumProperty.getInstance(EN_BASELINE, "BASELINE"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             case EN_TEXT_TOP:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_TEXT_BEFORE_EDGE, "TEXT_BEFORE_EDGE");
+                        return EnumProperty.getInstance(EN_TEXT_BEFORE_EDGE, "TEXT_BEFORE_EDGE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_BASELINE, "BASELINE"));
+                        return new EnumLength(EnumProperty.getInstance(EN_BASELINE, "BASELINE"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             case EN_MIDDLE:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_MIDDLE, "MIDDLE");
+                        return EnumProperty.getInstance(EN_MIDDLE, "MIDDLE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_BASELINE, "BASELINE"));
+                        return new EnumLength(EnumProperty.getInstance(EN_BASELINE, "BASELINE"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             case EN_BOTTOM:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_AFTER_EDGE, "AFTER_EDGE");
+                        return EnumProperty.getInstance(EN_AFTER_EDGE, "AFTER_EDGE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_BASELINE, "BASELINE"));
+                        return new EnumLength(EnumProperty.getInstance(EN_BASELINE, "BASELINE"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             case EN_TEXT_BOTTOM:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_TEXT_AFTER_EDGE, "TEXT_AFTER_EDGE");
+                        return EnumProperty.getInstance(EN_TEXT_AFTER_EDGE, "TEXT_AFTER_EDGE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_BASELINE, "BASELINE"));
+                        return new EnumLength(EnumProperty.getInstance(EN_BASELINE, "BASELINE"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             case EN_SUB:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_BASELINE, "BASELINE");
+                        return EnumProperty.getInstance(EN_BASELINE, "BASELINE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_SUB, "SUB"));
+                        return new EnumLength(EnumProperty.getInstance(EN_SUB, "SUB"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             case EN_SUPER:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_BASELINE, "BASELINE");
+                        return EnumProperty.getInstance(EN_BASELINE, "BASELINE");
                     case PR_ALIGNMENT_ADJUST:
-                        return new EnumLength(new EnumProperty(EN_AUTO, "AUTO"));
+                        return new EnumLength(EnumProperty.getInstance(EN_AUTO, "AUTO"));
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_SUPER, "SUPER"));
+                        return new EnumLength(EnumProperty.getInstance(EN_SUPER, "SUPER"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
             default:
                 switch (propId) {
                     case PR_ALIGNMENT_BASELINE:
-                        return new EnumProperty(EN_BASELINE, "BASELINE");
+                        return EnumProperty.getInstance(EN_BASELINE, "BASELINE");
                     case PR_ALIGNMENT_ADJUST:
                         return property;
                     case PR_BASELINE_SHIFT:
-                        return new EnumLength(new EnumProperty(EN_BASELINE, "BASELINE"));
+                        return new EnumLength(EnumProperty.getInstance(EN_BASELINE, "BASELINE"));
                     case PR_DOMINANT_BASELINE:
-                        return new EnumProperty(EN_AUTO, "AUTO");
+                        return EnumProperty.getInstance(EN_AUTO, "AUTO");
                 }
         }
         return null;
Index: src/java/org/apache/fop/fo/properties/EnumNumber.java
===================================================================
--- src/java/org/apache/fop/fo/properties/EnumNumber.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/EnumNumber.java	(working copy)
@@ -19,17 +19,32 @@
  
 package org.apache.fop.fo.properties;
 
+import java.util.Map;
+import java.util.WeakHashMap;
+
 /**
  * A number quantity in XSL which is specified as an enum, such as "no-limit".
  */
 public class EnumNumber extends NumberProperty {
-    private Property enumProperty;
+
+    private static final Map cache = new WeakHashMap();
+
+    private final EnumProperty enumProperty;
     
-    public EnumNumber(Property enumProperty) {
+    private EnumNumber(EnumProperty enumProperty) {
         super(null);
         this.enumProperty = enumProperty;
     }
 
+    public static EnumNumber getInstance(Property enumProperty) {
+        EnumNumber en = (EnumNumber)cache.get(enumProperty);
+        if (en == null) {
+            en = new EnumNumber((EnumProperty)enumProperty);
+            cache.put(enumProperty, en);
+        }
+        return en;
+    }
+
     public int getEnum() {
         return enumProperty.getEnum();
     }
Index: src/java/org/apache/fop/fo/properties/PositionShorthandParser.java
===================================================================
--- src/java/org/apache/fop/fo/properties/PositionShorthandParser.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/PositionShorthandParser.java	(working copy)
@@ -41,11 +41,11 @@
             switch (propVal) {
             case Constants.EN_STATIC:
             case Constants.EN_RELATIVE:
-                return new EnumProperty(Constants.EN_AUTO, "AUTO");
+                return EnumProperty.getInstance(Constants.EN_AUTO, "AUTO");
             case Constants.EN_ABSOLUTE:
-                return new EnumProperty(Constants.EN_ABSOLUTE, "ABSOLUTE");
+                return EnumProperty.getInstance(Constants.EN_ABSOLUTE, "ABSOLUTE");
             case Constants.EN_FIXED:
-                return new EnumProperty(Constants.EN_FIXED, "FIXED");
+                return EnumProperty.getInstance(Constants.EN_FIXED, "FIXED");
             default:
                 //nop
             }
@@ -53,13 +53,13 @@
         if (propId == Constants.PR_RELATIVE_POSITION) {
             switch (propVal) {
             case Constants.EN_STATIC:
-                return new EnumProperty(Constants.EN_STATIC, "STATIC");
+                return EnumProperty.getInstance(Constants.EN_STATIC, "STATIC");
             case Constants.EN_RELATIVE:
-                return new EnumProperty(Constants.EN_RELATIVE, "RELATIVE");
+                return EnumProperty.getInstance(Constants.EN_RELATIVE, "RELATIVE");
             case Constants.EN_ABSOLUTE:
-                return new EnumProperty(Constants.EN_STATIC, "STATIC");
+                return EnumProperty.getInstance(Constants.EN_STATIC, "STATIC");
             case Constants.EN_FIXED:
-                return new EnumProperty(Constants.EN_STATIC, "STATIC");
+                return EnumProperty.getInstance(Constants.EN_STATIC, "STATIC");
             default:
                 //nop
             }
Index: src/java/org/apache/fop/fo/properties/NumberProperty.java
===================================================================
--- src/java/org/apache/fop/fo/properties/NumberProperty.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/NumberProperty.java	(working copy)
@@ -58,7 +58,7 @@
                 return p;
             }
             if (p instanceof EnumProperty) {
-                return new EnumNumber(p);
+                return EnumNumber.getInstance(p);
             }
             Number val = p.getNumber();
             if (val != null) {
Index: src/java/org/apache/fop/fo/properties/LineHeightPropertyMaker.java
===================================================================
--- src/java/org/apache/fop/fo/properties/LineHeightPropertyMaker.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/LineHeightPropertyMaker.java	(working copy)
@@ -54,9 +54,9 @@
          */
         Property p = super.make(propertyList, value, fo);
         p.getSpace().setConditionality(
-                new EnumProperty(Constants.EN_RETAIN, "RETAIN"), true);
+                EnumProperty.getInstance(Constants.EN_RETAIN, "RETAIN"), true);
         p.getSpace().setPrecedence(
-                new EnumProperty(Constants.EN_FORCE, "FORCE"), true);
+                EnumProperty.getInstance(Constants.EN_FORCE, "FORCE"), true);
         return p;
     }
     
Index: src/java/org/apache/fop/fo/properties/SpacePropertyMaker.java
===================================================================
--- src/java/org/apache/fop/fo/properties/SpacePropertyMaker.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/SpacePropertyMaker.java	(working copy)
@@ -43,7 +43,7 @@
         Property prop = super.compute(propertyList);
         if (prop != null && prop instanceof SpaceProperty) {
             ((SpaceProperty)prop).setConditionality(
-                    new EnumProperty(Constants.EN_RETAIN, "RETAIN"), false);
+                    EnumProperty.getInstance(Constants.EN_RETAIN, "RETAIN"), false);
         }
         return prop;
     }
Index: src/java/org/apache/fop/fo/properties/WhiteSpaceShorthandParser.java
===================================================================
--- src/java/org/apache/fop/fo/properties/WhiteSpaceShorthandParser.java	(revision 479586)
+++ src/java/org/apache/fop/fo/properties/WhiteSpaceShorthandParser.java	(working copy)
@@ -42,17 +42,17 @@
             switch (propId) {
             case Constants.PR_LINEFEED_TREATMENT:
             case Constants.PR_WHITE_SPACE_TREATMENT:
-                return new EnumProperty(Constants.EN_PRESERVE, "PRESERVE");
+                return EnumProperty.getInstance(Constants.EN_PRESERVE, "PRESERVE");
             case Constants.PR_WHITE_SPACE_COLLAPSE:
-                return new EnumProperty(Constants.EN_FALSE, "FALSE");
+                return EnumProperty.getInstance(Constants.EN_FALSE, "FALSE");
             case Constants.PR_WRAP_OPTION:
-                return new EnumProperty(Constants.EN_NO_WRAP, "NO_WRAP");
+                return EnumProperty.getInstance(Constants.EN_NO_WRAP, "NO_WRAP");
             default:
                 //nop
             }
         case Constants.EN_NO_WRAP:
             if (propId == Constants.PR_WRAP_OPTION) {
-                return new EnumProperty(Constants.EN_NO_WRAP, "NO_WRAP");
+                return EnumProperty.getInstance(Constants.EN_NO_WRAP, "NO_WRAP");
             }
         case Constants.EN_NORMAL:
         default:
Index: src/java/org/apache/fop/fo/FOPropertyMapping.java
===================================================================
--- src/java/org/apache/fop/fo/FOPropertyMapping.java	(revision 479586)
+++ src/java/org/apache/fop/fo/FOPropertyMapping.java	(working copy)
@@ -265,7 +265,7 @@
             enums = new Property[ENUM_COUNT + 1];
         }
         if (enums[enumValue] == null) {
-            enums[enumValue] = new EnumProperty(enumValue, text);
+            enums[enumValue] = EnumProperty.getInstance(enumValue, text);
         }
         return enums[enumValue];
     }
