Please see robovm.com for more information.
robovm / robovm Goto Github PK
View Code? Open in Web Editor NEWFor more info see
Home Page: http://robovm.com
For more info see
Home Page: http://robovm.com
Please see robovm.com for more information.
Virtual method dispatch is currently done through a method lookup every time a virtual method is invoked. It works but it is slow.
The compiler currently marks every local variable as volatile when a method has one or more exception handler preventing these variables from being allocated in CPU registers. Only local variables that are used within exception handlers or reachable from code in exception handlers actually have to be volatile.
The dalvik tests are located in dalvik/tests in the Android sources. They test low level stuff such as exceptions, the GC and a lot more.
Should be Java_java_lang_Math_abs__F() and Java_java_lang_Math_abs__D()
It would be nice to be able to launch RoboVM compiled JUnit tests from within Eclipse.
In Android NullPointerException is thrown. RoboVM currently throws AssertionError.
Most of the code in rt/ comes from Android's libcore. There are a lot of unit tests in libcore that would be nice to integrate.
These are called by libcore's native code during serialization.
The Maven shade plugin doesn't seem to work properly. It leaves old stuff in the constant pool.
rvmGetHumanReadableClassName() returns nice names for primitive types and arrays
More efficient to call in process and more robust against future bitcode version changes. Candidates known so far are http://code.google.com/p/llvm-j and http://code.google.com/p/jllvm. jllmv seems to be more up-to-date but I like how llvm-j uses BridJ and not JNI like jllvm.
We're currently throwing IllegalAccessException in places where the RI doesn't. The reason is that we're using Class.getModifiers() in AccessibleObject.checkAccessibleFast() and Class.getModifiers() takes an inner class' access flag from its InnerClasses attribute. The RI just uses the direct access flags and ignores the InnerClasses attribute for inner classes when checking access for reflective invocations. See this bug report: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4471811.
Sample code:
import java.util.concurrent.ConcurrentLinkedQueue;
public class HelloWorld {
public static void main(String[] args) {
ConcurrentLinkedQueue strQ = new ConcurrentLinkedQueue();
strQ.add("test add");
System.out.println(strQ.peek());
}
}
after compile, try to run:
[lailin@/tmp/robo/test] $ HelloWorld/HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError:
Segmentation fault: 11
OS: OS X Lion , Detail: Darwin Kernel Version 11.4.2: Thu Aug 23 16:26:45 PDT 2012; root:xnu-1699.32.7~1/RELEASE_I386 i386
We currently use the element type (e.g. foo.Bar) as message while Android uses the array type ([[Lfoo.Bar;)
Add full debug info to LLVM bitcode to enable debugging in GDB/LLDB. Issue #7 adds source file and line number info. We also need type info for classes and local variable info.
The libcore tests have a few tests that fail, e.g. when trying to load a non-existing library or passing null to loadLibrary().
A block is essentially a struct with a function pointer. We should be able to implement that using bro. Here are some articles on how blocks are compiled in Objective-C:
http://www.informit.com/articles/article.aspx?p=1749597&seqNum=12
http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
The RI docs says that ExceptionInInitializerError can be thrown from Class.newInstance() and Constructor.newInstance().
The name is not checked for null in Java and not in native code.
The checkcast
and instanceof
bytecodes result in a search through the super classes and interfaces implemented by the object's class. This can be optimized. One approach would be to record each type a class inherits from or implements and the class itself in some kind of lookup table (maybe a perfect hash table?). A positive lookup means the class is either the same class, inherits from it or implements it. The lookup table could also be used to store interface method table pointers and used to speed up interface method dispatch (see issue #4).
The native code calls close() on the native pipe fd but read()/write() will not be interrupted. Here's a Linux kernel patch (which never got accepted) that describes the problem: http://lkml.indiana.edu/hypermail/linux/kernel/0708.1/1967.html
The Android kernel has probably been patched somehow to support this since it works in Android. The mail linked to above also describes a workaround which involves raising an arbitrary signal. That causes the blocking read()/write() call to wake up and return. The Android code we're using already does this for sockets (AsynchronousSocketCloseMonitor.cpp) so we could probably do something similar for other types of files.
Mac OS X doesn't have this problem and most likely not iOS either. Maybe the AsynchronousSocketCloseMonitor code is unnecessary on Darwin too? We need to test that.
Here's the code that was included in the mail on the LKML that demonstrates the issue and the workaround:
watchdog.c
#include <sys/types.h>
#include <sys/uio.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
int inout[2] = { -1, -1 };
void *watchdog(void *arg)
{
fprintf(stderr, "Sleeping...\n");
sleep(1);
fprintf(stderr, "Closing...\n");
close(inout[0]);
fprintf(stderr, "Closed.\n");
return NULL;
}
void wakeup(int sig)
{
fprintf(stderr, "Alarmed.\n");
}
int main(int argc, char *argv[])
{
pthread_t th;
char buf[1];
ssize_t r;
pipe(inout);
pthread_create(&th, NULL, watchdog, NULL);
signal(SIGALRM, wakeup);
alarm(5);
fprintf(stderr, "Reading...\n");
r = read(inout[0], buf, sizeof(buf));
if (r == -1)
perror("read");
fprintf(stderr, "Read done.\n");
pthread_join(th, NULL);
fprintf(stderr, "Exit.\n");
return 0;
}
The JVM spec permits a class to have multiple methods with the same name and parameter types but different return types. In Java this is used with covariant return type methods. Dalvik returns the first non-synthetic match. We should do too.
Field.getModifiers() masks out ACC_SYNTHETIC and Method.getModifiers() masks out ACC_SYNTHETIC, ACC_BRIDGE and ACC_VARARGS.
Also, classinfo.c does not properly read the MI_SYNTHETIC flag to set the ACC_SYNTHETIC access flag.
The first time a String constant is used it is created and interned. The next time the interned instance is looked up in a LRU hash table and used (if the interned strings table still holds it). We could store a disappearing pointer to the interned String instance where it's used to avoid the table lookup on subsequent accesses to that same String.
The libcore luni tests the format of the error messages.
Compiling a simple "Hello World" scala file gives me two files in classes/
, HelloWorldScala.java
and HelloWorldScala$.java
. Then, to compile it to a binary, I use robovm -verbose -cp scala-library.jar:classes/ HelloWorldScala
. It goes through and compiles a lot of classes, but then eventually gets to scala.concurrent.forkjoin.ForkJoinTask
and fails with this exception:
java.lang.NullPointerException
at soot.jimple.toolkits.annotation.arraycheck.ArrayBoundsCheckerAnalysis.doAnalysis(ArrayBoundsCheckerAnalysis.java:344)
at soot.jimple.toolkits.annotation.arraycheck.ArrayBoundsCheckerAnalysis.<init>(ArrayBoundsCheckerAnalysis.java:135)
at soot.jimple.toolkits.annotation.arraycheck.ArrayBoundsChecker.internalTransform(ArrayBoundsChecker.java:86)
at soot.BodyTransformer.transform(BodyTransformer.java:51)
at soot.Transform.apply(Transform.java:104)
at soot.BodyPack.internalApply(BodyPack.java:49)
at soot.Pack.apply(Pack.java:124)
at org.robovm.compiler.MethodCompiler.doCompile(MethodCompiler.java:228)
at org.robovm.compiler.AbstractMethodCompiler.compile(AbstractMethodCompiler.java:83)
at org.robovm.compiler.ClassCompiler.method(ClassCompiler.java:927)
at org.robovm.compiler.ClassCompiler.compile(ClassCompiler.java:451)
at org.robovm.compiler.ClassCompiler.compile(ClassCompiler.java:257)
at org.robovm.compiler.AppCompiler.compile(AppCompiler.java:204)
at org.robovm.compiler.AppCompiler.compile(AppCompiler.java:220)
at org.robovm.compiler.AppCompiler.main(AppCompiler.java:361)
This is using Scala 2.10 and RoboVM 0.0.1.
Block SIGPIPE signals. Threads calling write() on sockets shutdown for writing will otherwise be sent the SIGPIPE signal. We just want the write() call to return with an error. Dalvik does this too.
Once we have full debug support in GDB/LLDB we could implement a server that embeds GDB/LLDB and talks JDWP with a Java debug client (e.g. an IDE). LLDB seems to be easily embeddable in Python. It is unknown whether GDB/LLDB support enough of the operations required to get a usable JDWP server.
E.g. CET => GMT+01:00. Maybe the ICU 48 code fails to parse this info when using an ICU 49 data file?
In atomic.h we're using __sync_bool_compare_and_swap() and friends on Linux but OSAtomicCompareAndSwap32() and friends on Darwin. I think the reason was that clang didn't implement these earlier. That seems to have changed now so we should be able to use the same code on all platforms.
Compile, test, package RoboVM apps from Maven
We're currently using code from the android-4.1.1_r3 release
Interface method dispatch is currently done through a method lookup every time an interface method is invoked. It works but it is slow. How to do this efficiently is not as straight forward as vtables for virtual method dispatch. It seems to be common to keep one table of methods for each interface a class implements. Once the right interface method table has been located the dispatch proceeds just as with vtables. The problem is to find the correct table in an efficient manner.
ATM we will always check for the library using dlopen() and throw UnsatisfiedLinkError if it cannot be found, even if static JNI is used. If using static JNI we shouldn't even try to dlopen() and loadLibrary() should not throw otherwise callers will have to check for RoboVM and static JNI to know whether the ULE should be ignored.
To link in Objective-C frameworks
Mangler.mangleString(String) in the compiler mangles invalid unicode characters to $3F (ie ?). If two names contain a single but different invalid unicode character they are mangled to the same string which probably results in duplicate symbols in the LLVM IR later on.
E.g.
String.class.getMethod("indexOf", int.class).invoke("hello", 'l')
is legal and the 'l' Character should be unwrapped and converted to an int. At the moment we throw an exception.
Only the parameter types at index>0 are checked for null so if the first type is null NPE is thrown.
Doesn't seem to occur in Linux. E.g.
Exception in thread "main" java.lang.UnsatisfiedLinkError:
at sun.misc.Unsafe.putObject(Native Method)
at sun.misc.Unsafe.putObject(Native Method)
at java.util.concurrent.ConcurrentLinkedQueue$Node.<init>(ConcurrentLinkedQueue.java)
at java.util.concurrent.ConcurrentLinkedQueue.<init>(ConcurrentLinkedQueue.java)
at Hello.main(Hello.java)
Stack traces currently include no line number information. Add source file and line number debug info to the LLVM bitcode and use it at runtime (if not stripped) to get line numbers in stack traces.
I've got SSL support "working for me", but I'm not sure of the right way to incorporate this into robovm.
Android ships a slimmed down BouncyCastle, into com.android.org.bouncycastle...
Using the full bouncycastle works (with some additional class roots), but security.properties needs to be changed to specify the org.bouncycastle namespace rather than the com.android.org.bouncycastle namespace.
Q: Should we include the full bouncycastle or the Android's trimmed down bouncycastle? Or should we create a shim from the com.android.org.bouncycastle provider to the org.bouncycastle provider (just the one class would suffice, I think)?
In addition, the Android KeyStore uses a different format to other keystores. It is quite nice; each trusted CA is hashed and then stored in a hashtable-like directory structure with a CA per file.
Here are the current trusted CAs:
https://android.googlesource.com/platform/libcore/+/master/luni/src/main/files/cacerts/
On android these files are placed in getenv("ANDROID_ROOT")/etc/security/cacerts, which is /system/etc/security/cacerts
Because ANDROID_ROOT is not defined, this works out as "null/etc/security/cacerts" (i.e. a directory named null must be created in the current directory). I think we will want to fix this!
https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStore.java
Q: Is it better to define ANDROID_ROOT, or better to patch TrustedCertificateStore? I'm thinking it is better to define ANDROID_ROOT to be "", as it avoids forking the Android code and should work anywhere ANDROID_ROOT is later used. However, the only other place ANDROID_ROOT currently occurs is in rt/src/main/java/libcore/util/ZoneInfoDB.java, and there the code was patched to check for null.
Using JAVA_HOME or /system as Android does is not good since neither of them have anything to do with RoboVM. Using env->vm->options->basePath is less bad.
Included fruitstrap binary fails with iOS 6. With a working fruitstrap the app still fails with infinite recursion somewhere.
The inline ASM in checkso() clobbers the condition flags register (cc). The org.robovm.rt.bro.Struct$Marshaler.toNative() method:
public static @Pointer long toNative(Object o) {
if (o == null) {
return 0L;
}
return ((Struct<?>) o).getHandle();
}
ARM assembler without cc:
push {r4, r5, r7, lr}
mov r5, r0
add r7, sp, #8
cmp r1, #0
@ InlineAsm Start
mvns r4, #0; lsls r4, r4, #16; ldr r4, [sp, r4]
@ InlineAsm End
ittt eq
moveq r0, #0
moveq r1, #0
popeq {r4, r5, r7, pc}
mov r0, r5
blx _org_robovm_rt_bro_Struct$00_checkcast
mov r1, r0
mov r0, r5
blx _org_robovm_rt_bro_NativeObject$00_getHandle$00__J$00
pop {r4, r5, r7, pc}
and with cc:
push {r4, r5, r7, lr}
@ InlineAsm Start
mvns r4, #0; lsls r4, r4, #16; ldr r4, [sp, r4]
@ InlineAsm End
mov r5, r0
add r7, sp, #8
cmp r1, #0
ittt eq
moveq r0, #0
moveq r1, #0
popeq {r4, r5, r7, pc}
mov r0, r5
blx _org_robovm_rt_bro_Struct$00_checkcast
mov r1, r0
mov r0, r5
blx _org_robovm_rt_bro_NativeObject$00_getHandle$00__J$00
pop {r4, r5, r7, pc}
If r1==null (i.e. Java o==null) the first ASM will not return null but instead try to use the value in r1 as a Struct pointer. The getHandle() method will try to read from address 0x8 and a SIGSEGV will be raised.
The compiler just checks the package names at the moment. So a class in the user classpath could access a package private class in the bootclasspath by using the same package name.
The code which does this check is in Access.java
. We probably need to change this code to use Clazz
instances instead of SootClass
. Given a Clazz
instance it is easy to determine whether it is in the bootclasspath or not.
The libcore tests test this.
The libcore tests test this.
Doesn't Android implement these either? Or did we not translate the function names properly when porting the code from Android?
Java_org_apache_harmony_xnet_provider_jsse_NativeCrypto_i2d_1RSAPrivateKey
Java_org_apache_harmony_xnet_provider_jsse_NativeCrypto_i2d_1DSAPrivateKey
Java_org_apache_harmony_xnet_provider_jsse_NativeCrypto_i2d_1RSAPublicKey
Java_org_apache_harmony_xnet_provider_jsse_NativeCrypto_i2d_1DSAPublicKey
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.