Code reorganisation to shrink the size of JVM class files.

This commit is contained in:
igor%mir2.org 2004-09-24 13:11:02 +00:00
parent bfe57c6297
commit 511eb6c0fc
2 changed files with 188 additions and 218 deletions

View File

@ -86,8 +86,9 @@ class JavaMembers
if (member == null)
return Scriptable.NOT_FOUND;
}
if (member instanceof Scriptable)
return member; // why is this here?
if (member instanceof Scriptable) {
return member;
}
Context cx = Context.getContext();
Object rval;
Class type;
@ -109,8 +110,8 @@ class JavaMembers
return cx.getWrapFactory().wrap(cx, scope, rval, type);
}
public void put(Scriptable scope, String name, Object javaObject,
Object value, boolean isStatic)
void put(Scriptable scope, String name, Object javaObject,
Object value, boolean isStatic)
{
Hashtable ht = isStatic ? staticMembers : members;
Object member = ht.get(name);
@ -295,19 +296,12 @@ class JavaMembers
private void reflect(Scriptable scope)
{
ClassCache cache = ClassCache.get(scope);
// We reflect methods first, because we want overloaded field/method
// names to be allocated to the NativeJavaMethod before the field
// gets in the way.
reflectMethods(scope);
reflectFields(scope);
makeBeanProperties(scope, false);
makeBeanProperties(scope, true);
reflectCtors(scope);
}
private void reflectMethods(Scriptable scope)
{
Method[] methods = cl.getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
@ -327,8 +321,8 @@ class JavaMembers
overloadedMethods = (ObjArray)value;
} else {
if (!(value instanceof Method)) Kit.codeBug();
// value should be instance of Method as reflectMethods is
// called when staticMembers and members are empty
// value should be instance of Method as at this stage
// staticMembers and members can only contain methods
overloadedMethods = new ObjArray();
overloadedMethods.add(value);
ht.put(name, overloadedMethods);
@ -336,12 +330,39 @@ class JavaMembers
overloadedMethods.add(method);
}
}
initNativeMethods(staticMembers, scope);
initNativeMethods(members, scope);
}
private void reflectFields(Scriptable scope)
{
// replace Method instances by wrapped NativeJavaMethod objects
// first in staticMembers and then in members
for (int tableCursor = 0; tableCursor != 2; ++tableCursor) {
boolean isStatic = (tableCursor == 0);
Hashtable ht = (isStatic) ? staticMembers : members;
Enumeration e = ht.keys();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
MemberBox[] methodBoxes;
Object value = ht.get(name);
if (value instanceof Method) {
methodBoxes = new MemberBox[1];
methodBoxes[0] = new MemberBox((Method)value, cache);
} else {
ObjArray overloadedMethods = (ObjArray)value;
int N = overloadedMethods.size();
if (N < 2) Kit.codeBug();
methodBoxes = new MemberBox[N];
for (int i = 0; i != N; ++i) {
Method method = (Method)overloadedMethods.get(i);
methodBoxes[i] = new MemberBox(method, cache);
}
}
NativeJavaMethod fun = new NativeJavaMethod(methodBoxes);
if (scope != null) {
ScriptRuntime.setFunctionProtoAndParent(scope, fun);
}
ht.put(name, fun);
}
}
// Reflect fields.
Field[] fields = cl.getFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
@ -357,10 +378,19 @@ class JavaMembers
ht.put(name, field);
} else if (member instanceof NativeJavaMethod) {
NativeJavaMethod method = (NativeJavaMethod) member;
FieldAndMethods fam = new FieldAndMethods(scope,
method.methods,
field);
getFieldAndMethodsTable(isStatic).put(name, fam);
FieldAndMethods fam
= new FieldAndMethods(scope, method.methods, field);
Hashtable fmht = isStatic ? staticFieldAndMethods
: fieldAndMethods;
if (fmht == null) {
fmht = new Hashtable(4);
if (isStatic) {
staticFieldAndMethods = fmht;
} else {
fieldAndMethods = fmht;
}
}
fmht.put(name, fam);
ht.put(name, fam);
} else if (member instanceof Field) {
Field oldField = (Field) member;
@ -379,141 +409,95 @@ class JavaMembers
Kit.codeBug();
}
}
}
// Create bean propeties from corresponding get/set methods first for
// static members and then for instance members
for (int tableCursor = 0; tableCursor != 2; ++tableCursor) {
boolean isStatic = (tableCursor == 0);
Hashtable ht = (isStatic) ? staticMembers : members;
private void makeBeanProperties(Scriptable scope, boolean isStatic)
{
Hashtable ht = isStatic ? staticMembers : members;
Hashtable toAdd = new Hashtable();
Hashtable toAdd = new Hashtable();
// Now, For each member, make "bean" properties.
for (Enumeration e = ht.keys(); e.hasMoreElements(); ) {
// Now, For each member, make "bean" properties.
for (Enumeration e = ht.keys(); e.hasMoreElements(); ) {
// Is this a getter?
String name = (String) e.nextElement();
boolean memberIsGetMethod = name.startsWith("get");
boolean memberIsIsMethod = name.startsWith("is");
if (memberIsGetMethod || memberIsIsMethod) {
// Double check name component.
String nameComponent = name.substring(memberIsGetMethod ? 3 : 2);
if (nameComponent.length() == 0)
continue;
// Is this a getter?
String name = (String) e.nextElement();
boolean memberIsGetMethod = name.startsWith("get");
boolean memberIsIsMethod = name.startsWith("is");
if (memberIsGetMethod || memberIsIsMethod) {
// Double check name component.
String nameComponent
= name.substring(memberIsGetMethod ? 3 : 2);
if (nameComponent.length() == 0)
continue;
// Make the bean property name.
String beanPropertyName = nameComponent;
char ch0 = nameComponent.charAt(0);
if (Character.isUpperCase(ch0)) {
if (nameComponent.length() == 1) {
beanPropertyName = nameComponent.toLowerCase();
} else {
char ch1 = nameComponent.charAt(1);
if (!Character.isUpperCase(ch1)) {
beanPropertyName = Character.toLowerCase(ch0)
+nameComponent.substring(1);
}
}
}
// If we already have a member by this name, don't do this
// property.
if (ht.containsKey(beanPropertyName))
continue;
// Get the method by this name.
Object member = ht.get(name);
if (!(member instanceof NativeJavaMethod))
continue;
NativeJavaMethod njmGet = (NativeJavaMethod)member;
MemberBox getter = extractGetMethod(njmGet.methods, isStatic);
if (getter != null) {
// We have a getter. Now, do we have a setter?
NativeJavaMethod njmSet = null;
MemberBox setter = null;
String setterName = "set".concat(nameComponent);
if (ht.containsKey(setterName)) {
// Is this value a method?
member = ht.get(setterName);
if (member instanceof NativeJavaMethod) {
njmSet = (NativeJavaMethod)member;
Class type = getter.method().getReturnType();
setter = extractSetMethod(type, njmSet.methods,
isStatic);
// Make the bean property name.
String beanPropertyName = nameComponent;
char ch0 = nameComponent.charAt(0);
if (Character.isUpperCase(ch0)) {
if (nameComponent.length() == 1) {
beanPropertyName = nameComponent.toLowerCase();
} else {
char ch1 = nameComponent.charAt(1);
if (!Character.isUpperCase(ch1)) {
beanPropertyName = Character.toLowerCase(ch0)
+nameComponent.substring(1);
}
}
}
// Make the property.
BeanProperty bp = new BeanProperty(getter, setter);
toAdd.put(beanPropertyName, bp);
// If we already have a member by this name, don't do this
// property.
if (ht.containsKey(beanPropertyName))
continue;
// Get the method by this name.
Object member = ht.get(name);
if (!(member instanceof NativeJavaMethod))
continue;
NativeJavaMethod njmGet = (NativeJavaMethod)member;
MemberBox getter
= extractGetMethod(njmGet.methods, isStatic);
if (getter != null) {
// We have a getter. Now, do we have a setter?
NativeJavaMethod njmSet = null;
MemberBox setter = null;
String setterName = "set".concat(nameComponent);
if (ht.containsKey(setterName)) {
// Is this value a method?
member = ht.get(setterName);
if (member instanceof NativeJavaMethod) {
njmSet = (NativeJavaMethod)member;
Class type = getter.method().getReturnType();
setter = extractSetMethod(type, njmSet.methods,
isStatic);
}
}
// Make the property.
BeanProperty bp = new BeanProperty(getter, setter);
toAdd.put(beanPropertyName, bp);
}
}
}
// Add the new bean properties.
for (Enumeration e = toAdd.keys(); e.hasMoreElements();) {
Object key = e.nextElement();
Object value = toAdd.get(key);
ht.put(key, value);
}
}
// Add the new bean properties.
for (Enumeration e = toAdd.keys(); e.hasMoreElements();) {
Object key = e.nextElement();
Object value = toAdd.get(key);
ht.put(key, value);
}
}
private void reflectCtors(Scriptable scope)
{
// Reflect constructors
Constructor[] constructors = cl.getConstructors();
int N = constructors.length;
ctors = new MemberBox[N];
ClassCache cache = ClassCache.get(scope);
for (int i = 0; i != N; ++i) {
ctors = new MemberBox[constructors.length];
for (int i = 0; i != constructors.length; ++i) {
ctors[i] = new MemberBox(constructors[i], cache);
}
}
private static void initNativeMethods(Hashtable ht, Scriptable scope)
{
Enumeration e = ht.keys();
ClassCache cache = ClassCache.get(scope);
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
MemberBox[] methods;
Object value = ht.get(name);
if (value instanceof Method) {
methods = new MemberBox[1];
methods[0] = new MemberBox((Method)value, cache);
} else {
ObjArray overloadedMethods = (ObjArray)value;
int N = overloadedMethods.size();
if (N < 2) Kit.codeBug();
methods = new MemberBox[N];
for (int i = 0; i != N; ++i) {
Method method = (Method)overloadedMethods.get(i);
methods[i] = new MemberBox(method, cache);
}
}
NativeJavaMethod fun = new NativeJavaMethod(methods);
if (scope != null) {
fun.setPrototype(ScriptableObject.getFunctionPrototype(scope));
}
ht.put(name, fun);
}
}
private Hashtable getFieldAndMethodsTable(boolean isStatic)
{
Hashtable fmht = isStatic ? staticFieldAndMethods
: fieldAndMethods;
if (fmht == null) {
fmht = new Hashtable(11);
if (isStatic)
staticFieldAndMethods = fmht;
else
fieldAndMethods = fmht;
}
return fmht;
}
private static MemberBox extractGetMethod(MemberBox[] methods,
boolean isStatic)
{

View File

@ -70,39 +70,40 @@ public class NativeJavaMethod extends BaseFunction
this(new MemberBox(method, null), name);
}
private static String scriptSignature(Object value)
{
if (value == null) {
return "null";
} else if (value instanceof Boolean) {
return "boolean";
} else if (value instanceof String) {
return "string";
} else if (value instanceof Number) {
return "number";
} else if (value instanceof Scriptable) {
if (value instanceof Undefined) {
return "undefined";
} else if (value instanceof Wrapper) {
Object wrapped = ((Wrapper)value).unwrap();
return wrapped.getClass().getName();
} else if (value instanceof Function) {
return "function";
} else {
return "object";
}
} else {
return JavaMembers.javaSignature(value.getClass());
}
}
static String scriptSignature(Object[] values)
{
StringBuffer sig = new StringBuffer();
for (int i = 0; i < values.length; i++) {
if (i != 0)
for (int i = 0; i != values.length; ++i) {
Object value = values[i];
String s;
if (value == null) {
s = "null";
} else if (value instanceof Boolean) {
s = "boolean";
} else if (value instanceof String) {
s = "string";
} else if (value instanceof Number) {
s = "number";
} else if (value instanceof Scriptable) {
if (value instanceof Undefined) {
s = "undefined";
} else if (value instanceof Wrapper) {
Object wrapped = ((Wrapper)value).unwrap();
s = wrapped.getClass().getName();
} else if (value instanceof Function) {
s = "function";
} else {
s = "object";
}
} else {
s = JavaMembers.javaSignature(value.getClass());
}
if (i != 0) {
sig.append(',');
sig.append(scriptSignature(values[i]));
}
sig.append(s);
}
return sig.toString();
}
@ -117,7 +118,7 @@ public class NativeJavaMethod extends BaseFunction
sb.append("() {");
}
sb.append("/*\n");
toString(sb);
sb.append(toString());
sb.append(justbody ? "*/\n" : "*/}\n");
return sb.toString();
}
@ -125,12 +126,6 @@ public class NativeJavaMethod extends BaseFunction
public String toString()
{
StringBuffer sb = new StringBuffer();
toString(sb);
return sb.toString();
}
private void toString(StringBuffer sb)
{
for (int i = 0, N = methods.length; i != N; ++i) {
Method method = methods[i].method();
sb.append(JavaMembers.javaSignature(method.getReturnType()));
@ -139,6 +134,7 @@ public class NativeJavaMethod extends BaseFunction
sb.append(JavaMembers.liveConnectSignature(methods[i].argTypes));
sb.append('\n');
}
return sb.toString();
}
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
@ -405,60 +401,50 @@ public class NativeJavaMethod extends BaseFunction
private static int preferSignature(Object[] args,
Class[] sig1, Class[] sig2)
{
int preference = 0;
int totalPreference = 0;
for (int j = 0; j < args.length; j++) {
Class type1 = sig1[j];
Class type2 = sig2[j];
if (type1 == type2) {
continue;
}
Object arg = args[j];
preference |= preferConversion(args[j], type1, type2);
// Determine which of type1, type2 is easier to convert from arg.
if (preference == PREFERENCE_AMBIGUOUS) {
int rank1 = NativeJavaObject.getConversionWeight(arg, type1);
int rank2 = NativeJavaObject.getConversionWeight(arg, type2);
int preference;
if (rank1 < rank2) {
preference = PREFERENCE_FIRST_ARG;
} else if (rank1 > rank2) {
preference = PREFERENCE_SECOND_ARG;
} else {
// Equal ranks
if (rank1 == NativeJavaObject.CONVERSION_NONTRIVIAL) {
if (type1.isAssignableFrom(type2)) {
preference = PREFERENCE_SECOND_ARG;
} else if (type2.isAssignableFrom(type1)) {
preference = PREFERENCE_FIRST_ARG;
} else {
preference = PREFERENCE_AMBIGUOUS;
}
} else {
preference = PREFERENCE_AMBIGUOUS;
}
}
totalPreference |= preference;
if (totalPreference == PREFERENCE_AMBIGUOUS) {
break;
}
}
return preference;
return totalPreference;
}
/**
* Determine which of two types is the easier conversion.
* Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG,
* PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS.
*/
private static int preferConversion(Object fromObj,
Class toClass1, Class toClass2)
{
int rank1 =
NativeJavaObject.getConversionWeight(fromObj, toClass1);
int rank2 =
NativeJavaObject.getConversionWeight(fromObj, toClass2);
if (rank1 == NativeJavaObject.CONVERSION_NONTRIVIAL &&
rank2 == NativeJavaObject.CONVERSION_NONTRIVIAL) {
if (toClass1.isAssignableFrom(toClass2)) {
return PREFERENCE_SECOND_ARG;
}
else if (toClass2.isAssignableFrom(toClass1)) {
return PREFERENCE_FIRST_ARG;
}
}
else {
if (rank1 < rank2) {
return PREFERENCE_FIRST_ARG;
}
else if (rank1 > rank2) {
return PREFERENCE_SECOND_ARG;
}
}
return PREFERENCE_AMBIGUOUS;
}
private static final boolean debug = false;
private static void printDebug(String msg, MemberBox member,