mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
jso: trying to improve optimization of JSWrapper
This commit is contained in:
parent
9c0e3b5e59
commit
eed44998f0
|
@ -553,13 +553,15 @@ class JSClassProcessor {
|
||||||
newInvoke.setLocation(invoke.getLocation());
|
newInvoke.setLocation(invoke.getLocation());
|
||||||
List<Variable> newArgs = new ArrayList<>();
|
List<Variable> newArgs = new ArrayList<>();
|
||||||
if (invoke.getInstance() != null) {
|
if (invoke.getInstance() != null) {
|
||||||
Variable arg = marshaller.wrapArgument(callLocation, invoke.getInstance(),
|
var arg = invoke.getInstance();
|
||||||
ValueType.object(method.getOwnerName()), false);
|
arg = marshaller.wrapArgument(callLocation, arg,
|
||||||
|
ValueType.object(method.getOwnerName()), types.typeOf(arg), false);
|
||||||
newArgs.add(arg);
|
newArgs.add(arg);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < invoke.getArguments().size(); ++i) {
|
for (int i = 0; i < invoke.getArguments().size(); ++i) {
|
||||||
Variable arg = marshaller.wrapArgument(callLocation, invoke.getArguments().get(i),
|
var arg = invoke.getArguments().get(i);
|
||||||
method.parameterType(i), byRefParams[i]);
|
arg = marshaller.wrapArgument(callLocation, invoke.getArguments().get(i),
|
||||||
|
method.parameterType(i), types.typeOf(arg), byRefParams[i]);
|
||||||
newArgs.add(arg);
|
newArgs.add(arg);
|
||||||
}
|
}
|
||||||
newInvoke.setArguments(newArgs.toArray(new Variable[0]));
|
newInvoke.setArguments(newArgs.toArray(new Variable[0]));
|
||||||
|
@ -597,9 +599,10 @@ class JSClassProcessor {
|
||||||
if (propertyName == null) {
|
if (propertyName == null) {
|
||||||
propertyName = cutPrefix(method.getName(), 3);
|
propertyName = cutPrefix(method.getName(), 3);
|
||||||
}
|
}
|
||||||
Variable wrapped = marshaller.wrapArgument(callLocation, invoke.getArguments().get(0),
|
var value = invoke.getArguments().get(0);
|
||||||
method.parameterType(0), false);
|
value = marshaller.wrapArgument(callLocation, value,
|
||||||
addPropertySet(propertyName, invoke.getInstance(), wrapped, invoke.getLocation(), pure);
|
method.parameterType(0), types.typeOf(value), false);
|
||||||
|
addPropertySet(propertyName, invoke.getInstance(), value, invoke.getLocation(), pure);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript property "
|
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript property "
|
||||||
|
@ -616,8 +619,9 @@ class JSClassProcessor {
|
||||||
private boolean processIndexer(MethodReader method, CallLocation callLocation, InvokeInstruction invoke) {
|
private boolean processIndexer(MethodReader method, CallLocation callLocation, InvokeInstruction invoke) {
|
||||||
if (isProperGetIndexer(method.getDescriptor())) {
|
if (isProperGetIndexer(method.getDescriptor())) {
|
||||||
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
|
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
|
||||||
addIndexerGet(invoke.getInstance(), marshaller.wrapArgument(callLocation, invoke.getArguments().get(0),
|
var index = invoke.getArguments().get(0);
|
||||||
method.parameterType(0), false), result, invoke.getLocation());
|
addIndexerGet(invoke.getInstance(), marshaller.wrapArgument(callLocation, index,
|
||||||
|
method.parameterType(0), types.typeOf(index), false), result, invoke.getLocation());
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
result = marshaller.unwrapReturnValue(callLocation, result, method.getResultType(), false,
|
result = marshaller.unwrapReturnValue(callLocation, result, method.getResultType(), false,
|
||||||
canBeOnlyJava(invoke.getReceiver()));
|
canBeOnlyJava(invoke.getReceiver()));
|
||||||
|
@ -626,10 +630,11 @@ class JSClassProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (isProperSetIndexer(method.getDescriptor())) {
|
if (isProperSetIndexer(method.getDescriptor())) {
|
||||||
Variable index = marshaller.wrapArgument(callLocation, invoke.getArguments().get(0),
|
var index = invoke.getArguments().get(0);
|
||||||
method.parameterType(0), false);
|
marshaller.wrapArgument(callLocation, index, method.parameterType(0), types.typeOf(index), false);
|
||||||
Variable value = marshaller.wrapArgument(callLocation, invoke.getArguments().get(1),
|
var value = invoke.getArguments().get(1);
|
||||||
method.parameterType(1), false);
|
value = marshaller.wrapArgument(callLocation, value, method.parameterType(1),
|
||||||
|
types.typeOf(value), false);
|
||||||
addIndexerSet(invoke.getInstance(), index, value, invoke.getLocation());
|
addIndexerSet(invoke.getInstance(), index, value, invoke.getLocation());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -700,8 +705,9 @@ class JSClassProcessor {
|
||||||
invoke.getLocation()));
|
invoke.getLocation()));
|
||||||
newInvoke.setLocation(invoke.getLocation());
|
newInvoke.setLocation(invoke.getLocation());
|
||||||
for (int i = 0; i < invoke.getArguments().size(); ++i) {
|
for (int i = 0; i < invoke.getArguments().size(); ++i) {
|
||||||
Variable arg = marshaller.wrapArgument(callLocation, invoke.getArguments().get(i),
|
var arg = invoke.getArguments().get(i);
|
||||||
method.parameterType(i), byRefParams[i]);
|
arg = marshaller.wrapArgument(callLocation, arg,
|
||||||
|
method.parameterType(i), types.typeOf(arg), byRefParams[i]);
|
||||||
newArguments.add(arg);
|
newArguments.add(arg);
|
||||||
}
|
}
|
||||||
newInvoke.setArguments(newArguments.toArray(new Variable[0]));
|
newInvoke.setArguments(newArguments.toArray(new Variable[0]));
|
||||||
|
@ -906,7 +912,8 @@ class JSClassProcessor {
|
||||||
ExitInstruction exit = new ExitInstruction();
|
ExitInstruction exit = new ExitInstruction();
|
||||||
if (insn.getReceiver() != null) {
|
if (insn.getReceiver() != null) {
|
||||||
replacement.clear();
|
replacement.clear();
|
||||||
exit.setValueToReturn(marshaller.wrap(insn.getReceiver(), callee.getResultType(), null, false));
|
exit.setValueToReturn(marshaller.wrap(insn.getReceiver(), callee.getResultType(), JSType.MIXED,
|
||||||
|
null, false));
|
||||||
block.addAll(replacement);
|
block.addAll(replacement);
|
||||||
}
|
}
|
||||||
block.add(exit);
|
block.add(exit);
|
||||||
|
|
|
@ -147,7 +147,7 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||||
if (method.getResultType() != ValueType.VOID) {
|
if (method.getResultType() != ValueType.VOID) {
|
||||||
invocation.setReceiver(program.createVariable());
|
invocation.setReceiver(program.createVariable());
|
||||||
exit.setValueToReturn(marshaller.wrapArgument(callLocation, invocation.getReceiver(),
|
exit.setValueToReturn(marshaller.wrapArgument(callLocation, invocation.getReceiver(),
|
||||||
method.getResultType(), false));
|
method.getResultType(), JSType.MIXED, false));
|
||||||
basicBlock.addAll(marshallInstructions);
|
basicBlock.addAll(marshallInstructions);
|
||||||
marshallInstructions.clear();
|
marshallInstructions.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ class JSValueMarshaller {
|
||||||
this.replacement = replacement;
|
this.replacement = replacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable wrapArgument(CallLocation location, Variable var, ValueType type, boolean byRef) {
|
Variable wrapArgument(CallLocation location, Variable var, ValueType type, JSType jsType, boolean byRef) {
|
||||||
if (type instanceof ValueType.Object) {
|
if (type instanceof ValueType.Object) {
|
||||||
String className = ((ValueType.Object) type).getClassName();
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
ClassReader cls = classSource.get(className);
|
ClassReader cls = classSource.get(className);
|
||||||
|
@ -66,7 +66,7 @@ class JSValueMarshaller {
|
||||||
return wrapFunctor(location, var, cls);
|
return wrapFunctor(location, var, cls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wrap(var, type, location.getSourceLocation(), byRef);
|
return wrap(var, type, jsType, location.getSourceLocation(), byRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isProperFunctor(ClassReader type) {
|
boolean isProperFunctor(ClassReader type) {
|
||||||
|
@ -98,7 +98,7 @@ class JSValueMarshaller {
|
||||||
return functor;
|
return functor;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable wrap(Variable var, ValueType type, TextLocation location, boolean byRef) {
|
Variable wrap(Variable var, ValueType type, JSType jsType, TextLocation location, boolean byRef) {
|
||||||
if (byRef) {
|
if (byRef) {
|
||||||
InvokeInstruction insn = new InvokeInstruction();
|
InvokeInstruction insn = new InvokeInstruction();
|
||||||
insn.setMethod(JSMethods.ARRAY_DATA);
|
insn.setMethod(JSMethods.ARRAY_DATA);
|
||||||
|
@ -112,14 +112,19 @@ class JSValueMarshaller {
|
||||||
if (type instanceof ValueType.Object) {
|
if (type instanceof ValueType.Object) {
|
||||||
String className = ((ValueType.Object) type).getClassName();
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
if (className.equals("java.lang.Object")) {
|
if (className.equals("java.lang.Object")) {
|
||||||
var unwrapNative = new InvokeInstruction();
|
if (jsType != JSType.NULL && jsType != JSType.JS) {
|
||||||
unwrapNative.setLocation(location);
|
var unwrapNative = new InvokeInstruction();
|
||||||
unwrapNative.setType(InvocationType.SPECIAL);
|
unwrapNative.setLocation(location);
|
||||||
unwrapNative.setMethod(new MethodReference(JSWrapper.class, "javaToJs", Object.class, JSObject.class));
|
unwrapNative.setType(InvocationType.SPECIAL);
|
||||||
unwrapNative.setArguments(var);
|
unwrapNative.setMethod(new MethodReference(JSWrapper.class,
|
||||||
unwrapNative.setReceiver(program.createVariable());
|
"javaToJs", Object.class, JSObject.class));
|
||||||
replacement.add(unwrapNative);
|
unwrapNative.setArguments(var);
|
||||||
return unwrapNative.getReceiver();
|
unwrapNative.setReceiver(program.createVariable());
|
||||||
|
replacement.add(unwrapNative);
|
||||||
|
return unwrapNative.getReceiver();
|
||||||
|
} else {
|
||||||
|
return var;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!className.equals("java.lang.String")) {
|
if (!className.equals("java.lang.String")) {
|
||||||
return var;
|
return var;
|
||||||
|
@ -516,7 +521,7 @@ class JSValueMarshaller {
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable addStringWrap(Variable var, TextLocation location) {
|
Variable addStringWrap(Variable var, TextLocation location) {
|
||||||
return wrap(var, stringType, location, false);
|
return wrap(var, stringType, JSType.MIXED, location, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable addString(String str, TextLocation location) {
|
Variable addString(String str, TextLocation location) {
|
||||||
|
|
|
@ -244,6 +244,6 @@ public final class JSWrapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JSObjects.toString(js);
|
return JSObjects.isUndefined(js) ? "undefined" : JSObjects.toString(js);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,6 +244,53 @@ public class JSWrapperTest {
|
||||||
a = processObject(JSNumber.valueOf(23));
|
a = processObject(JSNumber.valueOf(23));
|
||||||
assertTrue(a instanceof JSString);
|
assertTrue(a instanceof JSString);
|
||||||
assertEquals("number", ((JSString) a).stringValue());
|
assertEquals("number", ((JSString) a).stringValue());
|
||||||
|
|
||||||
|
a = processObject(processObject(new A(24)));
|
||||||
|
assertEquals("A(24)", a.toString());
|
||||||
|
assertTrue(a instanceof A);
|
||||||
|
assertEquals(24, ((A) a).getX());
|
||||||
|
|
||||||
|
a = processObject(identity(processObject(new A(25))));
|
||||||
|
assertEquals("A(25)", a.toString());
|
||||||
|
assertTrue(a instanceof A);
|
||||||
|
assertEquals(25, ((A) a).getX());
|
||||||
|
|
||||||
|
a = processObject(identity(processObject(JSString.valueOf("asd"))));
|
||||||
|
assertEquals("asd", a.toString());
|
||||||
|
assertTrue(a instanceof JSString);
|
||||||
|
assertEquals("asd", ((JSString) a).stringValue());
|
||||||
|
|
||||||
|
a = processObject(processObject(identity(JSString.valueOf("zxc"))));
|
||||||
|
assertEquals("zxc", a.toString());
|
||||||
|
assertTrue(a instanceof JSString);
|
||||||
|
assertEquals("zxc", ((JSString) a).stringValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exportedObject() {
|
||||||
|
var r = new ReturningObject() {
|
||||||
|
@Override
|
||||||
|
public Object get() {
|
||||||
|
var o = createEmpty();
|
||||||
|
setProperty(o, "foo", JSNumber.valueOf(23));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var o = extract(r);
|
||||||
|
var foo = getProperty(o, "foo");
|
||||||
|
assertTrue(foo instanceof JSNumber);
|
||||||
|
assertEquals(JSNumber.valueOf(23), foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setProperty() {
|
||||||
|
var o = createEmpty();
|
||||||
|
callSetProperty(o, JSNumber.valueOf(23));
|
||||||
|
assertEquals(JSNumber.valueOf(23), getProperty(o, "foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void callSetProperty(Object instance, Object o) {
|
||||||
|
setProperty(instance, "foo", o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@JSBody(script = "return null;")
|
@JSBody(script = "return null;")
|
||||||
|
@ -255,6 +302,22 @@ public class JSWrapperTest {
|
||||||
@JSBody(params = "o", script = "return typeof o === 'number' ? 'number' : o;")
|
@JSBody(params = "o", script = "return typeof o === 'number' ? 'number' : o;")
|
||||||
private static native Object processObject(Object o);
|
private static native Object processObject(Object o);
|
||||||
|
|
||||||
|
private Object identity(Object o) {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JSBody(params = { "o", "name" }, script = "return o[name];")
|
||||||
|
private static native Object getProperty(Object o, String name);
|
||||||
|
|
||||||
|
@JSBody(params = { "o", "name", "value" }, script = "o[name] = value;")
|
||||||
|
private static native void setProperty(Object o, String name, Object value);
|
||||||
|
|
||||||
|
@JSBody(script = "return {};")
|
||||||
|
private static native Object createEmpty();
|
||||||
|
|
||||||
|
@JSBody(params = "o", script = "return o.get();")
|
||||||
|
private static native Object extract(ReturningObject o);
|
||||||
|
|
||||||
static class A {
|
static class A {
|
||||||
private int x;
|
private int x;
|
||||||
|
|
||||||
|
@ -271,4 +334,8 @@ public class JSWrapperTest {
|
||||||
return "A(" + x + ")";
|
return "A(" + x + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ReturningObject extends JSObject {
|
||||||
|
Object get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user