mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
Merge branch 'master' of git://oss.readytalk.com/avian, fixed problems that occured in broader testing
Conflicts: src/compile.cpp src/compiler.cpp src/powerpc.cpp src/x86.S src/x86.cpp
This commit is contained in:
commit
1d3ef1fc43
16
classpath/avian/Callback.java
Normal file
16
classpath/avian/Callback.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package avian;
|
||||||
|
|
||||||
|
public interface Callback<T> {
|
||||||
|
public void handleResult(T result);
|
||||||
|
public void handleException(Throwable exception);
|
||||||
|
}
|
15
classpath/avian/CallbackReceiver.java
Normal file
15
classpath/avian/CallbackReceiver.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package avian;
|
||||||
|
|
||||||
|
public interface CallbackReceiver<T> {
|
||||||
|
public T receive(Callback<T> callback) throws Exception;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -8,7 +8,7 @@
|
|||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
package java.util;
|
package avian;
|
||||||
|
|
||||||
public class Cell <T> {
|
public class Cell <T> {
|
||||||
public T value;
|
public T value;
|
238
classpath/avian/Continuations.java
Normal file
238
classpath/avian/Continuations.java
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package avian;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides methods to capture continuations and manage
|
||||||
|
* control flow when calling continuations.
|
||||||
|
*
|
||||||
|
* <p>A continuation is a snapshot of a thread's call stack which can
|
||||||
|
* be captured via <code>callWithCurrentContinuation</code> and later
|
||||||
|
* restored any number of times. The program may restore this
|
||||||
|
* snapshot by either feeding it a result (to be returned by
|
||||||
|
* <code>callWithCurrentContinuation</code>) or feeding it an
|
||||||
|
* exception (to be thrown by
|
||||||
|
* <code>callWithCurrentContinuation</code>). Continuations may be
|
||||||
|
* used to implement features such as coroutines, generators, and
|
||||||
|
* cooperative multitasking.
|
||||||
|
*
|
||||||
|
* <p>This class provides two static methods,
|
||||||
|
* <code>callWithCurrentContinuation</code> and
|
||||||
|
* <code>dynamicWind</code>, with similar semantics to the Scheme
|
||||||
|
* functions <code>call-with-current-continuation</code> and
|
||||||
|
* <code>dynamic-wind</code>, respectively. In addition, we define
|
||||||
|
* how continuations work with respect to native code, exceptions,
|
||||||
|
* try/finally blocks, synchronized blocks, and multithreading.
|
||||||
|
*
|
||||||
|
* <h3>Continuations and Continuation Contexts</h3>
|
||||||
|
*
|
||||||
|
* <p>A continuation can be thought of as a singly-linked list of
|
||||||
|
* stack frames representing the call trace, where the head of the
|
||||||
|
* list is the frame of the method most recently called (i.e. the top
|
||||||
|
* of the stack). However, this trace only extends as far as the most
|
||||||
|
* recent chain of Java frames - it ends just prior to the most recent
|
||||||
|
* native frame in the stack. The reason for this is that the VM
|
||||||
|
* cannot, in general, safely capture and restore native frames.
|
||||||
|
* Therefore, each call from native code to Java (including the
|
||||||
|
* original invocation of <code>main(String[])</code> or
|
||||||
|
* <code>Thread.run()</code>) represents a new continuation context in
|
||||||
|
* which continuations may be captured, and these will only contain
|
||||||
|
* frames from within that context.
|
||||||
|
*
|
||||||
|
* <p>Calling a continuation (i.e. feeding it a result or exception)
|
||||||
|
* causes the current continuation to be replaced with the calling
|
||||||
|
* continuation. When the last method in this new continuation
|
||||||
|
* returns, it returns to the native frame which created the current
|
||||||
|
* context, which may not be the same as the context in which that
|
||||||
|
* continuation was created.
|
||||||
|
*
|
||||||
|
* <p>We define the return type of a continuation context as the
|
||||||
|
* return type of the first method called in that context. A
|
||||||
|
* continuation may be called from a different context than the one in
|
||||||
|
* which it was created, provided the return type of the latter is
|
||||||
|
* compatible with the current context.
|
||||||
|
*
|
||||||
|
* <p>Given a thread executing in context "A" which wants to call a
|
||||||
|
* continuation created in context "B", the following rules apply:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
*
|
||||||
|
* <li>If the return type of "A" is <code>void</code>, the return
|
||||||
|
* type of "B" may be anything, including <code>void</code></li>
|
||||||
|
*
|
||||||
|
* <li>If the return type of "A" is a primitive type, the return
|
||||||
|
* type of "B" must match exactly</li>
|
||||||
|
*
|
||||||
|
* <li>If the return type of "A" is an object type, that type must
|
||||||
|
* assignable from the return type of "B" (i.e. the latter must
|
||||||
|
* either be the same as the former or a superclass or
|
||||||
|
* superinterface of it)</li>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>A thread may call a continuation created by a different thread
|
||||||
|
* provided the return types are compatible. Multiple threads may
|
||||||
|
* safely call the same continuation simultaneously without
|
||||||
|
* synchronization. Any attempt to call a continuation from a context
|
||||||
|
* with an incompatible return type will throw an {@link
|
||||||
|
* avian.IncompatibleContinuationException}.
|
||||||
|
*
|
||||||
|
* <h3>Winding, Unwinding, and Rewinding</h3>
|
||||||
|
*
|
||||||
|
* <p>Traditionally, Java provides one way to wind the execution stack
|
||||||
|
* (recursive method calls) and two ways to unwind it (normal returns
|
||||||
|
* and exception unwinding). With continuations, we add a new way to
|
||||||
|
* rewind the stack and a new way to unwind it.
|
||||||
|
*
|
||||||
|
* <p>The call stack of a continuation may share frames with other
|
||||||
|
* continuations - in which case they share a common history. When
|
||||||
|
* calling a continuation "B" from the current continuation "A", the
|
||||||
|
* VM must unwind past any frames which are in "A" but not in "B" and
|
||||||
|
* rewind past any frames in "B" but not in "A". During this
|
||||||
|
* unwinding and rewinding, control may pass through synchronized and
|
||||||
|
* try/finally blocks while going down the old stack and up the new
|
||||||
|
* stack.
|
||||||
|
*
|
||||||
|
* <p>However, unlike the traditional processes of winding and
|
||||||
|
* unwinding, the VM will ignore these blocks - monitors will not be
|
||||||
|
* released or acquired and finally blocks will not execute. This is
|
||||||
|
* by design. The purpose of such a block is to acquire a resource,
|
||||||
|
* such as a file handle or monitor, once before executing a task and
|
||||||
|
* release it after the task is finished, regardless of how often the
|
||||||
|
* task might temporarily yield control to other continuations.
|
||||||
|
*
|
||||||
|
* <p>Conversely, one might wish to acquire and release a resource
|
||||||
|
* each time control (re)winds to or unwinds from a continuation,
|
||||||
|
* respectively. In this case, we use <code>dynamicWind</code> to
|
||||||
|
* register functions which will run every time that frame is passed,
|
||||||
|
* regardless of how the stack is wound or unwound.
|
||||||
|
*/
|
||||||
|
public class Continuations {
|
||||||
|
private Continuations() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures the current continuation, passing a reference to the
|
||||||
|
* specified receiver.
|
||||||
|
*
|
||||||
|
* <p>This method will either return the result returned by
|
||||||
|
* <code>receiver.receive(Callback)</code>, propagate the exception
|
||||||
|
* thrown by that method, return the result passed to the
|
||||||
|
* handleResult(T) method of the continuation, or throw the
|
||||||
|
* exception passed to the handleException(Throwable) of the
|
||||||
|
* continuation.
|
||||||
|
*/
|
||||||
|
public static native <T> T callWithCurrentContinuation
|
||||||
|
(CallbackReceiver<T> receiver) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the specified "before" and "after" tasks each time a
|
||||||
|
* continuation containing the call is wound or unwound,
|
||||||
|
* respectively.
|
||||||
|
*
|
||||||
|
* <p>This method first calls <code>before.run()</code>, then
|
||||||
|
* <code>thunk.call()</code>, and finally <code>after.run()</code>,
|
||||||
|
* returning the result of the second call. If
|
||||||
|
* <code>before.run()</code> does not return normally, the second
|
||||||
|
* and third calls will not happen. If <code>thunk.call()</code>
|
||||||
|
* throws an exception, <code>after.run()</code>, will be called
|
||||||
|
* before the exception is propagated.
|
||||||
|
*
|
||||||
|
* <p>If <code>thunk.call()</code> calls a continuation (directly or
|
||||||
|
* via a subroutine) which does not include the current call to
|
||||||
|
* <code>dynamicWind<code>, <code>after.run()</code> will be called
|
||||||
|
* before control passes to that continuation. If this call throws
|
||||||
|
* an exception, the exception will propagate to the current caller
|
||||||
|
* of <code>dynamicWind</code>.
|
||||||
|
*
|
||||||
|
* <p>If <code>thunk.call()</code> creates a continuation which is
|
||||||
|
* later called from a continuation which does not include the
|
||||||
|
* current call to <code>dynamicWind</code>,
|
||||||
|
* <code>before.run()</code> will be called before control passes to
|
||||||
|
* that continuation. As above, if this call throws an exception,
|
||||||
|
* the exception will propagate to the current caller of
|
||||||
|
* <code>dynamicWind</code>.
|
||||||
|
*/
|
||||||
|
public static <T> T dynamicWind(Runnable before,
|
||||||
|
Callable<T> thunk,
|
||||||
|
Runnable after)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
UnwindResult result = dynamicWind2(before, thunk, after);
|
||||||
|
if (result.continuation != null) {
|
||||||
|
after.run();
|
||||||
|
if (result.exception != null) {
|
||||||
|
result.continuation.handleException(result.exception);
|
||||||
|
} else {
|
||||||
|
result.continuation.handleResult(result.result);
|
||||||
|
}
|
||||||
|
throw new AssertionError();
|
||||||
|
} else {
|
||||||
|
return (T) result.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native UnwindResult dynamicWind2(Runnable before,
|
||||||
|
Callable thunk,
|
||||||
|
Runnable after)
|
||||||
|
throws Exception;
|
||||||
|
|
||||||
|
private static UnwindResult wind(Runnable before,
|
||||||
|
Callable thunk,
|
||||||
|
Runnable after)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
before.run();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new UnwindResult(null, thunk.call(), null);
|
||||||
|
} finally {
|
||||||
|
after.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void rewind(Runnable before,
|
||||||
|
Callback continuation,
|
||||||
|
Object result,
|
||||||
|
Throwable exception)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
before.run();
|
||||||
|
|
||||||
|
if (exception != null) {
|
||||||
|
continuation.handleException(exception);
|
||||||
|
} else {
|
||||||
|
continuation.handleResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Continuation<T> implements Callback<T> {
|
||||||
|
public native void handleResult(T result);
|
||||||
|
public native void handleException(Throwable exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class UnwindResult {
|
||||||
|
public final Callback continuation;
|
||||||
|
public final Object result;
|
||||||
|
public final Throwable exception;
|
||||||
|
|
||||||
|
public UnwindResult(Callback continuation, Object result,
|
||||||
|
Throwable exception)
|
||||||
|
{
|
||||||
|
this.continuation = continuation;
|
||||||
|
this.result = result;
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
classpath/avian/IncompatibleContinuationException.java
Normal file
21
classpath/avian/IncompatibleContinuationException.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package avian;
|
||||||
|
|
||||||
|
public class IncompatibleContinuationException extends Exception {
|
||||||
|
public IncompatibleContinuationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncompatibleContinuationException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
17
classpath/avian/Machine.java
Normal file
17
classpath/avian/Machine.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package avian;
|
||||||
|
|
||||||
|
public abstract class Machine {
|
||||||
|
|
||||||
|
public static native void dumpHeap(String outputFile);
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -8,7 +8,9 @@
|
|||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
package java.util;
|
package avian;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
public class PersistentSet <T> implements Iterable <T> {
|
public class PersistentSet <T> implements Iterable <T> {
|
||||||
private static final Node NullNode = new Node(null);
|
private static final Node NullNode = new Node(null);
|
@ -8,7 +8,7 @@
|
|||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
package java.lang;
|
package avian;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
101
classpath/avian/resource/Handler.java
Normal file
101
classpath/avian/resource/Handler.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package avian.resource;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLStreamHandler;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class Handler extends URLStreamHandler {
|
||||||
|
protected URLConnection openConnection(URL url) {
|
||||||
|
return new ResourceConnection(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResourceConnection extends URLConnection {
|
||||||
|
public ResourceConnection(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContentLength() {
|
||||||
|
return ResourceInputStream.getContentLength(url.getFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return new ResourceInputStream(url.getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResourceInputStream extends InputStream {
|
||||||
|
private long peer;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public ResourceInputStream(String path) throws IOException {
|
||||||
|
peer = open(path);
|
||||||
|
if (peer == 0) {
|
||||||
|
throw new FileNotFoundException(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int getContentLength(String path);
|
||||||
|
|
||||||
|
private static native long open(String path) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(long peer, int position) throws IOException;
|
||||||
|
|
||||||
|
private static native int read(long peer, int position,
|
||||||
|
byte[] b, int offset, int length)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
public static native void close(long peer) throws IOException;
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
int c = read(peer, position);
|
||||||
|
if (c >= 0) {
|
||||||
|
++ position;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
if (b == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0 || offset + length > b.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int c = read(peer, position, b, offset, length);
|
||||||
|
if (c >= 0) {
|
||||||
|
position += c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (peer != 0) {
|
||||||
|
close(peer);
|
||||||
|
peer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -305,6 +305,21 @@ Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
|
Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path)
|
||||||
|
{
|
||||||
|
const char* chars = e->GetStringUTFChars(path, 0);
|
||||||
|
if (chars) {
|
||||||
|
STRUCT_STAT s;
|
||||||
|
int r = STAT(chars, &s);
|
||||||
|
bool v = (r == 0 and S_ISREG(s.st_mode));
|
||||||
|
e->ReleaseStringUTFChars(path, chars);
|
||||||
|
return v;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jboolean JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
|
Java_java_io_File_exists(JNIEnv* e, jclass, jstring path)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
There is NO WARRANTY for this software. See license.txt for
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "sys/time.h"
|
#include "sys/time.h"
|
||||||
@ -32,11 +32,14 @@
|
|||||||
# define SO_PREFIX ""
|
# define SO_PREFIX ""
|
||||||
#else
|
#else
|
||||||
# define SO_PREFIX "lib"
|
# define SO_PREFIX "lib"
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include "sys/utsname.h"
|
||||||
#include "sys/wait.h"
|
#include "sys/wait.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# define SO_SUFFIX ".jnilib"
|
# define SO_SUFFIX ".jnilib"
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
#elif defined WIN32
|
#elif defined WIN32
|
||||||
# define SO_SUFFIX ".dll"
|
# define SO_SUFFIX ".dll"
|
||||||
#else
|
#else
|
||||||
@ -349,6 +352,44 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name,
|
|||||||
r = e->NewStringUTF("\\");
|
r = e->NewStringUTF("\\");
|
||||||
} else if (strcmp(chars, "os.name") == 0) {
|
} else if (strcmp(chars, "os.name") == 0) {
|
||||||
r = e->NewStringUTF("Windows");
|
r = e->NewStringUTF("Windows");
|
||||||
|
} else if (strcmp(chars, "os.version") == 0) {
|
||||||
|
unsigned size = 32;
|
||||||
|
char buffer[size];
|
||||||
|
OSVERSIONINFO OSversion;
|
||||||
|
OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
|
||||||
|
::GetVersionEx(&OSversion);
|
||||||
|
snprintf(buffer, size, "%i.%i", (int)OSversion.dwMajorVersion, (int)OSversion.dwMinorVersion);
|
||||||
|
r = e->NewStringUTF(buffer);
|
||||||
|
} else if (strcmp(chars, "os.arch") == 0) {
|
||||||
|
#ifdef __i386__
|
||||||
|
r = e->NewStringUTF("x86");
|
||||||
|
#else
|
||||||
|
#ifdef __x86_64__
|
||||||
|
r = e->NewStringUTF("x86_64");
|
||||||
|
#else
|
||||||
|
#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
|
||||||
|
r = e->NewStringUTF("ppc");
|
||||||
|
#else
|
||||||
|
#ifdef __ia64__
|
||||||
|
r = e->NewStringUTF("ia64");
|
||||||
|
#else
|
||||||
|
#ifdef __arm__
|
||||||
|
r = e->NewStringUTF("arm");
|
||||||
|
#else
|
||||||
|
#ifdef __alpha__
|
||||||
|
r = e->NewStringUTF("alpha");
|
||||||
|
#else
|
||||||
|
#ifdef __sparc64__
|
||||||
|
r = e->NewStringUTF("sparc64");
|
||||||
|
#else
|
||||||
|
r = e->NewStringUTF("unknown");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
||||||
TCHAR buffer[MAX_PATH];
|
TCHAR buffer[MAX_PATH];
|
||||||
GetTempPath(MAX_PATH, buffer);
|
GetTempPath(MAX_PATH, buffer);
|
||||||
@ -368,10 +409,56 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name,
|
|||||||
#else
|
#else
|
||||||
r = e->NewStringUTF("Linux");
|
r = e->NewStringUTF("Linux");
|
||||||
#endif
|
#endif
|
||||||
|
} else if (strcmp(chars, "os.version") == 0) {
|
||||||
|
#ifdef __APPLE__
|
||||||
|
unsigned size = 32;
|
||||||
|
char buffer[size];
|
||||||
|
long minorVersion, majorVersion;
|
||||||
|
|
||||||
|
Gestalt(gestaltSystemVersionMajor, &majorVersion);
|
||||||
|
Gestalt(gestaltSystemVersionMinor, &minorVersion);
|
||||||
|
|
||||||
|
snprintf(buffer, size, "%ld.%ld", majorVersion, minorVersion);
|
||||||
|
r = e->NewStringUTF(buffer);
|
||||||
|
#else
|
||||||
|
struct utsname system_id;
|
||||||
|
uname(&system_id);
|
||||||
|
r = e->NewStringUTF(system_id.release);
|
||||||
|
#endif
|
||||||
|
} else if (strcmp(chars, "os.arch") == 0) {
|
||||||
|
#ifdef __i386__
|
||||||
|
r = e->NewStringUTF("x86");
|
||||||
|
#else
|
||||||
|
#ifdef __x86_64__
|
||||||
|
r = e->NewStringUTF("x86_64");
|
||||||
|
#else
|
||||||
|
#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
|
||||||
|
r = e->NewStringUTF("ppc");
|
||||||
|
#else
|
||||||
|
#ifdef __ia64__
|
||||||
|
r = e->NewStringUTF("ia64");
|
||||||
|
#else
|
||||||
|
#ifdef __arm__
|
||||||
|
r = e->NewStringUTF("arm");
|
||||||
|
#else
|
||||||
|
#ifdef __alpha__
|
||||||
|
r = e->NewStringUTF("alpha");
|
||||||
|
#else
|
||||||
|
#ifdef __sparc64__
|
||||||
|
r = e->NewStringUTF("sparc64");
|
||||||
|
#else
|
||||||
|
r = e->NewStringUTF("unknown");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
||||||
r = e->NewStringUTF("/tmp");
|
r = e->NewStringUTF("/tmp");
|
||||||
} else if (strcmp(chars, "user.home") == 0) {
|
} else if (strcmp(chars, "user.home") == 0) {
|
||||||
r = e->NewStringUTF(getenv("HOME"));
|
r = e->NewStringUTF(getenv("HOME"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -154,17 +154,19 @@ eagain()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
makeNonblocking(JNIEnv* e, int d)
|
setBlocking(JNIEnv* e, int d, bool blocking)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
u_long a = 1;
|
u_long a = (blocking ? 0 : 1);
|
||||||
int r = ioctlsocket(d, FIONBIO, &a);
|
int r = ioctlsocket(d, FIONBIO, &a);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int r = fcntl(d, F_SETFL, fcntl(d, F_GETFL) | O_NONBLOCK);
|
int r = fcntl(d, F_SETFL, (blocking
|
||||||
|
? (fcntl(d, F_GETFL) & (~O_NONBLOCK))
|
||||||
|
: (fcntl(d, F_GETFL) | O_NONBLOCK)));
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
return false;
|
return false;
|
||||||
@ -231,7 +233,6 @@ doAccept(JNIEnv* e, int s)
|
|||||||
socklen_t length = sizeof(address);
|
socklen_t length = sizeof(address);
|
||||||
int r = ::accept(s, &address, &length);
|
int r = ::accept(s, &address, &length);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
makeNonblocking(e, r);
|
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
@ -260,7 +261,7 @@ doWrite(int fd, const void* buffer, size_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
makeSocket(JNIEnv* e, bool blocking = false)
|
makeSocket(JNIEnv* e)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
static bool wsaInitialized = false;
|
static bool wsaInitialized = false;
|
||||||
@ -279,8 +280,6 @@ makeSocket(JNIEnv* e, bool blocking = false)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not blocking) makeNonblocking(e, s);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,6 +310,15 @@ Java_java_nio_channels_ServerSocketChannel_natDoListen(JNIEnv *e,
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv *e,
|
||||||
|
jclass,
|
||||||
|
jint socket,
|
||||||
|
jboolean blocking)
|
||||||
|
{
|
||||||
|
setBlocking(e, socket, blocking);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e,
|
||||||
jclass,
|
jclass,
|
||||||
@ -325,11 +333,14 @@ Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv *e,
|
|||||||
jclass,
|
jclass,
|
||||||
jstring host,
|
jstring host,
|
||||||
jint port,
|
jint port,
|
||||||
|
jboolean blocking,
|
||||||
jbooleanArray retVal)
|
jbooleanArray retVal)
|
||||||
{
|
{
|
||||||
int s = makeSocket(e);
|
int s = makeSocket(e);
|
||||||
if (e->ExceptionOccurred()) return 0;
|
if (e->ExceptionOccurred()) return 0;
|
||||||
|
|
||||||
|
setBlocking(e, s, blocking);
|
||||||
|
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
init(e, &address, host, port);
|
init(e, &address, host, port);
|
||||||
if (e->ExceptionOccurred()) return 0;
|
if (e->ExceptionOccurred()) return 0;
|
||||||
@ -425,7 +436,8 @@ class Pipe {
|
|||||||
address.sin_family = AF_INET;
|
address.sin_family = AF_INET;
|
||||||
address.sin_port = 0;
|
address.sin_port = 0;
|
||||||
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //INADDR_LOOPBACK;
|
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //INADDR_LOOPBACK;
|
||||||
listener_ = makeSocket(e, false);
|
listener_ = makeSocket(e);
|
||||||
|
setBlocking(e, listener_, false);
|
||||||
::doListen(e, listener_, &address);
|
::doListen(e, listener_, &address);
|
||||||
|
|
||||||
socklen_t length = sizeof(sockaddr_in);
|
socklen_t length = sizeof(sockaddr_in);
|
||||||
@ -435,7 +447,8 @@ class Pipe {
|
|||||||
throwIOException(e);
|
throwIOException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer_ = makeSocket(e, true);
|
writer_ = makeSocket(e);
|
||||||
|
setBlocking(e, writer_, true);
|
||||||
connected_ = ::doConnect(e, writer_, &address);
|
connected_ = ::doConnect(e, writer_, &address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,8 +498,8 @@ class Pipe {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (makeNonblocking(e, pipe[0])) {
|
if (setBlocking(e, pipe[0], false)) {
|
||||||
makeNonblocking(e, pipe[1]);
|
setBlocking(e, pipe[1], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +639,17 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
timeval time = { interval / 1000, (interval % 1000) * 1000 };
|
timeval time;
|
||||||
|
if (interval > 0) {
|
||||||
|
time.tv_sec = interval / 1000;
|
||||||
|
time.tv_usec = (interval % 1000) * 1000;
|
||||||
|
} else if (interval < 0) {
|
||||||
|
time.tv_sec = 0;
|
||||||
|
time.tv_usec = 0;
|
||||||
|
} else {
|
||||||
|
time.tv_sec = INT32_MAX;
|
||||||
|
time.tv_usec = 0;
|
||||||
|
}
|
||||||
int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time);
|
int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time);
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
@ -41,6 +41,12 @@ public class File {
|
|||||||
return isDirectory(path);
|
return isDirectory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native boolean isFile(String path);
|
||||||
|
|
||||||
|
public boolean isFile() {
|
||||||
|
return isFile(path);
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
int index = path.lastIndexOf(FileSeparator);
|
int index = path.lastIndexOf(FileSeparator);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@ -141,6 +147,19 @@ public class File {
|
|||||||
return mkdir();
|
return mkdir();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File[] listFiles() {
|
||||||
|
return listFiles(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public File[] listFiles(FilenameFilter filter) {
|
||||||
|
String[] list = list(filter);
|
||||||
|
File[] result = new File[list.length];
|
||||||
|
for (int i = 0; i < list.length; ++i) {
|
||||||
|
result[i] = new File(this, list[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public String[] list() {
|
public String[] list() {
|
||||||
return list(null);
|
return list(null);
|
||||||
}
|
}
|
||||||
|
22
classpath/java/lang/Appendable.java
Normal file
22
classpath/java/lang/Appendable.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.lang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface Appendable {
|
||||||
|
public Appendable append(char c) throws IOException;
|
||||||
|
|
||||||
|
public Appendable append(CharSequence sequence) throws IOException;
|
||||||
|
|
||||||
|
public Appendable append(CharSequence sequence, int start, int end)
|
||||||
|
throws IOException;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class ArrayIndexOutOfBoundsException extends RuntimeException {
|
public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||||
public ArrayIndexOutOfBoundsException(String message, Throwable cause) {
|
public ArrayIndexOutOfBoundsException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
@ -187,4 +187,40 @@ public final class Character implements Comparable<Character> {
|
|||||||
return isHighSurrogate(high) && isLowSurrogate(low);
|
return isHighSurrogate(high) && isLowSurrogate(low);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int codePointAt(CharSequence sequence, int offset) {
|
||||||
|
int length = sequence.length();
|
||||||
|
if (offset < 0 || offset >= length) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
char high = sequence.charAt(offset);
|
||||||
|
if (! isHighSurrogate(high) || offset >= length) {
|
||||||
|
return high;
|
||||||
|
}
|
||||||
|
char low = sequence.charAt(offset + 1);
|
||||||
|
if (! isLowSurrogate(low)) {
|
||||||
|
return high;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toCodePoint(high, low);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int codePointCount(CharSequence sequence, int start, int end) {
|
||||||
|
int length = sequence.length();
|
||||||
|
if (start < 0 || start > end || end >= length) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = start; i < end; ++i) {
|
||||||
|
if (isHighSurrogate(sequence.charAt(i))
|
||||||
|
&& (i + 1) < end
|
||||||
|
&& isLowSurrogate(sequence.charAt(i + 1)))
|
||||||
|
{
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
++ count;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,20 @@ import java.lang.reflect.Constructor;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.GenericDeclaration;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.security.Permissions;
|
||||||
|
import java.security.AllPermission;
|
||||||
|
|
||||||
public final class Class <T> {
|
public final class Class <T> implements Type, GenericDeclaration {
|
||||||
private static final int PrimitiveFlag = 1 << 4;
|
private static final int PrimitiveFlag = 1 << 5;
|
||||||
|
|
||||||
private short flags;
|
private short flags;
|
||||||
private byte vmFlags;
|
private byte vmFlags;
|
||||||
@ -55,6 +62,34 @@ public final class Class <T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
if (name == null) {
|
||||||
|
if ((vmFlags & PrimitiveFlag) != 0) {
|
||||||
|
if (this == primitiveClass('V')) {
|
||||||
|
name = "void".getBytes();
|
||||||
|
} else if (this == primitiveClass('Z')) {
|
||||||
|
name = "boolean".getBytes();
|
||||||
|
} else if (this == primitiveClass('B')) {
|
||||||
|
name = "byte".getBytes();
|
||||||
|
} else if (this == primitiveClass('C')) {
|
||||||
|
name = "char".getBytes();
|
||||||
|
} else if (this == primitiveClass('S')) {
|
||||||
|
name = "short".getBytes();
|
||||||
|
} else if (this == primitiveClass('I')) {
|
||||||
|
name = "int".getBytes();
|
||||||
|
} else if (this == primitiveClass('F')) {
|
||||||
|
name = "float".getBytes();
|
||||||
|
} else if (this == primitiveClass('J')) {
|
||||||
|
name = "long".getBytes();
|
||||||
|
} else if (this == primitiveClass('D')) {
|
||||||
|
name = "double".getBytes();
|
||||||
|
} else {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new String
|
return new String
|
||||||
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
|
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
|
||||||
}
|
}
|
||||||
@ -84,6 +119,9 @@ public final class Class <T> {
|
|||||||
ClassLoader loader)
|
ClassLoader loader)
|
||||||
throws ClassNotFoundException
|
throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
|
if (loader == null) {
|
||||||
|
loader = Class.class.loader;
|
||||||
|
}
|
||||||
Class c = loader.loadClass(name);
|
Class c = loader.loadClass(name);
|
||||||
if (initialize) {
|
if (initialize) {
|
||||||
c.initialize();
|
c.initialize();
|
||||||
@ -436,8 +474,63 @@ public final class Class <T> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean desiredAssertionStatus() {
|
public boolean desiredAssertionStatus() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T cast(Object o) {
|
||||||
|
return (T) o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getSigners() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnum() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeVariable<Class<T>>[] getTypeParameters() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSimpleName() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method getEnclosingMethod() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constructor getEnclosingConstructor() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getEnclosingClass() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class[] getDeclaredClasses() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A extends Annotation> A getAnnotation(Class<A> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProtectionDomain getProtectionDomain() {
|
||||||
|
Permissions p = new Permissions();
|
||||||
|
p.add(new AllPermission());
|
||||||
|
return new ProtectionDomain(null, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for GNU Classpath compatibility:
|
||||||
|
void setSigners(Object[] signers) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -11,8 +11,11 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class ClassNotFoundException extends Exception {
|
public class ClassNotFoundException extends Exception {
|
||||||
|
private final Throwable cause2;
|
||||||
|
|
||||||
public ClassNotFoundException(String message, Throwable cause) {
|
public ClassNotFoundException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
|
cause2 = cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassNotFoundException(String message) {
|
public ClassNotFoundException(String message) {
|
||||||
|
@ -53,4 +53,12 @@ public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Class<E> getDeclaringClass() {
|
||||||
|
Class c = getClass();
|
||||||
|
while (c.getSuperclass() != Enum.class) {
|
||||||
|
c = c.getSuperclass();
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -11,11 +11,14 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class ExceptionInInitializerError extends Error {
|
public class ExceptionInInitializerError extends Error {
|
||||||
|
private final Throwable cause2;
|
||||||
|
|
||||||
public ExceptionInInitializerError(String message) {
|
public ExceptionInInitializerError(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
cause2 = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExceptionInInitializerError() {
|
public ExceptionInInitializerError() {
|
||||||
super();
|
this(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public final class Long extends Number implements Comparable<Long> {
|
|||||||
|
|
||||||
char[] array = new char[size];
|
char[] array = new char[size];
|
||||||
|
|
||||||
int i = array.length - 1;
|
int i = size - 1;
|
||||||
for (long n = v; n != 0; n /= radix) {
|
for (long n = v; n != 0; n /= radix) {
|
||||||
long digit = n % radix;
|
long digit = n % radix;
|
||||||
if (negative) digit = -digit;
|
if (negative) digit = -digit;
|
||||||
@ -83,7 +83,7 @@ public final class Long extends Number implements Comparable<Long> {
|
|||||||
array[i] = '-';
|
array[i] = '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
return new String(array);
|
return new String(array, 0, size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toString(long v) {
|
public static String toString(long v) {
|
||||||
|
@ -25,7 +25,7 @@ public class Object {
|
|||||||
return this == o;
|
return this == o;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void finalize() { }
|
protected void finalize() throws Throwable { }
|
||||||
|
|
||||||
public native final Class<? extends Object> getClass();
|
public native final Class<? extends Object> getClass();
|
||||||
|
|
||||||
@ -41,5 +41,14 @@ public class Object {
|
|||||||
wait(0);
|
wait(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public native final void wait(long timeout) throws InterruptedException;
|
public native final void wait(long milliseconds) throws InterruptedException;
|
||||||
|
|
||||||
|
public final void wait(long milliseconds, int nanoseconds)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
if (nanoseconds != 0) {
|
||||||
|
++ milliseconds;
|
||||||
|
}
|
||||||
|
wait(milliseconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,6 @@ public class Runtime {
|
|||||||
|
|
||||||
public native long totalMemory();
|
public native long totalMemory();
|
||||||
|
|
||||||
public static native void dumpHeap(String outputFile);
|
|
||||||
|
|
||||||
private static class MyProcess extends Process {
|
private static class MyProcess extends Process {
|
||||||
private long pid;
|
private long pid;
|
||||||
private final int in;
|
private final int in;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class StackOverflowError extends Error {
|
public class StackOverflowError extends VirtualMachineError {
|
||||||
public StackOverflowError(String message) {
|
public StackOverflowError(String message) {
|
||||||
super(message, null);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackOverflowError() {
|
public StackOverflowError() {
|
||||||
|
@ -18,8 +18,8 @@ public class StackTraceElement {
|
|||||||
private String file;
|
private String file;
|
||||||
private int line;
|
private int line;
|
||||||
|
|
||||||
private StackTraceElement(String class_, String method, String file,
|
public StackTraceElement(String class_, String method, String file,
|
||||||
int line)
|
int line)
|
||||||
{
|
{
|
||||||
this.class_ = class_;
|
this.class_ = class_;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
@ -56,7 +56,7 @@ public class StackTraceElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getClassName() {
|
public String getClassName() {
|
||||||
return class_;
|
return class_.replace('/', '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMethodName() {
|
public String getMethodName() {
|
||||||
|
@ -12,14 +12,30 @@ package java.lang;
|
|||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Locale;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public final class String
|
||||||
|
implements Comparable<String>, CharSequence, Serializable
|
||||||
|
{
|
||||||
|
public static Comparator<String> CASE_INSENSITIVE_ORDER
|
||||||
|
= new Comparator<String>() {
|
||||||
|
public int compare(String a, String b) {
|
||||||
|
return a.compareToIgnoreCase(b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public final class String implements Comparable<String>, CharSequence {
|
|
||||||
private final Object data;
|
private final Object data;
|
||||||
private final int offset;
|
private final int offset;
|
||||||
private final int length;
|
private final int length;
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
|
|
||||||
|
public String() {
|
||||||
|
this(new char[0], 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public String(char[] data, int offset, int length, boolean copy) {
|
public String(char[] data, int offset, int length, boolean copy) {
|
||||||
this((Object) data, offset, length, copy);
|
this((Object) data, offset, length, copy);
|
||||||
}
|
}
|
||||||
@ -32,9 +48,11 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
this(data, 0, data.length);
|
this(data, 0, data.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String(byte bytes[], int offset, int length, String charsetName) throws UnsupportedEncodingException {
|
public String(byte bytes[], int offset, int length, String charsetName)
|
||||||
|
throws UnsupportedEncodingException
|
||||||
|
{
|
||||||
this(bytes, offset, length);
|
this(bytes, offset, length);
|
||||||
if (!charsetName.equals("UTF-8")) {
|
if (! charsetName.equalsIgnoreCase("UTF-8")) {
|
||||||
throw new UnsupportedEncodingException(charsetName);
|
throw new UnsupportedEncodingException(charsetName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,12 +75,29 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
|
|
||||||
public String(byte[] data, String charset)
|
public String(byte[] data, String charset)
|
||||||
throws UnsupportedEncodingException
|
throws UnsupportedEncodingException
|
||||||
{
|
{
|
||||||
this(data);
|
this(data);
|
||||||
if (! charset.equals("UTF-8")) {
|
if (! charset.equals("UTF-8")) {
|
||||||
throw new UnsupportedEncodingException(charset);
|
throw new UnsupportedEncodingException(charset);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String(byte bytes[], int highByte, int offset, int length) {
|
||||||
|
if (offset < 0 || offset + length > bytes.length) {
|
||||||
|
throw new IndexOutOfBoundsException
|
||||||
|
(offset + " < 0 or " + offset + " + " + length + " > " + bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] c = new char[length];
|
||||||
|
int mask = highByte << 8;
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
c[i] = (char) ((bytes[offset + i] & 0xFF) | mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = c;
|
||||||
|
this.offset = 0;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
private String(Object data, int offset, int length, boolean copy) {
|
private String(Object data, int offset, int length, boolean copy) {
|
||||||
int l;
|
int l;
|
||||||
@ -200,7 +235,7 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean equalsIgnoreCase(String s) {
|
public boolean equalsIgnoreCase(String s) {
|
||||||
return this == s || compareToIgnoreCase(s) == 0;
|
return this == s || (s != null && compareToIgnoreCase(s) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(String s) {
|
public int compareTo(String s) {
|
||||||
@ -381,7 +416,7 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IndexOutOfBoundsException
|
throw new IndexOutOfBoundsException
|
||||||
(start + " not in (0, " + end + ") or " + end + " > " + length);
|
(start + " not in [0, " + end + ") or " + end + " > " + length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,6 +569,10 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
return Pattern.matches(regex, this);
|
return Pattern.matches(regex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String replaceAll(String regex, String replacement) {
|
||||||
|
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
|
||||||
|
}
|
||||||
|
|
||||||
public native String intern();
|
public native String intern();
|
||||||
|
|
||||||
public static String valueOf(Object s) {
|
public static String valueOf(Object s) {
|
||||||
@ -557,7 +596,9 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String valueOf(int v) {
|
public static String valueOf(int v) {
|
||||||
return Integer.toString(v);
|
// use Integer.toString(int, int), because GNU Classpath's
|
||||||
|
// Integer.toString(int) just calls String.valueOf(int):
|
||||||
|
return Integer.toString(v, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String valueOf(long v) {
|
public static String valueOf(long v) {
|
||||||
@ -572,6 +613,14 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
return Double.toString(v);
|
return Double.toString(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String valueOf(char[] data, int offset, int length) {
|
||||||
|
return new String(data, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String valueOf(char[] data) {
|
||||||
|
return valueOf(data, 0, data.length);
|
||||||
|
}
|
||||||
|
|
||||||
public int lastIndexOf(int ch, int lastIndex) {
|
public int lastIndexOf(int ch, int lastIndex) {
|
||||||
for (int i = lastIndex ; i >= 0; --i) {
|
for (int i = lastIndex ; i >= 0; --i) {
|
||||||
if (charAt(i) == ch) {
|
if (charAt(i) == ch) {
|
||||||
@ -581,4 +630,63 @@ public final class String implements Comparable<String>, CharSequence {
|
|||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean regionMatches(int thisOffset, String match, int matchOffset,
|
||||||
|
int length)
|
||||||
|
{
|
||||||
|
return regionMatches(false, thisOffset, match, matchOffset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean regionMatches(boolean ignoreCase, int thisOffset,
|
||||||
|
String match, int matchOffset, int length)
|
||||||
|
{
|
||||||
|
String a = substring(thisOffset, thisOffset + length);
|
||||||
|
String b = match.substring(matchOffset, matchOffset + length);
|
||||||
|
if (ignoreCase) {
|
||||||
|
return a.equalsIgnoreCase(b);
|
||||||
|
} else {
|
||||||
|
return a.equals(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String match) {
|
||||||
|
return indexOf(match) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int codePointAt(int offset) {
|
||||||
|
return Character.codePointAt(this, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int codePointCount(int start, int end) {
|
||||||
|
return Character.codePointCount(this, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String replace(CharSequence match, CharSequence replacement) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toUpperCase(Locale locale) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toLowerCase(Locale locale) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// for GNU Classpath compatibility:
|
||||||
|
static char[] zeroBasedStringValue(String s) {
|
||||||
|
if (s.offset == 0) {
|
||||||
|
if (s.data instanceof char[]) {
|
||||||
|
char[] data = (char[]) s.data;
|
||||||
|
if (data.length == s.length) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.toCharArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
public class StringBuilder implements CharSequence {
|
public class StringBuilder implements CharSequence, Appendable {
|
||||||
private static final int BufferSize = 32;
|
private static final int BufferSize = 32;
|
||||||
|
|
||||||
private Cell chain;
|
private Cell chain;
|
||||||
@ -54,6 +54,14 @@ public class StringBuilder implements CharSequence {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringBuilder append(CharSequence sequence) {
|
||||||
|
return append(sequence.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Appendable append(CharSequence sequence, int start, int end) {
|
||||||
|
return append(sequence.subSequence(start, end));
|
||||||
|
}
|
||||||
|
|
||||||
public StringBuilder append(char[] b, int offset, int length) {
|
public StringBuilder append(char[] b, int offset, int length) {
|
||||||
return append(new String(b, offset, length));
|
return append(new String(b, offset, length));
|
||||||
}
|
}
|
||||||
@ -150,6 +158,10 @@ public class StringBuilder implements CharSequence {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringBuilder insert(int i, CharSequence s) {
|
||||||
|
return insert(i, s.toString());
|
||||||
|
}
|
||||||
|
|
||||||
public StringBuilder insert(int i, char c) {
|
public StringBuilder insert(int i, char c) {
|
||||||
return insert(i, new String(new char[] { c }, 0, 1, false));
|
return insert(i, new String(new char[] { c }, 0, 1, false));
|
||||||
}
|
}
|
||||||
@ -332,4 +344,8 @@ public class StringBuilder implements CharSequence {
|
|||||||
deleteCharAt(index);
|
deleteCharAt(index);
|
||||||
insert(index, ch);
|
insert(index, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ensureCapacity(int capacity) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -15,14 +15,30 @@ import java.util.WeakHashMap;
|
|||||||
|
|
||||||
public class Thread implements Runnable {
|
public class Thread implements Runnable {
|
||||||
private long peer;
|
private long peer;
|
||||||
|
private boolean interrupted;
|
||||||
|
private boolean daemon;
|
||||||
|
private byte state;
|
||||||
|
private byte priority;
|
||||||
private final Runnable task;
|
private final Runnable task;
|
||||||
private Map<ThreadLocal, Object> locals;
|
private Map<ThreadLocal, Object> locals;
|
||||||
private boolean interrupted;
|
|
||||||
private Object sleepLock;
|
private Object sleepLock;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private String name;
|
private UncaughtExceptionHandler exceptionHandler;
|
||||||
|
|
||||||
public Thread(Runnable task, String name) {
|
// package private for GNU Classpath, which inexplicably bypasses
|
||||||
|
// the accessor methods:
|
||||||
|
String name;
|
||||||
|
ThreadGroup group;
|
||||||
|
|
||||||
|
private static UncaughtExceptionHandler defaultExceptionHandler;
|
||||||
|
|
||||||
|
public static final int MIN_PRIORITY = 1;
|
||||||
|
public static final int NORM_PRIORITY = 5;
|
||||||
|
public static final int MAX_PRIORITY = 10;
|
||||||
|
|
||||||
|
public Thread(ThreadGroup group, Runnable task, String name, long stackSize)
|
||||||
|
{
|
||||||
|
this.group = group;
|
||||||
this.task = task;
|
this.task = task;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
@ -41,8 +57,28 @@ public class Thread implements Runnable {
|
|||||||
classLoader = current.classLoader;
|
classLoader = current.classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Thread(ThreadGroup group, Runnable task, String name) {
|
||||||
|
this(group, task, name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread(ThreadGroup group, String name) {
|
||||||
|
this(null, null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread(Runnable task, String name) {
|
||||||
|
this(null, task, name);
|
||||||
|
}
|
||||||
|
|
||||||
public Thread(Runnable task) {
|
public Thread(Runnable task) {
|
||||||
this(task, "Thread["+task+"]");
|
this(null, task, "Thread["+task+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread(String name) {
|
||||||
|
this(null, null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread() {
|
||||||
|
this((Runnable) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void start() {
|
public synchronized void start() {
|
||||||
@ -58,6 +94,28 @@ public class Thread implements Runnable {
|
|||||||
|
|
||||||
private native long doStart();
|
private native long doStart();
|
||||||
|
|
||||||
|
private static void run(Thread t) throws Throwable {
|
||||||
|
t.state = (byte) State.RUNNABLE.ordinal();
|
||||||
|
try {
|
||||||
|
t.run();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
UncaughtExceptionHandler eh = t.exceptionHandler;
|
||||||
|
UncaughtExceptionHandler deh = defaultExceptionHandler;
|
||||||
|
if (eh != null) {
|
||||||
|
eh.uncaughtException(t, e);
|
||||||
|
} else if (deh != null) {
|
||||||
|
deh.uncaughtException(t, e);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
synchronized (t) {
|
||||||
|
t.state = (byte) State.TERMINATED.ordinal();
|
||||||
|
t.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
task.run();
|
task.run();
|
||||||
@ -101,6 +159,10 @@ public class Thread implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isInterrupted() {
|
||||||
|
return currentThread().interrupted;
|
||||||
|
}
|
||||||
|
|
||||||
public static void sleep(long milliseconds) throws InterruptedException {
|
public static void sleep(long milliseconds) throws InterruptedException {
|
||||||
Thread t = currentThread();
|
Thread t = currentThread();
|
||||||
if (t.sleepLock == null) {
|
if (t.sleepLock == null) {
|
||||||
@ -111,6 +173,16 @@ public class Thread implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void sleep(long milliseconds, int nanoseconds)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
if (nanoseconds > 0) {
|
||||||
|
++ milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(milliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
public StackTraceElement[] getStackTrace() {
|
public StackTraceElement[] getStackTrace() {
|
||||||
return Throwable.resolveTrace(getStackTrace(peer));
|
return Throwable.resolveTrace(getStackTrace(peer));
|
||||||
}
|
}
|
||||||
@ -124,5 +196,125 @@ public class Thread implements Runnable {
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
|
||||||
|
UncaughtExceptionHandler eh = exceptionHandler;
|
||||||
|
return (eh == null ? group : eh);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
|
||||||
|
return defaultExceptionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUncaughtExceptionHandler(UncaughtExceptionHandler h) {
|
||||||
|
exceptionHandler = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultUncaughtExceptionHandler
|
||||||
|
(UncaughtExceptionHandler h)
|
||||||
|
{
|
||||||
|
defaultExceptionHandler = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return State.values()[state];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAlive() {
|
||||||
|
switch (getState()) {
|
||||||
|
case NEW:
|
||||||
|
case TERMINATED:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(int priority) {
|
||||||
|
if (priority < MIN_PRIORITY || priority > MAX_PRIORITY) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
this.priority = (byte) priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDaemon() {
|
||||||
|
return daemon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDaemon(boolean v) {
|
||||||
|
daemon = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native void yield();
|
||||||
|
|
||||||
|
public synchronized void join() throws InterruptedException {
|
||||||
|
while (getState() != State.TERMINATED) {
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void join(long milliseconds) throws InterruptedException
|
||||||
|
{
|
||||||
|
long then = System.currentTimeMillis();
|
||||||
|
long remaining = milliseconds;
|
||||||
|
while (remaining > 0 && getState() != State.TERMINATED) {
|
||||||
|
wait(remaining);
|
||||||
|
|
||||||
|
remaining = milliseconds - (System.currentTimeMillis() - then);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void join(long milliseconds, int nanoseconds)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
if (nanoseconds > 0) {
|
||||||
|
++ milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
join(milliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThreadGroup getThreadGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native boolean holdsLock(Object o);
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop(Throwable t) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void suspend() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resume() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface UncaughtExceptionHandler {
|
||||||
|
public void uncaughtException(Thread t, Throwable e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum State {
|
||||||
|
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
15
classpath/java/lang/ThreadDeath.java
Normal file
15
classpath/java/lang/ThreadDeath.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.lang;
|
||||||
|
|
||||||
|
public class ThreadDeath extends Error {
|
||||||
|
public ThreadDeath() { }
|
||||||
|
}
|
35
classpath/java/lang/ThreadGroup.java
Normal file
35
classpath/java/lang/ThreadGroup.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.lang;
|
||||||
|
|
||||||
|
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
|
||||||
|
private final ThreadGroup parent;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public ThreadGroup(ThreadGroup parent, String name) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
if (parent != null) {
|
||||||
|
parent.uncaughtException(t, e);
|
||||||
|
} else {
|
||||||
|
Thread.UncaughtExceptionHandler deh
|
||||||
|
= Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
if (deh != null) {
|
||||||
|
deh.uncaughtException(t, e);
|
||||||
|
} else if (! (e instanceof ThreadDeath)) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,8 +13,9 @@ package java.lang;
|
|||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class Throwable {
|
public class Throwable implements Serializable {
|
||||||
private String message;
|
private String message;
|
||||||
private Object trace;
|
private Object trace;
|
||||||
private Throwable cause;
|
private Throwable cause;
|
||||||
@ -109,4 +110,9 @@ public class Throwable {
|
|||||||
cause.printStackTrace(sb, nl);
|
cause.printStackTrace(sb, nl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Throwable fillInStackTrace() {
|
||||||
|
trace = trace(0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
21
classpath/java/lang/VirtualMachineError.java
Normal file
21
classpath/java/lang/VirtualMachineError.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.lang;
|
||||||
|
|
||||||
|
public class VirtualMachineError extends Error {
|
||||||
|
public VirtualMachineError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualMachineError() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,10 @@ public abstract class Reference<T> {
|
|||||||
this.queue = queue;
|
this.queue = queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Reference(T target) {
|
||||||
|
this(target, null);
|
||||||
|
}
|
||||||
|
|
||||||
public T get() {
|
public T get() {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
|
|
||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
public class Constructor<T> extends AccessibleObject implements Member {
|
public class Constructor<T> extends AccessibleObject
|
||||||
|
implements Member, GenericDeclaration
|
||||||
|
{
|
||||||
private Method<T> method;
|
private Method<T> method;
|
||||||
|
|
||||||
public Constructor(Method<T> method) {
|
public Constructor(Method<T> method) {
|
||||||
@ -46,6 +48,18 @@ public class Constructor<T> extends AccessibleObject implements Member {
|
|||||||
return method.getName();
|
return method.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSynthetic() {
|
||||||
|
return method.isSynthetic();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeVariable<Constructor<T>>[] getTypeParameters() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type[] getGenericParameterTypes() {
|
||||||
|
return method.getGenericParameterTypes();
|
||||||
|
}
|
||||||
|
|
||||||
private static native <T> T make(Class<T> c);
|
private static native <T> T make(Class<T> c);
|
||||||
|
|
||||||
public T newInstance(Object ... arguments)
|
public T newInstance(Object ... arguments)
|
||||||
|
@ -101,6 +101,38 @@ public class Field<T> extends AccessibleObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Boolean) get(instance)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getByte(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Byte) get(instance)).byteValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getShort(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Short) get(instance)).shortValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getChar(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Character) get(instance)).charValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInt(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Integer) get(instance)).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloat(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Float) get(instance)).floatValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Long) get(instance)).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDouble(Object instance) throws IllegalAccessException {
|
||||||
|
return ((Double) get(instance)).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
public void set(Object instance, Object value)
|
public void set(Object instance, Object value)
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
@ -162,6 +194,10 @@ public class Field<T> extends AccessibleObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnumConstant() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
private static native long getPrimitive
|
private static native long getPrimitive
|
||||||
(Object instance, int code, int offset);
|
(Object instance, int code, int offset);
|
||||||
|
|
||||||
|
15
classpath/java/lang/reflect/GenericDeclaration.java
Normal file
15
classpath/java/lang/reflect/GenericDeclaration.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
public interface GenericDeclaration {
|
||||||
|
public TypeVariable<?>[] getTypeParameters();
|
||||||
|
}
|
@ -19,4 +19,6 @@ public interface Member {
|
|||||||
public int getModifiers();
|
public int getModifiers();
|
||||||
|
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
|
public boolean isSynthetic();
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
|
|
||||||
package java.lang.reflect;
|
package java.lang.reflect;
|
||||||
|
|
||||||
public class Method<T> extends AccessibleObject implements Member {
|
public class Method<T> extends AccessibleObject
|
||||||
|
implements Member, GenericDeclaration
|
||||||
|
{
|
||||||
private byte vmFlags;
|
private byte vmFlags;
|
||||||
private byte returnCode;
|
private byte returnCode;
|
||||||
private byte parameterCount;
|
private byte parameterCount;
|
||||||
@ -124,4 +126,28 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
}
|
}
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSynthetic() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getDefaultValue() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type[] getGenericParameterTypes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getGenericReturnType() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class[] getExceptionTypes() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeVariable<Method<T>>[] getTypeParameters() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,4 +35,5 @@ public final class Modifier {
|
|||||||
public static boolean isSuper (int v) { return (v & SUPER) != 0; }
|
public static boolean isSuper (int v) { return (v & SUPER) != 0; }
|
||||||
public static boolean isNative (int v) { return (v & NATIVE) != 0; }
|
public static boolean isNative (int v) { return (v & NATIVE) != 0; }
|
||||||
public static boolean isAbstract (int v) { return (v & ABSTRACT) != 0; }
|
public static boolean isAbstract (int v) { return (v & ABSTRACT) != 0; }
|
||||||
|
public static boolean isInterface(int v) { return (v & INTERFACE) != 0; }
|
||||||
}
|
}
|
||||||
|
13
classpath/java/lang/reflect/Type.java
Normal file
13
classpath/java/lang/reflect/Type.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
public interface Type { }
|
19
classpath/java/lang/reflect/TypeVariable.java
Normal file
19
classpath/java/lang/reflect/TypeVariable.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.lang.reflect;
|
||||||
|
|
||||||
|
public interface TypeVariable<T extends GenericDeclaration>
|
||||||
|
extends Type
|
||||||
|
{
|
||||||
|
public Type[] getBounds();
|
||||||
|
public T getGenericDeclaration();
|
||||||
|
public String getName();
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -11,7 +11,6 @@
|
|||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public final class URL {
|
public final class URL {
|
||||||
@ -73,7 +72,7 @@ public final class URL {
|
|||||||
throws MalformedURLException
|
throws MalformedURLException
|
||||||
{
|
{
|
||||||
if ("resource".equals(protocol)) {
|
if ("resource".equals(protocol)) {
|
||||||
return new ResourceHandler();
|
return new avian.resource.Handler();
|
||||||
} else {
|
} else {
|
||||||
throw new MalformedURLException("unknown protocol: " + protocol);
|
throw new MalformedURLException("unknown protocol: " + protocol);
|
||||||
}
|
}
|
||||||
@ -88,87 +87,4 @@ public final class URL {
|
|||||||
this.file = file;
|
this.file = file;
|
||||||
this.ref = ref;
|
this.ref = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ResourceHandler extends URLStreamHandler {
|
|
||||||
protected URLConnection openConnection(URL url) {
|
|
||||||
return new ResourceConnection(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ResourceConnection extends URLConnection {
|
|
||||||
public ResourceConnection(URL url) {
|
|
||||||
super(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getContentLength() {
|
|
||||||
return ResourceInputStream.getContentLength(url.getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getInputStream() throws IOException {
|
|
||||||
return new ResourceInputStream(url.getFile());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ResourceInputStream extends InputStream {
|
|
||||||
private long peer;
|
|
||||||
private int position;
|
|
||||||
|
|
||||||
public ResourceInputStream(String path) throws IOException {
|
|
||||||
peer = open(path);
|
|
||||||
if (peer == 0) {
|
|
||||||
throw new FileNotFoundException(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native int getContentLength(String path);
|
|
||||||
|
|
||||||
private static native long open(String path) throws IOException;
|
|
||||||
|
|
||||||
private static native int read(long peer, int position) throws IOException;
|
|
||||||
|
|
||||||
private static native int read(long peer, int position,
|
|
||||||
byte[] b, int offset, int length)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
public static native void close(long peer) throws IOException;
|
|
||||||
|
|
||||||
public int read() throws IOException {
|
|
||||||
if (peer != 0) {
|
|
||||||
int c = read(peer, position);
|
|
||||||
if (c >= 0) {
|
|
||||||
++ position;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
} else {
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int read(byte[] b, int offset, int length) throws IOException {
|
|
||||||
if (peer != 0) {
|
|
||||||
if (b == null) {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < 0 || offset + length > b.length) {
|
|
||||||
throw new ArrayIndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int c = read(peer, position, b, offset, length);
|
|
||||||
if (c >= 0) {
|
|
||||||
position += c;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
} else {
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws IOException {
|
|
||||||
if (peer != 0) {
|
|
||||||
close(peer);
|
|
||||||
peer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,11 @@ public abstract class Selector {
|
|||||||
|
|
||||||
public abstract Selector wakeup();
|
public abstract Selector wakeup();
|
||||||
|
|
||||||
|
public abstract int selectNow() throws IOException;
|
||||||
|
|
||||||
public abstract int select(long interval) throws IOException;
|
public abstract int select(long interval) throws IOException;
|
||||||
|
|
||||||
|
public abstract int select() throws IOException;
|
||||||
|
|
||||||
public abstract void close();
|
public abstract void close();
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public class ServerSocketChannel extends SelectableChannel {
|
|||||||
return new ServerSocketChannel();
|
return new ServerSocketChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectableChannel configureBlocking(boolean v) {
|
public SelectableChannel configureBlocking(boolean v) throws IOException {
|
||||||
return channel.configureBlocking(v);
|
return channel.configureBlocking(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +61,7 @@ public class ServerSocketChannel extends SelectableChannel {
|
|||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
channel.socket = doListen(a.getHostName(), a.getPort());
|
channel.socket = doListen(a.getHostName(), a.getPort());
|
||||||
|
channel.configureBlocking(channel.isBlocking());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,21 +24,29 @@ public class SocketChannel extends SelectableChannel
|
|||||||
|
|
||||||
int socket = InvalidSocket;
|
int socket = InvalidSocket;
|
||||||
boolean connected = false;
|
boolean connected = false;
|
||||||
|
boolean blocking = true;
|
||||||
|
|
||||||
public static SocketChannel open() {
|
public static SocketChannel open() {
|
||||||
return new SocketChannel();
|
return new SocketChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectableChannel configureBlocking(boolean v) {
|
public SelectableChannel configureBlocking(boolean v) throws IOException {
|
||||||
if (v) throw new IllegalArgumentException();
|
blocking = v;
|
||||||
|
if (socket != InvalidSocket) {
|
||||||
|
configureBlocking(socket, v);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBlocking() {
|
||||||
|
return blocking;
|
||||||
|
}
|
||||||
|
|
||||||
public Socket socket() {
|
public Socket socket() {
|
||||||
return new Handle();
|
return new Handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean connect(SocketAddress address) throws Exception {
|
public boolean connect(SocketAddress address) throws IOException {
|
||||||
InetSocketAddress a;
|
InetSocketAddress a;
|
||||||
try {
|
try {
|
||||||
a = (InetSocketAddress) address;
|
a = (InetSocketAddress) address;
|
||||||
@ -46,6 +54,7 @@ public class SocketChannel extends SelectableChannel
|
|||||||
throw new UnsupportedAddressTypeException();
|
throw new UnsupportedAddressTypeException();
|
||||||
}
|
}
|
||||||
socket = doConnect(a.getHostName(), a.getPort());
|
socket = doConnect(a.getHostName(), a.getPort());
|
||||||
|
configureBlocking(blocking);
|
||||||
return connected;
|
return connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,11 +65,11 @@ public class SocketChannel extends SelectableChannel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int doConnect(String host, int port) throws Exception {
|
private int doConnect(String host, int port) throws IOException {
|
||||||
if (host == null) throw new NullPointerException();
|
if (host == null) throw new NullPointerException();
|
||||||
|
|
||||||
boolean b[] = new boolean[1];
|
boolean b[] = new boolean[1];
|
||||||
int s = natDoConnect(host, port, b);
|
int s = natDoConnect(host, port, blocking, b);
|
||||||
connected = b[0];
|
connected = b[0];
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -109,11 +118,14 @@ public class SocketChannel extends SelectableChannel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native void configureBlocking(int socket, boolean blocking)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
private static native void natSetTcpNoDelay(int socket, boolean on)
|
private static native void natSetTcpNoDelay(int socket, boolean on)
|
||||||
throws SocketException;
|
throws SocketException;
|
||||||
|
|
||||||
private static native int natDoConnect(String host, int port, boolean[] connected)
|
private static native int natDoConnect(String host, int port, boolean blocking, boolean[] connected)
|
||||||
throws Exception;
|
throws IOException;
|
||||||
private static native int natRead(int socket, byte[] buffer, int offset, int length)
|
private static native int natRead(int socket, byte[] buffer, int offset, int length)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
private static native int natWrite(int socket, byte[] buffer, int offset, int length)
|
private static native int natWrite(int socket, byte[] buffer, int offset, int length)
|
||||||
|
@ -48,7 +48,21 @@ class SocketSelector extends Selector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized int selectNow() throws IOException {
|
||||||
|
return doSelect(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int select() throws IOException {
|
||||||
|
return doSelect(0);
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized int select(long interval) throws IOException {
|
public synchronized int select(long interval) throws IOException {
|
||||||
|
if (interval < 0) throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
return doSelect(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int doSelect(long interval) throws IOException {
|
||||||
selectedKeys.clear();
|
selectedKeys.clear();
|
||||||
|
|
||||||
if (clearWoken()) return 0;
|
if (clearWoken()) return 0;
|
||||||
|
13
classpath/java/security/AllPermission.java
Normal file
13
classpath/java/security/AllPermission.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.security;
|
||||||
|
|
||||||
|
public class AllPermission extends Permission { }
|
13
classpath/java/security/CodeSource.java
Normal file
13
classpath/java/security/CodeSource.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.security;
|
||||||
|
|
||||||
|
public class CodeSource { }
|
17
classpath/java/security/Permission.java
Normal file
17
classpath/java/security/Permission.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.security;
|
||||||
|
|
||||||
|
public abstract class Permission {
|
||||||
|
public PermissionCollection newPermissionCollection() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
15
classpath/java/security/PermissionCollection.java
Normal file
15
classpath/java/security/PermissionCollection.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.security;
|
||||||
|
|
||||||
|
public abstract class PermissionCollection {
|
||||||
|
public abstract void add(Permission p);
|
||||||
|
}
|
41
classpath/java/security/Permissions.java
Normal file
41
classpath/java/security/Permissions.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.security;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class Permissions extends PermissionCollection {
|
||||||
|
private final Map<Class,PermissionCollection> collections = new HashMap();
|
||||||
|
|
||||||
|
public void add(Permission p) {
|
||||||
|
Class c = p.getClass();
|
||||||
|
PermissionCollection pc = collections.get(c);
|
||||||
|
if (pc == null) {
|
||||||
|
pc = p.newPermissionCollection();
|
||||||
|
if (pc == null) {
|
||||||
|
pc = new MyPermissionCollection();
|
||||||
|
}
|
||||||
|
collections.put(c, pc);
|
||||||
|
}
|
||||||
|
pc.add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyPermissionCollection extends PermissionCollection {
|
||||||
|
private final Set<Permission> permissions = new HashSet();
|
||||||
|
|
||||||
|
public void add(Permission p) {
|
||||||
|
permissions.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
classpath/java/security/ProtectionDomain.java
Normal file
23
classpath/java/security/ProtectionDomain.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.security;
|
||||||
|
|
||||||
|
public class ProtectionDomain {
|
||||||
|
private final CodeSource codeSource;
|
||||||
|
private final PermissionCollection permissions;
|
||||||
|
|
||||||
|
public ProtectionDomain(CodeSource codeSource,
|
||||||
|
PermissionCollection permissions)
|
||||||
|
{
|
||||||
|
this.codeSource = codeSource;
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,10 @@ public abstract class AbstractCollection<T> implements Collection<T> {
|
|||||||
|
|
||||||
public abstract int size();
|
public abstract int size();
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public <S> S[] toArray(S[] array) {
|
public <S> S[] toArray(S[] array) {
|
||||||
return Collections.toArray(this, array);
|
return Collections.toArray(this, array);
|
||||||
}
|
}
|
||||||
|
15
classpath/java/util/AbstractList.java
Normal file
15
classpath/java/util/AbstractList.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.util;
|
||||||
|
|
||||||
|
public abstract class AbstractList<T> extends AbstractCollection<T>
|
||||||
|
implements List<T>
|
||||||
|
{ }
|
15
classpath/java/util/AbstractSequentialList.java
Normal file
15
classpath/java/util/AbstractSequentialList.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.util;
|
||||||
|
|
||||||
|
public abstract class AbstractSequentialList<T> extends AbstractList<T>
|
||||||
|
implements List<T>
|
||||||
|
{ }
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
public class ArrayList<T> implements List<T> {
|
public class ArrayList<T> extends AbstractList<T> {
|
||||||
private static final int MinimumCapacity = 16;
|
private static final int MinimumCapacity = 16;
|
||||||
|
|
||||||
private Object[] array;
|
private Object[] array;
|
||||||
@ -94,7 +94,7 @@ public class ArrayList<T> implements List<T> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int indexOf(T element) {
|
public int indexOf(Object element) {
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
if (equal(element, array[i])) {
|
if (equal(element, array[i])) {
|
||||||
return i;
|
return i;
|
||||||
@ -103,8 +103,8 @@ public class ArrayList<T> implements List<T> {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int lastIndexOf(T element) {
|
public int lastIndexOf(Object element) {
|
||||||
for (int i = size; i >= 0; --i) {
|
for (int i = size - 1; i >= 0; --i) {
|
||||||
if (equal(element, array[i])) {
|
if (equal(element, array[i])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -159,23 +159,23 @@ public class ArrayList<T> implements List<T> {
|
|||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <S> S[] toArray(S[] a) {
|
|
||||||
return Collections.toArray(this, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
array = null;
|
array = null;
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return new Collections.ArrayListIterator(this);
|
return listIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListIterator<T> listIterator(int index) {
|
public ListIterator<T> listIterator(int index) {
|
||||||
return new Collections.ArrayListIterator(this, index);
|
return new Collections.ArrayListIterator(this, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator() {
|
||||||
|
return listIterator(0);
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Collections.toString(this);
|
return Collections.toString(this);
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,24 @@ public class Arrays {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int indexOf(Object element) {
|
||||||
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
if (equal(element, array[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int lastIndexOf(Object element) {
|
||||||
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
|
if (equal(element, array[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
public T get(int index) {
|
public T get(int index) {
|
||||||
return array[index];
|
return array[index];
|
||||||
}
|
}
|
||||||
@ -81,6 +99,10 @@ public class Arrays {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public <S> S[] toArray(S[] a) {
|
public <S> S[] toArray(S[] a) {
|
||||||
return (S[])array;
|
return (S[])array;
|
||||||
}
|
}
|
||||||
@ -102,7 +124,15 @@ public class Arrays {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return new Collections.ArrayListIterator(this);
|
return listIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator(int index) {
|
||||||
|
return new Collections.ArrayListIterator(this, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator() {
|
||||||
|
return listIterator(0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ public interface Collection<T> extends Iterable<T> {
|
|||||||
|
|
||||||
public boolean remove(Object element);
|
public boolean remove(Object element);
|
||||||
|
|
||||||
|
public Object[] toArray();
|
||||||
|
|
||||||
public <S> S[] toArray(S[] array);
|
public <S> S[] toArray(S[] array);
|
||||||
|
|
||||||
public void clear();
|
public void clear();
|
||||||
|
@ -64,6 +64,22 @@ public class Collections {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String toString(Map m) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{");
|
||||||
|
for (Iterator<Map.Entry> it = m.entrySet().iterator(); it.hasNext();) {
|
||||||
|
Map.Entry e = it.next();
|
||||||
|
sb.append(e.getKey())
|
||||||
|
.append("=")
|
||||||
|
.append(e.getValue());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
static class IteratorEnumeration<T> implements Enumeration<T> {
|
static class IteratorEnumeration<T> implements Enumeration<T> {
|
||||||
private final Iterator<T> it;
|
private final Iterator<T> it;
|
||||||
|
|
||||||
@ -113,6 +129,10 @@ public class Collections {
|
|||||||
synchronized (lock) { return collection.remove((T)e); }
|
synchronized (lock) { return collection.remove((T)e); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public <T> T[] toArray(T[] array) {
|
public <T> T[] toArray(T[] array) {
|
||||||
synchronized (lock) { return collection.toArray(array); }
|
synchronized (lock) { return collection.toArray(array); }
|
||||||
}
|
}
|
||||||
@ -182,7 +202,6 @@ public class Collections {
|
|||||||
return new SynchronizedMap<K, V> (map);
|
return new SynchronizedMap<K, V> (map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class SynchronizedSet<T>
|
static class SynchronizedSet<T>
|
||||||
extends SynchronizedCollection<T>
|
extends SynchronizedCollection<T>
|
||||||
implements Set<T>
|
implements Set<T>
|
||||||
@ -216,7 +235,7 @@ public class Collections {
|
|||||||
|
|
||||||
static class ArrayListIterator<T> implements ListIterator<T> {
|
static class ArrayListIterator<T> implements ListIterator<T> {
|
||||||
private final List<T> list;
|
private final List<T> list;
|
||||||
private boolean canRemove = false;
|
private int toRemove = -1;
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
public ArrayListIterator(List<T> list) {
|
public ArrayListIterator(List<T> list) {
|
||||||
@ -234,7 +253,7 @@ public class Collections {
|
|||||||
|
|
||||||
public T previous() {
|
public T previous() {
|
||||||
if (hasPrevious()) {
|
if (hasPrevious()) {
|
||||||
canRemove = true;
|
toRemove = index;
|
||||||
return list.get(index--);
|
return list.get(index--);
|
||||||
} else {
|
} else {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
@ -243,8 +262,8 @@ public class Collections {
|
|||||||
|
|
||||||
public T next() {
|
public T next() {
|
||||||
if (hasNext()) {
|
if (hasNext()) {
|
||||||
canRemove = true;
|
toRemove = ++index;
|
||||||
return list.get(++index);
|
return list.get(index);
|
||||||
} else {
|
} else {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
@ -255,9 +274,10 @@ public class Collections {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (canRemove) {
|
if (toRemove != -1) {
|
||||||
canRemove = false;
|
list.remove(toRemove);
|
||||||
list.remove(index--);
|
index = toRemove - 1;
|
||||||
|
toRemove = -1;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
@ -303,13 +323,56 @@ public class Collections {
|
|||||||
return inner.size();
|
return inner.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public <S> S[] toArray(S[] array) {
|
public <S> S[] toArray(S[] array) {
|
||||||
return inner.toArray(array);
|
return inner.toArray(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Set<T> unmodifiableSet(Set<T> hs) {
|
public static <T> Set<T> unmodifiableSet(Set<T> hs) {
|
||||||
return new UnmodifiableSet<T>(hs);
|
return new UnmodifiableSet<T>(hs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class KeyIterator<K, V> implements Iterator<K> {
|
||||||
|
private final Iterator<Map.Entry<K, V>> it;
|
||||||
|
|
||||||
|
public KeyIterator(Iterator<Map.Entry<K, V>> it) {
|
||||||
|
this.it = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
public K next() {
|
||||||
|
return it.next().getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ValueIterator<K, V> implements Iterator<V> {
|
||||||
|
private final Iterator<Map.Entry<K, V>> it;
|
||||||
|
|
||||||
|
public ValueIterator(Iterator<Map.Entry<K, V>> it) {
|
||||||
|
this.it = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V next() {
|
||||||
|
return it.next().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,19 +40,7 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
return Collections.toString(this);
|
||||||
sb.append("{");
|
|
||||||
for (Iterator<Entry<K, V>> it = iterator(); it.hasNext();) {
|
|
||||||
Entry<K, V> e = it.next();
|
|
||||||
sb.append(e.getKey())
|
|
||||||
.append("=")
|
|
||||||
.append(e.getValue());
|
|
||||||
if (it.hasNext()) {
|
|
||||||
sb.append(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb.append("}");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int nextPowerOfTwo(int n) {
|
private static int nextPowerOfTwo(int n) {
|
||||||
@ -324,7 +312,8 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
return (o instanceof Entry<?,?>) ? containsKey(((Entry<?,?>)o).getKey()) : false;
|
return (o instanceof Entry<?,?>)
|
||||||
|
&& containsKey(((Entry<?,?>)o).getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(Entry<K, V> e) {
|
public boolean add(Entry<K, V> e) {
|
||||||
@ -337,14 +326,18 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Object o) {
|
public boolean remove(Object o) {
|
||||||
return (o instanceof Entry<?,?>) ? remove((Entry<?,?>)o) : false;
|
return (o instanceof Entry<?,?>) && remove((Entry<?,?>)o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Entry<K, V> e) {
|
public boolean remove(Entry<K, V> e) {
|
||||||
return removeCell(e.getKey()) != null;
|
return removeCell(e.getKey()) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public <T> T[] toArray(T[] array) {
|
public <T> T[] toArray(T[] array) {
|
||||||
return Collections.toArray(this, array);
|
return Collections.toArray(this, array);
|
||||||
}
|
}
|
||||||
@ -385,6 +378,10 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
return removeCell(key) != null;
|
return removeCell(key) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public <T> T[] toArray(T[] array) {
|
public <T> T[] toArray(T[] array) {
|
||||||
return Collections.toArray(this, array);
|
return Collections.toArray(this, array);
|
||||||
}
|
}
|
||||||
@ -394,11 +391,10 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<K> iterator() {
|
public Iterator<K> iterator() {
|
||||||
return new KeyIterator(new MyIterator());
|
return new Collections.KeyIterator(new MyIterator());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class Values implements Collection<V> {
|
private class Values implements Collection<V> {
|
||||||
public int size() {
|
public int size() {
|
||||||
return HashMap.this.size();
|
return HashMap.this.size();
|
||||||
@ -424,6 +420,10 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
public <T> T[] toArray(T[] array) {
|
public <T> T[] toArray(T[] array) {
|
||||||
return Collections.toArray(this, array);
|
return Collections.toArray(this, array);
|
||||||
}
|
}
|
||||||
@ -433,7 +433,7 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<V> iterator() {
|
public Iterator<V> iterator() {
|
||||||
return new ValueIterator(new MyIterator());
|
return new Collections.ValueIterator(new MyIterator());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,44 +495,4 @@ public class HashMap<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class KeyIterator<K, V> implements Iterator<K> {
|
|
||||||
private final Iterator<Entry<K, V>> it;
|
|
||||||
|
|
||||||
public KeyIterator(Iterator<Entry<K, V>> it) {
|
|
||||||
this.it = it;
|
|
||||||
}
|
|
||||||
|
|
||||||
public K next() {
|
|
||||||
return it.next().getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return it.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ValueIterator<K, V> implements Iterator<V> {
|
|
||||||
private final Iterator<Entry<K, V>> it;
|
|
||||||
|
|
||||||
public ValueIterator(Iterator<Entry<K, V>> it) {
|
|
||||||
this.it = it;
|
|
||||||
}
|
|
||||||
|
|
||||||
public V next() {
|
|
||||||
return it.next().getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return it.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
public class HashSet<T> implements Set<T> {
|
public class HashSet<T> extends AbstractSet<T> implements Set<T> {
|
||||||
private static final Object Value = new Object();
|
private static final Object Value = new Object();
|
||||||
|
|
||||||
private final HashMap<T, Object> map;
|
private final HashMap<T, Object> map;
|
||||||
@ -54,10 +54,6 @@ public class HashSet<T> implements Set<T> {
|
|||||||
return map.remove(element) != Value;
|
return map.remove(element) != Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T[] toArray(T[] array) {
|
|
||||||
return Collections.toArray(this, array);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
map.clear();
|
map.clear();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class Hashtable<K, V> implements Map<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public synchronized String toString() {
|
||||||
return map.toString();
|
return map.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
public class LinkedList<T> implements List<T> {
|
public class LinkedList<T> extends AbstractSequentialList<T> {
|
||||||
private Cell<T> front;
|
private Cell<T> front;
|
||||||
private Cell<T> rear;
|
private Cell<T> rear;
|
||||||
private int size;
|
private int size;
|
||||||
@ -85,10 +85,6 @@ public class LinkedList<T> implements List<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <S> S[] toArray(S[] a) {
|
|
||||||
return Collections.toArray(this, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -97,8 +93,26 @@ public class LinkedList<T> implements List<T> {
|
|||||||
return find(element) != null;
|
return find(element) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAll(Collection<T> c) {
|
public int indexOf(Object element) {
|
||||||
for (T t: c) add(t);
|
int i = 0;
|
||||||
|
for (Cell<T> c = front; c != null; c = c.next) {
|
||||||
|
if (equal(c.value, element)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int lastIndexOf(Object element) {
|
||||||
|
int i = size;
|
||||||
|
for (Cell<T> c = rear; c != null; c = c.prev) {
|
||||||
|
-- i;
|
||||||
|
if (equal(c.value, element)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(T element) {
|
public boolean add(T element) {
|
||||||
@ -202,7 +216,19 @@ public class LinkedList<T> implements List<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return new MyIterator(front);
|
return listIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator(int index) {
|
||||||
|
MyIterator it = new MyIterator();
|
||||||
|
for (int i = 0; i < index; ++i) {
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator() {
|
||||||
|
return listIterator(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -221,18 +247,29 @@ public class LinkedList<T> implements List<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyIterator implements Iterator<T> {
|
private class MyIterator implements ListIterator<T> {
|
||||||
|
private Cell<T> toRemove;
|
||||||
private Cell<T> current;
|
private Cell<T> current;
|
||||||
private Cell<T> next;
|
|
||||||
|
|
||||||
public MyIterator(Cell<T> start) {
|
public T previous() {
|
||||||
next = start;
|
if (hasPrevious()) {
|
||||||
|
T v = current.value;
|
||||||
|
toRemove = current;
|
||||||
|
current = current.prev;
|
||||||
|
return v;
|
||||||
|
} else {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public T next() {
|
public T next() {
|
||||||
if (hasNext()) {
|
if (hasNext()) {
|
||||||
current = next;
|
if (current == null) {
|
||||||
next = next.next;
|
current = front;
|
||||||
|
} else {
|
||||||
|
current = current.next;
|
||||||
|
}
|
||||||
|
toRemove = current;
|
||||||
return current.value;
|
return current.value;
|
||||||
} else {
|
} else {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
@ -240,13 +277,22 @@ public class LinkedList<T> implements List<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return next != null;
|
if (current == null) {
|
||||||
|
return front != null;
|
||||||
|
} else {
|
||||||
|
return current.next != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPrevious() {
|
||||||
|
return current != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (current != null) {
|
if (toRemove != null) {
|
||||||
LinkedList.this.remove(current);
|
current = toRemove.prev;
|
||||||
current = null;
|
LinkedList.this.remove(toRemove);
|
||||||
|
toRemove = null;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,13 @@ public interface List<T> extends Collection<T> {
|
|||||||
|
|
||||||
public void add(int index, T element);
|
public void add(int index, T element);
|
||||||
|
|
||||||
|
public int indexOf(Object value);
|
||||||
|
|
||||||
|
public int lastIndexOf(Object value);
|
||||||
|
|
||||||
public boolean isEmpty();
|
public boolean isEmpty();
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator(int index);
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator();
|
||||||
}
|
}
|
||||||
|
205
classpath/java/util/TreeMap.java
Normal file
205
classpath/java/util/TreeMap.java
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.util;
|
||||||
|
|
||||||
|
public class TreeMap<K,V> implements Map<K,V> {
|
||||||
|
private TreeSet<MyEntry<K,V>> set;
|
||||||
|
|
||||||
|
public TreeMap(final Comparator<K> comparator) {
|
||||||
|
set = new TreeSet(new Comparator<MyEntry<K,V>>() {
|
||||||
|
public int compare(MyEntry<K,V> a, MyEntry<K,V> b) {
|
||||||
|
return comparator.compare(a.key, b.key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeMap() {
|
||||||
|
this(new Comparator<K>() {
|
||||||
|
public int compare(K a, K b) {
|
||||||
|
return ((Comparable) a).compareTo(b);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return Collections.toString(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get(Object key) {
|
||||||
|
MyEntry<K,V> e = set.find(new MyEntry(key, null));
|
||||||
|
return e == null ? null : e.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V put(K key, V value) {
|
||||||
|
MyEntry<K,V> e = set.addAndReplace(new MyEntry(key, value));
|
||||||
|
return e == null ? null : e.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putAll(Map<? extends K,? extends V> elts) {
|
||||||
|
for (Map.Entry<? extends K, ? extends V> entry : elts.entrySet()) {
|
||||||
|
put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public V remove(Object key) {
|
||||||
|
MyEntry<K,V> e = set.removeAndReturn(new MyEntry(key, null));
|
||||||
|
return e == null ? null : e.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
set.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return set.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
return set.contains(new MyEntry(key, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean equal(Object a, Object b) {
|
||||||
|
return a == null ? b == null : a.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
for (V v: values()) {
|
||||||
|
if (equal(v, value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Entry<K, V>> entrySet() {
|
||||||
|
return (Set<Entry<K, V>>) (Set) set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<K> keySet() {
|
||||||
|
return new KeySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<V> values() {
|
||||||
|
return new Values();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyEntry<K,V> implements Entry<K,V> {
|
||||||
|
public final K key;
|
||||||
|
public V value;
|
||||||
|
|
||||||
|
public MyEntry(K key, V value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public K getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(V value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class KeySet implements Set<K> {
|
||||||
|
public int size() {
|
||||||
|
return TreeMap.this.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return TreeMap.this.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object key) {
|
||||||
|
return containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(K key) {
|
||||||
|
return set.addAndReplace(new MyEntry(key, null)) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addAll(Collection<? extends K> collection) {
|
||||||
|
boolean change = false;
|
||||||
|
for (K k: collection) if (add(k)) change = true;
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object key) {
|
||||||
|
return set.removeAndReturn(new MyEntry(key, null)) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T[] toArray(T[] array) {
|
||||||
|
return Collections.toArray(this, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
TreeMap.this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<K> iterator() {
|
||||||
|
return new Collections.KeyIterator(set.iterator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Values implements Collection<V> {
|
||||||
|
public int size() {
|
||||||
|
return TreeMap.this.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return TreeMap.this.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object value) {
|
||||||
|
return containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(V value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addAll(Collection<? extends V> collection) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return toArray(new Object[size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T[] toArray(T[] array) {
|
||||||
|
return Collections.toArray(this, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
TreeMap.this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<V> iterator() {
|
||||||
|
return new Collections.ValueIterator(set.iterator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -10,7 +10,10 @@
|
|||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
public class TreeSet<T> extends AbstractSet<T> implements Collection<T> {
|
import avian.PersistentSet;
|
||||||
|
import avian.Cell;
|
||||||
|
|
||||||
|
public class TreeSet<T> extends AbstractSet<T> implements Collection<T> {
|
||||||
private PersistentSet<Cell<T>> set;
|
private PersistentSet<Cell<T>> set;
|
||||||
private int size;
|
private int size;
|
||||||
|
|
||||||
@ -49,34 +52,52 @@ public class TreeSet<T> extends AbstractSet<T> implements Collection<T> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by hashMaps for replacement
|
T addAndReplace(T value) {
|
||||||
public void addAndReplace(T value) {
|
|
||||||
PersistentSet.Path<Cell<T>> p = set.find(new Cell(value, null));
|
PersistentSet.Path<Cell<T>> p = set.find(new Cell(value, null));
|
||||||
if (p.fresh()) {
|
if (p.fresh()) {
|
||||||
set = p.add();
|
set = p.add();
|
||||||
++size;
|
++size;
|
||||||
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
T old = p.value().value;
|
||||||
set = p.replaceWith(new Cell(value, null));
|
set = p.replaceWith(new Cell(value, null));
|
||||||
|
return old;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Object value) {
|
T find(T value) {
|
||||||
|
PersistentSet.Path<Cell<T>> p = set.find(new Cell(value, null));
|
||||||
|
return p.fresh() ? null : p.value().value;
|
||||||
|
}
|
||||||
|
|
||||||
|
T removeAndReturn(T value) {
|
||||||
|
Cell<T> cell = removeCell(value);
|
||||||
|
return cell == null ? null : cell.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cell<T> removeCell(Object value) {
|
||||||
PersistentSet.Path<Cell<T>> p = set.find(new Cell(value, null));
|
PersistentSet.Path<Cell<T>> p = set.find(new Cell(value, null));
|
||||||
if (p.fresh()) {
|
if (p.fresh()) {
|
||||||
return false;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
--size;
|
--size;
|
||||||
|
|
||||||
|
Cell<T> old = p.value();
|
||||||
|
|
||||||
if (p.value().next != null) {
|
if (p.value().next != null) {
|
||||||
set = p.replaceWith(p.value().next);
|
set = p.replaceWith(p.value().next);
|
||||||
} else {
|
} else {
|
||||||
set = p.remove();
|
set = p.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return old;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object value) {
|
||||||
|
return removeCell(value) != null;
|
||||||
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
public class Vector<T> implements List<T> {
|
public class Vector<T> extends AbstractList<T> {
|
||||||
private final ArrayList<T> list;
|
private final ArrayList<T> list;
|
||||||
|
|
||||||
public Vector(int capacity) {
|
public Vector(int capacity) {
|
||||||
@ -77,10 +77,6 @@ public class Vector<T> implements List<T> {
|
|||||||
return list.isEmpty();
|
return list.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized <S> S[] toArray(S[] a) {
|
|
||||||
return list.toArray(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeElementAt(int index) {
|
public void removeElementAt(int index) {
|
||||||
remove(index);
|
remove(index);
|
||||||
}
|
}
|
||||||
@ -97,11 +93,11 @@ public class Vector<T> implements List<T> {
|
|||||||
list.clear();
|
list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int indexOf(T element) {
|
public synchronized int indexOf(Object element) {
|
||||||
return list.indexOf(element);
|
return list.indexOf(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int lastIndexOf(T element) {
|
public synchronized int lastIndexOf(Object element) {
|
||||||
return list.lastIndexOf(element);
|
return list.lastIndexOf(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +108,15 @@ public class Vector<T> implements List<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return new Collections.ArrayListIterator(this);
|
return listIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator(int index) {
|
||||||
|
return new Collections.ArrayListIterator(this, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListIterator<T> listIterator() {
|
||||||
|
return listIterator(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration<T> elements() {
|
public Enumeration<T> elements() {
|
||||||
|
15
classpath/java/util/concurrent/Callable.java
Normal file
15
classpath/java/util/concurrent/Callable.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.util.concurrent;
|
||||||
|
|
||||||
|
public interface Callable<T> {
|
||||||
|
public T call() throws Exception;
|
||||||
|
}
|
@ -113,8 +113,9 @@ public class Logger {
|
|||||||
if (level.intValue() < getEffectiveLevel().intValue()) {
|
if (level.intValue() < getEffectiveLevel().intValue()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogRecord r = new LogRecord(name, caller.getName(), level, message,
|
LogRecord r = new LogRecord
|
||||||
exception);
|
(name, caller == null ? "<unknown>" : caller.getName(), level, message,
|
||||||
|
exception);
|
||||||
publish(r);
|
publish(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2008, Avian Contributors
|
/* Copyright (c) 2008-2009, Avian Contributors
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
for any purpose with or without fee is hereby granted, provided
|
for any purpose with or without fee is hereby granted, provided
|
||||||
@ -63,7 +63,7 @@ public class ZipFile {
|
|||||||
return index.size();
|
return index.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration<ZipEntry> entries() {
|
public Enumeration<? extends ZipEntry> entries() {
|
||||||
return new MyEnumeration(window, index.values().iterator());
|
return new MyEnumeration(window, index.values().iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
170
makefile
170
makefile
@ -14,7 +14,9 @@ build-platform = \
|
|||||||
| sed 's/^cygwin.*$$/cygwin/')
|
| sed 's/^cygwin.*$$/cygwin/')
|
||||||
|
|
||||||
arch = $(build-arch)
|
arch = $(build-arch)
|
||||||
platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))
|
bootimage-platform = \
|
||||||
|
$(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))
|
||||||
|
platform = $(bootimage-platform)
|
||||||
|
|
||||||
mode = fast
|
mode = fast
|
||||||
process = compile
|
process = compile
|
||||||
@ -31,6 +33,29 @@ endif
|
|||||||
ifeq ($(heapdump),true)
|
ifeq ($(heapdump),true)
|
||||||
options := $(options)-heapdump
|
options := $(options)-heapdump
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(tails),true)
|
||||||
|
options := $(options)-tails
|
||||||
|
endif
|
||||||
|
ifeq ($(continuations),true)
|
||||||
|
options := $(options)-continuations
|
||||||
|
endif
|
||||||
|
ifdef gnu
|
||||||
|
options := $(options)-gnu
|
||||||
|
gnu-sources = $(src)/gnu.cpp
|
||||||
|
gnu-jar = $(gnu)/share/classpath/glibj.zip
|
||||||
|
gnu-libraries = \
|
||||||
|
$(gnu)/lib/classpath/libjavaio.a \
|
||||||
|
$(gnu)/lib/classpath/libjavalang.a \
|
||||||
|
$(gnu)/lib/classpath/libjavalangreflect.a \
|
||||||
|
$(gnu)/lib/classpath/libjavamath.a \
|
||||||
|
$(gnu)/lib/classpath/libjavanet.a \
|
||||||
|
$(gnu)/lib/classpath/libjavanio.a \
|
||||||
|
$(gnu)/lib/classpath/libjavautil.a
|
||||||
|
gnu-object-dep = $(build)/gnu-object.dep
|
||||||
|
gnu-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU
|
||||||
|
gnu-lflags = -lgmp
|
||||||
|
gnu-objects = $(shell find $(build)/gnu-objects -name "*.o")
|
||||||
|
endif
|
||||||
|
|
||||||
root = $(shell (cd .. && pwd))
|
root = $(shell (cd .. && pwd))
|
||||||
build = build
|
build = build
|
||||||
@ -41,6 +66,12 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
|
ifdef gnu
|
||||||
|
avian-classpath-build = $(build)/avian-classpath
|
||||||
|
else
|
||||||
|
avian-classpath-build = $(classpath-build)
|
||||||
|
endif
|
||||||
|
|
||||||
input = List
|
input = List
|
||||||
|
|
||||||
build-cxx = g++
|
build-cxx = g++
|
||||||
@ -71,13 +102,14 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
|
|||||||
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
||||||
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
|
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
|
||||||
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
||||||
|
$(gnu-cflags)
|
||||||
|
|
||||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
||||||
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
||||||
|
|
||||||
cflags = $(build-cflags)
|
cflags = $(build-cflags)
|
||||||
|
|
||||||
common-lflags = -lm -lz
|
common-lflags = -lm -lz $(gnu-lflags)
|
||||||
|
|
||||||
build-lflags =
|
build-lflags =
|
||||||
|
|
||||||
@ -111,7 +143,7 @@ endif
|
|||||||
|
|
||||||
ifeq ($(platform),darwin)
|
ifeq ($(platform),darwin)
|
||||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
|
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src)
|
||||||
lflags = $(common-lflags) -ldl -framework CoreFoundation
|
lflags = $(common-lflags) -ldl -framework CoreFoundation -framework CoreServices
|
||||||
ifeq ($(bootimage),true)
|
ifeq ($(bootimage),true)
|
||||||
bootimage-lflags = -Wl,-segprot,__BOOT,rwx,rwx
|
bootimage-lflags = -Wl,-segprot,__BOOT,rwx,rwx
|
||||||
endif
|
endif
|
||||||
@ -166,7 +198,6 @@ ifeq ($(platform),windows)
|
|||||||
strip = :
|
strip = :
|
||||||
inc = "$(root)/win64/include"
|
inc = "$(root)/win64/include"
|
||||||
lib = "$(root)/win64/lib"
|
lib = "$(root)/win64/lib"
|
||||||
cflags += -D__x86_64__ -D__WINDOWS__
|
|
||||||
pointer-size = 8
|
pointer-size = 8
|
||||||
object-format = pe-x86-64
|
object-format = pe-x86-64
|
||||||
endif
|
endif
|
||||||
@ -236,7 +267,8 @@ vm-sources = \
|
|||||||
$(src)/$(process).cpp \
|
$(src)/$(process).cpp \
|
||||||
$(src)/builtin.cpp \
|
$(src)/builtin.cpp \
|
||||||
$(src)/jnienv.cpp \
|
$(src)/jnienv.cpp \
|
||||||
$(src)/process.cpp
|
$(src)/process.cpp \
|
||||||
|
$(gnu-sources)
|
||||||
|
|
||||||
vm-asm-sources = $(src)/$(asm).S
|
vm-asm-sources = $(src)/$(asm).S
|
||||||
|
|
||||||
@ -266,11 +298,20 @@ ifeq ($(heapdump),true)
|
|||||||
cflags += -DAVIAN_HEAPDUMP
|
cflags += -DAVIAN_HEAPDUMP
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(tails),true)
|
||||||
|
cflags += -DAVIAN_TAILS
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(continuations),true)
|
||||||
|
cflags += -DAVIAN_CONTINUATIONS
|
||||||
|
asmflags += -DAVIAN_CONTINUATIONS
|
||||||
|
endif
|
||||||
|
|
||||||
bootimage-generator-sources = $(src)/bootimage.cpp
|
bootimage-generator-sources = $(src)/bootimage.cpp
|
||||||
bootimage-generator-objects = \
|
bootimage-generator-objects = \
|
||||||
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(native-build))
|
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(native-build))
|
||||||
bootimage-generator = \
|
bootimage-generator = \
|
||||||
$(build)/$(build-platform)-$(build-arch)$(options)/bootimage-generator
|
$(build)/$(bootimage-platform)-$(build-arch)$(options)/bootimage-generator
|
||||||
|
|
||||||
bootimage-bin = $(native-build)/bootimage.bin
|
bootimage-bin = $(native-build)/bootimage.bin
|
||||||
bootimage-object = $(native-build)/bootimage-bin.o
|
bootimage-object = $(native-build)/bootimage-bin.o
|
||||||
@ -309,11 +350,43 @@ classpath-sources = $(shell find $(classpath) -name '*.java')
|
|||||||
classpath-classes = \
|
classpath-classes = \
|
||||||
$(call java-classes,$(classpath-sources),$(classpath),$(classpath-build))
|
$(call java-classes,$(classpath-sources),$(classpath),$(classpath-build))
|
||||||
classpath-object = $(native-build)/classpath-jar.o
|
classpath-object = $(native-build)/classpath-jar.o
|
||||||
classpath-dep = $(classpath-build)/dep
|
classpath-dep = $(classpath-build).dep
|
||||||
|
|
||||||
|
gnu-blacklist = \
|
||||||
|
java/lang/AbstractStringBuffer.class \
|
||||||
|
java/lang/reflect/Proxy.class
|
||||||
|
|
||||||
|
gnu-overrides = \
|
||||||
|
avian/*.class \
|
||||||
|
avian/resource/*.class \
|
||||||
|
java/lang/Class.class \
|
||||||
|
java/lang/Enum.class \
|
||||||
|
java/lang/InheritableThreadLocal.class \
|
||||||
|
java/lang/Object.class \
|
||||||
|
java/lang/StackTraceElement.class \
|
||||||
|
java/lang/String*.class \
|
||||||
|
java/lang/StringBuffer.class \
|
||||||
|
java/lang/StringBuilder.class \
|
||||||
|
java/lang/Thread.class \
|
||||||
|
java/lang/ThreadLocal.class \
|
||||||
|
java/lang/Throwable.class \
|
||||||
|
java/lang/ref/PhantomReference.class \
|
||||||
|
java/lang/ref/Reference.class \
|
||||||
|
java/lang/ref/ReferenceQueue.class \
|
||||||
|
java/lang/ref/WeakReference.class \
|
||||||
|
java/lang/reflect/AccessibleObject.class \
|
||||||
|
java/lang/reflect/Constructor.class \
|
||||||
|
java/lang/reflect/Field.class \
|
||||||
|
java/lang/reflect/Method.class
|
||||||
|
|
||||||
test-sources = $(wildcard $(test)/*.java)
|
test-sources = $(wildcard $(test)/*.java)
|
||||||
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
|
test-classes = $(call java-classes,$(test-sources),$(test),$(test-build))
|
||||||
test-dep = $(test-build)/dep
|
test-dep = $(test-build).dep
|
||||||
|
|
||||||
|
test-extra-sources = $(wildcard $(test)/extra/*.java)
|
||||||
|
test-extra-classes = \
|
||||||
|
$(call java-classes,$(test-extra-sources),$(test),$(test-build))
|
||||||
|
test-extra-dep = $(test-build)-extra.dep
|
||||||
|
|
||||||
class-name = $(patsubst $(1)/%.class,%,$(2))
|
class-name = $(patsubst $(1)/%.class,%,$(2))
|
||||||
class-names = $(foreach x,$(2),$(call class-name,$(1),$(x)))
|
class-names = $(foreach x,$(2),$(call class-name,$(1),$(x)))
|
||||||
@ -324,7 +397,7 @@ args = $(flags) $(input)
|
|||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(static-library) $(executable) $(dynamic-library) \
|
build: $(static-library) $(executable) $(dynamic-library) \
|
||||||
$(executable-dynamic) $(classpath-dep) $(test-dep)
|
$(executable-dynamic) $(classpath-dep) $(test-dep) $(test-extra-dep)
|
||||||
|
|
||||||
$(test-classes): $(classpath-dep)
|
$(test-classes): $(classpath-dep)
|
||||||
|
|
||||||
@ -355,7 +428,7 @@ tarball:
|
|||||||
|
|
||||||
.PHONY: javadoc
|
.PHONY: javadoc
|
||||||
javadoc:
|
javadoc:
|
||||||
javadoc -sourcepath classpath -d build/javadoc -subpackages java \
|
javadoc -sourcepath classpath -d build/javadoc -subpackages avian:java \
|
||||||
-windowtitle "Avian v$(version) Class Library API" \
|
-windowtitle "Avian v$(version) Class Library API" \
|
||||||
-doctitle "Avian v$(version) Class Library API" \
|
-doctitle "Avian v$(version) Class Library API" \
|
||||||
-header "Avian v$(version)" \
|
-header "Avian v$(version)" \
|
||||||
@ -383,11 +456,24 @@ $(native-build)/type-generator.o: \
|
|||||||
$(classpath-build)/%.class: $(classpath)/%.java
|
$(classpath-build)/%.class: $(classpath)/%.java
|
||||||
@echo $(<)
|
@echo $(<)
|
||||||
|
|
||||||
$(classpath-dep): $(classpath-sources)
|
$(classpath-dep): $(classpath-sources) $(gnu-jar)
|
||||||
@echo "compiling classpath classes"
|
@echo "compiling classpath classes"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(avian-classpath-build)
|
||||||
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
|
$(javac) -d $(avian-classpath-build) \
|
||||||
|
-bootclasspath $(avian-classpath-build) \
|
||||||
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
|
$(shell $(MAKE) -s --no-print-directory $(classpath-classes))
|
||||||
|
ifdef gnu
|
||||||
|
(wd=$$(pwd) && \
|
||||||
|
cd $(avian-classpath-build) && \
|
||||||
|
$(jar) c0f "$$($(native-path) "$${wd}/$(build)/overrides.jar")" \
|
||||||
|
$(gnu-overrides))
|
||||||
|
@mkdir -p $(classpath-build)
|
||||||
|
(wd=$$(pwd) && \
|
||||||
|
cd $(classpath-build) && \
|
||||||
|
$(jar) xf $(gnu-jar) && \
|
||||||
|
rm $(gnu-blacklist) && \
|
||||||
|
jar xf "$$($(native-path) "$${wd}/$(build)/overrides.jar")")
|
||||||
|
endif
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
$(test-build)/%.class: $(test)/%.java
|
$(test-build)/%.class: $(test)/%.java
|
||||||
@ -395,13 +481,20 @@ $(test-build)/%.class: $(test)/%.java
|
|||||||
|
|
||||||
$(test-dep): $(test-sources)
|
$(test-dep): $(test-sources)
|
||||||
@echo "compiling test classes"
|
@echo "compiling test classes"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(test-build)
|
||||||
$(javac) -d $(dir $(@)) -bootclasspath $(classpath-build) \
|
$(javac) -d $(test-build) -bootclasspath $(classpath-build) \
|
||||||
$(shell $(MAKE) -s --no-print-directory $(test-classes))
|
$(shell $(MAKE) -s --no-print-directory $(test-classes))
|
||||||
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(dir $(@)) \
|
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(test-build) \
|
||||||
test/Subroutine.java
|
test/Subroutine.java
|
||||||
@touch $(@)
|
@touch $(@)
|
||||||
|
|
||||||
|
$(test-extra-dep): $(test-extra-sources)
|
||||||
|
@echo "compiling extra test classes"
|
||||||
|
@mkdir -p $(test-build)
|
||||||
|
$(javac) -d $(test-build) -bootclasspath $(classpath-build) \
|
||||||
|
$(shell $(MAKE) -s --no-print-directory $(test-extra-classes))
|
||||||
|
@touch $(@)
|
||||||
|
|
||||||
define compile-object
|
define compile-object
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
@ -411,7 +504,7 @@ endef
|
|||||||
define compile-asm-object
|
define compile-asm-object
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cc) $(cflags) -I$(src) -c $(<) -o $(@)
|
$(cc) -I$(src) $(asmflags) -c $(<) -o $(@)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(vm-cpp-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
|
$(vm-cpp-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
|
||||||
@ -439,9 +532,9 @@ $(boot-object): $(boot-source)
|
|||||||
$(compile-object)
|
$(compile-object)
|
||||||
|
|
||||||
$(build)/classpath.jar: $(classpath-dep)
|
$(build)/classpath.jar: $(classpath-dep)
|
||||||
(wd=$$(pwd); \
|
(wd=$$(pwd) && \
|
||||||
cd $(classpath-build); \
|
cd $(classpath-build) && \
|
||||||
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $$(find . -name '*.class'))
|
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .)
|
||||||
|
|
||||||
$(binaryToMacho): $(src)/binaryToMacho.cpp
|
$(binaryToMacho): $(src)/binaryToMacho.cpp
|
||||||
$(cxx) $(^) -o $(@)
|
$(cxx) $(^) -o $(@)
|
||||||
@ -452,8 +545,8 @@ ifeq ($(platform),darwin)
|
|||||||
$(binaryToMacho) $(asm) $(build)/classpath.jar __TEXT __text \
|
$(binaryToMacho) $(asm) $(build)/classpath.jar __TEXT __text \
|
||||||
__binary_classpath_jar_start __binary_classpath_jar_end > $(@)
|
__binary_classpath_jar_start __binary_classpath_jar_end > $(@)
|
||||||
else
|
else
|
||||||
(wd=$$(pwd); \
|
(wd=$$(pwd) && \
|
||||||
cd $(build); \
|
cd $(build) && \
|
||||||
$(objcopy) -I binary classpath.jar \
|
$(objcopy) -I binary classpath.jar \
|
||||||
-O $(object-format) -B $(object-arch) "$${wd}/$(@)")
|
-O $(object-format) -B $(object-arch) "$${wd}/$(@)")
|
||||||
endif
|
endif
|
||||||
@ -467,14 +560,15 @@ $(generator-objects): $(native-build)/%.o: $(src)/%.cpp
|
|||||||
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
|
$(jni-objects): $(native-build)/%.o: $(classpath)/%.cpp
|
||||||
$(compile-object)
|
$(compile-object)
|
||||||
|
|
||||||
|
$(static-library): $(gnu-object-dep)
|
||||||
$(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects)
|
$(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects)
|
||||||
@echo "creating $(@)"
|
@echo "creating $(@)"
|
||||||
rm -rf $(@)
|
rm -rf $(@)
|
||||||
$(ar) cru $(@) $(^)
|
$(ar) cru $(@) $(^) $(call gnu-objects)
|
||||||
$(ranlib) $(@)
|
$(ranlib) $(@)
|
||||||
|
|
||||||
$(bootimage-bin): $(bootimage-generator)
|
$(bootimage-bin): $(bootimage-generator)
|
||||||
$(<) $(classpath-build) > $(@)
|
$(<) $(classpath-build) $(@)
|
||||||
|
|
||||||
$(bootimage-object): $(bootimage-bin) $(binaryToMacho)
|
$(bootimage-object): $(bootimage-bin) $(binaryToMacho)
|
||||||
@echo "creating $(@)"
|
@echo "creating $(@)"
|
||||||
@ -482,24 +576,32 @@ ifeq ($(platform),darwin)
|
|||||||
$(binaryToMacho) $(asm) $(<) __BOOT __boot \
|
$(binaryToMacho) $(asm) $(<) __BOOT __boot \
|
||||||
__binary_bootimage_bin_start __binary_bootimage_bin_end > $(@)
|
__binary_bootimage_bin_start __binary_bootimage_bin_end > $(@)
|
||||||
else
|
else
|
||||||
(wd=$$(pwd); \
|
(wd=$$(pwd) && \
|
||||||
cd $(native-build); \
|
cd $(native-build) && \
|
||||||
$(objcopy) --rename-section=.data=.boot -I binary bootimage.bin \
|
$(objcopy) --rename-section=.data=.boot -I binary bootimage.bin \
|
||||||
-O $(object-format) -B $(object-arch) "$${wd}/$(@).tmp"; \
|
-O $(object-format) -B $(object-arch) "$${wd}/$(@).tmp" && \
|
||||||
$(objcopy) --set-section-flags .boot=alloc,load,code "$${wd}/$(@).tmp" \
|
$(objcopy) --set-section-flags .boot=alloc,load,code "$${wd}/$(@).tmp" \
|
||||||
"$${wd}/$(@)")
|
"$${wd}/$(@)")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(gnu-object-dep): $(gnu-libraries)
|
||||||
|
@mkdir -p $(build)/gnu-objects
|
||||||
|
(cd $(build)/gnu-objects && \
|
||||||
|
for x in $(gnu-libraries); do ar x $${x}; done)
|
||||||
|
@touch $(@)
|
||||||
|
|
||||||
|
$(executable): $(gnu-object-dep)
|
||||||
$(executable): \
|
$(executable): \
|
||||||
$(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \
|
$(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \
|
||||||
$(boot-object) $(vm-classpath-object)
|
$(boot-object) $(vm-classpath-object)
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
ifeq ($(platform),windows)
|
ifeq ($(platform),windows)
|
||||||
$(dlltool) -z $(@).def $(^)
|
$(dlltool) -z $(@).def $(^) $(call gnu-objects)
|
||||||
$(dlltool) -d $(@).def -e $(@).exp
|
$(dlltool) -d $(@).def -e $(@).exp
|
||||||
$(cc) $(@).exp $(^) $(lflags) -o $(@)
|
$(cc) $(@).exp $(^) $(call gnu-objects) $(lflags) -o $(@)
|
||||||
else
|
else
|
||||||
$(cc) $(^) $(rdynamic) $(lflags) $(bootimage-lflags) -o $(@)
|
$(cc) $(^) $(call gnu-objects) $(rdynamic) $(lflags) $(bootimage-lflags) \
|
||||||
|
-o $(@)
|
||||||
endif
|
endif
|
||||||
$(strip) $(strip-all) $(@)
|
$(strip) $(strip-all) $(@)
|
||||||
|
|
||||||
@ -509,7 +611,7 @@ make-bootimage-generator:
|
|||||||
(unset MAKEFLAGS && \
|
(unset MAKEFLAGS && \
|
||||||
make mode=$(mode) \
|
make mode=$(mode) \
|
||||||
arch=$(build-arch) \
|
arch=$(build-arch) \
|
||||||
platform=$(build-platform) \
|
platform=$(bootimage-platform) \
|
||||||
bootimage=$(bootimage) \
|
bootimage=$(bootimage) \
|
||||||
heapdump=$(heapdump) \
|
heapdump=$(heapdump) \
|
||||||
bootimage-generator= \
|
bootimage-generator= \
|
||||||
@ -528,11 +630,13 @@ else
|
|||||||
$(cc) $(^) $(rdynamic) $(lflags) -o $(@)
|
$(cc) $(^) $(rdynamic) $(lflags) -o $(@)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(dynamic-library): $(gnu-object-dep)
|
||||||
$(dynamic-library): \
|
$(dynamic-library): \
|
||||||
$(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \
|
$(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \
|
||||||
$(boot-object) $(vm-classpath-object)
|
$(boot-object) $(vm-classpath-object) $(gnu-libraries)
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
$(cc) $(^) $(shared) $(lflags) $(bootimage-lflags) -o $(@)
|
$(cc) $(^) $(call gnu-objects) $(shared) $(lflags) $(bootimage-lflags) \
|
||||||
|
-o $(@)
|
||||||
$(strip) $(strip-all) $(@)
|
$(strip) $(strip-all) $(@)
|
||||||
|
|
||||||
$(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
|
$(executable-dynamic): $(driver-dynamic-object) $(dynamic-library)
|
||||||
|
23
readme.txt
23
readme.txt
@ -76,7 +76,8 @@ certain flags described below, all of which are optional.
|
|||||||
|
|
||||||
$ make platform={linux,windows,darwin} arch={i386,x86_64,powerpc} \
|
$ make platform={linux,windows,darwin} arch={i386,x86_64,powerpc} \
|
||||||
process={compile,interpret} mode={debug,debug-fast,fast,small} \
|
process={compile,interpret} mode={debug,debug-fast,fast,small} \
|
||||||
bootimage={true,false} heapdump={true,false}
|
bootimage={true,false} heapdump={true,false} tails={true,false} \
|
||||||
|
continuations={true,false}
|
||||||
|
|
||||||
* platform - the target platform
|
* platform - the target platform
|
||||||
default: output of $(uname -s | tr [:upper:] [:lower:]),
|
default: output of $(uname -s | tr [:upper:] [:lower:]),
|
||||||
@ -86,7 +87,7 @@ certain flags described below, all of which are optional.
|
|||||||
default: output of $(uname -m), normalized in some cases
|
default: output of $(uname -m), normalized in some cases
|
||||||
(e.g. i686 -> i386)
|
(e.g. i686 -> i386)
|
||||||
|
|
||||||
* mode - which set of compilation flags to use, which determine
|
* mode - which set of compilation flags to use to determine
|
||||||
optimization level, debug symbols, and whether to enable
|
optimization level, debug symbols, and whether to enable
|
||||||
assertions
|
assertions
|
||||||
default: fast
|
default: fast
|
||||||
@ -105,6 +106,18 @@ certain flags described below, all of which are optional.
|
|||||||
heapdump.cpp for details.
|
heapdump.cpp for details.
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
|
* tails - if true, optimize each tail call by replacing the caller's
|
||||||
|
stack frame with the callee's. This convention ensures proper
|
||||||
|
tail recursion, suitable for languages such as Scheme. This
|
||||||
|
option is only valid for process=compile builds.
|
||||||
|
default: false
|
||||||
|
|
||||||
|
* continuations - if true, support continuations via the
|
||||||
|
avian.Continuations methods callWithCurrentContinuation and
|
||||||
|
dynamicWind. See Continuations.java for details. This option is
|
||||||
|
only valid for process=compile builds.
|
||||||
|
default: false
|
||||||
|
|
||||||
These flags determine the name of the directory used for the build.
|
These flags determine the name of the directory used for the build.
|
||||||
The name always starts with ${platform}-${arch}, and each non-default
|
The name always starts with ${platform}-${arch}, and each non-default
|
||||||
build option is appended to the name. For example, a debug build with
|
build option is appended to the name. For example, a debug build with
|
||||||
@ -390,12 +403,12 @@ Step 5: Run ProGuard with stage1 as input and stage2 as output.
|
|||||||
$ java -jar ../../proguard4.3/lib/proguard.jar \
|
$ java -jar ../../proguard4.3/lib/proguard.jar \
|
||||||
-injars stage1 -outjars stage2 @../vm.pro @hello.pro
|
-injars stage1 -outjars stage2 @../vm.pro @hello.pro
|
||||||
|
|
||||||
(note: pass -dontusemixedcaseclassnames to ProGuard when building on systems with case-insensitive filesystems such as Windows and OS X)
|
(note: pass -dontusemixedcaseclassnames to ProGuard when building on
|
||||||
|
systems with case-insensitive filesystems such as Windows and OS X)
|
||||||
|
|
||||||
Step 6: Build the boot image.
|
Step 6: Build the boot image.
|
||||||
|
|
||||||
$ ../build/linux-i386-bootimage/bootimage-generator stage2 \
|
$ ../build/linux-i386-bootimage/bootimage-generator stage2 bootimage.bin
|
||||||
> bootimage.bin
|
|
||||||
|
|
||||||
Step 7: Make an object file out of the boot image.
|
Step 7: Make an object file out of the boot image.
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
extern "C" void NO_RETURN
|
extern "C" void NO_RETURN
|
||||||
vmJump(void* address, void* base, void* stack, void* thread);
|
vmJump(void* address, void* base, void* stack, void* thread,
|
||||||
|
uintptr_t returnLow, uintptr_t returnHigh);
|
||||||
|
|
||||||
#if (defined __i386__) || (defined __x86_64__)
|
#if (defined __i386__) || (defined __x86_64__)
|
||||||
# include "x86.h"
|
# include "x86.h"
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
#ifdef AVIAN_TAILS
|
||||||
|
const bool TailCalls = true;
|
||||||
|
#else
|
||||||
|
const bool TailCalls = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
enum Operation {
|
enum Operation {
|
||||||
Return,
|
Return,
|
||||||
LoadBarrier,
|
LoadBarrier,
|
||||||
@ -31,13 +37,20 @@ enum UnaryOperation {
|
|||||||
AlignedCall,
|
AlignedCall,
|
||||||
Jump,
|
Jump,
|
||||||
LongJump,
|
LongJump,
|
||||||
|
AlignedJump,
|
||||||
JumpIfLess,
|
JumpIfLess,
|
||||||
JumpIfGreater,
|
JumpIfGreater,
|
||||||
JumpIfLessOrEqual,
|
JumpIfLessOrEqual,
|
||||||
JumpIfGreaterOrEqual,
|
JumpIfGreaterOrEqual,
|
||||||
JumpIfEqual,
|
JumpIfEqual,
|
||||||
JumpIfNotEqual,
|
JumpIfNotEqual,
|
||||||
JumpIfUnordered
|
JumpIfFloatUnordered,
|
||||||
|
JumpIfFloatLess,
|
||||||
|
JumpIfFloatGreater,
|
||||||
|
JumpIfFloatLessOrEqual,
|
||||||
|
JumpIfFloatGreaterOrEqual,
|
||||||
|
JumpIfFloatEqual,
|
||||||
|
JumpIfFloatNotEqual,
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned UnaryOperationCount = JumpIfNotEqual + 1;
|
const unsigned UnaryOperationCount = JumpIfNotEqual + 1;
|
||||||
@ -225,12 +238,6 @@ class DelayedPromise: public ListenPromise {
|
|||||||
DelayedPromise* next;
|
DelayedPromise* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TraceHandler {
|
|
||||||
public:
|
|
||||||
virtual void handleTrace(Promise* address, unsigned padIndex,
|
|
||||||
unsigned padding) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Assembler {
|
class Assembler {
|
||||||
public:
|
public:
|
||||||
class Operand { };
|
class Operand { };
|
||||||
@ -259,7 +266,7 @@ class Assembler {
|
|||||||
|
|
||||||
class Memory: public Operand {
|
class Memory: public Operand {
|
||||||
public:
|
public:
|
||||||
Memory(int base, int offset, int index = NoRegister, unsigned scale = 0):
|
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
|
||||||
base(base), offset(offset), index(index), scale(scale)
|
base(base), offset(offset), index(index), scale(scale)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -290,22 +297,33 @@ class Assembler {
|
|||||||
virtual unsigned floatRegisterCount() = 0;
|
virtual unsigned floatRegisterCount() = 0;
|
||||||
virtual uint64_t generalRegisters() = 0;
|
virtual uint64_t generalRegisters() = 0;
|
||||||
virtual uint64_t floatRegisters() = 0;
|
virtual uint64_t floatRegisters() = 0;
|
||||||
|
virtual uint64_t allRegisters() = 0;
|
||||||
|
|
||||||
virtual int stack() = 0;
|
virtual int stack() = 0;
|
||||||
virtual int thread() = 0;
|
virtual int thread() = 0;
|
||||||
virtual int returnLow() = 0;
|
virtual int returnLow() = 0;
|
||||||
virtual int returnHigh() = 0;
|
virtual int returnHigh() = 0;
|
||||||
|
virtual int virtualCallTarget() = 0;
|
||||||
|
virtual int virtualCallIndex() = 0;
|
||||||
|
|
||||||
virtual bool bigEndian() = 0;
|
virtual bool bigEndian() = 0;
|
||||||
|
|
||||||
virtual bool supportsFloatCompare(unsigned size) = 0;
|
virtual bool supportsFloatCompare(unsigned size) = 0;
|
||||||
|
|
||||||
|
virtual bool alwaysCondensed(BinaryOperation op) = 0;
|
||||||
|
virtual bool alwaysCondensed(TernaryOperation op) = 0;
|
||||||
|
|
||||||
virtual bool reserved(int register_) = 0;
|
virtual bool reserved(int register_) = 0;
|
||||||
|
|
||||||
|
virtual unsigned frameFootprint(unsigned footprint) = 0;
|
||||||
virtual unsigned argumentFootprint(unsigned footprint) = 0;
|
virtual unsigned argumentFootprint(unsigned footprint) = 0;
|
||||||
virtual unsigned argumentRegisterCount() = 0;
|
virtual unsigned argumentRegisterCount() = 0;
|
||||||
virtual int argumentRegister(unsigned index) = 0;
|
virtual int argumentRegister(unsigned index) = 0;
|
||||||
|
|
||||||
|
virtual unsigned stackAlignmentInWords() = 0;
|
||||||
|
|
||||||
|
virtual bool matchCall(void* returnAddress, void* target) = 0;
|
||||||
|
|
||||||
virtual void updateCall(UnaryOperation op, bool assertAlignment,
|
virtual void updateCall(UnaryOperation op, bool assertAlignment,
|
||||||
void* returnAddress, void* newTarget) = 0;
|
void* returnAddress, void* newTarget) = 0;
|
||||||
|
|
||||||
@ -318,6 +336,8 @@ class Assembler {
|
|||||||
virtual unsigned frameHeaderSize() = 0;
|
virtual unsigned frameHeaderSize() = 0;
|
||||||
virtual unsigned frameReturnAddressSize() = 0;
|
virtual unsigned frameReturnAddressSize() = 0;
|
||||||
virtual unsigned frameFooterSize() = 0;
|
virtual unsigned frameFooterSize() = 0;
|
||||||
|
virtual int returnAddressOffset() = 0;
|
||||||
|
virtual int framePointerOffset() = 0;
|
||||||
virtual void nextFrame(void** stack, void** base) = 0;
|
virtual void nextFrame(void** stack, void** base) = 0;
|
||||||
|
|
||||||
virtual BinaryOperation hasBinaryIntrinsic(Thread* t, object method) = 0;
|
virtual BinaryOperation hasBinaryIntrinsic(Thread* t, object method) = 0;
|
||||||
@ -361,7 +381,15 @@ class Assembler {
|
|||||||
virtual void saveFrame(unsigned stackOffset, unsigned baseOffset) = 0;
|
virtual void saveFrame(unsigned stackOffset, unsigned baseOffset) = 0;
|
||||||
virtual void pushFrame(unsigned argumentCount, ...) = 0;
|
virtual void pushFrame(unsigned argumentCount, ...) = 0;
|
||||||
virtual void allocateFrame(unsigned footprint) = 0;
|
virtual void allocateFrame(unsigned footprint) = 0;
|
||||||
|
virtual void adjustFrame(unsigned footprint) = 0;
|
||||||
virtual void popFrame() = 0;
|
virtual void popFrame() = 0;
|
||||||
|
virtual void popFrameForTailCall(unsigned footprint, int offset,
|
||||||
|
int returnAddressSurrogate,
|
||||||
|
int framePointerSurrogate) = 0;
|
||||||
|
virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint)
|
||||||
|
= 0;
|
||||||
|
virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffsetFromThread)
|
||||||
|
= 0;
|
||||||
|
|
||||||
virtual void apply(Operation op) = 0;
|
virtual void apply(Operation op) = 0;
|
||||||
|
|
||||||
|
@ -33,12 +33,9 @@ endsWith(const char* suffix, const char* s, unsigned length)
|
|||||||
|
|
||||||
object
|
object
|
||||||
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||||
unsigned capacity, uintptr_t* codeMap, const char* className,
|
uintptr_t* codeMap, const char* className,
|
||||||
const char* methodName, const char* methodSpec)
|
const char* methodName, const char* methodSpec)
|
||||||
{
|
{
|
||||||
unsigned size = 0;
|
|
||||||
t->m->processor->compileThunks(t, image, code, &size, capacity);
|
|
||||||
|
|
||||||
object constants = 0;
|
object constants = 0;
|
||||||
PROTECT(t, constants);
|
PROTECT(t, constants);
|
||||||
|
|
||||||
@ -79,8 +76,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
== 0)))
|
== 0)))
|
||||||
{
|
{
|
||||||
t->m->processor->compileMethod
|
t->m->processor->compileMethod
|
||||||
(t, zone, code, &size, capacity, &constants, &calls, &addresses,
|
(t, zone, &constants, &calls, &addresses, method);
|
||||||
method);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,8 +115,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
- reinterpret_cast<intptr_t>(code));
|
- reinterpret_cast<intptr_t>(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
image->codeSize = size;
|
|
||||||
|
|
||||||
return constants;
|
return constants;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +138,7 @@ visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
|
|||||||
image->loader = w->visitRoot(m->loader);
|
image->loader = w->visitRoot(m->loader);
|
||||||
image->types = w->visitRoot(m->types);
|
image->types = w->visitRoot(m->types);
|
||||||
|
|
||||||
m->processor->visitRoots(image, w);
|
m->processor->visitRoots(w);
|
||||||
|
|
||||||
for (; constants; constants = tripleThird(t, constants)) {
|
for (; constants; constants = tripleThird(t, constants)) {
|
||||||
w->visitRoot(tripleFirst(t, constants));
|
w->visitRoot(tripleFirst(t, constants));
|
||||||
@ -187,7 +181,7 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
|
|||||||
and (currentOffset * BytesPerWord) == ClassStaticTable)
|
and (currentOffset * BytesPerWord) == ClassStaticTable)
|
||||||
{
|
{
|
||||||
FixedAllocator allocator
|
FixedAllocator allocator
|
||||||
(t, reinterpret_cast<uint8_t*>(heap + position),
|
(t->m->system, reinterpret_cast<uint8_t*>(heap + position),
|
||||||
(capacity - position) * BytesPerWord);
|
(capacity - position) * BytesPerWord);
|
||||||
|
|
||||||
unsigned totalInBytes;
|
unsigned totalInBytes;
|
||||||
@ -285,21 +279,18 @@ offset(object a, uintptr_t* b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
writeBootImage(Thread* t, FILE* out, const char* className,
|
writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||||
|
unsigned codeCapacity, const char* className,
|
||||||
const char* methodName, const char* methodSpec)
|
const char* methodName, const char* methodSpec)
|
||||||
{
|
{
|
||||||
Zone zone(t->m->system, t->m->heap, 64 * 1024);
|
Zone zone(t->m->system, t->m->heap, 64 * 1024);
|
||||||
BootImage image;
|
|
||||||
|
|
||||||
const unsigned CodeCapacity = 32 * 1024 * 1024;
|
|
||||||
uint8_t* code = static_cast<uint8_t*>(t->m->heap->allocate(CodeCapacity));
|
|
||||||
uintptr_t* codeMap = static_cast<uintptr_t*>
|
uintptr_t* codeMap = static_cast<uintptr_t*>
|
||||||
(t->m->heap->allocate(codeMapSize(CodeCapacity)));
|
(t->m->heap->allocate(codeMapSize(codeCapacity)));
|
||||||
memset(codeMap, 0, codeMapSize(CodeCapacity));
|
memset(codeMap, 0, codeMapSize(codeCapacity));
|
||||||
|
|
||||||
object constants = makeCodeImage
|
object constants = makeCodeImage
|
||||||
(t, &zone, &image, code, CodeCapacity, codeMap, className, methodName,
|
(t, &zone, image, code, codeMap, className, methodName, methodSpec);
|
||||||
methodSpec);
|
|
||||||
|
|
||||||
if (t->exception) return;
|
if (t->exception) return;
|
||||||
|
|
||||||
@ -312,16 +303,20 @@ writeBootImage(Thread* t, FILE* out, const char* className,
|
|||||||
(t->m->heap->allocate(heapMapSize(HeapCapacity)));
|
(t->m->heap->allocate(heapMapSize(HeapCapacity)));
|
||||||
memset(heapMap, 0, heapMapSize(HeapCapacity));
|
memset(heapMap, 0, heapMapSize(HeapCapacity));
|
||||||
|
|
||||||
|
// this map will not be used when the bootimage is loaded, so
|
||||||
|
// there's no need to preserve it:
|
||||||
|
t->m->byteArrayMap = makeWeakHashMap(t, 0, 0);
|
||||||
|
|
||||||
collect(t, Heap::MajorCollection);
|
collect(t, Heap::MajorCollection);
|
||||||
|
|
||||||
HeapWalker* heapWalker = makeHeapImage
|
HeapWalker* heapWalker = makeHeapImage
|
||||||
(t, &image, heap, heapMap, HeapCapacity, constants);
|
(t, image, heap, heapMap, HeapCapacity, constants);
|
||||||
|
|
||||||
updateConstants(t, constants, code, codeMap, heapWalker->map());
|
updateConstants(t, constants, code, codeMap, heapWalker->map());
|
||||||
|
|
||||||
image.classCount = hashMapSize(t, t->m->classMap);
|
image->classCount = hashMapSize(t, t->m->classMap);
|
||||||
unsigned* classTable = static_cast<unsigned*>
|
unsigned* classTable = static_cast<unsigned*>
|
||||||
(t->m->heap->allocate(image.classCount * sizeof(unsigned)));
|
(t->m->heap->allocate(image->classCount * sizeof(unsigned)));
|
||||||
|
|
||||||
{ unsigned i = 0;
|
{ unsigned i = 0;
|
||||||
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
|
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
|
||||||
@ -329,9 +324,9 @@ writeBootImage(Thread* t, FILE* out, const char* className,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image.stringCount = hashMapSize(t, t->m->stringMap);
|
image->stringCount = hashMapSize(t, t->m->stringMap);
|
||||||
unsigned* stringTable = static_cast<unsigned*>
|
unsigned* stringTable = static_cast<unsigned*>
|
||||||
(t->m->heap->allocate(image.stringCount * sizeof(unsigned)));
|
(t->m->heap->allocate(image->stringCount * sizeof(unsigned)));
|
||||||
|
|
||||||
{ unsigned i = 0;
|
{ unsigned i = 0;
|
||||||
for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
|
for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
|
||||||
@ -340,29 +335,28 @@ writeBootImage(Thread* t, FILE* out, const char* className,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned* callTable = t->m->processor->makeCallTable
|
unsigned* callTable = t->m->processor->makeCallTable(t, heapWalker);
|
||||||
(t, &image, heapWalker, code);
|
|
||||||
|
|
||||||
heapWalker->dispose();
|
heapWalker->dispose();
|
||||||
|
|
||||||
image.magic = BootImage::Magic;
|
image->magic = BootImage::Magic;
|
||||||
image.codeBase = reinterpret_cast<uintptr_t>(code);
|
image->codeBase = reinterpret_cast<uintptr_t>(code);
|
||||||
|
|
||||||
fprintf(stderr, "class count %d string count %d call count %d\n"
|
fprintf(stderr, "class count %d string count %d call count %d\n"
|
||||||
"heap size %d code size %d\n",
|
"heap size %d code size %d\n",
|
||||||
image.classCount, image.stringCount, image.callCount, image.heapSize,
|
image->classCount, image->stringCount, image->callCount,
|
||||||
image.codeSize);
|
image->heapSize, image->codeSize);
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
fwrite(&image, sizeof(BootImage), 1, out);
|
fwrite(image, sizeof(BootImage), 1, out);
|
||||||
|
|
||||||
fwrite(classTable, image.classCount * sizeof(unsigned), 1, out);
|
fwrite(classTable, image->classCount * sizeof(unsigned), 1, out);
|
||||||
fwrite(stringTable, image.stringCount * sizeof(unsigned), 1, out);
|
fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, out);
|
||||||
fwrite(callTable, image.callCount * sizeof(unsigned) * 2, 1, out);
|
fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, out);
|
||||||
|
|
||||||
unsigned offset = (image.classCount * sizeof(unsigned))
|
unsigned offset = (image->classCount * sizeof(unsigned))
|
||||||
+ (image.stringCount * sizeof(unsigned))
|
+ (image->stringCount * sizeof(unsigned))
|
||||||
+ (image.callCount * sizeof(unsigned) * 2);
|
+ (image->callCount * sizeof(unsigned) * 2);
|
||||||
|
|
||||||
while (offset % BytesPerWord) {
|
while (offset % BytesPerWord) {
|
||||||
uint8_t c = 0;
|
uint8_t c = 0;
|
||||||
@ -370,11 +364,11 @@ writeBootImage(Thread* t, FILE* out, const char* className,
|
|||||||
++ offset;
|
++ offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(heapMap, pad(heapMapSize(image.heapSize)), 1, out);
|
fwrite(heapMap, pad(heapMapSize(image->heapSize)), 1, out);
|
||||||
fwrite(heap, pad(image.heapSize), 1, out);
|
fwrite(heap, pad(image->heapSize), 1, out);
|
||||||
|
|
||||||
fwrite(codeMap, pad(codeMapSize(image.codeSize)), 1, out);
|
fwrite(codeMap, pad(codeMapSize(image->codeSize)), 1, out);
|
||||||
fwrite(code, pad(image.codeSize), 1, out);
|
fwrite(code, pad(image->codeSize), 1, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,8 +377,8 @@ writeBootImage(Thread* t, FILE* out, const char* className,
|
|||||||
int
|
int
|
||||||
main(int ac, const char** av)
|
main(int ac, const char** av)
|
||||||
{
|
{
|
||||||
if (ac < 2 or ac > 5) {
|
if (ac < 3 or ac > 6) {
|
||||||
fprintf(stderr, "usage: %s <classpath> "
|
fprintf(stderr, "usage: %s <classpath> <output file> "
|
||||||
"[<class name> [<method name> [<method spec>]]]\n", av[0]);
|
"[<class name> [<method name> [<method spec>]]]\n", av[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -393,15 +387,29 @@ main(int ac, const char** av)
|
|||||||
Heap* h = makeHeap(s, 128 * 1024 * 1024);
|
Heap* h = makeHeap(s, 128 * 1024 * 1024);
|
||||||
Finder* f = makeFinder(s, av[1], 0);
|
Finder* f = makeFinder(s, av[1], 0);
|
||||||
Processor* p = makeProcessor(s, h);
|
Processor* p = makeProcessor(s, h);
|
||||||
|
|
||||||
|
BootImage image;
|
||||||
|
const unsigned CodeCapacity = 32 * 1024 * 1024;
|
||||||
|
uint8_t* code = static_cast<uint8_t*>(h->allocate(CodeCapacity));
|
||||||
|
p->initialize(&image, code, CodeCapacity);
|
||||||
|
|
||||||
Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
|
Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
|
||||||
Thread* t = p->makeThread(m, 0, 0);
|
Thread* t = p->makeThread(m, 0, 0);
|
||||||
|
|
||||||
enter(t, Thread::ActiveState);
|
enter(t, Thread::ActiveState);
|
||||||
enter(t, Thread::IdleState);
|
enter(t, Thread::IdleState);
|
||||||
|
|
||||||
|
FILE* output = fopen(av[2], "wb");
|
||||||
|
if (output == 0) {
|
||||||
|
fprintf(stderr, "unable to open %s\n", av[2]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
writeBootImage
|
writeBootImage
|
||||||
(t, stdout, (ac > 2 ? av[2] : 0), (ac > 3 ? av[3] : 0),
|
(t, output, &image, code, CodeCapacity,
|
||||||
(ac > 4 ? av[4] : 0));
|
(ac > 3 ? av[3] : 0), (ac > 4 ? av[4] : 0), (ac > 5 ? av[5] : 0));
|
||||||
|
|
||||||
|
fclose(output);
|
||||||
|
|
||||||
if (t->exception) {
|
if (t->exception) {
|
||||||
printTrace(t, t->exception);
|
printTrace(t, t->exception);
|
||||||
|
@ -39,10 +39,12 @@ class BootImage {
|
|||||||
unsigned types;
|
unsigned types;
|
||||||
unsigned methodTree;
|
unsigned methodTree;
|
||||||
unsigned methodTreeSentinal;
|
unsigned methodTreeSentinal;
|
||||||
|
unsigned virtualThunks;
|
||||||
|
|
||||||
uintptr_t codeBase;
|
uintptr_t codeBase;
|
||||||
|
|
||||||
unsigned defaultThunk;
|
unsigned defaultThunk;
|
||||||
|
unsigned defaultVirtualThunk;
|
||||||
unsigned nativeThunk;
|
unsigned nativeThunk;
|
||||||
unsigned aioobThunk;
|
unsigned aioobThunk;
|
||||||
|
|
||||||
@ -50,6 +52,7 @@ class BootImage {
|
|||||||
unsigned thunkSize;
|
unsigned thunkSize;
|
||||||
|
|
||||||
unsigned compileMethodCall;
|
unsigned compileMethodCall;
|
||||||
|
unsigned compileVirtualMethodCall;
|
||||||
unsigned invokeNativeCall;
|
unsigned invokeNativeCall;
|
||||||
unsigned throwArrayIndexOutOfBoundsCall;
|
unsigned throwArrayIndexOutOfBoundsCall;
|
||||||
|
|
||||||
|
668
src/builtin.cpp
668
src/builtin.cpp
File diff suppressed because it is too large
Load Diff
34
src/common.h
34
src/common.h
@ -30,7 +30,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined __i386__) || (defined __POWERPC__)
|
#if (defined __i386__) || (defined __POWERPC__)
|
||||||
# define LD "d"
|
# define LD "ld"
|
||||||
# define LLD "lld"
|
# define LLD "lld"
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# define ULD "lu"
|
# define ULD "lu"
|
||||||
@ -39,16 +39,18 @@
|
|||||||
# define LX "x"
|
# define LX "x"
|
||||||
# define ULD "u"
|
# define ULD "u"
|
||||||
#endif
|
#endif
|
||||||
#elif defined __x86_64__ && defined __LINUX__
|
#elif defined __x86_64__
|
||||||
# define LD "ld"
|
# ifdef __MINGW32__
|
||||||
# define LX "lx"
|
# define LD "I64d"
|
||||||
# define LLD "ld"
|
# define LX "I64x"
|
||||||
# define ULD "lu"
|
# define LLD "I64d"
|
||||||
#elif defined __x86_64__ && defined __WINDOWS__
|
# define ULD "I64x"
|
||||||
# define LD "I64d"
|
# else
|
||||||
# define LX "I64x"
|
# define LD "ld"
|
||||||
# define LLD "I64d"
|
# define LX "lx"
|
||||||
# define ULD "I64x"
|
# define LLD "ld"
|
||||||
|
# define ULD "lu"
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
# error "Unsupported architecture"
|
# error "Unsupported architecture"
|
||||||
#endif
|
#endif
|
||||||
@ -108,10 +110,16 @@ avg(unsigned a, unsigned b)
|
|||||||
return (a + b) / 2;
|
return (a + b) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
pad(unsigned n, unsigned alignment)
|
||||||
|
{
|
||||||
|
return (n + (alignment - 1)) & ~(alignment - 1);
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
pad(unsigned n)
|
pad(unsigned n)
|
||||||
{
|
{
|
||||||
return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
|
return pad(n, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
@ -286,7 +294,7 @@ bitsToFloat(uint32_t bits)
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline intptr_t
|
inline int
|
||||||
difference(void* a, void* b)
|
difference(void* a, void* b)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
|
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
|
||||||
|
@ -17,14 +17,28 @@
|
|||||||
#define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA
|
#define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA
|
||||||
|
|
||||||
#define LOCAL(x) L##x
|
#define LOCAL(x) L##x
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
.globl _vmInvoke
|
# define GLOBAL(x) _##x
|
||||||
_vmInvoke:
|
|
||||||
#else
|
#else
|
||||||
.globl vmInvoke
|
# define GLOBAL(x) x
|
||||||
vmInvoke:
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define THREAD_CONTINUATION 96
|
||||||
|
#define THREAD_EXCEPTION 36
|
||||||
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 100
|
||||||
|
#define THREAD_EXCEPTION_OFFSET 104
|
||||||
|
#define THREAD_EXCEPTION_HANDLER 108
|
||||||
|
|
||||||
|
#define CONTINUATION_NEXT 4
|
||||||
|
#define CONTINUATION_ADDRESS 16
|
||||||
|
#define CONTINUATION_RETURN_ADDRESS_OFFSET 20
|
||||||
|
#define CONTINUATION_FRAME_POINTER_OFFSET 24
|
||||||
|
#define CONTINUATION_LENGTH 28
|
||||||
|
#define CONTINUATION_BODY 32
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke)
|
||||||
|
GLOBAL(vmInvoke):
|
||||||
// save return address
|
// save return address
|
||||||
mflr r0
|
mflr r0
|
||||||
stw r0,8(r1)
|
stw r0,8(r1)
|
||||||
@ -73,24 +87,94 @@ vmInvoke:
|
|||||||
|
|
||||||
// copy arguments into place
|
// copy arguments into place
|
||||||
li r16,0
|
li r16,0
|
||||||
b LOCAL(test)
|
addi r18,r1,ARGUMENT_BASE
|
||||||
|
b LOCAL(vmInvoke_argumentTest)
|
||||||
|
|
||||||
LOCAL(loop):
|
LOCAL(vmInvoke_argumentLoop):
|
||||||
lwzx r17,r16,r5
|
lwzx r17,r16,r5
|
||||||
addi r18,r16,ARGUMENT_BASE
|
stwx r17,r16,r18
|
||||||
stwx r17,r18,r1
|
|
||||||
addi r16,r16,BYTES_PER_WORD
|
addi r16,r16,BYTES_PER_WORD
|
||||||
|
|
||||||
LOCAL(test):
|
LOCAL(vmInvoke_argumentTest):
|
||||||
cmplw r16,r6
|
cmplw r16,r6
|
||||||
blt LOCAL(loop)
|
blt LOCAL(vmInvoke_argumentLoop)
|
||||||
|
|
||||||
// load and call function address
|
// load and call function address
|
||||||
mtctr r4
|
mtctr r4
|
||||||
bctrl
|
bctrl
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_returnAddress):
|
||||||
// restore stack pointer
|
// restore stack pointer
|
||||||
lwz r1,0(r1)
|
lwz r1,0(r1)
|
||||||
|
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// call the next continuation, if any
|
||||||
|
lwz r5,THREAD_CONTINUATION(r13)
|
||||||
|
cmplwi r5,0
|
||||||
|
beq LOCAL(vmInvoke_exit)
|
||||||
|
|
||||||
|
lwz r6,CONTINUATION_LENGTH(r5)
|
||||||
|
slwi r6,r6,2
|
||||||
|
subfic r7,r6,-80
|
||||||
|
stwux r1,r1,r7
|
||||||
|
|
||||||
|
addi r7,r5,CONTINUATION_BODY
|
||||||
|
|
||||||
|
li r8,0
|
||||||
|
addi r10,r1,ARGUMENT_BASE
|
||||||
|
b LOCAL(vmInvoke_continuationTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationLoop):
|
||||||
|
lwzx r9,r7,r8
|
||||||
|
stwx r9,r10,r8
|
||||||
|
addi r8,r8,4
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationTest):
|
||||||
|
cmplw r8,r6
|
||||||
|
ble LOCAL(vmInvoke_continuationLoop)
|
||||||
|
|
||||||
|
lwz r7,CONTINUATION_RETURN_ADDRESS_OFFSET(r5)
|
||||||
|
bl LOCAL(vmInvoke_getPC)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_getPC):
|
||||||
|
mflr r10
|
||||||
|
la r10,lo16(LOCAL(vmInvoke_returnAddress)-LOCAL(vmInvoke_getPC))(r10)
|
||||||
|
stwx r10,r1,r7
|
||||||
|
|
||||||
|
lwz r7,CONTINUATION_FRAME_POINTER_OFFSET(r5)
|
||||||
|
lwz r8,0(r1)
|
||||||
|
add r7,r7,r1
|
||||||
|
stw r8,0(r7)
|
||||||
|
stw r7,0(r1)
|
||||||
|
|
||||||
|
lwz r7,CONTINUATION_NEXT(r5)
|
||||||
|
stw r7,THREAD_CONTINUATION(r13)
|
||||||
|
|
||||||
|
// call the continuation unless we're handling an exception
|
||||||
|
lwz r7,THREAD_EXCEPTION(r13)
|
||||||
|
cmpwi r7,0
|
||||||
|
bne LOCAL(vmInvoke_handleException)
|
||||||
|
lwz r7,CONTINUATION_ADDRESS(r5)
|
||||||
|
mtctr r7
|
||||||
|
bctr
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_handleException):
|
||||||
|
// we're handling an exception - call the exception handler instead
|
||||||
|
li r8,0
|
||||||
|
stw r8,THREAD_EXCEPTION(r13)
|
||||||
|
lwz r8,THREAD_EXCEPTION_STACK_ADJUSTMENT(r13)
|
||||||
|
lwz r9,0(r1)
|
||||||
|
subfic r8,r8,0
|
||||||
|
stwux r9,r1,r8
|
||||||
|
lwz r8,THREAD_EXCEPTION_OFFSET(r13)
|
||||||
|
stwx r7,r1,r8
|
||||||
|
|
||||||
|
lwz r7,THREAD_EXCEPTION_HANDLER(r13)
|
||||||
|
mtctr r7
|
||||||
|
bctr
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_exit):
|
||||||
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
// restore callee-saved registers
|
// restore callee-saved registers
|
||||||
subi r9,r1,80
|
subi r9,r1,80
|
||||||
@ -118,23 +202,82 @@ LOCAL(test):
|
|||||||
// handle return value based on expected type
|
// handle return value based on expected type
|
||||||
lwz r8,44(r1)
|
lwz r8,44(r1)
|
||||||
|
|
||||||
LOCAL(void):
|
LOCAL(vmInvoke_void):
|
||||||
cmplwi r8,VOID_TYPE
|
cmplwi r8,VOID_TYPE
|
||||||
bne LOCAL(int64)
|
bne LOCAL(vmInvoke_int64)
|
||||||
b LOCAL(exit)
|
b LOCAL(vmInvoke_return)
|
||||||
|
|
||||||
LOCAL(int64):
|
LOCAL(vmInvoke_int64):
|
||||||
cmplwi r8,INT64_TYPE
|
cmplwi r8,INT64_TYPE
|
||||||
bne LOCAL(int32)
|
bne LOCAL(vmInvoke_int32)
|
||||||
b LOCAL(exit)
|
b LOCAL(vmInvoke_return)
|
||||||
|
|
||||||
LOCAL(int32):
|
LOCAL(vmInvoke_int32):
|
||||||
li r3,0
|
li r3,0
|
||||||
|
|
||||||
LOCAL(exit):
|
LOCAL(vmInvoke_return):
|
||||||
// load return address
|
// load return address
|
||||||
lwz r0,8(r1)
|
lwz r0,8(r1)
|
||||||
mtlr r0
|
mtlr r0
|
||||||
|
|
||||||
// return
|
// return
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
.globl GLOBAL(vmJumpAndInvoke)
|
||||||
|
GLOBAL(vmJumpAndInvoke):
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// r3: thread
|
||||||
|
// r4: address
|
||||||
|
// r5: (unused)
|
||||||
|
// r6: stack
|
||||||
|
// r7: argumentFootprint
|
||||||
|
// r8: arguments
|
||||||
|
// r9: frameSize
|
||||||
|
|
||||||
|
// restore (pseudo)-stack pointer (we don't want to touch the real
|
||||||
|
// stack pointer, since we haven't copied the arguments yet)
|
||||||
|
lwz r6,0(r6)
|
||||||
|
|
||||||
|
// make everything between r1 and r6 one big stack frame while we
|
||||||
|
// shuffle things around
|
||||||
|
stw r6,0(r1)
|
||||||
|
|
||||||
|
// allocate new frame, adding room for callee-saved registers
|
||||||
|
subfic r10,r9,-80
|
||||||
|
stwux r6,r6,r10
|
||||||
|
|
||||||
|
mr r13,r3
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
li r9,0
|
||||||
|
addi r11,r6,ARGUMENT_BASE
|
||||||
|
b LOCAL(vmJumpAndInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentLoop):
|
||||||
|
lwzx r12,r8,r9
|
||||||
|
stwx r12,r11,r9
|
||||||
|
addi r9,r9,4
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentTest):
|
||||||
|
cmplw r9,r7
|
||||||
|
ble LOCAL(vmJumpAndInvoke_argumentLoop)
|
||||||
|
|
||||||
|
// the arguments have been copied, so we can set the real stack
|
||||||
|
// pointer now
|
||||||
|
mr r1,r6
|
||||||
|
|
||||||
|
// set return address to vmInvoke_returnAddress
|
||||||
|
bl LOCAL(vmJumpAndInvoke_getPC)
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_getPC):
|
||||||
|
mflr r10
|
||||||
|
la r10,lo16(LOCAL(vmInvoke_returnAddress)-LOCAL(vmJumpAndInvoke_getPC))(r10)
|
||||||
|
mtlr r10
|
||||||
|
|
||||||
|
mtctr r4
|
||||||
|
bctr
|
||||||
|
#else // not AVIAN_CONTINUATIONS
|
||||||
|
// vmJumpAndInvoke should only be called when continuations are
|
||||||
|
// enabled
|
||||||
|
trap
|
||||||
|
#endif // not AVIAN_CONTINUATIONS
|
||||||
|
@ -12,23 +12,25 @@
|
|||||||
|
|
||||||
#define LOCAL(x) .L##x
|
#define LOCAL(x) .L##x
|
||||||
|
|
||||||
|
#if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
|
||||||
|
# define GLOBAL(x) _##x
|
||||||
|
#else
|
||||||
|
# define GLOBAL(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __MINGW32__
|
||||||
# if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
|
|
||||||
.globl _vmInvoke
|
#define CALLEE_SAVED_REGISTER_FOOTPRINT 64
|
||||||
_vmInvoke:
|
|
||||||
# else
|
.globl GLOBAL(vmInvoke)
|
||||||
.globl vmInvoke
|
GLOBAL(vmInvoke):
|
||||||
vmInvoke:
|
|
||||||
#error other
|
|
||||||
# endif
|
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp,%rbp
|
movq %rsp,%rbp
|
||||||
|
|
||||||
//NEW
|
|
||||||
// %rcx: thread
|
// %rcx: thread
|
||||||
// %rdx: function
|
// %rdx: function
|
||||||
// %r8 : arguments
|
// %r8 : arguments
|
||||||
@ -39,7 +41,7 @@ vmInvoke:
|
|||||||
// allocate stack space, adding room for callee-saved registers
|
// allocate stack space, adding room for callee-saved registers
|
||||||
movl 48(%rbp),%eax
|
movl 48(%rbp),%eax
|
||||||
subq %rax,%rsp
|
subq %rax,%rsp
|
||||||
subq $64,%rsp
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
|
||||||
|
|
||||||
// save callee-saved registers
|
// save callee-saved registers
|
||||||
movq %rsp,%r11
|
movq %rsp,%r11
|
||||||
@ -58,26 +60,33 @@ vmInvoke:
|
|||||||
|
|
||||||
// copy arguments into place
|
// copy arguments into place
|
||||||
movq $0,%r11
|
movq $0,%r11
|
||||||
jmp LOCAL(test)
|
jmp LOCAL(vmInvoke_argumentTest)
|
||||||
|
|
||||||
LOCAL(loop):
|
LOCAL(vmInvoke_argumentLoop):
|
||||||
movq (%r8,%r11,1),%rsi
|
movq (%r8,%r11,1),%rsi
|
||||||
movq %rsi,(%rsp,%r11,1)
|
movq %rsi,(%rsp,%r11,1)
|
||||||
addq $8,%r11
|
addq $8,%r11
|
||||||
|
|
||||||
LOCAL(test):
|
LOCAL(vmInvoke_argumentTest):
|
||||||
cmpq %r9,%r11
|
cmpq %r9,%r11
|
||||||
jb LOCAL(loop)
|
jb LOCAL(vmInvoke_argumentLoop)
|
||||||
|
|
||||||
// call function
|
// call function
|
||||||
call *%rdx
|
call *%rdx
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke_returnAddress)
|
||||||
|
GLOBAL(vmInvoke_returnAddress):
|
||||||
// restore stack pointer
|
// restore stack pointer
|
||||||
movq %rbp,%rsp
|
movq %rbp,%rsp
|
||||||
|
|
||||||
// restore callee-saved registers
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
# include "continuations-x86.S"
|
||||||
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
|
// restore callee-saved registers (below the stack pointer, but in
|
||||||
|
// the red zone)
|
||||||
movq %rsp,%r11
|
movq %rsp,%r11
|
||||||
subq $64,%r11
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r11
|
||||||
|
|
||||||
movq 0(%r11),%rbx
|
movq 0(%r11),%rbx
|
||||||
movq 8(%r11),%r12
|
movq 8(%r11),%r12
|
||||||
@ -90,16 +99,67 @@ LOCAL(test):
|
|||||||
// return
|
// return
|
||||||
popq %rbp
|
popq %rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#elif defined __LINUX__
|
.globl GLOBAL(vmJumpAndInvoke)
|
||||||
|
GLOBAL(vmJumpAndInvoke):
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// %rcx: thread
|
||||||
|
// %rdx: address
|
||||||
|
// %r8 : base
|
||||||
|
// %r9 : (unused)
|
||||||
|
// 8(%rsp): argumentFootprint
|
||||||
|
// 16(%rsp): arguments
|
||||||
|
// 24(%rsp): frameSize
|
||||||
|
|
||||||
# if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
|
movq %r8,%rbp
|
||||||
.globl _vmInvoke
|
|
||||||
_vmInvoke:
|
// restore (pseudo)-stack pointer (we don't want to touch the real
|
||||||
# else
|
// stack pointer, since we haven't copied the arguments yet)
|
||||||
.globl vmInvoke
|
movq %rbp,%r9
|
||||||
vmInvoke:
|
|
||||||
# endif
|
// allocate new frame, adding room for callee-saved registers
|
||||||
|
movl 24(%rsp),%eax
|
||||||
|
subq %rax,%r9
|
||||||
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r9
|
||||||
|
|
||||||
|
movq %rcx,%rbx
|
||||||
|
|
||||||
|
// set return address
|
||||||
|
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
|
||||||
|
movq %r10,(%r9)
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
movq $0,%r11
|
||||||
|
movq 16(%rsp),%r8
|
||||||
|
movq 8(%rsp),%rax
|
||||||
|
jmp LOCAL(vmJumpAndInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentLoop):
|
||||||
|
movq (%r8,%r11,1),%r10
|
||||||
|
movq %r10,8(%r9,%r11,1)
|
||||||
|
addq $8,%r11
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentTest):
|
||||||
|
cmpq %rax,%r11
|
||||||
|
jb LOCAL(vmJumpAndInvoke_argumentLoop)
|
||||||
|
|
||||||
|
// the arguments have been copied, so we can set the real stack
|
||||||
|
// pointer now
|
||||||
|
movq %r9,%rsp
|
||||||
|
|
||||||
|
jmp *%rdx
|
||||||
|
#else // not AVIAN_CONTINUATIONS
|
||||||
|
// vmJumpAndInvoke should only be called when continuations are
|
||||||
|
// enabled
|
||||||
|
int3
|
||||||
|
#endif // not AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
|
#else // not __MINGW32__
|
||||||
|
|
||||||
|
#define CALLEE_SAVED_REGISTER_FOOTPRINT 48
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke)
|
||||||
|
GLOBAL(vmInvoke):
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp,%rbp
|
movq %rsp,%rbp
|
||||||
|
|
||||||
@ -111,8 +171,8 @@ vmInvoke:
|
|||||||
// %r9 : returnType (ignored)
|
// %r9 : returnType (ignored)
|
||||||
|
|
||||||
// allocate stack space, adding room for callee-saved registers
|
// allocate stack space, adding room for callee-saved registers
|
||||||
subq %r8,%rsp
|
subq %r8,%rsp
|
||||||
subq $48,%rsp
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
|
||||||
|
|
||||||
// save callee-saved registers
|
// save callee-saved registers
|
||||||
movq %rsp,%r9
|
movq %rsp,%r9
|
||||||
@ -129,26 +189,33 @@ vmInvoke:
|
|||||||
|
|
||||||
// copy arguments into place
|
// copy arguments into place
|
||||||
movq $0,%r9
|
movq $0,%r9
|
||||||
jmp LOCAL(test)
|
jmp LOCAL(vmInvoke_argumentTest)
|
||||||
|
|
||||||
LOCAL(loop):
|
LOCAL(vmInvoke_argumentLoop):
|
||||||
movq (%rdx,%r9,1),%r8
|
movq (%rdx,%r9,1),%r8
|
||||||
movq %r8,(%rsp,%r9,1)
|
movq %r8,(%rsp,%r9,1)
|
||||||
addq $8,%r9
|
addq $8,%r9
|
||||||
|
|
||||||
LOCAL(test):
|
LOCAL(vmInvoke_argumentTest):
|
||||||
cmpq %rcx,%r9
|
cmpq %rcx,%r9
|
||||||
jb LOCAL(loop)
|
jb LOCAL(vmInvoke_argumentLoop)
|
||||||
|
|
||||||
// call function
|
// call function
|
||||||
call *%rsi
|
call *%rsi
|
||||||
|
|
||||||
|
.globl GLOBAL(vmInvoke_returnAddress)
|
||||||
|
GLOBAL(vmInvoke_returnAddress):
|
||||||
// restore stack pointer
|
// restore stack pointer
|
||||||
movq %rbp,%rsp
|
movq %rbp,%rsp
|
||||||
|
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
# include "continuations-x86.S"
|
||||||
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
// restore callee-saved registers
|
// restore callee-saved registers (below the stack pointer, but in
|
||||||
|
// the red zone)
|
||||||
movq %rsp,%r9
|
movq %rsp,%r9
|
||||||
subq $48,%r9
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r9
|
||||||
|
|
||||||
movq 0(%r9),%rbx
|
movq 0(%r9),%rbx
|
||||||
movq 8(%r9),%r12
|
movq 8(%r9),%r12
|
||||||
@ -160,19 +227,66 @@ LOCAL(test):
|
|||||||
popq %rbp
|
popq %rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#else
|
.globl GLOBAL(vmJumpAndInvoke)
|
||||||
#error unsupported platorm / architecture combo
|
GLOBAL(vmJumpAndInvoke):
|
||||||
#endif //defined __WINDOWS__
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// %rdi: thread
|
||||||
|
// %rsi: address
|
||||||
|
// %rdx: base
|
||||||
|
// %rcx: (unused)
|
||||||
|
// %r8 : argumentFootprint
|
||||||
|
// %r9 : arguments
|
||||||
|
// 8(%rsp): frameSize
|
||||||
|
|
||||||
|
movq %rdx,%rbp
|
||||||
|
|
||||||
|
// restore (pseudo)-stack pointer (we don't want to touch the real
|
||||||
|
// stack pointer, since we haven't copied the arguments yet)
|
||||||
|
movq %rbp,%rcx
|
||||||
|
|
||||||
|
// allocate new frame, adding room for callee-saved registers
|
||||||
|
movl 8(%rsp),%eax
|
||||||
|
subq %rax,%rcx
|
||||||
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rcx
|
||||||
|
|
||||||
|
movq %rdi,%rbx
|
||||||
|
|
||||||
|
// set return address
|
||||||
|
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
|
||||||
|
movq %r10,(%rcx)
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
movq $0,%r11
|
||||||
|
jmp LOCAL(vmJumpAndInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentLoop):
|
||||||
|
movq (%r9,%r11,1),%r10
|
||||||
|
movq %r10,8(%rcx,%r11,1)
|
||||||
|
addq $8,%r11
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentTest):
|
||||||
|
cmpq %r8,%r11
|
||||||
|
jb LOCAL(vmJumpAndInvoke_argumentLoop)
|
||||||
|
|
||||||
|
// the arguments have been copied, so we can set the real stack
|
||||||
|
// pointer now
|
||||||
|
movq %rcx,%rsp
|
||||||
|
|
||||||
|
jmp *%rsi
|
||||||
|
#else // not AVIAN_CONTINUATIONS
|
||||||
|
// vmJumpAndInvoke should only be called when continuations are
|
||||||
|
// enabled
|
||||||
|
int3
|
||||||
|
#endif // not AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
|
#endif // not __MINGW32__
|
||||||
|
|
||||||
#elif defined __i386__
|
#elif defined __i386__
|
||||||
|
|
||||||
# if defined __APPLE__ || defined __MINGW32__ || defined __CYGWIN32__
|
#define CALLEE_SAVED_REGISTER_FOOTPRINT 16
|
||||||
.globl _vmInvoke
|
|
||||||
_vmInvoke:
|
.globl GLOBAL(vmInvoke)
|
||||||
# else
|
GLOBAL(vmInvoke):
|
||||||
.globl vmInvoke
|
|
||||||
vmInvoke:
|
|
||||||
# endif
|
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
movl %esp,%ebp
|
movl %esp,%ebp
|
||||||
|
|
||||||
@ -185,7 +299,7 @@ vmInvoke:
|
|||||||
|
|
||||||
// allocate stack space, adding room for callee-saved registers
|
// allocate stack space, adding room for callee-saved registers
|
||||||
subl 24(%ebp),%esp
|
subl 24(%ebp),%esp
|
||||||
subl $16,%esp
|
subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp
|
||||||
|
|
||||||
// save callee-saved registers
|
// save callee-saved registers
|
||||||
movl %esp,%ecx
|
movl %esp,%ecx
|
||||||
@ -201,26 +315,33 @@ vmInvoke:
|
|||||||
// copy arguments into place
|
// copy arguments into place
|
||||||
movl $0,%ecx
|
movl $0,%ecx
|
||||||
movl 16(%ebp),%edx
|
movl 16(%ebp),%edx
|
||||||
jmp LOCAL(test)
|
jmp LOCAL(vmInvoke_argumentTest)
|
||||||
|
|
||||||
LOCAL(loop):
|
LOCAL(vmInvoke_argumentLoop):
|
||||||
movl (%edx,%ecx,1),%eax
|
movl (%edx,%ecx,1),%eax
|
||||||
movl %eax,(%esp,%ecx,1)
|
movl %eax,(%esp,%ecx,1)
|
||||||
addl $4,%ecx
|
addl $4,%ecx
|
||||||
|
|
||||||
LOCAL(test):
|
LOCAL(vmInvoke_argumentTest):
|
||||||
cmpl 20(%ebp),%ecx
|
cmpl 20(%ebp),%ecx
|
||||||
jb LOCAL(loop)
|
jb LOCAL(vmInvoke_argumentLoop)
|
||||||
|
|
||||||
// call function
|
// call function
|
||||||
call *12(%ebp)
|
call *12(%ebp)
|
||||||
|
|
||||||
// restore stack pointer
|
.globl vmInvoke_returnAddress
|
||||||
movl %ebp,%esp
|
vmInvoke_returnAddress:
|
||||||
|
// restore stack pointer, preserving the area containing saved
|
||||||
|
// registers
|
||||||
|
movl %ebp,%ecx
|
||||||
|
subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%ecx
|
||||||
|
movl %ecx,%esp
|
||||||
|
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
# include "continuations-x86.S"
|
||||||
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
// restore callee-saved registers
|
// restore callee-saved registers
|
||||||
subl $16,%esp
|
|
||||||
|
|
||||||
movl 0(%esp),%ebx
|
movl 0(%esp),%ebx
|
||||||
movl 4(%esp),%esi
|
movl 4(%esp),%esi
|
||||||
movl 8(%esp),%edi
|
movl 8(%esp),%edi
|
||||||
@ -228,24 +349,86 @@ LOCAL(test):
|
|||||||
// handle return value based on expected type
|
// handle return value based on expected type
|
||||||
movl 28(%ebp),%ecx
|
movl 28(%ebp),%ecx
|
||||||
|
|
||||||
addl $16,%esp
|
addl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp
|
||||||
|
|
||||||
LOCAL(void):
|
LOCAL(vmInvoke_void):
|
||||||
cmpl $VOID_TYPE,%ecx
|
cmpl $VOID_TYPE,%ecx
|
||||||
jne LOCAL(int64)
|
jne LOCAL(vmInvoke_int64)
|
||||||
jmp LOCAL(exit)
|
jmp LOCAL(vmInvoke_return)
|
||||||
|
|
||||||
LOCAL(int64):
|
LOCAL(vmInvoke_int64):
|
||||||
cmpl $INT64_TYPE,%ecx
|
cmpl $INT64_TYPE,%ecx
|
||||||
jne LOCAL(int32)
|
jne LOCAL(vmInvoke_int32)
|
||||||
jmp LOCAL(exit)
|
jmp LOCAL(vmInvoke_return)
|
||||||
|
|
||||||
LOCAL(int32):
|
LOCAL(vmInvoke_int32):
|
||||||
movl $0,%edx
|
movl $0,%edx
|
||||||
|
|
||||||
LOCAL(exit):
|
LOCAL(vmInvoke_return):
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
LOCAL(getPC):
|
||||||
|
movl (%esp),%esi
|
||||||
|
ret
|
||||||
|
|
||||||
|
.globl GLOBAL(vmJumpAndInvoke)
|
||||||
|
GLOBAL(vmJumpAndInvoke):
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
// 4(%esp): thread
|
||||||
|
// 8(%esp): address
|
||||||
|
// 12(%esp): base
|
||||||
|
// 16(%esp): (unused)
|
||||||
|
// 20(%esp): argumentFootprint
|
||||||
|
// 24(%esp): arguments
|
||||||
|
// 28(%esp): frameSize
|
||||||
|
|
||||||
|
movl 12(%esp),%ebp
|
||||||
|
|
||||||
|
// restore (pseudo)-stack pointer (we don't want to touch the real
|
||||||
|
// stack pointer, since we haven't copied the arguments yet)
|
||||||
|
movl %ebp,%ecx
|
||||||
|
|
||||||
|
// allocate new frame, adding room for callee-saved registers
|
||||||
|
subl 28(%esp),%ecx
|
||||||
|
subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%ecx
|
||||||
|
|
||||||
|
movl 4(%esp),%ebx
|
||||||
|
|
||||||
|
// set return address
|
||||||
|
call LOCAL(getPC)
|
||||||
|
addl $_GLOBAL_OFFSET_TABLE_,%esi
|
||||||
|
movl vmInvoke_returnAddress@GOT(%esi),%esi
|
||||||
|
movl %esi,(%ecx)
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
movl $0,%esi
|
||||||
|
movl 20(%esp),%edx
|
||||||
|
movl 24(%esp),%eax
|
||||||
|
jmp LOCAL(vmJumpAndInvoke_argumentTest)
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentLoop):
|
||||||
|
movl (%eax,%esi,1),%edi
|
||||||
|
movl %edi,4(%ecx,%esi,1)
|
||||||
|
addl $4,%esi
|
||||||
|
|
||||||
|
LOCAL(vmJumpAndInvoke_argumentTest):
|
||||||
|
cmpl %edx,%esi
|
||||||
|
jb LOCAL(vmJumpAndInvoke_argumentLoop)
|
||||||
|
|
||||||
|
movl 8(%esp),%esi
|
||||||
|
|
||||||
|
// the arguments have been copied, so we can set the real stack
|
||||||
|
// pointer now
|
||||||
|
movl %ecx,%esp
|
||||||
|
|
||||||
|
jmp *%esi
|
||||||
|
#else // not AVIAN_CONTINUATIONS
|
||||||
|
// vmJumpAndInvoke should only be called when continuations are
|
||||||
|
// enabled
|
||||||
|
int3
|
||||||
|
#endif // AVIAN_CONTINUATIONS
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error unsupported architecture
|
#error unsupported architecture
|
||||||
#endif //def __x86_64__
|
#endif //def __x86_64__
|
||||||
|
3065
src/compile.cpp
3065
src/compile.cpp
File diff suppressed because it is too large
Load Diff
874
src/compiler.cpp
874
src/compiler.cpp
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,11 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
class TraceHandler {
|
||||||
|
public:
|
||||||
|
virtual void handleTrace(Promise* address, unsigned argumentIndex) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
public:
|
public:
|
||||||
class Client {
|
class Client {
|
||||||
@ -28,9 +33,9 @@ class Compiler {
|
|||||||
|
|
||||||
static const unsigned Aligned = 1 << 0;
|
static const unsigned Aligned = 1 << 0;
|
||||||
static const unsigned NoReturn = 1 << 1;
|
static const unsigned NoReturn = 1 << 1;
|
||||||
|
static const unsigned TailJump = 1 << 2;
|
||||||
|
|
||||||
class Operand { };
|
class Operand { };
|
||||||
class StackElement { };
|
|
||||||
class State { };
|
class State { };
|
||||||
class Subroutine { };
|
class Subroutine { };
|
||||||
|
|
||||||
@ -39,7 +44,7 @@ class Compiler {
|
|||||||
|
|
||||||
virtual Subroutine* startSubroutine() = 0;
|
virtual Subroutine* startSubroutine() = 0;
|
||||||
virtual void endSubroutine(Subroutine* subroutine) = 0;
|
virtual void endSubroutine(Subroutine* subroutine) = 0;
|
||||||
virtual void restoreFromSubroutine(Subroutine* subroutine) = 0;
|
virtual void linkSubroutine(Subroutine* subroutine) = 0;
|
||||||
|
|
||||||
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
|
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
|
||||||
unsigned localFootprint, unsigned alignedFrameSize) = 0;
|
unsigned localFootprint, unsigned alignedFrameSize) = 0;
|
||||||
@ -52,16 +57,16 @@ class Compiler {
|
|||||||
virtual Promise* poolAppend(intptr_t value) = 0;
|
virtual Promise* poolAppend(intptr_t value) = 0;
|
||||||
virtual Promise* poolAppendPromise(Promise* value) = 0;
|
virtual Promise* poolAppendPromise(Promise* value) = 0;
|
||||||
|
|
||||||
virtual Operand* constant(int64_t value) = 0;
|
virtual Operand* constant(int64_t value, unsigned code) = 0;
|
||||||
virtual Operand* promiseConstant(Promise* value) = 0;
|
virtual Operand* promiseConstant(Promise* value, unsigned code) = 0;
|
||||||
virtual Operand* address(Promise* address) = 0;
|
virtual Operand* address(Promise* address) = 0;
|
||||||
virtual Operand* memory(Operand* base,
|
virtual Operand* memory(Operand* base,
|
||||||
|
unsigned code,
|
||||||
int displacement = 0,
|
int displacement = 0,
|
||||||
Operand* index = 0,
|
Operand* index = 0,
|
||||||
unsigned scale = 1) = 0;
|
unsigned scale = 1) = 0;
|
||||||
|
|
||||||
virtual Operand* stack() = 0;
|
virtual Operand* register_(int number) = 0;
|
||||||
virtual Operand* thread() = 0;
|
|
||||||
|
|
||||||
virtual void push(unsigned footprint) = 0;
|
virtual void push(unsigned footprint) = 0;
|
||||||
virtual void push(unsigned footprint, Operand* value) = 0;
|
virtual void push(unsigned footprint, Operand* value) = 0;
|
||||||
@ -69,15 +74,14 @@ class Compiler {
|
|||||||
virtual Operand* pop(unsigned footprint) = 0;
|
virtual Operand* pop(unsigned footprint) = 0;
|
||||||
virtual void pushed() = 0;
|
virtual void pushed() = 0;
|
||||||
virtual void popped(unsigned footprint) = 0;
|
virtual void popped(unsigned footprint) = 0;
|
||||||
virtual StackElement* top() = 0;
|
virtual unsigned topOfStack() = 0;
|
||||||
virtual unsigned footprint(StackElement*) = 0;
|
|
||||||
virtual unsigned index(StackElement*) = 0;
|
|
||||||
virtual Operand* peek(unsigned footprint, unsigned index) = 0;
|
virtual Operand* peek(unsigned footprint, unsigned index) = 0;
|
||||||
|
|
||||||
virtual Operand* call(Operand* address,
|
virtual Operand* call(Operand* address,
|
||||||
unsigned flags,
|
unsigned flags,
|
||||||
TraceHandler* traceHandler,
|
TraceHandler* traceHandler,
|
||||||
unsigned resultSize,
|
unsigned resultSize,
|
||||||
|
unsigned resultCode,
|
||||||
unsigned argumentCount,
|
unsigned argumentCount,
|
||||||
...) = 0;
|
...) = 0;
|
||||||
|
|
||||||
@ -85,11 +89,12 @@ class Compiler {
|
|||||||
unsigned flags,
|
unsigned flags,
|
||||||
TraceHandler* traceHandler,
|
TraceHandler* traceHandler,
|
||||||
unsigned resultSize,
|
unsigned resultSize,
|
||||||
|
unsigned resultCode,
|
||||||
unsigned argumentFootprint) = 0;
|
unsigned argumentFootprint) = 0;
|
||||||
|
|
||||||
virtual void return_(unsigned size, Operand* value) = 0;
|
virtual void return_(unsigned size, Operand* value) = 0;
|
||||||
|
|
||||||
virtual void initLocal(unsigned size, unsigned index) = 0;
|
virtual void initLocal(unsigned size, unsigned index, unsigned code) = 0;
|
||||||
virtual void initLocalsFromLogicalIp(unsigned logicalIp) = 0;
|
virtual void initLocalsFromLogicalIp(unsigned logicalIp) = 0;
|
||||||
virtual void storeLocal(unsigned footprint, Operand* src,
|
virtual void storeLocal(unsigned footprint, Operand* src,
|
||||||
unsigned index) = 0;
|
unsigned index) = 0;
|
||||||
@ -114,8 +119,15 @@ class Compiler {
|
|||||||
virtual void jge(Operand* address) = 0;
|
virtual void jge(Operand* address) = 0;
|
||||||
virtual void je(Operand* address) = 0;
|
virtual void je(Operand* address) = 0;
|
||||||
virtual void jne(Operand* address) = 0;
|
virtual void jne(Operand* address) = 0;
|
||||||
virtual void juo(Operand* address) = 0;
|
virtual void fjl(Operand* address) = 0;
|
||||||
|
virtual void fjg(Operand* address) = 0;
|
||||||
|
virtual void fjle(Operand* address) = 0;
|
||||||
|
virtual void fjge(Operand* address) = 0;
|
||||||
|
virtual void fje(Operand* address) = 0;
|
||||||
|
virtual void fjne(Operand* address) = 0;
|
||||||
|
virtual void fjuo(Operand* address) = 0;
|
||||||
virtual void jmp(Operand* address) = 0;
|
virtual void jmp(Operand* address) = 0;
|
||||||
|
virtual void exit(Operand* address) = 0;
|
||||||
virtual Operand* add(unsigned size, Operand* a, Operand* b) = 0;
|
virtual Operand* add(unsigned size, Operand* a, Operand* b) = 0;
|
||||||
virtual Operand* sub(unsigned size, Operand* a, Operand* b) = 0;
|
virtual Operand* sub(unsigned size, Operand* a, Operand* b) = 0;
|
||||||
virtual Operand* mul(unsigned size, Operand* a, Operand* b) = 0;
|
virtual Operand* mul(unsigned size, Operand* a, Operand* b) = 0;
|
||||||
@ -134,8 +146,8 @@ class Compiler {
|
|||||||
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0;
|
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0;
|
||||||
virtual Operand* neg(unsigned size, Operand* a) = 0;
|
virtual Operand* neg(unsigned size, Operand* a) = 0;
|
||||||
virtual Operand* fneg(unsigned size, Operand* a) = 0;
|
virtual Operand* fneg(unsigned size, Operand* a) = 0;
|
||||||
virtual Operand* operation(BinaryOperation op, unsigned aSize, unsigned resSize, Operand* a) = 0;
|
virtual Operand* operation(BinaryOperation op, unsigned aSize, unsigned resSize, unsigned resCode, Operand* a) = 0;
|
||||||
virtual Operand* operation(TernaryOperation op, unsigned aSize, unsigned bSize, unsigned resSize, Operand* a, Operand* b) = 0;
|
virtual Operand* operation(TernaryOperation op, unsigned aSize, unsigned bSize, unsigned resSize, unsigned resCode, Operand* a, Operand* b) = 0;
|
||||||
virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
||||||
virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
||||||
virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
||||||
|
161
src/continuations-x86.S
Normal file
161
src/continuations-x86.S
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#ifdef __x86_64__
|
||||||
|
|
||||||
|
#define THREAD_CONTINUATION 168
|
||||||
|
#define THREAD_EXCEPTION 64
|
||||||
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 176
|
||||||
|
#define THREAD_EXCEPTION_OFFSET 184
|
||||||
|
#define THREAD_EXCEPTION_HANDLER 192
|
||||||
|
|
||||||
|
#define CONTINUATION_NEXT 8
|
||||||
|
#define CONTINUATION_ADDRESS 32
|
||||||
|
#define CONTINUATION_RETURN_ADDRESS_OFFSET 40
|
||||||
|
#define CONTINUATION_FRAME_POINTER_OFFSET 48
|
||||||
|
#define CONTINUATION_LENGTH 56
|
||||||
|
#define CONTINUATION_BODY 64
|
||||||
|
|
||||||
|
// call the next continuation, if any
|
||||||
|
movq THREAD_CONTINUATION(%rbx),%rcx
|
||||||
|
cmpq $0,%rcx
|
||||||
|
je LOCAL(vmInvoke_exit)
|
||||||
|
|
||||||
|
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
|
||||||
|
// + CALLEE_SAVED_REGISTER_FOOTPRINT
|
||||||
|
movq CONTINUATION_LENGTH(%rcx),%rsi
|
||||||
|
shlq $3,%rsi
|
||||||
|
subq %rsi,%rsp
|
||||||
|
subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp
|
||||||
|
|
||||||
|
// copy the continuation body into the frame
|
||||||
|
leaq CONTINUATION_BODY(%rcx),%rdi
|
||||||
|
|
||||||
|
movq $0,%r9
|
||||||
|
jmp LOCAL(vmInvoke_continuationTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationLoop):
|
||||||
|
movq (%rdi,%r9,1),%r8
|
||||||
|
movq %r8,(%rsp,%r9,1)
|
||||||
|
addq $8,%r9
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationTest):
|
||||||
|
cmpq %rsi,%r9
|
||||||
|
jb LOCAL(vmInvoke_continuationLoop)
|
||||||
|
|
||||||
|
// set the return address to vmInvoke_returnAddress
|
||||||
|
movq CONTINUATION_RETURN_ADDRESS_OFFSET(%rcx),%rdi
|
||||||
|
movq vmInvoke_returnAddress@GOTPCREL(%rip),%r10
|
||||||
|
movq %r10,(%rsp,%rdi,1)
|
||||||
|
|
||||||
|
// save the current base pointer in the frame and update it
|
||||||
|
movq CONTINUATION_FRAME_POINTER_OFFSET(%rcx),%rdi
|
||||||
|
movq %rbp,(%rsp,%rdi,1)
|
||||||
|
addq %rsp,%rdi
|
||||||
|
movq %rdi,%rbp
|
||||||
|
|
||||||
|
// consume the continuation
|
||||||
|
movq CONTINUATION_NEXT(%rcx),%rdi
|
||||||
|
movq %rdi,THREAD_CONTINUATION(%rbx)
|
||||||
|
|
||||||
|
// call the continuation unless we're handling an exception
|
||||||
|
movq THREAD_EXCEPTION(%rbx),%rsi
|
||||||
|
cmpq $0,%rsi
|
||||||
|
jne LOCAL(vmInvoke_handleException)
|
||||||
|
jmp *CONTINUATION_ADDRESS(%rcx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_handleException):
|
||||||
|
// we're handling an exception - call the exception handler instead
|
||||||
|
movq $0,THREAD_EXCEPTION(%rbx)
|
||||||
|
movq THREAD_EXCEPTION_STACK_ADJUSTMENT(%rbx),%rdi
|
||||||
|
subq %rdi,%rsp
|
||||||
|
movq THREAD_EXCEPTION_OFFSET(%rbx),%rdi
|
||||||
|
movq %rsi,(%rsp,%rdi,1)
|
||||||
|
|
||||||
|
jmp *THREAD_EXCEPTION_HANDLER(%rbx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_exit):
|
||||||
|
|
||||||
|
#elif defined __i386__
|
||||||
|
|
||||||
|
#define THREAD_CONTINUATION 96
|
||||||
|
#define THREAD_EXCEPTION 36
|
||||||
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 100
|
||||||
|
#define THREAD_EXCEPTION_OFFSET 104
|
||||||
|
#define THREAD_EXCEPTION_HANDLER 108
|
||||||
|
|
||||||
|
#define CONTINUATION_NEXT 4
|
||||||
|
#define CONTINUATION_ADDRESS 16
|
||||||
|
#define CONTINUATION_RETURN_ADDRESS_OFFSET 20
|
||||||
|
#define CONTINUATION_FRAME_POINTER_OFFSET 24
|
||||||
|
#define CONTINUATION_LENGTH 28
|
||||||
|
#define CONTINUATION_BODY 32
|
||||||
|
|
||||||
|
// call the next continuation, if any
|
||||||
|
movl THREAD_CONTINUATION(%ebx),%ecx
|
||||||
|
cmpl $0,%ecx
|
||||||
|
je LOCAL(vmInvoke_exit)
|
||||||
|
|
||||||
|
// allocate a frame of size (continuation.length * BYTES_PER_WORD)
|
||||||
|
movl CONTINUATION_LENGTH(%ecx),%esi
|
||||||
|
shll $2,%esi
|
||||||
|
subl %esi,%esp
|
||||||
|
|
||||||
|
// copy the continuation body into the frame
|
||||||
|
leal CONTINUATION_BODY(%ecx),%edi
|
||||||
|
|
||||||
|
push %eax
|
||||||
|
push %edx
|
||||||
|
|
||||||
|
movl $0,%edx
|
||||||
|
jmp LOCAL(vmInvoke_continuationTest)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationLoop):
|
||||||
|
movl (%edi,%edx,1),%eax
|
||||||
|
movl %eax,8(%esp,%edx,1)
|
||||||
|
addl $4,%edx
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_continuationTest):
|
||||||
|
cmpl %esi,%edx
|
||||||
|
jb LOCAL(vmInvoke_continuationLoop)
|
||||||
|
|
||||||
|
pop %edx
|
||||||
|
pop %eax
|
||||||
|
|
||||||
|
// set the return address to vmInvoke_returnAddress
|
||||||
|
movl CONTINUATION_RETURN_ADDRESS_OFFSET(%ecx),%edi
|
||||||
|
call LOCAL(getPC)
|
||||||
|
addl $_GLOBAL_OFFSET_TABLE_,%esi
|
||||||
|
movl vmInvoke_returnAddress@GOT(%esi),%esi
|
||||||
|
movl %esi,(%esp,%edi,1)
|
||||||
|
|
||||||
|
// save the current base pointer in the frame and update it
|
||||||
|
movl CONTINUATION_FRAME_POINTER_OFFSET(%ecx),%edi
|
||||||
|
movl %ebp,(%esp,%edi,1)
|
||||||
|
addl %esp,%edi
|
||||||
|
movl %edi,%ebp
|
||||||
|
|
||||||
|
// consume the continuation
|
||||||
|
movl CONTINUATION_NEXT(%ecx),%edi
|
||||||
|
movl %edi,THREAD_CONTINUATION(%ebx)
|
||||||
|
|
||||||
|
// call the continuation unless we're handling an exception
|
||||||
|
movl THREAD_EXCEPTION(%ebx),%esi
|
||||||
|
cmpl $0,%esi
|
||||||
|
jne LOCAL(vmInvoke_handleException)
|
||||||
|
|
||||||
|
jmp *CONTINUATION_ADDRESS(%ecx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_handleException):
|
||||||
|
// we're handling an exception - call the exception handler instead
|
||||||
|
movl $0,THREAD_EXCEPTION(%ebx)
|
||||||
|
movl THREAD_EXCEPTION_STACK_ADJUSTMENT(%ebx),%edi
|
||||||
|
subl %edi,%esp
|
||||||
|
movl THREAD_EXCEPTION_OFFSET(%ebx),%edi
|
||||||
|
movl %esi,(%esp,%edi,1)
|
||||||
|
|
||||||
|
jmp *THREAD_EXCEPTION_HANDLER(%ebx)
|
||||||
|
|
||||||
|
LOCAL(vmInvoke_exit):
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error unsupported architecture
|
||||||
|
#endif
|
||||||
|
|
413
src/gnu.cpp
Normal file
413
src/gnu.cpp
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/* Copyright (c) 2009, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#include "machine.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "processor.h"
|
||||||
|
|
||||||
|
using namespace vm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void
|
||||||
|
setProperty(Thread* t, object method, object properties,
|
||||||
|
const char* name, const void* value, const char* format = "%s")
|
||||||
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
PROTECT(t, properties);
|
||||||
|
|
||||||
|
object n = makeString(t, "%s", name);
|
||||||
|
PROTECT(t, n);
|
||||||
|
|
||||||
|
object v = makeString(t, format, value);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, method, properties, n, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
|
||||||
|
jobject JNICALL
|
||||||
|
NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
|
||||||
|
{
|
||||||
|
const char* pointerClassName;
|
||||||
|
const char* initSpec;
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
pointerClassName = "gnu/classpath/Pointer64";
|
||||||
|
initSpec = "(J)V";
|
||||||
|
} else {
|
||||||
|
pointerClassName = "gnu/classpath/Pointer32";
|
||||||
|
initSpec = "(I)V";
|
||||||
|
}
|
||||||
|
|
||||||
|
object pointerClass = resolveClass(t, pointerClassName);
|
||||||
|
if (UNLIKELY(pointerClass == 0)) return 0;
|
||||||
|
PROTECT(t, pointerClass);
|
||||||
|
|
||||||
|
object pointerConstructor = resolveMethod
|
||||||
|
(t, pointerClass, "<init>", initSpec);
|
||||||
|
if (UNLIKELY(pointerConstructor == 0)) return 0;
|
||||||
|
|
||||||
|
object pointer = make(t, pointerClass);
|
||||||
|
PROTECT(t, pointer);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, pointerConstructor, pointer, address);
|
||||||
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
object bufferClass = resolveClass
|
||||||
|
(t, "java/nio/DirectByteBufferImpl$ReadWrite");
|
||||||
|
if (UNLIKELY(bufferClass == 0)) return 0;
|
||||||
|
PROTECT(t, bufferClass);
|
||||||
|
|
||||||
|
object bufferConstructor = resolveMethod
|
||||||
|
(t, bufferClass, "<init>", "(Lgnu/classpath/Pointer;int)V");
|
||||||
|
if (UNLIKELY(bufferConstructor == 0)) return 0;
|
||||||
|
|
||||||
|
object buffer = make(t, bufferClass);
|
||||||
|
PROTECT(t, buffer);
|
||||||
|
|
||||||
|
t->m->processor->invoke
|
||||||
|
(t, bufferConstructor, buffer, &pointer, static_cast<jint>(capacity));
|
||||||
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
return makeLocalReference(t, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* JNICALL
|
||||||
|
GetDirectBufferAddress(Thread* t, jobject buffer)
|
||||||
|
{
|
||||||
|
object addressField = resolveField
|
||||||
|
(t, objectClass(t, *buffer), "address", "Lgnu/classpath/Pointer;");
|
||||||
|
if (UNLIKELY(addressField == 0)) return 0;
|
||||||
|
|
||||||
|
object address = cast<object>(*buffer, fieldOffset(t, addressField));
|
||||||
|
if (address == 0) return 0;
|
||||||
|
|
||||||
|
const char* dataSpec;
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
dataSpec = "J";
|
||||||
|
} else {
|
||||||
|
dataSpec = "I";
|
||||||
|
}
|
||||||
|
|
||||||
|
object dataField = resolveField
|
||||||
|
(t, objectClass(t, address), "data", dataSpec);
|
||||||
|
if (UNLIKELY(dataField == 0)) return 0;
|
||||||
|
|
||||||
|
return cast<void*>(address, fieldOffset(t, dataField));
|
||||||
|
}
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetDirectBufferCapacity(Thread* t, jobject buffer)
|
||||||
|
{
|
||||||
|
object capField = resolveField(t, objectClass(t, *buffer), "cap", "I");
|
||||||
|
if (UNLIKELY(capField == 0)) return 0;
|
||||||
|
|
||||||
|
return cast<jint>(*buffer, fieldOffset(t, capField));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vm
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_gnu_classpath_VMSystemProperties_preInit
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object properties = reinterpret_cast<object>(arguments[0]);
|
||||||
|
PROTECT(t, properties);
|
||||||
|
|
||||||
|
object method = resolveMethod
|
||||||
|
(t, "java/util/Properties", "setProperty",
|
||||||
|
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
|
||||||
|
|
||||||
|
if (UNLIKELY(t->exception)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "java.vm.name", "Avian");
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "java.protocol.handler.pkgs", "avian");
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "file.encoding", "ASCII");
|
||||||
|
|
||||||
|
// specify a bogus library path so we can do our own search in
|
||||||
|
// VMRuntime.nativeLoad:
|
||||||
|
#define LIBRARY_PATH_SENTINAL "*"
|
||||||
|
setProperty(t, method, properties, "java.library.path",
|
||||||
|
LIBRARY_PATH_SENTINAL);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# define FILE_SEPARATOR "\\"
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "line.separator", "\r\n");
|
||||||
|
setProperty(t, method, properties, "file.separator", FILE_SEPARATOR);
|
||||||
|
setProperty(t, method, properties, "path.separator", ";");
|
||||||
|
setProperty(t, method, properties, "os.name", "Windows");
|
||||||
|
|
||||||
|
TCHAR buffer[MAX_PATH];
|
||||||
|
GetTempPath(MAX_PATH, buffer);
|
||||||
|
setProperty(t, method, properties, "java.io.tmpdir", buffer);
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "user.home",
|
||||||
|
_wgetenv(L"USERPROFILE"), "%ls");
|
||||||
|
|
||||||
|
GetCurrentDirectory(MAX_PATH, buffer);
|
||||||
|
setProperty(t, method, properties, "user.dir", buffer);
|
||||||
|
#else
|
||||||
|
# define FILE_SEPARATOR "/"
|
||||||
|
|
||||||
|
setProperty(t, method, properties, "line.separator", "\n");
|
||||||
|
setProperty(t, method, properties, "file.separator", FILE_SEPARATOR);
|
||||||
|
setProperty(t, method, properties, "path.separator", ":");
|
||||||
|
# ifdef __APPLE__
|
||||||
|
setProperty(t, method, properties, "os.name", "Mac OS X");
|
||||||
|
# else
|
||||||
|
setProperty(t, method, properties, "os.name", "Linux");
|
||||||
|
# endif
|
||||||
|
setProperty(t, method, properties, "java.io.tmpdir", "/tmp");
|
||||||
|
setProperty(t, method, properties, "user.home", getenv("HOME"));
|
||||||
|
setProperty(t, method, properties, "user.dir", getenv("PWD"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
setProperty(t, method, properties, "os.arch", "x86");
|
||||||
|
#elif defined __x86_64__
|
||||||
|
setProperty(t, method, properties, "os.arch", "x86_64");
|
||||||
|
#elif defined(__ppc__) || defined(__powerpc__) \
|
||||||
|
|| defined(__ppc64__) || defined(__powerpc64__)
|
||||||
|
setProperty(t, method, properties, "os.arch", "ppc");
|
||||||
|
#elif defined __ia64__
|
||||||
|
setProperty(t, method, properties, "os.arch", "ia64");
|
||||||
|
#elif defined __arm__
|
||||||
|
setProperty(t, method, properties, "os.arch", "arm");
|
||||||
|
#elif defined __alpha__
|
||||||
|
setProperty(t, method, properties, "os.arch", "alpha");
|
||||||
|
#elif defined __sparc64__
|
||||||
|
setProperty(t, method, properties, "os.arch", "sparc64");
|
||||||
|
#else
|
||||||
|
setProperty(t, method, properties, "os.arch", "unknown");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_gnu_classpath_VMStackWalker_getClassContext
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
class Visitor: public Processor::StackVisitor {
|
||||||
|
public:
|
||||||
|
Visitor(Thread* t):
|
||||||
|
t(t), skipCount(1), trace(0), index(0), protector(t, &trace)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual bool visit(Processor::StackWalker* walker) {
|
||||||
|
if (skipCount == 0) {
|
||||||
|
if (trace == 0) {
|
||||||
|
trace = makeObjectArray
|
||||||
|
(t, arrayBody(t, t->m->types, Machine::ClassType),
|
||||||
|
walker->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(t, index < objectArrayLength(t, trace));
|
||||||
|
|
||||||
|
set(t, trace, ArrayBody + (index * BytesPerWord),
|
||||||
|
methodClass(t, walker->method()));
|
||||||
|
|
||||||
|
++ index;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
-- skipCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* t;
|
||||||
|
unsigned skipCount;
|
||||||
|
object trace;
|
||||||
|
unsigned index;
|
||||||
|
Thread::SingleProtector protector;
|
||||||
|
} v(t);
|
||||||
|
|
||||||
|
t->m->processor->walkStack(t, &v);
|
||||||
|
|
||||||
|
if (v.trace == 0) {
|
||||||
|
v.trace = makeObjectArray
|
||||||
|
(t, arrayBody(t, t->m->types, Machine::ClassType), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>(v.trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_gnu_classpath_VMStackWalker_getClassLoader
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<int64_t>
|
||||||
|
(classLoader(t, reinterpret_cast<object>(arguments[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_mapLibraryName
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = reinterpret_cast<object>(arguments[0]);
|
||||||
|
PROTECT(t, name);
|
||||||
|
|
||||||
|
const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1;
|
||||||
|
const unsigned nameLength = stringLength(t, name);
|
||||||
|
const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1;
|
||||||
|
const unsigned total = soPrefixLength + nameLength + soSuffixLength;
|
||||||
|
|
||||||
|
object s = makeByteArray(t, total + 1);
|
||||||
|
char* p = reinterpret_cast<char*>(&byteArrayBody(t, s, 0));
|
||||||
|
|
||||||
|
memcpy(p, SO_PREFIX, soPrefixLength);
|
||||||
|
stringChars(t, name, p + soPrefixLength);
|
||||||
|
memcpy(p + soPrefixLength + nameLength, SO_SUFFIX, soSuffixLength);
|
||||||
|
p[total] = 0;
|
||||||
|
|
||||||
|
return reinterpret_cast<int64_t>(makeString(t, s, 0, total, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_System_arraycopy
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMSystem_arraycopy
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
Avian_java_lang_System_arraycopy(t, 0, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_Runtime_load
|
||||||
|
(Thread* t, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_nativeLoad
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
object name = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
|
// given that we set java.library.path to LIBRARY_PATH_SENTINAL, we
|
||||||
|
// can determine which names are filenames and which are library
|
||||||
|
// names by looking for the prefix LIBRARY_PATH_SENTINAL
|
||||||
|
// FILE_SEPARATOR
|
||||||
|
|
||||||
|
unsigned length = stringLength(t, name);
|
||||||
|
char n[length + 1];
|
||||||
|
stringChars(t, name, n);
|
||||||
|
|
||||||
|
const unsigned pathPrefixLength
|
||||||
|
= sizeof(LIBRARY_PATH_SENTINAL) - 1
|
||||||
|
+ sizeof(FILE_SEPARATOR) - 1;
|
||||||
|
|
||||||
|
bool mapName = (strncmp(n, LIBRARY_PATH_SENTINAL FILE_SEPARATOR,
|
||||||
|
pathPrefixLength) == 0);
|
||||||
|
if (mapName) {
|
||||||
|
// strip the path prefix, SO prefix, and SO suffix before passing
|
||||||
|
// the name to Runtime.load
|
||||||
|
|
||||||
|
const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1;
|
||||||
|
const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1;
|
||||||
|
const unsigned newOffset
|
||||||
|
= stringOffset(t, name) + pathPrefixLength + soPrefixLength;
|
||||||
|
const unsigned newLength
|
||||||
|
= length - pathPrefixLength - soPrefixLength - soSuffixLength;
|
||||||
|
|
||||||
|
name = makeString(t, stringData(t, name), newOffset, newLength, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t args[] = { reinterpret_cast<uintptr_t>(name), mapName };
|
||||||
|
|
||||||
|
Avian_java_lang_Runtime_load(t, 0, args);
|
||||||
|
|
||||||
|
if (t->exception) {
|
||||||
|
t->exception = 0;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_Class_primitiveClass
|
||||||
|
(Thread* t, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_getPrimitiveClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return Avian_java_lang_Class_primitiveClass(t, 0, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_System_identityHashCode
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMSystem_identityHashCode
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
return Avian_java_lang_System_identityHashCode(t, 0, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_Runtime_gc
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_gc
|
||||||
|
(Thread* t, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
Avian_java_lang_Runtime_gc(t, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_runFinalizationForExit
|
||||||
|
(Thread*, object, uintptr_t*)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Avian_java_lang_VMRuntime_exit
|
||||||
|
(Thread*, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
exit(arguments[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_SystemClassLoader_findClass
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_loadClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
uintptr_t args[] = { 0, arguments[0] };
|
||||||
|
|
||||||
|
return Avian_avian_SystemClassLoader_findClass(t, 0, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_avian_SystemClassLoader_findLoadedClass
|
||||||
|
(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
|
Avian_java_lang_VMClassLoader_findLoadedClass
|
||||||
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
|
{
|
||||||
|
uintptr_t args[] = { 0, arguments[1] };
|
||||||
|
|
||||||
|
return Avian_avian_SystemClassLoader_findLoadedClass(t, 0, args);
|
||||||
|
}
|
37
src/heap.cpp
37
src/heap.cpp
@ -34,6 +34,12 @@ const bool Verbose2 = false;
|
|||||||
const bool Debug = false;
|
const bool Debug = false;
|
||||||
const bool DebugFixies = false;
|
const bool DebugFixies = false;
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
const bool DebugAllocation = false;
|
||||||
|
#else
|
||||||
|
const bool DebugAllocation = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ACQUIRE(x) MutexLock MAKE_NAME(monitorLock_) (x)
|
#define ACQUIRE(x) MutexLock MAKE_NAME(monitorLock_) (x)
|
||||||
|
|
||||||
class MutexLock {
|
class MutexLock {
|
||||||
@ -422,7 +428,9 @@ class Segment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
free(context, data, (footprint(capacity())) * BytesPerWord);
|
if (data) {
|
||||||
|
free(context, data, (footprint(capacity())) * BytesPerWord);
|
||||||
|
}
|
||||||
data = 0;
|
data = 0;
|
||||||
map = 0;
|
map = 0;
|
||||||
}
|
}
|
||||||
@ -1673,11 +1681,22 @@ void* tryAllocate(Context* c, unsigned size)
|
|||||||
{
|
{
|
||||||
ACQUIRE(c->lock);
|
ACQUIRE(c->lock);
|
||||||
|
|
||||||
|
if (DebugAllocation) {
|
||||||
|
size = pad(size) + 2 * BytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
if (size + c->count < c->limit) {
|
if (size + c->count < c->limit) {
|
||||||
void* p = c->system->tryAllocate(size);
|
void* p = c->system->tryAllocate(size);
|
||||||
if (p) {
|
if (p) {
|
||||||
c->count += size;
|
c->count += size;
|
||||||
return p;
|
|
||||||
|
if (DebugAllocation) {
|
||||||
|
static_cast<uintptr_t*>(p)[0] = 0x22377322;
|
||||||
|
static_cast<uintptr_t*>(p)[(size / BytesPerWord) - 1] = 0x22377322;
|
||||||
|
return static_cast<uintptr_t*>(p) + 1;
|
||||||
|
} else {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1686,7 +1705,21 @@ void* tryAllocate(Context* c, unsigned size)
|
|||||||
void free(Context* c, const void* p, unsigned size) {
|
void free(Context* c, const void* p, unsigned size) {
|
||||||
ACQUIRE(c->lock);
|
ACQUIRE(c->lock);
|
||||||
|
|
||||||
|
if (DebugAllocation) {
|
||||||
|
size = pad(size) + 2 * BytesPerWord;
|
||||||
|
|
||||||
|
memset(const_cast<void*>(p), 0xFE, size - (2 * BytesPerWord));
|
||||||
|
|
||||||
|
p = static_cast<const uintptr_t*>(p) - 1;
|
||||||
|
|
||||||
|
expect(c->system, static_cast<const uintptr_t*>(p)[0] == 0x22377322);
|
||||||
|
|
||||||
|
expect(c->system, static_cast<const uintptr_t*>(p)
|
||||||
|
[(size / BytesPerWord) - 1] == 0x22377322);
|
||||||
|
}
|
||||||
|
|
||||||
expect(c->system, c->count >= size);
|
expect(c->system, c->count >= size);
|
||||||
|
|
||||||
c->system->free(p);
|
c->system->free(p);
|
||||||
c->count -= size;
|
c->count -= size;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ class Context {
|
|||||||
while (stack) {
|
while (stack) {
|
||||||
Stack* dead = stack;
|
Stack* dead = stack;
|
||||||
stack = dead->next;
|
stack = dead->next;
|
||||||
thread->m->heap->free(stack, sizeof(Stack));
|
thread->m->heap->free(dead, sizeof(Stack));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ const unsigned FrameMethodOffset = 2;
|
|||||||
const unsigned FrameIpOffset = 3;
|
const unsigned FrameIpOffset = 3;
|
||||||
const unsigned FrameFootprint = 4;
|
const unsigned FrameFootprint = 4;
|
||||||
|
|
||||||
|
class ClassInitList;
|
||||||
|
|
||||||
class Thread: public vm::Thread {
|
class Thread: public vm::Thread {
|
||||||
public:
|
public:
|
||||||
static const unsigned StackSizeInBytes = 64 * 1024;
|
static const unsigned StackSizeInBytes = 64 * 1024;
|
||||||
@ -36,16 +38,39 @@ class Thread: public vm::Thread {
|
|||||||
ip(0),
|
ip(0),
|
||||||
sp(0),
|
sp(0),
|
||||||
frame(-1),
|
frame(-1),
|
||||||
code(0)
|
code(0),
|
||||||
|
classInitList(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned ip;
|
unsigned ip;
|
||||||
unsigned sp;
|
unsigned sp;
|
||||||
int frame;
|
int frame;
|
||||||
object code;
|
object code;
|
||||||
|
ClassInitList* classInitList;
|
||||||
uintptr_t stack[StackSizeInWords];
|
uintptr_t stack[StackSizeInWords];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClassInitList {
|
||||||
|
public:
|
||||||
|
ClassInitList(Thread* t, object class_, ClassInitList* next):
|
||||||
|
t(t), class_(class_), next(next)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
static void push(Thread* t, object class_) {
|
||||||
|
t->classInitList = new (t->m->heap->allocate(sizeof(ClassInitList)))
|
||||||
|
ClassInitList(t, class_, t->classInitList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop() {
|
||||||
|
t->classInitList = next;
|
||||||
|
t->m->heap->free(this, sizeof(ClassInitList));
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* t;
|
||||||
|
object class_;
|
||||||
|
ClassInitList* next;
|
||||||
|
};
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
pushObject(Thread* t, object o)
|
pushObject(Thread* t, object o)
|
||||||
{
|
{
|
||||||
@ -142,7 +167,7 @@ popLong(Thread* t)
|
|||||||
return (b << 32) | a;
|
return (b << 32) | a;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float
|
inline double
|
||||||
popDouble(Thread* t)
|
popDouble(Thread* t)
|
||||||
{
|
{
|
||||||
return bitsToDouble(popLong(t));
|
return bitsToDouble(popLong(t));
|
||||||
@ -348,12 +373,14 @@ popFrame(Thread* t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)) {
|
if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)
|
||||||
if (t->exception) {
|
and t->classInitList)
|
||||||
t->exception = makeExceptionInInitializerError(t, t->exception);
|
{
|
||||||
}
|
assert(t, t->classInitList->class_ == methodClass(t, method));
|
||||||
classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag);
|
|
||||||
release(t, t->m->classLock);
|
t->classInitList->pop();
|
||||||
|
|
||||||
|
postInitClass(t, methodClass(t, method));
|
||||||
}
|
}
|
||||||
|
|
||||||
t->sp = frameBase(t, t->frame);
|
t->sp = frameBase(t, t->frame);
|
||||||
@ -410,8 +437,7 @@ makeNativeMethodData(Thread* t, object method, void* function)
|
|||||||
object data = makeNativeMethodData(t,
|
object data = makeNativeMethodData(t,
|
||||||
function,
|
function,
|
||||||
0, // argument table size
|
0, // argument table size
|
||||||
count,
|
count);
|
||||||
false);
|
|
||||||
|
|
||||||
unsigned argumentTableSize = BytesPerWord * 2;
|
unsigned argumentTableSize = BytesPerWord * 2;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@ -460,7 +486,7 @@ makeNativeMethodData(Thread* t, object method, void* function)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline void
|
||||||
resolveNativeMethodData(Thread* t, object method)
|
resolveNativeMethodData(Thread* t, object method)
|
||||||
{
|
{
|
||||||
if (methodCode(t, method) == 0) {
|
if (methodCode(t, method) == 0) {
|
||||||
@ -468,8 +494,13 @@ resolveNativeMethodData(Thread* t, object method)
|
|||||||
if (LIKELY(p)) {
|
if (LIKELY(p)) {
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
object data = makeNativeMethodData(t, method, p);
|
object data = makeNativeMethodData(t, method, p);
|
||||||
|
|
||||||
|
// ensure other threads see updated methodVmFlags before
|
||||||
|
// methodCode, and that the native method data is initialized
|
||||||
|
// before it is visible to those threads:
|
||||||
|
memoryBarrier();
|
||||||
|
|
||||||
set(t, method, MethodCode, data);
|
set(t, method, MethodCode, data);
|
||||||
return data;
|
|
||||||
} else {
|
} else {
|
||||||
object message = makeString
|
object message = makeString
|
||||||
(t, "%s.%s%s",
|
(t, "%s.%s%s",
|
||||||
@ -477,11 +508,8 @@ resolveNativeMethodData(Thread* t, object method)
|
|||||||
&byteArrayBody(t, methodName(t, method), 0),
|
&byteArrayBody(t, methodName(t, method), 0),
|
||||||
&byteArrayBody(t, methodSpec(t, method), 0));
|
&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
t->exception = makeUnsatisfiedLinkError(t, message);
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return methodCode(t, method);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -498,35 +526,79 @@ checkStack(Thread* t, object method)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
void
|
||||||
invokeNative(Thread* t, object method)
|
pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect)
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
switch (returnCode) {
|
||||||
|
case ByteField:
|
||||||
|
case BooleanField:
|
||||||
|
if (DebugRun) {
|
||||||
|
fprintf(stderr, "result: %d\n", static_cast<int8_t>(result));
|
||||||
|
}
|
||||||
|
pushInt(t, static_cast<int8_t>(result));
|
||||||
|
break;
|
||||||
|
|
||||||
object data = resolveNativeMethodData(t, method);
|
case CharField:
|
||||||
if (UNLIKELY(t->exception)) {
|
if (DebugRun) {
|
||||||
return VoidField;
|
fprintf(stderr, "result: %d\n", static_cast<uint16_t>(result));
|
||||||
|
}
|
||||||
|
pushInt(t, static_cast<uint16_t>(result));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ShortField:
|
||||||
|
if (DebugRun) {
|
||||||
|
fprintf(stderr, "result: %d\n", static_cast<int16_t>(result));
|
||||||
|
}
|
||||||
|
pushInt(t, static_cast<int16_t>(result));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FloatField:
|
||||||
|
case IntField:
|
||||||
|
if (DebugRun) {
|
||||||
|
fprintf(stderr, "result: %d\n", static_cast<int32_t>(result));
|
||||||
|
}
|
||||||
|
pushInt(t, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LongField:
|
||||||
|
case DoubleField:
|
||||||
|
if (DebugRun) {
|
||||||
|
fprintf(stderr, "result: %"LLD"\n", result);
|
||||||
|
}
|
||||||
|
pushLong(t, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ObjectField:
|
||||||
|
if (indirect) {
|
||||||
|
if (DebugRun) {
|
||||||
|
fprintf(stderr, "result: %p at %p\n",
|
||||||
|
static_cast<uintptr_t>(result) == 0 ? 0 :
|
||||||
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)),
|
||||||
|
reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
||||||
|
}
|
||||||
|
pushObject(t, static_cast<uintptr_t>(result) == 0 ? 0 :
|
||||||
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
||||||
|
} else {
|
||||||
|
if (DebugRun) {
|
||||||
|
fprintf(stderr, "result: %p\n", reinterpret_cast<object>(result));
|
||||||
|
}
|
||||||
|
pushObject(t, reinterpret_cast<object>(result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VoidField:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort(t);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PROTECT(t, data);
|
void
|
||||||
|
marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count,
|
||||||
pushFrame(t, method);
|
object data, bool indirect)
|
||||||
|
{
|
||||||
unsigned count = nativeMethodDataLength(t, data) - 1;
|
|
||||||
|
|
||||||
unsigned size = nativeMethodDataArgumentTableSize(t, data);
|
|
||||||
uintptr_t args[size / BytesPerWord];
|
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
|
|
||||||
args[offset++] = reinterpret_cast<uintptr_t>(t);
|
|
||||||
|
|
||||||
unsigned i = 0;
|
|
||||||
if (methodFlags(t, method) & ACC_STATIC) {
|
|
||||||
++ i;
|
|
||||||
args[offset++] = reinterpret_cast<uintptr_t>
|
|
||||||
(pushReference(t, methodClass(t, method)));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned sp = frameBase(t, t->frame);
|
unsigned sp = frameBase(t, t->frame);
|
||||||
for (; i < count; ++i) {
|
for (; i < count; ++i) {
|
||||||
unsigned type = nativeMethodDataParameterTypes(t, data, i + 1);
|
unsigned type = nativeMethodDataParameterTypes(t, data, i + 1);
|
||||||
@ -548,16 +620,48 @@ invokeNative(Thread* t, object method)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case POINTER_TYPE: {
|
case POINTER_TYPE: {
|
||||||
object* v = reinterpret_cast<object*>(t->stack + ((sp++) * 2) + 1);
|
if (indirect) {
|
||||||
if (*v == 0) {
|
object* v = reinterpret_cast<object*>(t->stack + ((sp++) * 2) + 1);
|
||||||
v = 0;
|
if (*v == 0) {
|
||||||
|
v = 0;
|
||||||
|
}
|
||||||
|
args[offset++] = reinterpret_cast<uintptr_t>(v);
|
||||||
|
} else {
|
||||||
|
args[offset++] = reinterpret_cast<uintptr_t>(peekObject(t, sp++));
|
||||||
}
|
}
|
||||||
args[offset++] = reinterpret_cast<uintptr_t>(v);
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
invokeNativeSlow(Thread* t, object method)
|
||||||
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
object data = methodCode(t, method);
|
||||||
|
PROTECT(t, data);
|
||||||
|
|
||||||
|
pushFrame(t, method);
|
||||||
|
|
||||||
|
unsigned count = nativeMethodDataLength(t, data) - 1;
|
||||||
|
|
||||||
|
unsigned size = nativeMethodDataArgumentTableSize(t, data);
|
||||||
|
uintptr_t args[size / BytesPerWord];
|
||||||
|
unsigned offset = 0;
|
||||||
|
|
||||||
|
args[offset++] = reinterpret_cast<uintptr_t>(t);
|
||||||
|
|
||||||
|
unsigned i = 0;
|
||||||
|
if (methodFlags(t, method) & ACC_STATIC) {
|
||||||
|
++ i;
|
||||||
|
args[offset++] = reinterpret_cast<uintptr_t>
|
||||||
|
(pushReference(t, methodClass(t, method)));
|
||||||
|
}
|
||||||
|
|
||||||
|
marshalArguments(t, args + offset, i, count, data, true);
|
||||||
|
|
||||||
unsigned returnCode = methodReturnCode(t, method);
|
unsigned returnCode = methodReturnCode(t, method);
|
||||||
unsigned returnType = fieldType(t, returnCode);
|
unsigned returnType = fieldType(t, returnCode);
|
||||||
@ -609,80 +713,67 @@ invokeNative(Thread* t, object method)
|
|||||||
return VoidField;
|
return VoidField;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (returnCode) {
|
pushResult(t, returnCode, result, true);
|
||||||
case ByteField:
|
|
||||||
case BooleanField:
|
|
||||||
if (DebugRun) {
|
|
||||||
fprintf(stderr, "result: %d\n", static_cast<int8_t>(result));
|
|
||||||
}
|
|
||||||
pushInt(t, static_cast<int8_t>(result));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CharField:
|
|
||||||
if (DebugRun) {
|
|
||||||
fprintf(stderr, "result: %d\n", static_cast<uint16_t>(result));
|
|
||||||
}
|
|
||||||
pushInt(t, static_cast<uint16_t>(result));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ShortField:
|
|
||||||
if (DebugRun) {
|
|
||||||
fprintf(stderr, "result: %d\n", static_cast<int16_t>(result));
|
|
||||||
}
|
|
||||||
pushInt(t, static_cast<int16_t>(result));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FloatField:
|
|
||||||
case IntField:
|
|
||||||
if (DebugRun) {
|
|
||||||
fprintf(stderr, "result: %d\n", static_cast<int32_t>(result));
|
|
||||||
}
|
|
||||||
pushInt(t, result);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LongField:
|
|
||||||
case DoubleField:
|
|
||||||
if (DebugRun) {
|
|
||||||
fprintf(stderr, "result: %"LLD"\n", result);
|
|
||||||
}
|
|
||||||
pushLong(t, result);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ObjectField:
|
|
||||||
if (DebugRun) {
|
|
||||||
fprintf(stderr, "result: %p at %p\n",
|
|
||||||
static_cast<uintptr_t>(result) == 0 ? 0 :
|
|
||||||
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)),
|
|
||||||
reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
||||||
}
|
|
||||||
pushObject(t, static_cast<uintptr_t>(result) == 0 ? 0 :
|
|
||||||
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VoidField:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
invokeNative(Thread* t, object method)
|
||||||
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
resolveNativeMethodData(t, method);
|
||||||
|
|
||||||
|
if (UNLIKELY(t->exception)) {
|
||||||
|
return VoidField;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodVmFlags(t, method) & FastNative) {
|
||||||
|
pushFrame(t, method);
|
||||||
|
|
||||||
|
object data = methodCode(t, method);
|
||||||
|
uintptr_t arguments[methodParameterFootprint(t, method)];
|
||||||
|
marshalArguments
|
||||||
|
(t, arguments, (methodFlags(t, method) & ACC_STATIC) ? 1 : 0,
|
||||||
|
nativeMethodDataLength(t, data) - 1, data, false);
|
||||||
|
|
||||||
|
uint64_t result = reinterpret_cast<FastNativeFunction>
|
||||||
|
(nativeMethodDataFunction(t, methodCode(t, method)))
|
||||||
|
(t, method, arguments);
|
||||||
|
|
||||||
|
popFrame(t);
|
||||||
|
|
||||||
|
if (UNLIKELY(t->exception)) {
|
||||||
|
return VoidField;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushResult(t, methodReturnCode(t, method), result, false);
|
||||||
|
|
||||||
|
return methodReturnCode(t, method);
|
||||||
|
} else {
|
||||||
|
return invokeNativeSlow(t, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
classInit2(Thread* t, object class_, unsigned ipOffset)
|
classInit2(Thread* t, object class_, unsigned ipOffset)
|
||||||
{
|
{
|
||||||
|
for (ClassInitList* list = t->classInitList; list; list = list->next) {
|
||||||
|
if (list->class_ == class_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
acquire(t, t->m->classLock);
|
|
||||||
if (classVmFlags(t, class_) & NeedInitFlag
|
if (preInitClass(t, class_)) {
|
||||||
and (classVmFlags(t, class_) & InitFlag) == 0)
|
ClassInitList::push(t, class_);
|
||||||
{
|
|
||||||
classVmFlags(t, class_) |= InitFlag;
|
|
||||||
t->code = classInitializer(t, class_);
|
t->code = classInitializer(t, class_);
|
||||||
t->ip -= ipOffset;
|
t->ip -= ipOffset;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
release(t, t->m->classLock);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -911,7 +1002,7 @@ interpret(Thread* t)
|
|||||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
pushObject(t, makeObjectArray(t, class_, count, true));
|
pushObject(t, makeObjectArray(t, class_, count));
|
||||||
} else {
|
} else {
|
||||||
object message = makeString(t, "%d", count);
|
object message = makeString(t, "%d", count);
|
||||||
exception = makeNegativeArraySizeException(t, message);
|
exception = makeNegativeArraySizeException(t, message);
|
||||||
@ -2352,7 +2443,7 @@ interpret(Thread* t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object array = makeArray(t, counts[0], true);
|
object array = makeArray(t, counts[0]);
|
||||||
setObjectClass(t, array, class_);
|
setObjectClass(t, array, class_);
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
@ -2383,35 +2474,35 @@ interpret(Thread* t)
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case T_BOOLEAN:
|
case T_BOOLEAN:
|
||||||
array = makeBooleanArray(t, count, true);
|
array = makeBooleanArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_CHAR:
|
case T_CHAR:
|
||||||
array = makeCharArray(t, count, true);
|
array = makeCharArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
array = makeFloatArray(t, count, true);
|
array = makeFloatArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_DOUBLE:
|
case T_DOUBLE:
|
||||||
array = makeDoubleArray(t, count, true);
|
array = makeDoubleArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_BYTE:
|
case T_BYTE:
|
||||||
array = makeByteArray(t, count, true);
|
array = makeByteArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_SHORT:
|
case T_SHORT:
|
||||||
array = makeShortArray(t, count, true);
|
array = makeShortArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_INT:
|
case T_INT:
|
||||||
array = makeIntArray(t, count, true);
|
array = makeIntArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_LONG:
|
case T_LONG:
|
||||||
array = makeLongArray(t, count, true);
|
array = makeLongArray(t, count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
@ -3001,7 +3092,7 @@ class MyProcessor: public Processor {
|
|||||||
return vm::makeClass
|
return vm::makeClass
|
||||||
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
|
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
|
||||||
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
|
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
|
||||||
methodTable, staticTable, loader, 0, false);
|
methodTable, staticTable, loader, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
@ -3010,22 +3101,6 @@ class MyProcessor: public Processor {
|
|||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
|
||||||
initClass(vm::Thread* t, object c)
|
|
||||||
{
|
|
||||||
PROTECT(t, c);
|
|
||||||
|
|
||||||
acquire(t, t->m->classLock);
|
|
||||||
if (classVmFlags(t, c) & NeedInitFlag
|
|
||||||
and (classVmFlags(t, c) & InitFlag) == 0)
|
|
||||||
{
|
|
||||||
classVmFlags(t, c) |= InitFlag;
|
|
||||||
invoke(t, classInitializer(t, c), 0);
|
|
||||||
} else {
|
|
||||||
release(t, t->m->classLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
||||||
{
|
{
|
||||||
@ -3038,6 +3113,10 @@ class MyProcessor: public Processor {
|
|||||||
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (ClassInitList* list = t->classInitList; list; list = list->next) {
|
||||||
|
v->visit(reinterpret_cast<object*>(&(list->class_)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
@ -3157,25 +3236,21 @@ class MyProcessor: public Processor {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void compileThunks(vm::Thread*, BootImage*, uint8_t*, unsigned*,
|
virtual void initialize(BootImage*, uint8_t*, unsigned) {
|
||||||
unsigned)
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void compileMethod(vm::Thread*, Zone*, object*, object*,
|
||||||
|
DelayedPromise**, object)
|
||||||
{
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void compileMethod(vm::Thread*, Zone*, uint8_t*, unsigned*, unsigned,
|
virtual void visitRoots(HeapWalker*) {
|
||||||
object*, object*, DelayedPromise**, object)
|
|
||||||
{
|
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visitRoots(BootImage*, HeapWalker*) {
|
virtual unsigned* makeCallTable(vm::Thread*, HeapWalker*) {
|
||||||
abort(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual unsigned* makeCallTable(vm::Thread*, BootImage*, HeapWalker*,
|
|
||||||
uint8_t*)
|
|
||||||
{
|
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3183,6 +3258,29 @@ class MyProcessor: public Processor {
|
|||||||
expect(s, image == 0);
|
expect(s, image == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void callWithCurrentContinuation(vm::Thread*, object) {
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dynamicWind(vm::Thread*, object, object, object) {
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void feedResultToContinuation(vm::Thread*, object, object){
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void feedExceptionToContinuation(vm::Thread*, object, object) {
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void walkContinuationBody(vm::Thread*, Heap::Walker*, object,
|
||||||
|
unsigned)
|
||||||
|
{
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void dispose(vm::Thread* t) {
|
virtual void dispose(vm::Thread* t) {
|
||||||
t->m->heap->free(t, sizeof(Thread));
|
t->m->heap->free(t, sizeof(Thread));
|
||||||
}
|
}
|
||||||
|
118
src/jnienv.cpp
118
src/jnienv.cpp
@ -99,6 +99,14 @@ GetEnv(Machine* m, Thread** t, jint version)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jsize JNICALL
|
||||||
|
GetVersion(Thread* t)
|
||||||
|
{
|
||||||
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
return JNI_VERSION_1_6;
|
||||||
|
}
|
||||||
|
|
||||||
jsize JNICALL
|
jsize JNICALL
|
||||||
GetStringLength(Thread* t, jstring s)
|
GetStringLength(Thread* t, jstring s)
|
||||||
{
|
{
|
||||||
@ -258,6 +266,26 @@ ExceptionCheck(Thread* t)
|
|||||||
return t->exception != 0;
|
return t->exception != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef AVIAN_GNU
|
||||||
|
jobject JNICALL
|
||||||
|
NewDirectByteBuffer(Thread*, void*, jlong)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* JNICALL
|
||||||
|
GetDirectBufferAddress(Thread*, jobject)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetDirectBufferCapacity(Thread*, jobject)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif// not AVIAN_GNU
|
||||||
|
|
||||||
jclass JNICALL
|
jclass JNICALL
|
||||||
GetObjectClass(Thread* t, jobject o)
|
GetObjectClass(Thread* t, jobject o)
|
||||||
{
|
{
|
||||||
@ -817,22 +845,12 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...)
|
|||||||
va_end(a);
|
va_end(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
|
||||||
findField(Thread* t, jclass c, const char* name, const char* spec)
|
|
||||||
{
|
|
||||||
object n = makeByteArray(t, "%s", name);
|
|
||||||
PROTECT(t, n);
|
|
||||||
|
|
||||||
object s = makeByteArray(t, "%s", spec);
|
|
||||||
return vm::findField(t, *c, n, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
jfieldID JNICALL
|
jfieldID JNICALL
|
||||||
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object field = findField(t, c, name, spec);
|
object field = resolveField(t, *c, name, spec);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
return fieldOffset(t, field);
|
return fieldOffset(t, field);
|
||||||
@ -843,7 +861,7 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object field = findField(t, c, name, spec);
|
object field = resolveField(t, *c, name, spec);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
return fieldOffset(t, field);
|
return fieldOffset(t, field);
|
||||||
@ -998,7 +1016,7 @@ GetStaticObjectField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return makeLocalReference(t, arrayBody(t, classStaticTable(t, *c), field));
|
return makeLocalReference(t, cast<object>(classStaticTable(t, *c), field));
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -1006,8 +1024,7 @@ GetStaticBooleanField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<int8_t>(classStaticTable(t, *c), field);
|
||||||
return v ? intValue(t, v) != 0 : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jbyte JNICALL
|
jbyte JNICALL
|
||||||
@ -1015,8 +1032,7 @@ GetStaticByteField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<int8_t>(classStaticTable(t, *c), field);
|
||||||
return static_cast<jbyte>(v ? intValue(t, v) : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jchar JNICALL
|
jchar JNICALL
|
||||||
@ -1024,8 +1040,7 @@ GetStaticCharField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<uint16_t>(classStaticTable(t, *c), field);
|
||||||
return static_cast<jchar>(v ? intValue(t, v) : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jshort JNICALL
|
jshort JNICALL
|
||||||
@ -1033,8 +1048,7 @@ GetStaticShortField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<int16_t>(classStaticTable(t, *c), field);
|
||||||
return static_cast<jshort>(v ? intValue(t, v) : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jint JNICALL
|
jint JNICALL
|
||||||
@ -1042,8 +1056,7 @@ GetStaticIntField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<int32_t>(classStaticTable(t, *c), field);
|
||||||
return v ? intValue(t, v) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong JNICALL
|
jlong JNICALL
|
||||||
@ -1051,8 +1064,7 @@ GetStaticLongField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<int64_t>(classStaticTable(t, *c), field);
|
||||||
return static_cast<jlong>(v ? longValue(t, v) : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jfloat JNICALL
|
jfloat JNICALL
|
||||||
@ -1060,10 +1072,7 @@ GetStaticFloatField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<float>(classStaticTable(t, *c), field);
|
||||||
jint i = v ? intValue(t, v) : 0;
|
|
||||||
jfloat f; memcpy(&f, &i, 4);
|
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jdouble JNICALL
|
jdouble JNICALL
|
||||||
@ -1071,10 +1080,7 @@ GetStaticDoubleField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, *c), field);
|
return cast<double>(classStaticTable(t, *c), field);
|
||||||
jlong i = v ? longValue(t, v) : 0;
|
|
||||||
jdouble f; memcpy(&f, &i, 4);
|
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1082,17 +1088,15 @@ SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord),
|
set(t, classStaticTable(t, *c), field, (v ? *v : 0));
|
||||||
(v ? *v : 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v)
|
SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object o = makeInt(t, v ? 1 : 0);
|
cast<int8_t>(classStaticTable(t, *c), field) = v;
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1100,8 +1104,7 @@ SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object o = makeInt(t, v);
|
cast<int8_t>(classStaticTable(t, *c), field) = v;
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1109,8 +1112,7 @@ SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object o = makeInt(t, v);
|
cast<uint16_t>(classStaticTable(t, *c), field) = v;
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1118,8 +1120,7 @@ SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object o = makeInt(t, v);
|
cast<int16_t>(classStaticTable(t, *c), field) = v;
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1127,8 +1128,7 @@ SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object o = makeInt(t, v);
|
cast<int32_t>(classStaticTable(t, *c), field) = v;
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1136,8 +1136,7 @@ SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object o = makeLong(t, v);
|
cast<int64_t>(classStaticTable(t, *c), field) = v;
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1145,9 +1144,7 @@ SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
jint i; memcpy(&i, &v, 4);
|
cast<float>(classStaticTable(t, *c), field) = v;
|
||||||
object o = makeInt(t, i);
|
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1155,9 +1152,7 @@ SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
jlong i; memcpy(&i, &v, 8);
|
cast<double>(classStaticTable(t, *c), field) = v;
|
||||||
object o = makeLong(t, i);
|
|
||||||
set(t, classStaticTable(t, *c), ArrayBody + (field * BytesPerWord), o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject JNICALL
|
jobject JNICALL
|
||||||
@ -1883,6 +1878,17 @@ append(char** p, const char* value, unsigned length, char tail)
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
#ifdef AVIAN_GNU
|
||||||
|
jobject JNICALL
|
||||||
|
NewDirectByteBuffer(Thread*, void*, jlong);
|
||||||
|
|
||||||
|
void* JNICALL
|
||||||
|
GetDirectBufferAddress(Thread*, jobject);
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetDirectBufferCapacity(Thread*, jobject);
|
||||||
|
#endif//AVIAN_GNU
|
||||||
|
|
||||||
void
|
void
|
||||||
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
||||||
{
|
{
|
||||||
@ -1895,6 +1901,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
|||||||
|
|
||||||
memset(envTable, 0, sizeof(JNIEnvVTable));
|
memset(envTable, 0, sizeof(JNIEnvVTable));
|
||||||
|
|
||||||
|
envTable->GetVersion = ::GetVersion;
|
||||||
envTable->GetStringLength = ::GetStringLength;
|
envTable->GetStringLength = ::GetStringLength;
|
||||||
envTable->GetStringChars = ::GetStringChars;
|
envTable->GetStringChars = ::GetStringChars;
|
||||||
envTable->ReleaseStringChars = ::ReleaseStringChars;
|
envTable->ReleaseStringChars = ::ReleaseStringChars;
|
||||||
@ -1907,6 +1914,9 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
|||||||
envTable->FindClass = ::FindClass;
|
envTable->FindClass = ::FindClass;
|
||||||
envTable->ThrowNew = ::ThrowNew;
|
envTable->ThrowNew = ::ThrowNew;
|
||||||
envTable->ExceptionCheck = ::ExceptionCheck;
|
envTable->ExceptionCheck = ::ExceptionCheck;
|
||||||
|
envTable->NewDirectByteBuffer = ::NewDirectByteBuffer;
|
||||||
|
envTable->GetDirectBufferAddress = ::GetDirectBufferAddress;
|
||||||
|
envTable->GetDirectBufferCapacity = ::GetDirectBufferCapacity;
|
||||||
envTable->DeleteLocalRef = ::DeleteLocalRef;
|
envTable->DeleteLocalRef = ::DeleteLocalRef;
|
||||||
envTable->GetObjectClass = ::GetObjectClass;
|
envTable->GetObjectClass = ::GetObjectClass;
|
||||||
envTable->IsInstanceOf = ::IsInstanceOf;
|
envTable->IsInstanceOf = ::IsInstanceOf;
|
||||||
|
517
src/machine.cpp
517
src/machine.cpp
@ -196,7 +196,7 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
|
walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
|
||||||
unsigned arrayElementSize, unsigned arrayLength, unsigned start)
|
unsigned arrayElementSize, unsigned arrayLength, unsigned start)
|
||||||
{
|
{
|
||||||
@ -207,7 +207,7 @@ walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
|
|||||||
for (unsigned i = start; i < fixedSizeInWords; ++i) {
|
for (unsigned i = start; i < fixedSizeInWords; ++i) {
|
||||||
if (mask[i / 32] & (static_cast<uint32_t>(1) << (i % 32))) {
|
if (mask[i / 32] & (static_cast<uint32_t>(1) << (i % 32))) {
|
||||||
if (not w->visit(i)) {
|
if (not w->visit(i)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,12 +240,31 @@ walk(Thread*, Heap::Walker* w, uint32_t* mask, unsigned fixedSize,
|
|||||||
if (not w->visit
|
if (not w->visit
|
||||||
(fixedSizeInWords + (i * arrayElementSizeInWords) + j))
|
(fixedSizeInWords + (i * arrayElementSizeInWords) + j))
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
findInInterfaces(Thread* t, object class_, object name, object spec,
|
||||||
|
object (*find)(Thread*, object, object, object))
|
||||||
|
{
|
||||||
|
object result = 0;
|
||||||
|
if (classInterfaceTable(t, class_)) {
|
||||||
|
for (unsigned i = 0;
|
||||||
|
i < arrayLength(t, classInterfaceTable(t, class_)) and result == 0;
|
||||||
|
i += 2)
|
||||||
|
{
|
||||||
|
result = find
|
||||||
|
(t, arrayBody(t, classInterfaceTable(t, class_), i), name, spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -479,6 +498,33 @@ postCollect(Thread* t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
finalizeObject(Thread* t, object o)
|
||||||
|
{
|
||||||
|
if (t->state == Thread::ExitState) {
|
||||||
|
// don't waste time running Java finalizers if we're exiting the
|
||||||
|
// VM
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (object c = objectClass(t, o); c; c = classSuper(t, c)) {
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||||
|
object m = arrayBody(t, classMethodTable(t, c), i);
|
||||||
|
|
||||||
|
if (strcmp(reinterpret_cast<const int8_t*>("finalize"),
|
||||||
|
&byteArrayBody(t, methodName(t, m), 0)) == 0
|
||||||
|
and strcmp(reinterpret_cast<const int8_t*>("()V"),
|
||||||
|
&byteArrayBody(t, methodSpec(t, m), 0)) == 0)
|
||||||
|
{
|
||||||
|
t->m->processor->invoke(t, m, o);
|
||||||
|
t->exception = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeByteArray(Thread* t, const char* format, va_list a)
|
makeByteArray(Thread* t, const char* format, va_list a)
|
||||||
{
|
{
|
||||||
@ -495,21 +541,31 @@ makeByteArray(Thread* t, const char* format, va_list a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
parseUtf8(Thread* t, Stream& s, unsigned length)
|
parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount,
|
||||||
|
unsigned sourceIndex, unsigned lastByteRead)
|
||||||
{
|
{
|
||||||
object value = makeByteArray(t, length + 1);
|
PROTECT(t, bytesSoFar);
|
||||||
|
|
||||||
|
unsigned length = byteArrayLength(t, bytesSoFar) - 1;
|
||||||
|
object value = makeCharArray(t, length + 1);
|
||||||
|
|
||||||
unsigned vi = 0;
|
unsigned vi = 0;
|
||||||
for (unsigned si = 0; si < length; ++si) {
|
for (; vi < byteCount; ++vi) {
|
||||||
unsigned a = s.read1();
|
charArrayBody(t, value, vi) = byteArrayBody(t, bytesSoFar, vi);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned a = lastByteRead;
|
||||||
|
unsigned si = sourceIndex;
|
||||||
|
while (true) {
|
||||||
if (a & 0x80) {
|
if (a & 0x80) {
|
||||||
// todo: handle non-ASCII characters properly
|
|
||||||
if (a & 0x20) {
|
if (a & 0x20) {
|
||||||
// 3 bytes
|
// 3 bytes
|
||||||
si += 2;
|
si += 2;
|
||||||
assert(t, si < length);
|
assert(t, si < length);
|
||||||
/*unsigned b = */s.read1();
|
unsigned b = s.read1();
|
||||||
/*unsigned c = */s.read1();
|
unsigned c = s.read1();
|
||||||
byteArrayBody(t, value, vi++) = '_';
|
charArrayBody(t, value, vi++)
|
||||||
|
= ((a & 0xf) << 12) | ((b & 0x3f) << 6) | (c & 0x3f);
|
||||||
} else {
|
} else {
|
||||||
// 2 bytes
|
// 2 bytes
|
||||||
++ si;
|
++ si;
|
||||||
@ -517,9 +573,55 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
|
|||||||
unsigned b = s.read1();
|
unsigned b = s.read1();
|
||||||
|
|
||||||
if (a == 0xC0 and b == 0x80) {
|
if (a == 0xC0 and b == 0x80) {
|
||||||
|
charArrayBody(t, value, vi++) = 0;
|
||||||
|
} else {
|
||||||
|
charArrayBody(t, value, vi++) = ((a & 0x1f) << 6) | (b & 0x3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
charArrayBody(t, value, vi++) = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++si < length) {
|
||||||
|
a = s.read1();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vi < length) {
|
||||||
|
PROTECT(t, value);
|
||||||
|
|
||||||
|
object v = makeCharArray(t, vi + 1);
|
||||||
|
memcpy(&charArrayBody(t, v, 0), &charArrayBody(t, value, 0), vi * 2);
|
||||||
|
value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
charArrayBody(t, value, vi) = 0;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
parseUtf8(Thread* t, Stream& s, unsigned length)
|
||||||
|
{
|
||||||
|
object value = makeByteArray(t, length + 1);
|
||||||
|
unsigned vi = 0;
|
||||||
|
for (unsigned si = 0; si < length; ++si) {
|
||||||
|
unsigned a = s.read1();
|
||||||
|
if (a & 0x80) {
|
||||||
|
if (a & 0x20) {
|
||||||
|
// 3 bytes
|
||||||
|
return parseUtf8NonAscii(t, s, value, vi, si, a);
|
||||||
|
} else {
|
||||||
|
// 2 bytes
|
||||||
|
unsigned b = s.read1();
|
||||||
|
|
||||||
|
if (a == 0xC0 and b == 0x80) {
|
||||||
|
++ si;
|
||||||
|
assert(t, si < length);
|
||||||
byteArrayBody(t, value, vi++) = 0;
|
byteArrayBody(t, value, vi++) = 0;
|
||||||
} else {
|
} else {
|
||||||
byteArrayBody(t, value, vi++) = '_';
|
return parseUtf8NonAscii(t, s, value, vi, si, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -539,6 +641,28 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
removeByteArray(Thread* t, object o)
|
||||||
|
{
|
||||||
|
hashMapRemove(t, t->m->byteArrayMap, o, byteArrayHash, objectEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
internByteArray(Thread* t, object array)
|
||||||
|
{
|
||||||
|
PROTECT(t, array);
|
||||||
|
|
||||||
|
object n = hashMapFindNode
|
||||||
|
(t, t->m->byteArrayMap, array, byteArrayHash, byteArrayEqual);
|
||||||
|
if (n) {
|
||||||
|
return jreferenceTarget(t, tripleFirst(t, n));
|
||||||
|
} else {
|
||||||
|
hashMapInsert(t, t->m->byteArrayMap, array, 0, byteArrayHash);
|
||||||
|
addFinalizer(t, array, removeByteArray);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
||||||
{
|
{
|
||||||
@ -561,6 +685,11 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
|||||||
case CONSTANT_Utf8: {
|
case CONSTANT_Utf8: {
|
||||||
if (singletonObject(t, pool, i) == 0) {
|
if (singletonObject(t, pool, i) == 0) {
|
||||||
object value = parseUtf8(t, s, s.read2());
|
object value = parseUtf8(t, s, s.read2());
|
||||||
|
if (objectClass(t, value)
|
||||||
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
|
{
|
||||||
|
value = internByteArray(t, value);
|
||||||
|
}
|
||||||
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
||||||
}
|
}
|
||||||
} return 1;
|
} return 1;
|
||||||
@ -581,7 +710,8 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
|
|||||||
parsePoolEntry(t, s, index, pool, si);
|
parsePoolEntry(t, s, index, pool, si);
|
||||||
|
|
||||||
object value = singletonObject(t, pool, si);
|
object value = singletonObject(t, pool, si);
|
||||||
value = makeString(t, value, 0, byteArrayLength(t, value) - 1, 0);
|
value = makeString
|
||||||
|
(t, value, 0, cast<uintptr_t>(value, BytesPerWord) - 1, 0);
|
||||||
value = intern(t, value);
|
value = intern(t, value);
|
||||||
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
set(t, pool, SingletonBody + (i * BytesPerWord), value);
|
||||||
}
|
}
|
||||||
@ -628,8 +758,13 @@ object
|
|||||||
parsePool(Thread* t, Stream& s)
|
parsePool(Thread* t, Stream& s)
|
||||||
{
|
{
|
||||||
unsigned count = s.read2() - 1;
|
unsigned count = s.read2() - 1;
|
||||||
|
unsigned old;
|
||||||
object pool = makeSingletonOfSize(t, count);
|
unsigned floatMaskSize = 0;
|
||||||
|
do {
|
||||||
|
old = floatMaskSize;
|
||||||
|
floatMaskSize = singletonMaskSize(count + floatMaskSize);
|
||||||
|
} while (floatMaskSize != old);
|
||||||
|
object pool = makeSingletonOfSize(t, count + floatMaskSize);
|
||||||
PROTECT(t, pool);
|
PROTECT(t, pool);
|
||||||
|
|
||||||
if (count) {
|
if (count) {
|
||||||
@ -641,12 +776,18 @@ parsePool(Thread* t, Stream& s)
|
|||||||
switch (s.read1()) {
|
switch (s.read1()) {
|
||||||
case CONSTANT_Class:
|
case CONSTANT_Class:
|
||||||
case CONSTANT_String:
|
case CONSTANT_String:
|
||||||
|
assert(t, !singletonIsFloat(t, pool, i));
|
||||||
singletonMarkObject(t, pool, i);
|
singletonMarkObject(t, pool, i);
|
||||||
s.skip(2);
|
s.skip(2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONSTANT_Integer:
|
case CONSTANT_Integer:
|
||||||
|
assert(t, !singletonIsFloat(t, pool, i));
|
||||||
|
s.skip(4);
|
||||||
|
break;
|
||||||
case CONSTANT_Float:
|
case CONSTANT_Float:
|
||||||
|
singletonMarkBit(t, pool, count, i);
|
||||||
|
assert(t, singletonIsFloat(t, pool, i));
|
||||||
s.skip(4);
|
s.skip(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -654,17 +795,27 @@ parsePool(Thread* t, Stream& s)
|
|||||||
case CONSTANT_Fieldref:
|
case CONSTANT_Fieldref:
|
||||||
case CONSTANT_Methodref:
|
case CONSTANT_Methodref:
|
||||||
case CONSTANT_InterfaceMethodref:
|
case CONSTANT_InterfaceMethodref:
|
||||||
|
assert(t, !singletonIsFloat(t, pool, i));
|
||||||
singletonMarkObject(t, pool, i);
|
singletonMarkObject(t, pool, i);
|
||||||
s.skip(4);
|
s.skip(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONSTANT_Long:
|
case CONSTANT_Long:
|
||||||
|
assert(t, !singletonIsFloat(t, pool, i));
|
||||||
|
s.skip(8);
|
||||||
|
++ i;
|
||||||
|
break;
|
||||||
case CONSTANT_Double:
|
case CONSTANT_Double:
|
||||||
|
singletonMarkBit(t, pool, count, i);
|
||||||
|
singletonMarkBit(t, pool, count, i + 1);
|
||||||
|
assert(t, singletonIsFloat(t, pool, i));
|
||||||
|
assert(t, singletonIsFloat(t, pool, i + 1));
|
||||||
s.skip(8);
|
s.skip(8);
|
||||||
++ i;
|
++ i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONSTANT_Utf8:
|
case CONSTANT_Utf8:
|
||||||
|
assert(t, !singletonIsFloat(t, pool, i));
|
||||||
singletonMarkObject(t, pool, i);
|
singletonMarkObject(t, pool, i);
|
||||||
s.skip(s.read2());
|
s.skip(s.read2());
|
||||||
break;
|
break;
|
||||||
@ -728,6 +879,8 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
PROTECT(t, name);
|
PROTECT(t, name);
|
||||||
|
|
||||||
object interface = resolveClass(t, name);
|
object interface = resolveClass(t, name);
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
PROTECT(t, interface);
|
PROTECT(t, interface);
|
||||||
|
|
||||||
hashMapInsertMaybe(t, map, name, interface, byteArrayHash, byteArrayEqual);
|
hashMapInsertMaybe(t, map, name, interface, byteArrayHash, byteArrayEqual);
|
||||||
@ -1161,6 +1314,17 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
|
|
||||||
hashMapInsert(t, virtualMap, method, method, methodHash);
|
hashMapInsert(t, virtualMap, method, method, methodHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UNLIKELY(strcmp
|
||||||
|
(reinterpret_cast<const int8_t*>("finalize"),
|
||||||
|
&byteArrayBody(t, methodName(t, method), 0)) == 0
|
||||||
|
and strcmp
|
||||||
|
(reinterpret_cast<const int8_t*>("()V"),
|
||||||
|
&byteArrayBody(t, methodSpec(t, method), 0)) == 0
|
||||||
|
and (not emptyMethod(t, method))))
|
||||||
|
{
|
||||||
|
classVmFlags(t, class_) |= HasFinalizerFlag;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
methodOffset(t, method) = i;
|
methodOffset(t, method) = i;
|
||||||
|
|
||||||
@ -1313,14 +1477,9 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
|
|||||||
expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_));
|
expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_));
|
||||||
|
|
||||||
expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType)
|
expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType)
|
||||||
or classFixedSize(t, bootstrapClass) == classFixedSize(t, class_));
|
or classFixedSize(t, bootstrapClass) >= classFixedSize(t, class_));
|
||||||
|
|
||||||
expect(t,
|
expect(t, (classVmFlags(t, class_) & HasFinalizerFlag) == 0);
|
||||||
(classVmFlags(t, bootstrapClass) & ReferenceFlag)
|
|
||||||
or (classObjectMask(t, bootstrapClass) == 0
|
|
||||||
and classObjectMask(t, class_) == 0)
|
|
||||||
or intArrayEqual(t, classObjectMask(t, bootstrapClass),
|
|
||||||
classObjectMask(t, class_)));
|
|
||||||
|
|
||||||
PROTECT(t, bootstrapClass);
|
PROTECT(t, bootstrapClass);
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
@ -1329,7 +1488,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
|
|||||||
|
|
||||||
classVmFlags(t, bootstrapClass) &= ~BootstrapFlag;
|
classVmFlags(t, bootstrapClass) &= ~BootstrapFlag;
|
||||||
classVmFlags(t, bootstrapClass) |= classVmFlags(t, class_);
|
classVmFlags(t, bootstrapClass) |= classVmFlags(t, class_);
|
||||||
classFlags(t, bootstrapClass) = classFlags(t, class_);
|
classFlags(t, bootstrapClass) |= classFlags(t, class_);
|
||||||
|
|
||||||
set(t, bootstrapClass, ClassSuper, classSuper(t, class_));
|
set(t, bootstrapClass, ClassSuper, classSuper(t, class_));
|
||||||
set(t, bootstrapClass, ClassInterfaceTable, classInterfaceTable(t, class_));
|
set(t, bootstrapClass, ClassInterfaceTable, classInterfaceTable(t, class_));
|
||||||
@ -1518,7 +1677,7 @@ boot(Thread* t)
|
|||||||
|
|
||||||
m->unsafe = true;
|
m->unsafe = true;
|
||||||
|
|
||||||
m->loader = allocate(t, sizeof(void*) * 3, true);
|
m->loader = allocate(t, FixedSizeOfSystemClassLoader, true);
|
||||||
|
|
||||||
m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
|
m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
|
||||||
arrayLength(t, m->types) = TypeCount;
|
arrayLength(t, m->types) = TypeCount;
|
||||||
@ -1544,9 +1703,12 @@ boot(Thread* t)
|
|||||||
|
|
||||||
m->unsafe = false;
|
m->unsafe = false;
|
||||||
|
|
||||||
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|
classFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|
||||||
|= SingletonFlag;
|
|= SingletonFlag;
|
||||||
|
|
||||||
|
classFlags(t, arrayBody(t, m->types, Machine::ContinuationType))
|
||||||
|
|= ContinuationFlag;
|
||||||
|
|
||||||
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|
||||||
|= ReferenceFlag;
|
|= ReferenceFlag;
|
||||||
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|
||||||
@ -1709,6 +1871,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
|||||||
bootstrapClassMap(0),
|
bootstrapClassMap(0),
|
||||||
monitorMap(0),
|
monitorMap(0),
|
||||||
stringMap(0),
|
stringMap(0),
|
||||||
|
byteArrayMap(0),
|
||||||
types(0),
|
types(0),
|
||||||
jniMethodTable(0),
|
jniMethodTable(0),
|
||||||
finalizers(0),
|
finalizers(0),
|
||||||
@ -1717,6 +1880,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
|||||||
weakReferences(0),
|
weakReferences(0),
|
||||||
tenuredWeakReferences(0),
|
tenuredWeakReferences(0),
|
||||||
unsafe(false),
|
unsafe(false),
|
||||||
|
triedBuiltinOnLoad(false),
|
||||||
heapPoolIndex(0)
|
heapPoolIndex(0)
|
||||||
{
|
{
|
||||||
heap->setClient(heapClient);
|
heap->setClient(heapClient);
|
||||||
@ -1779,6 +1943,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
|||||||
heapIndex(0),
|
heapIndex(0),
|
||||||
heapOffset(0),
|
heapOffset(0),
|
||||||
protector(0),
|
protector(0),
|
||||||
|
classInitStack(0),
|
||||||
runnable(this),
|
runnable(this),
|
||||||
defaultHeap(static_cast<uintptr_t*>
|
defaultHeap(static_cast<uintptr_t*>
|
||||||
(m->heap->allocate(ThreadHeapSizeInBytes))),
|
(m->heap->allocate(ThreadHeapSizeInBytes))),
|
||||||
@ -1829,6 +1994,7 @@ Thread::init()
|
|||||||
boot(this);
|
boot(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m->byteArrayMap = makeWeakHashMap(this, 0, 0);
|
||||||
m->monitorMap = makeWeakHashMap(this, 0, 0);
|
m->monitorMap = makeWeakHashMap(this, 0, 0);
|
||||||
|
|
||||||
m->jniMethodTable = makeVector(this, 0, 0);
|
m->jniMethodTable = makeVector(this, 0, 0);
|
||||||
@ -1842,8 +2008,12 @@ Thread::init()
|
|||||||
if (javaThread) {
|
if (javaThread) {
|
||||||
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
|
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
|
||||||
} else {
|
} else {
|
||||||
|
const unsigned NewState = 0;
|
||||||
|
const unsigned NormalPriority = 5;
|
||||||
|
|
||||||
this->javaThread = makeThread
|
this->javaThread = makeThread
|
||||||
(this, reinterpret_cast<int64_t>(this), 0, 0, 0, 0, m->loader, 0);
|
(this, reinterpret_cast<int64_t>(this), 0, 0, NewState, NormalPriority,
|
||||||
|
0, 0, 0, m->loader, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2057,44 +2227,53 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
|||||||
// another thread wants to enter the exclusive state, either for a
|
// another thread wants to enter the exclusive state, either for a
|
||||||
// collection or some other reason. We give it a chance here.
|
// collection or some other reason. We give it a chance here.
|
||||||
ENTER(t, Thread::IdleState);
|
ENTER(t, Thread::IdleState);
|
||||||
|
|
||||||
|
while (t->m->exclusive) {
|
||||||
|
t->m->stateLock->wait(t->systemThread, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
do {
|
||||||
case Machine::MovableAllocation:
|
switch (type) {
|
||||||
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
case Machine::MovableAllocation:
|
||||||
> ThreadHeapSizeInWords)
|
if (t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||||
{
|
> ThreadHeapSizeInWords)
|
||||||
t->heap = 0;
|
{
|
||||||
if (t->m->heapPoolIndex < ThreadHeapPoolSize) {
|
t->heap = 0;
|
||||||
t->heap = static_cast<uintptr_t*>
|
if (t->m->heapPoolIndex < ThreadHeapPoolSize) {
|
||||||
(t->m->heap->tryAllocate(ThreadHeapSizeInBytes));
|
t->heap = static_cast<uintptr_t*>
|
||||||
|
(t->m->heap->tryAllocate(ThreadHeapSizeInBytes));
|
||||||
|
|
||||||
if (t->heap) {
|
if (t->heap) {
|
||||||
memset(t->heap, 0, ThreadHeapSizeInBytes);
|
memset(t->heap, 0, ThreadHeapSizeInBytes);
|
||||||
|
|
||||||
t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
|
t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
|
||||||
t->heapOffset += t->heapIndex;
|
t->heapOffset += t->heapIndex;
|
||||||
t->heapIndex = 0;
|
t->heapIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Machine::FixedAllocation:
|
||||||
|
if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes)
|
||||||
|
{
|
||||||
|
t->heap = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Machine::ImmortalAllocation:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case Machine::FixedAllocation:
|
if (t->heap == 0) {
|
||||||
if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes) {
|
// fprintf(stderr, "gc");
|
||||||
t->heap = 0;
|
// vmPrintTrace(t);
|
||||||
|
collect(t, Heap::MinorCollection);
|
||||||
}
|
}
|
||||||
break;
|
} while (type == Machine::MovableAllocation
|
||||||
|
and t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||||
case Machine::ImmortalAllocation:
|
> ThreadHeapSizeInWords);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t->heap == 0) {
|
|
||||||
// fprintf(stderr, "gc");
|
|
||||||
// vmPrintTrace(t);
|
|
||||||
collect(t, Heap::MinorCollection);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Machine::MovableAllocation: {
|
case Machine::MovableAllocation: {
|
||||||
@ -2133,6 +2312,28 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
makeNewGeneral(Thread* t, object class_)
|
||||||
|
{
|
||||||
|
assert(t, t->state == Thread::ActiveState);
|
||||||
|
|
||||||
|
object instance = makeNew(t, class_);
|
||||||
|
PROTECT(t, instance);
|
||||||
|
|
||||||
|
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
||||||
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
|
jreferenceVmNext(t, instance) = t->m->weakReferences;
|
||||||
|
t->m->weakReferences = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classVmFlags(t, class_) & HasFinalizerFlag) {
|
||||||
|
addFinalizer(t, instance, finalizeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeByteArray(Thread* t, const char* format, ...)
|
makeByteArray(Thread* t, const char* format, ...)
|
||||||
{
|
{
|
||||||
@ -2399,7 +2600,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
|||||||
set(t, class_, ClassSuper, sc);
|
set(t, class_, ClassSuper, sc);
|
||||||
|
|
||||||
classVmFlags(t, class_)
|
classVmFlags(t, class_)
|
||||||
|= (classVmFlags(t, sc) & (ReferenceFlag | WeakReferenceFlag));
|
|= (classVmFlags(t, sc)
|
||||||
|
& (ReferenceFlag | WeakReferenceFlag | HasFinalizerFlag));
|
||||||
}
|
}
|
||||||
|
|
||||||
parseInterfaceTable(t, s, class_, pool);
|
parseInterfaceTable(t, s, class_, pool);
|
||||||
@ -2432,6 +2634,8 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
|||||||
classLoader(t, class_),
|
classLoader(t, class_),
|
||||||
vtableLength);
|
vtableLength);
|
||||||
|
|
||||||
|
PROTECT(t, real);
|
||||||
|
|
||||||
t->m->processor->initVtable(t, real);
|
t->m->processor->initVtable(t, real);
|
||||||
|
|
||||||
updateClassTables(t, real, class_);
|
updateClassTables(t, real, class_);
|
||||||
@ -2510,24 +2714,58 @@ resolveClass(Thread* t, object spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
resolveMethod(Thread* t, object class_, const char* methodName,
|
||||||
const char* methodSpec)
|
const char* methodSpec)
|
||||||
{
|
{
|
||||||
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
|
PROTECT(t, class_);
|
||||||
if (LIKELY(t->exception == 0)) {
|
|
||||||
PROTECT(t, class_);
|
|
||||||
|
|
||||||
object name = makeByteArray(t, methodName);
|
object name = makeByteArray(t, methodName);
|
||||||
PROTECT(t, name);
|
PROTECT(t, name);
|
||||||
|
|
||||||
object spec = makeByteArray(t, methodSpec);
|
object spec = makeByteArray(t, methodSpec);
|
||||||
object reference = makeReference(t, class_, name, spec);
|
|
||||||
|
|
||||||
return findMethodInClass(t, class_, referenceName(t, reference),
|
object method = findMethodInClass(t, class_, name, spec);
|
||||||
referenceSpec(t, reference));
|
|
||||||
|
if (t->exception == 0 and method == 0) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s %s not found in %s", methodName, methodSpec,
|
||||||
|
&byteArrayBody(t, className(t, class_), 0));
|
||||||
|
|
||||||
|
t->exception = makeNoSuchMethodError(t, message);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveField(Thread* t, object class_, const char* fieldName,
|
||||||
|
const char* fieldSpec)
|
||||||
|
{
|
||||||
|
PROTECT(t, class_);
|
||||||
|
|
||||||
|
object name = makeByteArray(t, fieldName);
|
||||||
|
PROTECT(t, name);
|
||||||
|
|
||||||
|
object spec = makeByteArray(t, fieldSpec);
|
||||||
|
PROTECT(t, spec);
|
||||||
|
|
||||||
|
object field = findInInterfaces(t, class_, name, spec, findFieldInClass);
|
||||||
|
|
||||||
|
for (; class_ != 0 and field == 0; class_ = classSuper(t, class_)) {
|
||||||
|
field = findFieldInClass(t, class_, name, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (t->exception == 0 and field == 0) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s %s not found in %s", fieldName, fieldSpec,
|
||||||
|
&byteArrayBody(t, className(t, class_), 0));
|
||||||
|
|
||||||
|
t->exception = makeNoSuchFieldError(t, message);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
@ -2556,6 +2794,92 @@ resolveObjectArrayClass(Thread* t, object elementSpec)
|
|||||||
return resolveClass(t, spec);
|
return resolveClass(t, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
classNeedsInit(Thread* t, object c)
|
||||||
|
{
|
||||||
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
|
if (classVmFlags(t, c) & InitFlag) {
|
||||||
|
// the class is currently being initialized. If this the thread
|
||||||
|
// which is initializing it, we should not try to initialize it
|
||||||
|
// recursively. Otherwise, we must wait for the responsible
|
||||||
|
// thread to finish.
|
||||||
|
for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) {
|
||||||
|
if (s->class_ == c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
preInitClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
|
PROTECT(t, c);
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
|
if (classVmFlags(t, c) & InitFlag) {
|
||||||
|
// the class is currently being initialized. If this the
|
||||||
|
// thread which is initializing it, we should not try to
|
||||||
|
// initialize it recursively.
|
||||||
|
for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) {
|
||||||
|
if (s->class_ == c) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// some other thread is on the job - wait for it to finish.
|
||||||
|
while (classVmFlags(t, c) & InitFlag) {
|
||||||
|
ENTER(t, Thread::IdleState);
|
||||||
|
t->m->classLock->wait(t->systemThread, 0);
|
||||||
|
}
|
||||||
|
} else if (classVmFlags(t, c) & InitErrorFlag) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s", &byteArrayBody(t, className(t, c), 0));
|
||||||
|
t->exception = makeNoClassDefFoundError(t, message);
|
||||||
|
} else {
|
||||||
|
classVmFlags(t, c) |= InitFlag;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
postInitClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
if (t->exception) {
|
||||||
|
t->exception = makeExceptionInInitializerError(t, t->exception);
|
||||||
|
classVmFlags(t, c) |= NeedInitFlag | InitErrorFlag;
|
||||||
|
classVmFlags(t, c) &= ~InitFlag;
|
||||||
|
} else {
|
||||||
|
classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag);
|
||||||
|
}
|
||||||
|
t->m->classLock->notifyAll(t->systemThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
initClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
if (preInitClass(t, c)) {
|
||||||
|
Thread::ClassInitStack stack(t, c);
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, classInitializer(t, c), 0);
|
||||||
|
|
||||||
|
postInitClass(t, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeObjectArray(Thread* t, object elementClass, unsigned count)
|
makeObjectArray(Thread* t, object elementClass, unsigned count)
|
||||||
{
|
{
|
||||||
@ -2606,7 +2930,6 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
|
|||||||
object (*makeError)(Thread*, object))
|
object (*makeError)(Thread*, object))
|
||||||
{
|
{
|
||||||
object originalClass = class_;
|
object originalClass = class_;
|
||||||
PROTECT(t, class_);
|
|
||||||
|
|
||||||
object o = 0;
|
object o = 0;
|
||||||
if ((classFlags(t, class_) & ACC_INTERFACE)
|
if ((classFlags(t, class_) & ACC_INTERFACE)
|
||||||
@ -2617,9 +2940,17 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (o == 0) {
|
if (o == 0) {
|
||||||
|
if (find == findFieldInClass) {
|
||||||
|
o = findInInterfaces(t, originalClass, name, spec, find);
|
||||||
|
}
|
||||||
|
|
||||||
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
|
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
|
||||||
o = find(t, class_, name, spec);
|
o = find(t, class_, name, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (o == 0 and find == findMethodInClass) {
|
||||||
|
o = findInInterfaces(t, originalClass, name, spec, find);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o == 0) {
|
if (o == 0) {
|
||||||
@ -2760,13 +3091,6 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
|
|
||||||
postCollect(m->rootThread);
|
postCollect(m->rootThread);
|
||||||
|
|
||||||
for (object f = m->finalizeQueue; f; f = finalizerNext(t, f)) {
|
|
||||||
void (*function)(Thread*, object);
|
|
||||||
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
|
|
||||||
function(t, finalizerTarget(t, f));
|
|
||||||
}
|
|
||||||
m->finalizeQueue = 0;
|
|
||||||
|
|
||||||
killZombies(t, m->rootThread);
|
killZombies(t, m->rootThread);
|
||||||
|
|
||||||
for (unsigned i = 0; i < m->heapPoolIndex; ++i) {
|
for (unsigned i = 0; i < m->heapPoolIndex; ++i) {
|
||||||
@ -2779,6 +3103,14 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
#ifdef VM_STRESS
|
#ifdef VM_STRESS
|
||||||
if (not stress) t->stress = false;
|
if (not stress) t->stress = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
object f = m->finalizeQueue;
|
||||||
|
m->finalizeQueue = 0;
|
||||||
|
for (; f; f = finalizerNext(t, f)) {
|
||||||
|
void (*function)(Thread*, object);
|
||||||
|
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord);
|
||||||
|
function(t, finalizerTarget(t, f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2788,6 +3120,8 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start)
|
|||||||
object objectMask = static_cast<object>
|
object objectMask = static_cast<object>
|
||||||
(t->m->heap->follow(classObjectMask(t, class_)));
|
(t->m->heap->follow(classObjectMask(t, class_)));
|
||||||
|
|
||||||
|
bool more = true;
|
||||||
|
|
||||||
if (objectMask) {
|
if (objectMask) {
|
||||||
unsigned fixedSize = classFixedSize(t, class_);
|
unsigned fixedSize = classFixedSize(t, class_);
|
||||||
unsigned arrayElementSize = classArrayElementSize(t, class_);
|
unsigned arrayElementSize = classArrayElementSize(t, class_);
|
||||||
@ -2799,17 +3133,21 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start)
|
|||||||
memcpy(mask, &intArrayBody(t, objectMask, 0),
|
memcpy(mask, &intArrayBody(t, objectMask, 0),
|
||||||
intArrayLength(t, objectMask) * 4);
|
intArrayLength(t, objectMask) * 4);
|
||||||
|
|
||||||
::walk(t, w, mask, fixedSize, arrayElementSize, arrayLength, start);
|
more = ::walk(t, w, mask, fixedSize, arrayElementSize, arrayLength, start);
|
||||||
} else if (classVmFlags(t, class_) & SingletonFlag) {
|
} else if (classFlags(t, class_) & SingletonFlag) {
|
||||||
unsigned length = singletonLength(t, o);
|
unsigned length = singletonLength(t, o);
|
||||||
if (length) {
|
if (length) {
|
||||||
::walk(t, w, singletonMask(t, o),
|
more = ::walk(t, w, singletonMask(t, o),
|
||||||
(singletonCount(t, o) + 2) * BytesPerWord, 0, 0, start);
|
(singletonCount(t, o) + 2) * BytesPerWord, 0, 0, start);
|
||||||
} else if (start == 0) {
|
} else if (start == 0) {
|
||||||
w->visit(0);
|
more = w->visit(0);
|
||||||
}
|
}
|
||||||
} else if (start == 0) {
|
} else if (start == 0) {
|
||||||
w->visit(0);
|
more = w->visit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (more and classFlags(t, class_) & ContinuationFlag) {
|
||||||
|
t->m->processor->walkContinuationBody(t, w, o, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2840,16 +3178,17 @@ visitRoots(Machine* m, Heap::Visitor* v)
|
|||||||
v->visit(&(m->bootstrapClassMap));
|
v->visit(&(m->bootstrapClassMap));
|
||||||
v->visit(&(m->monitorMap));
|
v->visit(&(m->monitorMap));
|
||||||
v->visit(&(m->stringMap));
|
v->visit(&(m->stringMap));
|
||||||
|
v->visit(&(m->byteArrayMap));
|
||||||
v->visit(&(m->types));
|
v->visit(&(m->types));
|
||||||
v->visit(&(m->jniMethodTable));
|
v->visit(&(m->jniMethodTable));
|
||||||
|
|
||||||
for (Reference* r = m->jniReferences; r; r = r->next) {
|
|
||||||
v->visit(&(r->target));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Thread* t = m->rootThread; t; t = t->peer) {
|
for (Thread* t = m->rootThread; t; t = t->peer) {
|
||||||
::visitRoots(t, v);
|
::visitRoots(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Reference* r = m->jniReferences; r; r = r->next) {
|
||||||
|
v->visit(&(r->target));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2956,11 +3295,11 @@ makeTrace(Thread* t, Thread* target)
|
|||||||
void
|
void
|
||||||
runJavaThread(Thread* t)
|
runJavaThread(Thread* t)
|
||||||
{
|
{
|
||||||
object method = resolveMethod(t, "java/lang/Thread", "run", "()V");
|
object method = resolveMethod
|
||||||
|
(t, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V");
|
||||||
|
|
||||||
if (t->exception == 0) {
|
if (t->exception == 0) {
|
||||||
t->m->processor->invoke
|
t->m->processor->invoke(t, method, 0, t->javaThread);
|
||||||
(t, findMethod(t, method, objectClass(t, t->javaThread)),
|
|
||||||
t->javaThread);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
210
src/machine.h
210
src/machine.h
@ -74,20 +74,31 @@ enum StackTag {
|
|||||||
const int NativeLine = -1;
|
const int NativeLine = -1;
|
||||||
const int UnknownLine = -2;
|
const int UnknownLine = -2;
|
||||||
|
|
||||||
// class flags:
|
// class flags (note that we must be careful not to overlap the
|
||||||
|
// standard ACC_* flags):
|
||||||
|
const unsigned HasFinalMemberFlag = 1 << 13;
|
||||||
|
const unsigned SingletonFlag = 1 << 14;
|
||||||
|
const unsigned ContinuationFlag = 1 << 15;
|
||||||
|
|
||||||
|
// class vmFlags:
|
||||||
const unsigned ReferenceFlag = 1 << 0;
|
const unsigned ReferenceFlag = 1 << 0;
|
||||||
const unsigned WeakReferenceFlag = 1 << 1;
|
const unsigned WeakReferenceFlag = 1 << 1;
|
||||||
const unsigned NeedInitFlag = 1 << 2;
|
const unsigned NeedInitFlag = 1 << 2;
|
||||||
const unsigned InitFlag = 1 << 3;
|
const unsigned InitFlag = 1 << 3;
|
||||||
const unsigned PrimitiveFlag = 1 << 4;
|
const unsigned InitErrorFlag = 1 << 4;
|
||||||
const unsigned SingletonFlag = 1 << 5;
|
const unsigned PrimitiveFlag = 1 << 5;
|
||||||
const unsigned BootstrapFlag = 1 << 6;
|
const unsigned BootstrapFlag = 1 << 6;
|
||||||
const unsigned HasFinalMemberFlag = 1 << 7;
|
const unsigned HasFinalizerFlag = 1 << 7;
|
||||||
|
|
||||||
// method flags:
|
// method vmFlags:
|
||||||
const unsigned ClassInitFlag = 1 << 0;
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
const unsigned CompiledFlag = 1 << 1;
|
const unsigned CompiledFlag = 1 << 1;
|
||||||
const unsigned ConstructorFlag = 1 << 2;
|
const unsigned ConstructorFlag = 1 << 2;
|
||||||
|
const unsigned FastNative = 1 << 3;
|
||||||
|
|
||||||
|
#ifndef JNI_VERSION_1_6
|
||||||
|
#define JNI_VERSION_1_6 0x00010006
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef Machine JavaVM;
|
typedef Machine JavaVM;
|
||||||
typedef Thread JNIEnv;
|
typedef Thread JNIEnv;
|
||||||
@ -1181,6 +1192,7 @@ class Machine {
|
|||||||
object bootstrapClassMap;
|
object bootstrapClassMap;
|
||||||
object monitorMap;
|
object monitorMap;
|
||||||
object stringMap;
|
object stringMap;
|
||||||
|
object byteArrayMap;
|
||||||
object types;
|
object types;
|
||||||
object jniMethodTable;
|
object jniMethodTable;
|
||||||
object finalizers;
|
object finalizers;
|
||||||
@ -1189,6 +1201,7 @@ class Machine {
|
|||||||
object weakReferences;
|
object weakReferences;
|
||||||
object tenuredWeakReferences;
|
object tenuredWeakReferences;
|
||||||
bool unsafe;
|
bool unsafe;
|
||||||
|
bool triedBuiltinOnLoad;
|
||||||
JavaVMVTable javaVMVTable;
|
JavaVMVTable javaVMVTable;
|
||||||
JNIEnvVTable jniEnvVTable;
|
JNIEnvVTable jniEnvVTable;
|
||||||
uintptr_t* heapPool[ThreadHeapPoolSize];
|
uintptr_t* heapPool[ThreadHeapPoolSize];
|
||||||
@ -1256,6 +1269,25 @@ class Thread {
|
|||||||
object* p;
|
object* p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClassInitStack {
|
||||||
|
public:
|
||||||
|
ClassInitStack(Thread* t, object class_):
|
||||||
|
next(t->classInitStack),
|
||||||
|
class_(class_),
|
||||||
|
protector(t, &(this->class_))
|
||||||
|
{
|
||||||
|
t->classInitStack = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ClassInitStack() {
|
||||||
|
protector.t->classInitStack = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassInitStack* next;
|
||||||
|
object class_;
|
||||||
|
SingleProtector protector;
|
||||||
|
};
|
||||||
|
|
||||||
class Runnable: public System::Runnable {
|
class Runnable: public System::Runnable {
|
||||||
public:
|
public:
|
||||||
Runnable(Thread* t): t(t) { }
|
Runnable(Thread* t): t(t) { }
|
||||||
@ -1308,6 +1340,7 @@ class Thread {
|
|||||||
unsigned heapIndex;
|
unsigned heapIndex;
|
||||||
unsigned heapOffset;
|
unsigned heapOffset;
|
||||||
Protector* protector;
|
Protector* protector;
|
||||||
|
ClassInitStack* classInitStack;
|
||||||
Runnable runnable;
|
Runnable runnable;
|
||||||
uintptr_t* defaultHeap;
|
uintptr_t* defaultHeap;
|
||||||
uintptr_t* heap;
|
uintptr_t* heap;
|
||||||
@ -1320,6 +1353,8 @@ class Thread {
|
|||||||
#endif // VM_STRESS
|
#endif // VM_STRESS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*);
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
objectClass(Thread*, object o)
|
objectClass(Thread*, object o)
|
||||||
{
|
{
|
||||||
@ -1454,17 +1489,17 @@ expect(Thread* t, bool v)
|
|||||||
|
|
||||||
class FixedAllocator: public Allocator {
|
class FixedAllocator: public Allocator {
|
||||||
public:
|
public:
|
||||||
FixedAllocator(Thread* t, uint8_t* base, unsigned capacity):
|
FixedAllocator(System* s, uint8_t* base, unsigned capacity):
|
||||||
t(t), base(base), offset(0), capacity(capacity)
|
s(s), base(base), offset(0), capacity(capacity)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void* tryAllocate(unsigned) {
|
virtual void* tryAllocate(unsigned) {
|
||||||
abort(t);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* allocate(unsigned size) {
|
virtual void* allocate(unsigned size) {
|
||||||
unsigned paddedSize = pad(size);
|
unsigned paddedSize = pad(size);
|
||||||
expect(t, offset + paddedSize < capacity);
|
expect(s, offset + paddedSize < capacity);
|
||||||
|
|
||||||
void* p = base + offset;
|
void* p = base + offset;
|
||||||
offset += paddedSize;
|
offset += paddedSize;
|
||||||
@ -1472,10 +1507,10 @@ class FixedAllocator: public Allocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void free(const void*, unsigned) {
|
virtual void free(const void*, unsigned) {
|
||||||
abort(t);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* t;
|
System* s;
|
||||||
uint8_t* base;
|
uint8_t* base;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
unsigned capacity;
|
unsigned capacity;
|
||||||
@ -1508,6 +1543,9 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
|||||||
inline object
|
inline object
|
||||||
allocateSmall(Thread* t, unsigned sizeInBytes)
|
allocateSmall(Thread* t, unsigned sizeInBytes)
|
||||||
{
|
{
|
||||||
|
assert(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||||
|
<= ThreadHeapSizeInWords);
|
||||||
|
|
||||||
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
||||||
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
||||||
cast<object>(o, 0) = 0;
|
cast<object>(o, 0) = 0;
|
||||||
@ -1696,7 +1734,7 @@ makeClassNotFoundException(Thread* t, object message)
|
|||||||
{
|
{
|
||||||
PROTECT(t, message);
|
PROTECT(t, message);
|
||||||
object trace = makeTrace(t);
|
object trace = makeTrace(t);
|
||||||
return makeClassNotFoundException(t, message, trace, 0);
|
return makeClassNotFoundException(t, message, trace, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
@ -1719,6 +1757,12 @@ makeInterruptedException(Thread* t)
|
|||||||
return makeInterruptedException(t, 0, makeTrace(t), 0);
|
return makeInterruptedException(t, 0, makeTrace(t), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeIncompatibleContinuationException(Thread* t)
|
||||||
|
{
|
||||||
|
return makeIncompatibleContinuationException(t, 0, makeTrace(t), 0);
|
||||||
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
makeStackOverflowError(Thread* t)
|
makeStackOverflowError(Thread* t)
|
||||||
{
|
{
|
||||||
@ -1741,6 +1785,14 @@ makeNoSuchMethodError(Thread* t, object message)
|
|||||||
return makeNoSuchMethodError(t, message, trace, 0);
|
return makeNoSuchMethodError(t, message, trace, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeNoClassDefFoundError(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeNoClassDefFoundError(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
makeUnsatisfiedLinkError(Thread* t, object message)
|
makeUnsatisfiedLinkError(Thread* t, object message)
|
||||||
{
|
{
|
||||||
@ -1754,7 +1806,7 @@ makeExceptionInInitializerError(Thread* t, object cause)
|
|||||||
{
|
{
|
||||||
PROTECT(t, cause);
|
PROTECT(t, cause);
|
||||||
object trace = makeTrace(t);
|
object trace = makeTrace(t);
|
||||||
return makeExceptionInInitializerError(t, 0, trace, cause);
|
return makeExceptionInInitializerError(t, 0, trace, cause, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
@ -1770,27 +1822,16 @@ makeNew(Thread* t, object class_)
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
object
|
||||||
makeNewWeakReference(Thread* t, object class_)
|
makeNewGeneral(Thread* t, object class_);
|
||||||
{
|
|
||||||
assert(t, t->state == Thread::ActiveState);
|
|
||||||
|
|
||||||
object instance = makeNew(t, class_);
|
|
||||||
PROTECT(t, instance);
|
|
||||||
|
|
||||||
ACQUIRE(t, t->m->referenceLock);
|
|
||||||
|
|
||||||
jreferenceVmNext(t, instance) = t->m->weakReferences;
|
|
||||||
t->m->weakReferences = instance;
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
make(Thread* t, object class_)
|
make(Thread* t, object class_)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
|
if (UNLIKELY(classVmFlags(t, class_)
|
||||||
return makeNewWeakReference(t, class_);
|
& (WeakReferenceFlag | HasFinalizerFlag)))
|
||||||
|
{
|
||||||
|
return makeNewGeneral(t, class_);
|
||||||
} else {
|
} else {
|
||||||
return makeNew(t, class_);
|
return makeNew(t, class_);
|
||||||
}
|
}
|
||||||
@ -1913,9 +1954,9 @@ stringCharAt(Thread* t, object s, int i)
|
|||||||
if (objectClass(t, data)
|
if (objectClass(t, data)
|
||||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
return byteArrayBody(t, data, i);
|
return byteArrayBody(t, data, stringOffset(t, s) + i);
|
||||||
} else {
|
} else {
|
||||||
return charArrayBody(t, data, i);
|
return charArrayBody(t, data, stringOffset(t, s) + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1936,15 +1977,6 @@ stringEqual(Thread* t, object a, object b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
intArrayEqual(Thread* t, object a, object b)
|
|
||||||
{
|
|
||||||
return a == b or
|
|
||||||
((intArrayLength(t, a) == intArrayLength(t, b)) and
|
|
||||||
memcmp(&intArrayBody(t, a, 0), &intArrayBody(t, b, 0),
|
|
||||||
intArrayLength(t, a) * 4) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
methodHash(Thread* t, object method)
|
methodHash(Thread* t, object method)
|
||||||
{
|
{
|
||||||
@ -2040,33 +2072,72 @@ fieldSize(Thread* t, object field)
|
|||||||
object
|
object
|
||||||
findLoadedClass(Thread* t, object spec);
|
findLoadedClass(Thread* t, object spec);
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
emptyMethod(Thread* t, object method)
|
||||||
|
{
|
||||||
|
return ((methodFlags(t, method) & ACC_NATIVE) == 0)
|
||||||
|
and (codeLength(t, methodCode(t, method)) == 1)
|
||||||
|
and (codeBody(t, methodCode(t, method), 0) == return_);
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
parseClass(Thread* t, const uint8_t* data, unsigned length);
|
parseClass(Thread* t, const uint8_t* data, unsigned length);
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveClass(Thread* t, object spec);
|
resolveClass(Thread* t, object name);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveClass(Thread* t, const char* name)
|
||||||
|
{
|
||||||
|
return resolveClass(t, makeByteArray(t, "%s", name));
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
resolveMethod(Thread* t, object class_, const char* methodName,
|
||||||
const char* methodSpec);
|
const char* methodSpec);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveMethod(Thread* t, const char* className, const char* methodName,
|
||||||
|
const char* methodSpec)
|
||||||
|
{
|
||||||
|
object class_ = resolveClass(t, className);
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
return resolveMethod(t, class_, methodName, methodSpec);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveField(Thread* t, object class_, const char* fieldName,
|
||||||
|
const char* fieldSpec);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveField(Thread* t, const char* className, const char* fieldName,
|
||||||
|
const char* fieldSpec)
|
||||||
|
{
|
||||||
|
object class_ = resolveClass(t, className);
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
return resolveField(t, class_, fieldName, fieldSpec);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveObjectArrayClass(Thread* t, object elementSpec);
|
resolveObjectArrayClass(Thread* t, object elementSpec);
|
||||||
|
|
||||||
inline bool
|
bool
|
||||||
classNeedsInit(Thread* t, object c)
|
classNeedsInit(Thread* t, object c);
|
||||||
{
|
|
||||||
return classVmFlags(t, c) & NeedInitFlag
|
|
||||||
and (classVmFlags(t, c) & InitFlag) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
bool
|
||||||
initClass(Thread* t, object c)
|
preInitClass(Thread* t, object c);
|
||||||
{
|
|
||||||
if (classNeedsInit(t, c)) {
|
void
|
||||||
t->m->processor->initClass(t, c);
|
postInitClass(Thread* t, object c);
|
||||||
}
|
|
||||||
}
|
void
|
||||||
|
initClass(Thread* t, object c);
|
||||||
|
|
||||||
object
|
object
|
||||||
makeObjectArray(Thread* t, object elementClass, unsigned count);
|
makeObjectArray(Thread* t, object elementClass, unsigned count);
|
||||||
@ -2095,13 +2166,6 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
|
|||||||
object (*find)(Thread*, object, object, object),
|
object (*find)(Thread*, object, object, object),
|
||||||
object (*makeError)(Thread*, object));
|
object (*makeError)(Thread*, object));
|
||||||
|
|
||||||
inline object
|
|
||||||
findField(Thread* t, object class_, object name, object spec)
|
|
||||||
{
|
|
||||||
return findInHierarchy
|
|
||||||
(t, class_, name, spec, findFieldInClass, makeNoSuchFieldError);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
findMethod(Thread* t, object class_, object name, object spec)
|
findMethod(Thread* t, object class_, object name, object spec)
|
||||||
{
|
{
|
||||||
@ -2369,6 +2433,26 @@ makeSingletonOfSize(Thread* t, unsigned count)
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
singletonMarkBit(Thread* t, object singleton, unsigned start, unsigned index)
|
||||||
|
{
|
||||||
|
uintptr_t& val = singletonValue(t, singleton, start + (index / BitsPerWord));
|
||||||
|
val |= static_cast<uintptr_t>(1) << (index % BitsPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
singletonGetBit(Thread* t, object singleton, unsigned start, unsigned index)
|
||||||
|
{
|
||||||
|
uintptr_t& val = singletonValue(t, singleton, start + (index / BitsPerWord));
|
||||||
|
return (val & static_cast<uintptr_t>(1) << (index % BitsPerWord)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
singletonIsFloat(Thread* t, object singleton, unsigned index)
|
||||||
|
{
|
||||||
|
return singletonGetBit(t, singleton, singletonLength(t, singleton) - 2 * singletonMaskSize(t, singleton), index);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dumpHeap(Thread* t, FILE* out);
|
dumpHeap(Thread* t, FILE* out);
|
||||||
|
|
||||||
|
@ -83,6 +83,10 @@ main(int ac, const char** av)
|
|||||||
++ vmArgs.nOptions;
|
++ vmArgs.nOptions;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOT_BUILTINS
|
||||||
|
++ vmArgs.nOptions;
|
||||||
|
#endif
|
||||||
|
|
||||||
JavaVMOption options[vmArgs.nOptions];
|
JavaVMOption options[vmArgs.nOptions];
|
||||||
vmArgs.options = options;
|
vmArgs.options = options;
|
||||||
|
|
||||||
@ -103,6 +107,11 @@ main(int ac, const char** av)
|
|||||||
= const_cast<char*>("-Davian.bootstrap=" BOOT_LIBRARY);
|
= const_cast<char*>("-Davian.bootstrap=" BOOT_LIBRARY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOT_BUILTINS
|
||||||
|
options[optionIndex++].optionString
|
||||||
|
= const_cast<char*>("-Davian.builtins=" BOOT_BUILTINS);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CLASSPATH_PROPERTY "-Djava.class.path="
|
#define CLASSPATH_PROPERTY "-Djava.class.path="
|
||||||
|
|
||||||
unsigned classpathSize = strlen(classpath);
|
unsigned classpathSize = strlen(classpath);
|
||||||
|
@ -63,8 +63,6 @@ const unsigned VisitSignalIndex = 0;
|
|||||||
const unsigned SegFaultSignalIndex = 1;
|
const unsigned SegFaultSignalIndex = 1;
|
||||||
const unsigned InterruptSignalIndex = 2;
|
const unsigned InterruptSignalIndex = 2;
|
||||||
|
|
||||||
const unsigned ExecutableAreaSizeInBytes = 16 * 1024 * 1024;
|
|
||||||
|
|
||||||
class MySystem;
|
class MySystem;
|
||||||
MySystem* system;
|
MySystem* system;
|
||||||
|
|
||||||
@ -126,9 +124,7 @@ class MySystem: public System {
|
|||||||
|
|
||||||
r->setInterrupted(true);
|
r->setInterrupted(true);
|
||||||
|
|
||||||
if (flags & Waiting) {
|
pthread_kill(thread, InterruptSignal);
|
||||||
pthread_kill(thread, InterruptSignal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void join() {
|
virtual void join() {
|
||||||
@ -518,9 +514,7 @@ class MySystem: public System {
|
|||||||
|
|
||||||
MySystem():
|
MySystem():
|
||||||
threadVisitor(0),
|
threadVisitor(0),
|
||||||
visitTarget(0),
|
visitTarget(0)
|
||||||
executableArea(0),
|
|
||||||
executableOffset(0)
|
|
||||||
{
|
{
|
||||||
expect(this, system == 0);
|
expect(this, system == 0);
|
||||||
system = this;
|
system = this;
|
||||||
@ -559,33 +553,23 @@ class MySystem: public System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void* tryAllocateExecutable(unsigned sizeInBytes) {
|
virtual void* tryAllocateExecutable(unsigned sizeInBytes) {
|
||||||
if (executableArea == 0) {
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
const unsigned Extra = MAP_32BIT;
|
const unsigned Extra = MAP_32BIT;
|
||||||
#else
|
#else
|
||||||
const unsigned Extra = 0;
|
const unsigned Extra = 0;
|
||||||
#endif
|
#endif
|
||||||
void* p = mmap(0, ExecutableAreaSizeInBytes, PROT_EXEC | PROT_READ
|
void* p = mmap(0, sizeInBytes, PROT_EXEC | PROT_READ
|
||||||
| PROT_WRITE, MAP_PRIVATE | MAP_ANON | Extra, -1, 0);
|
| PROT_WRITE, MAP_PRIVATE | MAP_ANON | Extra, -1, 0);
|
||||||
|
|
||||||
if (p != MAP_FAILED) {
|
if (p == MAP_FAILED) {
|
||||||
executableArea = static_cast<uint8_t*>(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (executableArea
|
|
||||||
and executableOffset + pad(sizeInBytes) < ExecutableAreaSizeInBytes)
|
|
||||||
{
|
|
||||||
void* r = executableArea + executableOffset;
|
|
||||||
executableOffset += pad(sizeInBytes);
|
|
||||||
return r;
|
|
||||||
} else {
|
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
return static_cast<uint8_t*>(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void freeExecutable(const void*, unsigned) {
|
virtual void freeExecutable(const void* p, unsigned sizeInBytes) {
|
||||||
// ignore
|
munmap(const_cast<void*>(p), sizeInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool success(Status s) {
|
virtual bool success(Status s) {
|
||||||
@ -642,13 +626,16 @@ class MySystem: public System {
|
|||||||
visitTarget = target;
|
visitTarget = target;
|
||||||
|
|
||||||
int rv = pthread_kill(target->thread, VisitSignal);
|
int rv = pthread_kill(target->thread, VisitSignal);
|
||||||
expect(this, rv == 0);
|
|
||||||
|
|
||||||
while (visitTarget) visitLock->wait(t, 0);
|
if (rv == 0) {
|
||||||
|
while (visitTarget) visitLock->wait(t, 0);
|
||||||
|
|
||||||
threadVisitor = 0;
|
threadVisitor = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||||
@ -780,11 +767,6 @@ class MySystem: public System {
|
|||||||
registerHandler(0, VisitSignalIndex);
|
registerHandler(0, VisitSignalIndex);
|
||||||
system = 0;
|
system = 0;
|
||||||
|
|
||||||
if (executableArea) {
|
|
||||||
int r UNUSED = munmap(executableArea, ExecutableAreaSizeInBytes);
|
|
||||||
assert(this, r == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
::free(this);
|
::free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -850,7 +832,7 @@ handleSignal(int signal, siginfo_t* info, void* context)
|
|||||||
sigaddset(&set, SegFaultSignal);
|
sigaddset(&set, SegFaultSignal);
|
||||||
sigprocmask(SIG_UNBLOCK, &set, 0);
|
sigprocmask(SIG_UNBLOCK, &set, 0);
|
||||||
|
|
||||||
vmJump(ip, base, stack, thread);
|
vmJump(ip, base, stack, thread, 0, 0);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -868,6 +850,7 @@ handleSignal(int signal, siginfo_t* info, void* context)
|
|||||||
} else {
|
} else {
|
||||||
switch (signal) {
|
switch (signal) {
|
||||||
case VisitSignal:
|
case VisitSignal:
|
||||||
|
case InterruptSignal:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -161,4 +161,6 @@ vmJump:
|
|||||||
mtlr r3
|
mtlr r3
|
||||||
mr r1,r5
|
mr r1,r5
|
||||||
mr r13,r6
|
mr r13,r6
|
||||||
|
mr r4,r7
|
||||||
|
mr r3,r8
|
||||||
blr
|
blr
|
||||||
|
181
src/powerpc.cpp
181
src/powerpc.cpp
@ -65,6 +65,7 @@ inline int sth(int rs, int ra, int i) { return D(44, rs, ra, i); }
|
|||||||
inline int sthx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 407, 0); }
|
inline int sthx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 407, 0); }
|
||||||
inline int stw(int rs, int ra, int i) { return D(36, rs, ra, i); }
|
inline int stw(int rs, int ra, int i) { return D(36, rs, ra, i); }
|
||||||
inline int stwu(int rs, int ra, int i) { return D(37, rs, ra, i); }
|
inline int stwu(int rs, int ra, int i) { return D(37, rs, ra, i); }
|
||||||
|
inline int stwux(int rs, int ra, int rb) { return X(31, rs, ra, rb, 183, 0); }
|
||||||
inline int stwx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 151, 0); }
|
inline int stwx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 151, 0); }
|
||||||
inline int add(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 266, 0); }
|
inline int add(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 266, 0); }
|
||||||
inline int addc(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 10, 0); }
|
inline int addc(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 10, 0); }
|
||||||
@ -136,7 +137,7 @@ inline int blt(int i) { return bc(12, 0, i, 0); }
|
|||||||
inline int bgt(int i) { return bc(12, 1, i, 0); }
|
inline int bgt(int i) { return bc(12, 1, i, 0); }
|
||||||
inline int bge(int i) { return bc(4, 0, i, 0); }
|
inline int bge(int i) { return bc(4, 0, i, 0); }
|
||||||
inline int ble(int i) { return bc(4, 1, i, 0); }
|
inline int ble(int i) { return bc(4, 1, i, 0); }
|
||||||
inline int be(int i) { return bc(12, 2, i, 0); }
|
inline int beq(int i) { return bc(12, 2, i, 0); }
|
||||||
inline int bne(int i) { return bc(4, 2, i, 0); }
|
inline int bne(int i) { return bc(4, 2, i, 0); }
|
||||||
inline int cmpw(int ra, int rb) { return cmp(0, ra, rb); }
|
inline int cmpw(int ra, int rb) { return cmp(0, ra, rb); }
|
||||||
inline int cmplw(int ra, int rb) { return cmpl(0, ra, rb); }
|
inline int cmplw(int ra, int rb) { return cmpl(0, ra, rb); }
|
||||||
@ -158,6 +159,9 @@ carry16(intptr_t v)
|
|||||||
|
|
||||||
const unsigned FrameFooterSize = 6;
|
const unsigned FrameFooterSize = 6;
|
||||||
|
|
||||||
|
const unsigned StackAlignmentInBytes = 16;
|
||||||
|
const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord;
|
||||||
|
|
||||||
const int StackRegister = 1;
|
const int StackRegister = 1;
|
||||||
const int ThreadRegister = 13;
|
const int ThreadRegister = 13;
|
||||||
|
|
||||||
@ -905,9 +909,15 @@ moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src,
|
|||||||
{
|
{
|
||||||
assert(c, srcSize == BytesPerWord);
|
assert(c, srcSize == BytesPerWord);
|
||||||
assert(c, dstSize == BytesPerWord);
|
assert(c, dstSize == BytesPerWord);
|
||||||
assert(c, dst->index == NoRegister);
|
|
||||||
|
|
||||||
issue(c, stwu(src->low, dst->base, dst->offset));
|
if (dst->index == NoRegister) {
|
||||||
|
issue(c, stwu(src->low, dst->base, dst->offset));
|
||||||
|
} else {
|
||||||
|
assert(c, dst->offset == 0);
|
||||||
|
assert(c, dst->scale == 1);
|
||||||
|
|
||||||
|
issue(c, stwux(src->low, dst->base, dst->index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1498,7 +1508,7 @@ jumpIfEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* target)
|
|||||||
assert(c, size == BytesPerWord);
|
assert(c, size == BytesPerWord);
|
||||||
|
|
||||||
appendOffsetTask(c, target->value, offset(c), true);
|
appendOffsetTask(c, target->value, offset(c), true);
|
||||||
issue(c, be(0));
|
issue(c, beq(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1588,6 +1598,9 @@ populateTables(ArchitectureContext* c)
|
|||||||
uo[index(Jump, R)] = CAST1(jumpR);
|
uo[index(Jump, R)] = CAST1(jumpR);
|
||||||
uo[index(Jump, C)] = CAST1(jumpC);
|
uo[index(Jump, C)] = CAST1(jumpC);
|
||||||
|
|
||||||
|
uo[index(AlignedJump, R)] = CAST1(jumpR);
|
||||||
|
uo[index(AlignedJump, C)] = CAST1(jumpC);
|
||||||
|
|
||||||
uo[index(JumpIfEqual, C)] = CAST1(jumpIfEqualC);
|
uo[index(JumpIfEqual, C)] = CAST1(jumpIfEqualC);
|
||||||
uo[index(JumpIfNotEqual, C)] = CAST1(jumpIfNotEqualC);
|
uo[index(JumpIfNotEqual, C)] = CAST1(jumpIfNotEqualC);
|
||||||
uo[index(JumpIfGreater, C)] = CAST1(jumpIfGreaterC);
|
uo[index(JumpIfGreater, C)] = CAST1(jumpIfGreaterC);
|
||||||
@ -1679,6 +1692,14 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
return (BytesPerWord == 4 ? 3 : NoRegister);
|
return (BytesPerWord == 4 ? 3 : NoRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int virtualCallTarget() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int virtualCallIndex() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool bigEndian() {
|
virtual bool bigEndian() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1695,8 +1716,12 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual unsigned frameFootprint(unsigned footprint) {
|
||||||
|
return max(footprint, StackAlignmentInWords);
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned argumentFootprint(unsigned footprint) {
|
virtual unsigned argumentFootprint(unsigned footprint) {
|
||||||
return footprint;
|
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned argumentRegisterCount() {
|
virtual unsigned argumentRegisterCount() {
|
||||||
@ -1708,6 +1733,30 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
|
|
||||||
return index + 3;
|
return index + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual uint64_t generalRegisters() {
|
||||||
|
return (static_cast<uint64_t>(1) << 32) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint64_t floatRegisters() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint64_t allRegisters() {
|
||||||
|
return generalRegisters() | floatRegisters();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual unsigned stackAlignmentInWords() {
|
||||||
|
return StackAlignmentInWords;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool matchCall(void* returnAddress, void* target) {
|
||||||
|
uint32_t* instruction = static_cast<uint32_t*>(returnAddress) - 1;
|
||||||
|
|
||||||
|
return *instruction == static_cast<uint32_t>
|
||||||
|
(bl(static_cast<uint8_t*>(target)
|
||||||
|
- reinterpret_cast<uint8_t*>(instruction)));
|
||||||
|
}
|
||||||
|
|
||||||
virtual void updateCall(UnaryOperation op UNUSED,
|
virtual void updateCall(UnaryOperation op UNUSED,
|
||||||
bool assertAlignment UNUSED, void* returnAddress,
|
bool assertAlignment UNUSED, void* returnAddress,
|
||||||
@ -1730,6 +1779,10 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual unsigned constantCallSize() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
virtual uintptr_t getConstant(const void* src) {
|
virtual uintptr_t getConstant(const void* src) {
|
||||||
const int32_t* p = static_cast<const int32_t*>(src);
|
const int32_t* p = static_cast<const int32_t*>(src);
|
||||||
return (p[0] << 16) | (p[1] & 0xFFFF);
|
return (p[0] << 16) | (p[1] & 0xFFFF);
|
||||||
@ -1740,7 +1793,7 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
||||||
const unsigned alignment = 16 / BytesPerWord;
|
const unsigned alignment = StackAlignmentInBytes / BytesPerWord;
|
||||||
return (ceiling(sizeInWords + FrameFooterSize, alignment) * alignment);
|
return (ceiling(sizeInWords + FrameFooterSize, alignment) * alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1760,6 +1813,14 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
return FrameFooterSize;
|
return FrameFooterSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int returnAddressOffset() {
|
||||||
|
return 8 / BytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int framePointerOffset() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void nextFrame(void** stack, void**) {
|
virtual void nextFrame(void** stack, void**) {
|
||||||
assert(&c, *static_cast<void**>(*stack) != *stack);
|
assert(&c, *static_cast<void**>(*stack) != *stack);
|
||||||
|
|
||||||
@ -1778,6 +1839,14 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool alwaysCondensed(BinaryOperation op) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool alwaysCondensed(TernaryOperation op) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void plan
|
virtual void plan
|
||||||
(UnaryOperation,
|
(UnaryOperation,
|
||||||
unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
||||||
@ -1898,8 +1967,8 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
unsigned, const uint8_t* bTypeMask, const uint64_t* bRegisterMask,
|
unsigned, const uint8_t* bTypeMask, const uint64_t* bRegisterMask,
|
||||||
unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask)
|
unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask)
|
||||||
{
|
{
|
||||||
*cTypeMask = *bTypeMask;
|
*cTypeMask = (1 << RegisterOperand);
|
||||||
*cRegisterMask = *bRegisterMask;
|
*cRegisterMask = ~static_cast<uint64_t>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void acquire() {
|
virtual void acquire() {
|
||||||
@ -1990,18 +2059,110 @@ class MyAssembler: public Assembler {
|
|||||||
moveAndUpdateRM(&c, BytesPerWord, &stack, BytesPerWord, &stackDst);
|
moveAndUpdateRM(&c, BytesPerWord, &stack, BytesPerWord, &stackDst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void adjustFrame(unsigned footprint) {
|
||||||
|
Register nextStack(0);
|
||||||
|
Memory stackSrc(StackRegister, 0);
|
||||||
|
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &nextStack);
|
||||||
|
|
||||||
|
Memory stackDst(StackRegister, -footprint * BytesPerWord);
|
||||||
|
moveAndUpdateRM(&c, BytesPerWord, &nextStack, BytesPerWord, &stackDst);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void popFrame() {
|
virtual void popFrame() {
|
||||||
Register stack(StackRegister);
|
Register stack(StackRegister);
|
||||||
Memory stackSrc(StackRegister, 0);
|
Memory stackSrc(StackRegister, 0);
|
||||||
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack);
|
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack);
|
||||||
|
|
||||||
Assembler::Register returnAddress(0);
|
Register returnAddress(0);
|
||||||
Assembler::Memory returnAddressSrc(StackRegister, 8);
|
Memory returnAddressSrc(StackRegister, 8);
|
||||||
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &returnAddress);
|
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &returnAddress);
|
||||||
|
|
||||||
issue(&c, mtlr(returnAddress.low));
|
issue(&c, mtlr(returnAddress.low));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void popFrameForTailCall(unsigned footprint,
|
||||||
|
int offset,
|
||||||
|
int returnAddressSurrogate,
|
||||||
|
int framePointerSurrogate)
|
||||||
|
{
|
||||||
|
if (TailCalls) {
|
||||||
|
if (offset) {
|
||||||
|
Register tmp(0);
|
||||||
|
Memory returnAddressSrc(StackRegister, 8 + (footprint * BytesPerWord));
|
||||||
|
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &tmp);
|
||||||
|
|
||||||
|
issue(&c, mtlr(tmp.low));
|
||||||
|
|
||||||
|
Memory stackSrc(StackRegister, footprint * BytesPerWord);
|
||||||
|
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp);
|
||||||
|
|
||||||
|
Memory stackDst(StackRegister, (footprint - offset) * BytesPerWord);
|
||||||
|
moveAndUpdateRM(&c, BytesPerWord, &tmp, BytesPerWord, &stackDst);
|
||||||
|
|
||||||
|
if (returnAddressSurrogate != NoRegister) {
|
||||||
|
assert(&c, offset > 0);
|
||||||
|
|
||||||
|
Register ras(returnAddressSurrogate);
|
||||||
|
Memory dst(StackRegister, 8 + (offset * BytesPerWord));
|
||||||
|
moveRM(&c, BytesPerWord, &ras, BytesPerWord, &dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framePointerSurrogate != NoRegister) {
|
||||||
|
assert(&c, offset > 0);
|
||||||
|
|
||||||
|
Register fps(framePointerSurrogate);
|
||||||
|
Memory dst(StackRegister, offset * BytesPerWord);
|
||||||
|
moveRM(&c, BytesPerWord, &fps, BytesPerWord, &dst);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
popFrame();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
abort(&c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint) {
|
||||||
|
popFrame();
|
||||||
|
|
||||||
|
assert(&c, argumentFootprint >= StackAlignmentInWords);
|
||||||
|
assert(&c, (argumentFootprint % StackAlignmentInWords) == 0);
|
||||||
|
|
||||||
|
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
|
||||||
|
Register tmp(0);
|
||||||
|
Memory stackSrc(StackRegister, 0);
|
||||||
|
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp);
|
||||||
|
|
||||||
|
Memory stackDst(StackRegister,
|
||||||
|
(argumentFootprint - StackAlignmentInWords)
|
||||||
|
* BytesPerWord);
|
||||||
|
moveAndUpdateRM(&c, BytesPerWord, &tmp, BytesPerWord, &stackDst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return_(&c);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffsetFromThread)
|
||||||
|
{
|
||||||
|
popFrame();
|
||||||
|
|
||||||
|
Register tmp1(0);
|
||||||
|
Memory stackSrc(StackRegister, 0);
|
||||||
|
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp1);
|
||||||
|
|
||||||
|
Register tmp2(5);
|
||||||
|
Memory newStackSrc(ThreadRegister, stackOffsetFromThread);
|
||||||
|
moveMR(&c, BytesPerWord, &newStackSrc, BytesPerWord, &tmp2);
|
||||||
|
|
||||||
|
Register stack(StackRegister);
|
||||||
|
subR(&c, BytesPerWord, &stack, &tmp2, &tmp2);
|
||||||
|
|
||||||
|
Memory stackDst(StackRegister, 0, tmp2.low);
|
||||||
|
moveAndUpdateRM(&c, BytesPerWord, &tmp1, BytesPerWord, &stackDst);
|
||||||
|
|
||||||
|
return_(&c);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void apply(Operation op) {
|
virtual void apply(Operation op) {
|
||||||
arch_->c.operations[op](&c);
|
arch_->c.operations[op](&c);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ mangle(int8_t c, char* dst)
|
|||||||
unsigned
|
unsigned
|
||||||
jniNameLength(Thread* t, object method, bool decorate)
|
jniNameLength(Thread* t, object method, bool decorate)
|
||||||
{
|
{
|
||||||
unsigned size = 5;
|
unsigned size = 0;
|
||||||
|
|
||||||
object className = ::className(t, methodClass(t, method));
|
object className = ::className(t, methodClass(t, method));
|
||||||
for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
|
for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
|
||||||
@ -96,10 +96,11 @@ jniNameLength(Thread* t, object method, bool decorate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
makeJNIName(Thread* t, char* name, object method, bool decorate)
|
makeJNIName(Thread* t, const char* prefix, unsigned prefixLength, char* name,
|
||||||
|
object method, bool decorate)
|
||||||
{
|
{
|
||||||
memcpy(name, "Java_", 5);
|
memcpy(name, prefix, prefixLength);
|
||||||
name += 5;
|
name += prefixLength;
|
||||||
|
|
||||||
object className = ::className(t, methodClass(t, method));
|
object className = ::className(t, methodClass(t, method));
|
||||||
for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
|
for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
|
||||||
@ -146,31 +147,30 @@ resolveNativeMethod(Thread* t, const char* undecorated, const char* decorated)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace vm {
|
|
||||||
|
|
||||||
void*
|
void*
|
||||||
resolveNativeMethod2(Thread* t, object method)
|
resolveNativeMethod(Thread* t, object method, const char* prefix,
|
||||||
|
unsigned prefixLength, int footprint UNUSED)
|
||||||
{
|
{
|
||||||
unsigned undecoratedSize = jniNameLength(t, method, false);
|
unsigned undecoratedSize = prefixLength + jniNameLength(t, method, false);
|
||||||
char undecorated[undecoratedSize + 1 + 6]; // extra 6 is for code below
|
char undecorated[undecoratedSize + 1 + 6]; // extra 6 is for code below
|
||||||
makeJNIName(t, undecorated + 1, method, false);
|
makeJNIName(t, prefix, prefixLength, undecorated + 1, method, false);
|
||||||
|
|
||||||
unsigned decoratedSize = jniNameLength(t, method, true);
|
unsigned decoratedSize = prefixLength + jniNameLength(t, method, true);
|
||||||
char decorated[decoratedSize + 1 + 6]; // extra 6 is for code below
|
char decorated[decoratedSize + 1 + 6]; // extra 6 is for code below
|
||||||
makeJNIName(t, decorated + 1, method, true);
|
makeJNIName(t, prefix, prefixLength, decorated + 1, method, true);
|
||||||
|
|
||||||
void* p = ::resolveNativeMethod(t, undecorated + 1, decorated + 1);
|
void* p = resolveNativeMethod(t, undecorated + 1, decorated + 1);
|
||||||
if (p) {
|
if (p) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
// on windows, we also try the _%s@%d and %s@%d variants
|
// on windows, we also try the _%s@%d and %s@%d variants
|
||||||
unsigned footprint = methodParameterFootprint(t, method) + 1;
|
if (footprint == -1) {
|
||||||
if (methodFlags(t, method) & ACC_STATIC) {
|
footprint = methodParameterFootprint(t, method) + 1;
|
||||||
++ footprint;
|
if (methodFlags(t, method) & ACC_STATIC) {
|
||||||
|
++ footprint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*undecorated = '_';
|
*undecorated = '_';
|
||||||
@ -181,13 +181,13 @@ resolveNativeMethod2(Thread* t, object method)
|
|||||||
snprintf(decorated + decoratedSize + 1, 5, "@%d",
|
snprintf(decorated + decoratedSize + 1, 5, "@%d",
|
||||||
footprint * BytesPerWord);
|
footprint * BytesPerWord);
|
||||||
|
|
||||||
p = ::resolveNativeMethod(t, undecorated, decorated);
|
p = resolveNativeMethod(t, undecorated, decorated);
|
||||||
if (p) {
|
if (p) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// one more try without the leading underscore
|
// one more try without the leading underscore
|
||||||
p = ::resolveNativeMethod(t, undecorated + 1, decorated + 1);
|
p = resolveNativeMethod(t, undecorated + 1, decorated + 1);
|
||||||
if (p) {
|
if (p) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -196,6 +196,27 @@ resolveNativeMethod2(Thread* t, object method)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
|
||||||
|
void*
|
||||||
|
resolveNativeMethod(Thread* t, object method)
|
||||||
|
{
|
||||||
|
void* p = ::resolveNativeMethod(t, method, "Java_", 5, -1);
|
||||||
|
if (p) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ::resolveNativeMethod(t, method, "Avian_", 6, 3);
|
||||||
|
if (p) {
|
||||||
|
methodVmFlags(t, method) |= FastNative;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
findLineNumber(Thread* t, object method, unsigned ip)
|
findLineNumber(Thread* t, object method, unsigned ip)
|
||||||
{
|
{
|
||||||
|
@ -126,17 +126,7 @@ isSpecialMethod(Thread* t, object method, object class_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
resolveNativeMethod2(Thread* t, object method);
|
resolveNativeMethod(Thread* t, object method);
|
||||||
|
|
||||||
inline void*
|
|
||||||
resolveNativeMethod(Thread* t, object method)
|
|
||||||
{
|
|
||||||
if (methodCode(t, method)) {
|
|
||||||
return pointerValue(t, methodCode(t, method));
|
|
||||||
} else {
|
|
||||||
return resolveNativeMethod2(t, method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
findInterfaceMethod(Thread* t, object method, object class_)
|
findInterfaceMethod(Thread* t, object method, object class_)
|
||||||
|
@ -78,9 +78,6 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
initVtable(Thread* t, object c) = 0;
|
initVtable(Thread* t, object c) = 0;
|
||||||
|
|
||||||
virtual void
|
|
||||||
initClass(Thread* t, object c) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||||
|
|
||||||
@ -117,23 +114,38 @@ class Processor {
|
|||||||
getStackTrace(Thread* t, Thread* target) = 0;
|
getStackTrace(Thread* t, Thread* target) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
compileThunks(Thread* t, BootImage* image, uint8_t* code, unsigned* size,
|
initialize(BootImage* image, uint8_t* code, unsigned capacity) = 0;
|
||||||
unsigned capacity) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
compileMethod(Thread* t, Zone* zone, uint8_t* code, unsigned* offset,
|
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
|
||||||
unsigned capacity, object* constants, object* calls,
|
|
||||||
DelayedPromise** addresses, object method) = 0;
|
DelayedPromise** addresses, object method) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitRoots(BootImage* image, HeapWalker* w) = 0;
|
visitRoots(HeapWalker* w) = 0;
|
||||||
|
|
||||||
virtual unsigned*
|
virtual unsigned*
|
||||||
makeCallTable(Thread* t, BootImage* image, HeapWalker* w, uint8_t* code) = 0;
|
makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
boot(Thread* t, BootImage* image) = 0;
|
boot(Thread* t, BootImage* image) = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
callWithCurrentContinuation(Thread* t, object receiver) = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
dynamicWind(Thread* t, object before, object thunk, object after) = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
feedResultToContinuation(Thread* t, object continuation, object result) = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
feedExceptionToContinuation(Thread* t, object continuation,
|
||||||
|
object exception) = 0;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
|
||||||
|
= 0;
|
||||||
|
|
||||||
object
|
object
|
||||||
invoke(Thread* t, object method, object this_, ...)
|
invoke(Thread* t, object method, object this_, ...)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,7 @@ THUNK(makeMultidimensionalArray)
|
|||||||
THUNK(throw_)
|
THUNK(throw_)
|
||||||
THUNK(checkCast)
|
THUNK(checkCast)
|
||||||
THUNK(instanceOf64)
|
THUNK(instanceOf64)
|
||||||
THUNK(makeNewWeakReference64)
|
THUNK(makeNewGeneral64)
|
||||||
THUNK(makeNew64)
|
THUNK(makeNew64)
|
||||||
THUNK(set)
|
THUNK(set)
|
||||||
THUNK(gcIfNecessary)
|
THUNK(gcIfNecessary)
|
||||||
|
@ -1323,12 +1323,6 @@ parseJavaClass(Object* type, Stream* s, Object* declarations)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (equal(typeJavaName(type), "java/lang/Class")) {
|
|
||||||
// add inline vtable
|
|
||||||
addMember(type, Array::make
|
|
||||||
(type, 0, "void*", "vtable", sizeOf("void*", 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeSuper(type)) {
|
if (typeSuper(type)) {
|
||||||
for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) {
|
for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) {
|
||||||
addMethod(type, car(p));
|
addMethod(type, car(p));
|
||||||
@ -1372,23 +1366,25 @@ parseType(Object::ObjectType type, Object* p, Object* declarations,
|
|||||||
|
|
||||||
Type* t = Type::make(type, name, javaName);
|
Type* t = Type::make(type, name, javaName);
|
||||||
|
|
||||||
if (javaName and *javaName != '[') {
|
bool isJavaType = javaName and *javaName != '[';
|
||||||
assert(cdr(p) == 0);
|
|
||||||
|
|
||||||
|
if (isJavaType) {
|
||||||
const char* file = append(javaClassDirectory, "/", javaName, ".class");
|
const char* file = append(javaClassDirectory, "/", javaName, ".class");
|
||||||
Stream s(fopen(file, "rb"), true);
|
Stream s(fopen(file, "rb"), true);
|
||||||
parseJavaClass(t, &s, declarations);
|
parseJavaClass(t, &s, declarations);
|
||||||
} else {
|
}
|
||||||
for (p = cdr(p); p; p = cdr(p)) {
|
|
||||||
if (type == Object::Type) {
|
|
||||||
parseSubdeclaration(t, car(p), declarations);
|
|
||||||
} else {
|
|
||||||
Object* member = parseMember(t, car(p), declarations);
|
|
||||||
assert(member->type == Object::Scalar);
|
|
||||||
addMember(t, member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (p = cdr(p); p; p = cdr(p)) {
|
||||||
|
if (type == Object::Type) {
|
||||||
|
parseSubdeclaration(t, car(p), declarations);
|
||||||
|
} else {
|
||||||
|
Object* member = parseMember(t, car(p), declarations);
|
||||||
|
assert(member->type == Object::Scalar);
|
||||||
|
addMember(t, member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not isJavaType) {
|
||||||
if (type == Object::Type and typeSuper(t)) {
|
if (type == Object::Type and typeSuper(t)) {
|
||||||
for (Object* p = typeMethods(typeSuper(t)); p; p = cdr(p)) {
|
for (Object* p = typeMethods(typeSuper(t)); p; p = cdr(p)) {
|
||||||
addMethod(t, car(p));
|
addMethod(t, car(p));
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user