Two tweaks to improve Array instantiation performance.
1) For reference-type arrays, we no longer need to initialize to 'null' explicitly since 'undefined' works just as well.
2) Instead of caching a protoTypeArray and using for-in to copy expandos, cache the names and values in a pair of arrays. Array iteration is generally faster than for-in. This also uses the "static-initializer-inner-class" pattern to avoid lazy checks and also factor the code out.
Review by: bobv
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3651 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
index 30f3f7e..4e907dc 100644
--- a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
+++ b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
@@ -21,6 +21,55 @@
*/
public final class Array {
+ private static final class ExpandoWrapper {
+ /**
+ * A JS array containing the names of any expandos we need to add to arrays
+ * (such as "hashCode", "equals", "toString").
+ */
+ private static final Object expandoNames = makeEmptyJsArray();
+
+ /**
+ * A JS array containing the values of any expandos we need to add to arrays
+ * (such as hashCode(), equals(), toString()).
+ */
+ private static final Object expandoValues = makeEmptyJsArray();
+
+ static {
+ initExpandos(new Array(), expandoNames, expandoValues);
+ }
+
+ public static void wrapArray(Array array) {
+ wrapArray(array, expandoNames, expandoValues);
+ }
+
+ private static native void initExpandos(Array protoType,
+ Object expandoNames, Object expandoValues) /*-{
+ var i = 0, value;
+ for (var name in protoType) {
+ // Only copy non-null values over; this generally means only functions
+ // will get copied over, and not fields, which is good because we will
+ // setup the fields manually and it's best if length doesn't get blown
+ // away.
+ if (value = protoType[name]) {
+ expandoNames[i] = name;
+ expandoValues[i] = value;
+ ++i;
+ }
+ }
+ }-*/;
+
+ private static native Object makeEmptyJsArray() /*-{
+ return [];
+ }-*/;
+
+ private static native void wrapArray(Array array, Object expandoNames,
+ Object expandoValues) /*-{
+ for (var i = 0, c = expandoNames.length; i < c; ++i) {
+ array[expandoNames[i]] = expandoValues[i];
+ }
+ }-*/;
+ }
+
/*
* TODO: static init instead of lazy init when we can elide the clinit calls.
*/
@@ -34,12 +83,6 @@
static final int ZERO_SEED_TYPE = 1;
/**
- * Stores the prototype Array so that arrays can get their polymorphic methods
- * via expando.
- */
- private static Array protoTypeArray;
-
- /**
* Creates a copy of the specified array.
*/
public static <T> T[] clone(T[] array) {
@@ -123,10 +166,7 @@
*/
public static Array initValues(Class arrayClass, int typeId, int queryId,
Array array) {
- if (protoTypeArray == null) {
- protoTypeArray = new Array();
- }
- wrapArray(array, protoTypeArray);
+ ExpandoWrapper.wrapArray(array);
array.arrayClass = arrayClass;
Util.setTypeId(array, typeId);
array.queryId = queryId;
@@ -151,7 +191,7 @@
private static native Array arraySlice(Array array, int fromIndex, int toIndex) /*-{
return array.slice(fromIndex, toIndex);
}-*/;
-
+
/**
* Use JSNI to effect a castless type change.
*/
@@ -177,11 +217,12 @@
* @return the new JSON array
*/
private static native Array createFromSeed(int seedType, int length) /*-{
- var seedArray = [null, 0, false, [0, 0]];
- var value = seedArray[seedType];
var array = new Array(length);
- for (var i = 0; i < length; ++i) {
- array[i] = value;
+ if (seedType > 0) {
+ var value = [null, 0, false, [0, 0]][seedType];
+ for (var i = 0; i < length; ++i) {
+ array[i] = value;
+ }
}
return array;
}-*/;
@@ -212,23 +253,9 @@
return array[index] = value;
}-*/;
- private static native Array wrapArray(Array array, Array protoTypeArray) /*-{
- for (var i in protoTypeArray) {
- // Only copy non-null values over; this generally means only functions
- // will get copied over, and not fields, which is fine because we will
- // setup the fields manually and it's best if length doesn't get blown
- // away.
- var toCopy = protoTypeArray[i];
- if (toCopy) {
- array[i] = toCopy;
- }
- }
- return array;
- }-*/;
-
/*
* Explicitly initialize all fields to JS false values; see comment in
- * wrapArray(Array, Array).
+ * ExpandoWrapper.initExpandos().
*/
public volatile int length = 0;
protected Class arrayClass = null;