diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index baaad278f2..1ceb275748 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -1,6 +1,10 @@ package java.io; public class File { + static { + System.loadLibrary("natives"); + } + private final String path; public File(String path) { diff --git a/classpath/java/io/FileInputStream.java b/classpath/java/io/FileInputStream.java index 41b383fbfb..23a4b278aa 100644 --- a/classpath/java/io/FileInputStream.java +++ b/classpath/java/io/FileInputStream.java @@ -1,6 +1,10 @@ package java.io; public class FileInputStream extends InputStream { + static { + System.loadLibrary("natives"); + } + private int fd; public FileInputStream(FileDescriptor fd) { diff --git a/classpath/java/io/FileOutputStream.java b/classpath/java/io/FileOutputStream.java index 11e31a2f41..8437d3691c 100644 --- a/classpath/java/io/FileOutputStream.java +++ b/classpath/java/io/FileOutputStream.java @@ -1,6 +1,10 @@ package java.io; public class FileOutputStream extends OutputStream { + static { + System.loadLibrary("natives"); + } + private int fd; public FileOutputStream(FileDescriptor fd) { diff --git a/classpath/java/lang/Object.java b/classpath/java/lang/Object.java index 7ba7eb9090..4e4fb4ca2c 100644 --- a/classpath/java/lang/Object.java +++ b/classpath/java/lang/Object.java @@ -1,7 +1,15 @@ package java.lang; public class Object { - protected native Object clone() throws CloneNotSupportedException; + protected Object clone() throws CloneNotSupportedException { + if (this instanceof Cloneable) { + return clone(this); + } else { + throw new CloneNotSupportedException(); + } + } + + private static native Object clone(Object o); public boolean equals(Object o) { return this == o; diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index fd278d8320..ef59bebe41 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -31,6 +31,18 @@ public final class String implements Comparable { } private String(Object data, int offset, int length, boolean copy) { + int l; + if (data instanceof char[]) { + l = ((char[]) data).length; + } else { + l = ((byte[]) data).length; + } + + if (offset < 0 || offset + length > l) { + throw new IndexOutOfBoundsException + (offset + " < 0 or " + offset + " + " + length + " > " + l); + } + if (copy) { Object c; if (data instanceof char[]) { @@ -59,7 +71,9 @@ public final class String implements Comparable { public int hashCode() { if (hash == 0) { - for (int i = 0; i < length; ++i) hash = (hash * 31) + charAt(i); + int h = 0; + for (int i = 0; i < length; ++i) h = (h * 31) + charAt(i); + hash = h; } return hash; } diff --git a/classpath/java/lang/StringBuffer.java b/classpath/java/lang/StringBuffer.java index fcb34d1e0e..497e2d1843 100644 --- a/classpath/java/lang/StringBuffer.java +++ b/classpath/java/lang/StringBuffer.java @@ -21,6 +21,11 @@ public class StringBuffer { return this; } + public synchronized StringBuffer append(char v) { + sb.append(v); + return this; + } + public synchronized StringBuffer append(int v) { sb.append(v); return this; diff --git a/classpath/java/lang/StringBuilder.java b/classpath/java/lang/StringBuilder.java index 8f90196985..2f1111a439 100644 --- a/classpath/java/lang/StringBuilder.java +++ b/classpath/java/lang/StringBuilder.java @@ -3,6 +3,8 @@ package java.lang; public class StringBuilder { private Cell chain; private int length; + private char[] buffer; + private int position; public StringBuilder(int capacity) { } @@ -10,12 +12,28 @@ public class StringBuilder { this(0); } - public StringBuilder append(String s) { - if (s.length() > 0) { - chain = new Cell(s, chain); - length += s.length(); + private void flush() { + if (position > 0) { + char[] b = buffer; + int p = position; + buffer = null; + position = 0; + append(new String(b, 0, p, false)); + length -= p; + } + } + + public StringBuilder append(String s) { + if (s == null) { + return append("null"); + } else { + if (s.length() > 0) { + flush(); + chain = new Cell(s, chain); + length += s.length(); + } + return this; } - return this; } public StringBuilder append(char[] b, int offset, int length) { @@ -26,6 +44,20 @@ public class StringBuilder { return append(o == null ? "null" : o.toString()); } + public StringBuilder append(char v) { + if (buffer == null) { + buffer = new char[32]; + } else if (position >= buffer.length) { + flush(); + buffer = new char[32]; + } + + buffer[position++] = v; + ++ length; + + return this; + } + public StringBuilder append(int v) { return append(String.valueOf(v)); } @@ -39,6 +71,8 @@ public class StringBuilder { throw new IndexOutOfBoundsException(); } + flush(); + int index = length; -- length; Cell p = null; @@ -83,6 +117,8 @@ public class StringBuilder { return; } + flush(); + int index = length; length = v; for (Cell c = chain; c != null; c = c.next) { @@ -106,6 +142,8 @@ public class StringBuilder { throw new IndexOutOfBoundsException(); } + flush(); + int index = length; for (Cell c = chain; c != null; c = c.next) { int start = index - c.value.length(); @@ -124,7 +162,7 @@ public class StringBuilder { c.value.getChars(start - index, end - start, dst, dstOffset + (start - srcOffset)); } - } + } } public String toString() { diff --git a/classpath/java/util/HashMap.java b/classpath/java/util/HashMap.java index abb559279f..bbfb51cb49 100644 --- a/classpath/java/util/HashMap.java +++ b/classpath/java/util/HashMap.java @@ -5,7 +5,7 @@ public class HashMap implements Map { private Cell[] array; private final Helper helper; - HashMap(int capacity, Helper helper) { + public HashMap(int capacity, Helper helper) { if (capacity > 0) { array = new Cell[nextPowerOfTwo(capacity)]; } @@ -20,6 +20,22 @@ public class HashMap implements Map { this(0); } + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + for (Iterator> it = iterator(); it.hasNext();) { + Entry 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) { int r = 1; while (r < n) r <<= 1; @@ -85,8 +101,7 @@ public class HashMap implements Map { array[index] = cell; } - // primarily for use by WeakHashMap: - void remove(Cell cell) { + public void remove(Cell cell) { int index = cell.hashCode() & (array.length - 1); Cell p = null; for (Cell c = array[index]; c != null; c = c.next()) { @@ -366,7 +381,7 @@ public class HashMap implements Map { } } } - return false; + return nextCell != null; } public void remove() { diff --git a/src/builtin.cpp b/src/builtin.cpp index 1780014946..689ab82be5 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -10,7 +10,7 @@ namespace { object doInvoke(Thread* t, object this_, object instance, object arguments) { - object v = pushReference(t, run2(t, this_, instance, arguments)); + object v = run2(t, this_, instance, arguments); if (t->exception) { t->exception = makeInvocationTargetException(t, t->exception); } @@ -64,6 +64,16 @@ Object_hashCode(Thread* t, jobject this_) return objectHash(t, *this_); } +jobject +Object_clone(Thread* t, jclass, jobject o) +{ + object clone = make(t, objectClass(t, *o)); + memcpy(static_cast(clone) + 1, + static_cast(*o) + 1, + (baseSize(t, *o, objectClass(t, *o)) - 1) * BytesPerWord); + return pushReference(t, clone); +} + jclass ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset, jint length) @@ -816,6 +826,8 @@ populateBuiltinMap(Thread* t, object map) reinterpret_cast(::Object_wait) }, { "Java_java_lang_Object_hashCode", reinterpret_cast(::Object_hashCode) }, + { "Java_java_lang_Object_clone", + reinterpret_cast(::Object_clone) }, { "Java_java_lang_reflect_Array_get", reinterpret_cast(::Array_get) }, diff --git a/src/machine.h b/src/machine.h index edadcc0410..bb1765a3c1 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1829,7 +1829,9 @@ inline uint32_t hash(const int8_t* s, unsigned length) { uint32_t h = 0; - for (unsigned i = 0; i < length; ++i) h = (h * 31) + s[i]; + for (unsigned i = 0; i < length; ++i) { + h = (h * 31) + static_cast(s[i]); + } return h; } @@ -1837,7 +1839,9 @@ inline uint32_t hash(const uint16_t* s, unsigned length) { uint32_t h = 0; - for (unsigned i = 0; i < length; ++i) h = (h * 31) + s[i]; + for (unsigned i = 0; i < length; ++i) { + h = (h * 31) + s[i]; + } return h; } @@ -1934,9 +1938,11 @@ stringHash(Thread* t, object s) if (objectClass(t, data) == arrayBody(t, t->vm->types, Machine::ByteArrayType)) { - stringHashCode(t, s) = byteArrayHash(t, data); + stringHashCode(t, s) = hash + (&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s)); } else { - stringHashCode(t, s) = charArrayHash(t, data); + stringHashCode(t, s) = hash + (&charArrayBody(t, data, stringOffset(t, s)), stringLength(t, s)); } } return stringHashCode(t, s); diff --git a/src/run.cpp b/src/run.cpp index bb850ed53c..9da0177d9b 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -1570,12 +1570,13 @@ run(Thread* t) object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - if (instanceOf(t, class_, peekObject(t, sp - 1))) { + if (instanceOf(t, class_, popObject(t))) { pushInt(t, 1); } else { pushInt(t, 0); } } else { + popObject(t); pushInt(t, 0); } } goto loop;