mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Code reorganisation to shrink the size of JVM class files.
This commit is contained in:
parent
bfe57c6297
commit
511eb6c0fc
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user