зеркало из https://github.com/mozilla/gecko-dev.git
JavaAdapter.createAdapterCode now takes the function name to function arity instead of Scriptable object. It allows to remove a hack from optimizer/Codegen where it created a temporary Scriptable just to populate it with FunctionNode as a source of arity values thus violating requirement on types of JS values.
The rest of JavaAdapter code is updated to use the ned form of the method as well.
This commit is contained in:
Родитель
0335328a4b
Коммит
b976cc3dce
|
@ -89,10 +89,15 @@ public final class JavaAdapter
|
|||
|
||||
static Object js_createAdpter(Context cx, Scriptable scope, Object[] args)
|
||||
{
|
||||
int N = args.length;
|
||||
if (N == 0) {
|
||||
throw ScriptRuntime.typeError0("msg.adapter.zero.args");
|
||||
}
|
||||
|
||||
Class superClass = null;
|
||||
Class[] intfs = new Class[args.length-1];
|
||||
Class[] intfs = new Class[N - 1];
|
||||
int interfaceCount = 0;
|
||||
for (int i=0; i < args.length-1; i++) {
|
||||
for (int i = 0; i != N - 1; ++i) {
|
||||
Object arg = args[i];
|
||||
if (!(arg instanceof NativeJavaClass)) {
|
||||
throw ScriptRuntime.typeError2("msg.not.java.class.arg",
|
||||
|
@ -116,7 +121,7 @@ public final class JavaAdapter
|
|||
|
||||
Class[] interfaces = new Class[interfaceCount];
|
||||
System.arraycopy(intfs, 0, interfaces, 0, interfaceCount);
|
||||
Scriptable obj = (Scriptable) args[args.length - 1];
|
||||
Scriptable obj = ScriptRuntime.toObject(cx, scope, args[N - 1]);
|
||||
|
||||
JavaAdapterSignature sig;
|
||||
sig = new JavaAdapterSignature(superClass, interfaces, obj);
|
||||
|
@ -126,7 +131,8 @@ public final class JavaAdapter
|
|||
synchronized (generatedClasses) {
|
||||
adapterName = "adapter" + serial++;
|
||||
}
|
||||
byte[] code = createAdapterCode(cx, obj, adapterName,
|
||||
ObjToIntMap names = getObjectFunctionNames(obj);
|
||||
byte[] code = createAdapterCode(names, adapterName,
|
||||
superClass, interfaces, null);
|
||||
|
||||
adapterClass = loadAdapterClass(cx, adapterName, code);
|
||||
|
@ -158,10 +164,11 @@ public final class JavaAdapter
|
|||
synchronized (generatedClasses) {
|
||||
adapterName = "adapter" + serial++;
|
||||
}
|
||||
ObjToIntMap names = getObjectFunctionNames(obj);
|
||||
byte[] code = createAdapterCode(names, adapterName,
|
||||
superClass, interfaces, null);
|
||||
Context cx = Context.enter();
|
||||
try {
|
||||
byte[] code = createAdapterCode(cx, obj, adapterName,
|
||||
superClass, interfaces, null);
|
||||
adapterClass = loadAdapterClass(cx, adapterName, code);
|
||||
generatedClasses.put(sig, adapterClass);
|
||||
} finally {
|
||||
|
@ -185,7 +192,29 @@ public final class JavaAdapter
|
|||
throw new ClassNotFoundException("adapter");
|
||||
}
|
||||
|
||||
public static byte[] createAdapterCode(Context cx, Scriptable jsObj,
|
||||
private static ObjToIntMap getObjectFunctionNames(Scriptable obj)
|
||||
{
|
||||
Object[] ids = ScriptableObject.getPropertyIds(obj);
|
||||
ObjToIntMap map = new ObjToIntMap(ids.length);
|
||||
for (int i = 0; i != ids.length; ++i) {
|
||||
if (!(ids[i] instanceof String))
|
||||
continue;
|
||||
String id = (String) ids[i];
|
||||
Object value = ScriptableObject.getProperty(obj, id);
|
||||
if (value instanceof Function) {
|
||||
Function f = (Function)value;
|
||||
int length = ScriptRuntime.toInt32(
|
||||
ScriptableObject.getProperty(f, "length"));
|
||||
if (length < 0) {
|
||||
length = 0;
|
||||
}
|
||||
map.put(id, length);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static byte[] createAdapterCode(ObjToIntMap functionNames,
|
||||
String adapterName,
|
||||
Class superClass,
|
||||
Class[] interfaces,
|
||||
|
@ -221,14 +250,13 @@ public final class JavaAdapter
|
|||
for (int j = 0; j < methods.length; j++) {
|
||||
Method method = methods[j];
|
||||
int mods = method.getModifiers();
|
||||
if (Modifier.isStatic(mods) || Modifier.isFinal(mods) ||
|
||||
jsObj == null)
|
||||
{
|
||||
if (Modifier.isStatic(mods) || Modifier.isFinal(mods)) {
|
||||
continue;
|
||||
}
|
||||
if (!ScriptableObject.hasProperty(jsObj, method.getName())) {
|
||||
String methodName = method.getName();
|
||||
if (!functionNames.has(methodName)) {
|
||||
try {
|
||||
superClass.getMethod(method.getName(),
|
||||
superClass.getMethod(methodName,
|
||||
method.getParameterTypes());
|
||||
// The class we're extending implements this method and
|
||||
// the JavaScript object doesn't have an override. See
|
||||
|
@ -240,7 +268,6 @@ public final class JavaAdapter
|
|||
}
|
||||
// make sure to generate only one instance of a particular
|
||||
// method/signature.
|
||||
String methodName = method.getName();
|
||||
String methodKey = methodName + getMethodSignature(method);
|
||||
if (! generatedOverrides.has(methodKey)) {
|
||||
generateMethod(cfw, adapterName, methodName,
|
||||
|
@ -266,12 +293,10 @@ public final class JavaAdapter
|
|||
// resulting class won't be instantiable. otherwise, if the object
|
||||
// has a property of the same name, then an override is intended.
|
||||
boolean isAbstractMethod = Modifier.isAbstract(mods);
|
||||
if (isAbstractMethod ||
|
||||
(jsObj != null && ScriptableObject.hasProperty(jsObj,method.getName())))
|
||||
{
|
||||
String methodName = method.getName();
|
||||
if (isAbstractMethod || functionNames.has(methodName)) {
|
||||
// make sure to generate only one instance of a particular
|
||||
// method/signature.
|
||||
String methodName = method.getName();
|
||||
String methodSignature = getMethodSignature(method);
|
||||
String methodKey = methodName + methodSignature;
|
||||
if (! generatedOverrides.has(methodKey)) {
|
||||
|
@ -292,35 +317,20 @@ public final class JavaAdapter
|
|||
}
|
||||
}
|
||||
|
||||
// Generate Java methods, fields for remaining properties that
|
||||
// are not overrides.
|
||||
if (jsObj != null) {
|
||||
Object[] ids = ScriptableObject.getPropertyIds(jsObj);
|
||||
for (int i = 0; i != ids.length; ++i) {
|
||||
if (!(ids[i] instanceof String))
|
||||
// Generate Java methods for remaining properties that are not
|
||||
// overrides.
|
||||
ObjToIntMap.Iterator iter = new ObjToIntMap.Iterator(functionNames);
|
||||
for (iter.start(); !iter.done(); iter.next()) {
|
||||
String functionName = (String)iter.getKey();
|
||||
if (generatedMethods.has(functionName))
|
||||
continue;
|
||||
String id = (String) ids[i];
|
||||
if (generatedMethods.has(id))
|
||||
continue;
|
||||
Object f = ScriptableObject.getProperty(jsObj, id);
|
||||
int length;
|
||||
if (f instanceof Function) {
|
||||
Function p = (Function) f;
|
||||
length = (int) Context.toNumber(
|
||||
ScriptableObject.getProperty(p, "length"));
|
||||
} else if (f instanceof FunctionNode) {
|
||||
// This is used only by optimizer/Codegen
|
||||
length = ((FunctionNode)f).getParamCount();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
int length = iter.getValue();
|
||||
Class[] parms = new Class[length];
|
||||
for (int k=0; k < length; k++)
|
||||
parms[k] = ScriptRuntime.ObjectClass;
|
||||
generateMethod(cfw, adapterName, id, parms,
|
||||
generateMethod(cfw, adapterName, functionName, parms,
|
||||
ScriptRuntime.ObjectClass);
|
||||
}
|
||||
}
|
||||
return cfw.toByteArray();
|
||||
}
|
||||
|
||||
|
@ -655,7 +665,7 @@ public final class JavaAdapter
|
|||
// System.out.flush();
|
||||
cfw.startMethod(methodName, methodSignature,
|
||||
ClassFileWriter.ACC_PUBLIC);
|
||||
cfw.add(ByteCode.BIPUSH, (byte) parms.length); // > 255 parms?
|
||||
cfw.addPush(parms.length);
|
||||
cfw.add(ByteCode.ANEWARRAY, "java/lang/Object");
|
||||
cfw.add(ByteCode.ASTORE, arrayLocal);
|
||||
|
||||
|
|
|
@ -152,21 +152,20 @@ public class Codegen extends Interpreter {
|
|||
|
||||
if (!isPrimary) {
|
||||
String adapterClassName = nameHelper.getScriptClassName(true);
|
||||
ScriptableObject obj = new NativeObject();
|
||||
int functionCount = scriptOrFn.getFunctionCount();
|
||||
ObjToIntMap functionNames = new ObjToIntMap(functionCount);
|
||||
for (int i = 0; i != functionCount; ++i) {
|
||||
OptFunctionNode fn;
|
||||
fn = (OptFunctionNode)scriptOrFn.getFunctionNode(i);
|
||||
FunctionNode fn = scriptOrFn.getFunctionNode(i);
|
||||
String name = fn.getFunctionName();
|
||||
if (name != null && name.length() != 0) {
|
||||
obj.put(fn.getFunctionName(), obj, fn);
|
||||
functionNames.put(name, fn.getParamCount());
|
||||
}
|
||||
}
|
||||
if (superClass == null) {
|
||||
superClass = ScriptRuntime.ObjectClass;
|
||||
}
|
||||
byte[] classFile = JavaAdapter.createAdapterCode(
|
||||
cx, obj, adapterClassName,
|
||||
functionNames, adapterClassName,
|
||||
superClass, interfaces,
|
||||
mainClassName);
|
||||
try {
|
||||
|
|
Загрузка…
Ссылка в новой задаче