fix openjdk-src bootimage build

The main change here is to use a lazily-populated vector to associate
runtime data with classes instead of referencing them directly from
the class which requires updating immutable references in the heap
image.  The other changes employ other strategies to avoid trying to
update immutable references.
This commit is contained in:
Joel Dice 2010-11-26 12:41:31 -07:00
parent 4f23601b56
commit 459f4d5194
16 changed files with 426 additions and 154 deletions

View File

@ -10,8 +10,4 @@
package avian; package avian;
public class ClassAddendum extends Addendum { public class ClassAddendum extends Addendum { }
public volatile Class class_;
public Object[] signers;
public volatile Class arrayClass;
}

View File

@ -16,6 +16,7 @@ public class VMClass {
public short fixedSize; public short fixedSize;
public byte arrayElementSize; public byte arrayElementSize;
public byte arrayDimensions; public byte arrayDimensions;
public int runtimeDataIndex;
public int[] objectMask; public int[] objectMask;
public byte[] name; public byte[] name;
public byte[] sourceFile; public byte[] sourceFile;
@ -24,7 +25,7 @@ public class VMClass {
public VMMethod[] virtualTable; public VMMethod[] virtualTable;
public VMField[] fieldTable; public VMField[] fieldTable;
public VMMethod[] methodTable; public VMMethod[] methodTable;
public volatile avian.ClassAddendum addendum; public avian.ClassAddendum addendum;
public Object staticTable; public Object staticTable;
public ClassLoader loader; public ClassLoader loader;
} }

View File

@ -18,6 +18,7 @@ public class VMMethod {
public short flags; public short flags;
public short offset; public short offset;
public int nativeID; public int nativeID;
public int runtimeDataIndex;
public byte[] name; public byte[] name;
public byte[] spec; public byte[] spec;
public MethodAddendum addendum; public MethodAddendum addendum;

View File

@ -572,10 +572,6 @@ public final class Class <T> implements Type, AnnotatedElement {
return (T) o; return (T) o;
} }
public Object[] getSigners() {
return vmClass.addendum.signers;
}
public Package getPackage() { public Package getPackage() {
if ((vmClass.vmFlags & PrimitiveFlag) != 0 || isArray()) { if ((vmClass.vmFlags & PrimitiveFlag) != 0 || isArray()) {
return null; return null;

View File

@ -72,13 +72,13 @@ ifeq ($(build-platform),darwin)
library-path-variable = DYLD_LIBRARY_PATH library-path-variable = DYLD_LIBRARY_PATH
endif endif
ifdef openjdk ifneq ($(openjdk),)
openjdk-arch = $(arch) openjdk-arch = $(arch)
ifeq ($(arch),x86_64) ifeq ($(arch),x86_64)
openjdk-arch = amd64 openjdk-arch = amd64
endif endif
ifdef openjdk-src ifneq ($(openjdk-src),)
include openjdk-src.mk include openjdk-src.mk
options := $(options)-openjdk-src options := $(options)-openjdk-src
classpath-objects = $(openjdk-objects) classpath-objects = $(openjdk-objects)
@ -436,8 +436,7 @@ 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),$(build)) $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build))
bootimage-generator = \ bootimage-generator = $(build)/bootimage-generator
$(build)/$(bootimage-platform)-$(build-arch)$(options)/bootimage-generator
bootimage-bin = $(build)/bootimage.bin bootimage-bin = $(build)/bootimage.bin
bootimage-object = $(build)/bootimage-bin.o bootimage-object = $(build)/bootimage-bin.o
@ -454,10 +453,11 @@ $(error "bootimage cross-builds not yet supported")
endif endif
vm-classpath-object = $(bootimage-object) vm-classpath-object = $(bootimage-object)
cflags += -DBOOT_IMAGE=\"bootimageBin\" cflags += -DBOOT_IMAGE=\"bootimageBin\" -DAVIAN_CLASSPATH=\"\"
else else
vm-classpath-object = $(classpath-object) vm-classpath-object = $(classpath-object)
cflags += -DBOOT_CLASSPATH=\"[classpathJar]\" cflags += -DBOOT_CLASSPATH=\"[classpathJar]\" \
-DAVIAN_CLASSPATH=\"[classpathJar]\"
endif endif
driver-source = $(src)/main.cpp driver-source = $(src)/main.cpp
@ -509,7 +509,7 @@ ifneq ($(classpath),avian)
$(classpath-src)/avian/VMMethod.java \ $(classpath-src)/avian/VMMethod.java \
$(classpath-src)/avian/resource/Handler.java $(classpath-src)/avian/resource/Handler.java
ifdef openjdk ifneq ($(openjdk),)
classpath-sources := $(classpath-sources) \ classpath-sources := $(classpath-sources) \
$(classpath-src)/avian/OpenJDK.java $(classpath-src)/avian/OpenJDK.java
endif endif
@ -759,6 +759,8 @@ $(bootimage-generator):
$(MAKE) mode=$(mode) \ $(MAKE) mode=$(mode) \
arch=$(build-arch) \ arch=$(build-arch) \
platform=$(bootimage-platform) \ platform=$(bootimage-platform) \
openjdk=$(openjdk) \
openjdk-src=$(openjdk-src) \
bootimage-generator= \ bootimage-generator= \
build-bootimage-generator=$(bootimage-generator) \ build-bootimage-generator=$(bootimage-generator) \
$(bootimage-generator) $(bootimage-generator)

View File

@ -23,6 +23,38 @@ using namespace vm;
namespace { namespace {
const unsigned HeapCapacity = 768 * 1024 * 1024;
// Notes on immutable references in the heap image:
//
// One of the advantages of a bootimage-based build is that reduces
// the overhead of major GCs at runtime since we can avoid scanning
// the pre-built heap image entirely. However, this only works if we
// can ensure that no part of the heap image (with an exception noted
// below) ever points to runtime-allocated objects. Therefore (most)
// references in the heap image are considered immutable, and any
// attempt to update them at runtime will cause the process to abort.
//
// However, some references in the heap image really must be updated
// at runtime: e.g. the static field table for each class. Therefore,
// we allocate these as "fixed" objects, subject to mark-and-sweep
// collection, instead of as "copyable" objects subject to copying
// collection. This strategy avoids the necessity of maintaining
// "dirty reference" bitsets at runtime for the entire heap image;
// each fixed object has its own bitset specific to that object.
//
// In addition to the "fixed" object solution, there are other
// strategies available to avoid attempts to update immutable
// references at runtime:
//
// * Table-based: use a lazily-updated array or vector to associate
// runtime data with heap image objects (see
// e.g. getClassRuntimeData in machine.cpp).
//
// * Update references at build time: for example, we set the names
// of primitive classes before generating the heap image so that we
// need not populate them lazily at runtime.
bool bool
endsWith(const char* suffix, const char* s, unsigned length) endsWith(const char* suffix, const char* s, unsigned length)
{ {
@ -44,7 +76,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
DelayedPromise* addresses = 0; DelayedPromise* addresses = 0;
for (Finder::Iterator it(t->m->finder); it.hasMore();) { for (Finder::Iterator it
(static_cast<Finder*>
(systemClassLoaderFinder(t, root(t, Machine::BootLoader))));
it.hasMore();)
{
unsigned nameSize = 0; unsigned nameSize = 0;
const char* name = it.next(&nameSize); const char* name = it.next(&nameSize);
@ -53,7 +89,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
{ {
// fprintf(stderr, "%.*s\n", nameSize - 6, name); // fprintf(stderr, "%.*s\n", nameSize - 6, name);
object c = resolveSystemClass object c = resolveSystemClass
(t, makeByteArray(t, "%.*s", nameSize - 6, name)); (t, root(t, Machine::BootLoader),
makeByteArray(t, "%.*s", nameSize - 6, name), true);
if (t->exception) return 0; if (t->exception) return 0;
@ -62,21 +99,53 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
if (classMethodTable(t, c)) { if (classMethodTable(t, c)) {
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) { for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object method = arrayBody(t, classMethodTable(t, c), i); object method = arrayBody(t, classMethodTable(t, c), i);
if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) if (((methodName == 0
and ((methodName == 0 or ::strcmp
(reinterpret_cast<char*>
(&byteArrayBody
(t, vm::methodName(t, method), 0)), methodName) == 0)
and (methodSpec == 0
or ::strcmp or ::strcmp
(reinterpret_cast<char*> (reinterpret_cast<char*>
(&byteArrayBody (&byteArrayBody
(t, vm::methodName(t, method), 0)), methodName) == 0) (t, vm::methodSpec(t, method), 0)), methodSpec)
and (methodSpec == 0 == 0)))
or ::strcmp
(reinterpret_cast<char*>
(&byteArrayBody
(t, vm::methodSpec(t, method), 0)), methodSpec)
== 0)))
{ {
t->m->processor->compileMethod if (methodCode(t, method)
(t, zone, &constants, &calls, &addresses, method); or (methodFlags(t, method) & ACC_NATIVE))
{
PROTECT(t, method);
t->m->processor->compileMethod
(t, zone, &constants, &calls, &addresses, method);
}
object addendum = methodAddendum(t, method);
if (addendum and methodAddendumExceptionTable(t, addendum)) {
PROTECT(t, addendum);
// resolve exception types now to avoid trying to update
// immutable references at runtime
for (unsigned i = 0; i < shortArrayLength
(t, methodAddendumExceptionTable(t, addendum)); ++i)
{
uint16_t index = shortArrayBody
(t, methodAddendumExceptionTable(t, addendum), i) - 1;
object o = singletonObject
(t, addendumPool(t, addendum), index);
if (objectClass(t, o) == type(t, Machine::ReferenceType)) {
o = resolveClass
(t, root(t, Machine::BootLoader), referenceName(t, o));
if (t->exception) return 0;
set(t, addendumPool(t, addendum),
SingletonBody + (index * BytesPerWord), o);
}
}
}
} }
} }
} }
@ -89,7 +158,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
if (methodFlags(t, method) & ACC_NATIVE) { if (methodFlags(t, method) & ACC_NATIVE) {
address = reinterpret_cast<uintptr_t>(code + image->thunks.native.start); address = reinterpret_cast<uintptr_t>(code + image->thunks.native.start);
} else { } else {
address = methodCompiled(t, method); address = codeCompiled(t, methodCode(t, method));
} }
static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls))) static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls)))
@ -131,14 +200,17 @@ visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
{ {
Machine* m = t->m; Machine* m = t->m;
for (HashMapIterator it(t, m->classMap); it.hasMore();) { for (HashMapIterator it(t, classLoaderMap(t, root(t, Machine::BootLoader)));
it.hasMore();)
{
w->visitRoot(tripleSecond(t, it.next())); w->visitRoot(tripleSecond(t, it.next()));
} }
image->loader = w->visitRoot(m->loader); image->bootLoader = w->visitRoot(root(t, Machine::BootLoader));
image->appLoader = w->visitRoot(root(t, Machine::AppLoader));
image->types = w->visitRoot(m->types); image->types = w->visitRoot(m->types);
m->processor->visitRoots(w); m->processor->visitRoots(t, w);
for (; constants; constants = tripleThird(t, constants)) { for (; constants; constants = tripleThird(t, constants)) {
w->visitRoot(tripleFirst(t, constants)); w->visitRoot(tripleFirst(t, constants));
@ -177,9 +249,17 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
unsigned size = objectSize(t, p); unsigned size = objectSize(t, p);
unsigned number; unsigned number;
if (currentObject if ((currentObject
and (currentOffset * BytesPerWord) == ClassStaticTable) and (currentOffset * BytesPerWord) == ClassStaticTable)
or instanceOf(t, type(t, Machine::SystemClassLoaderType), p))
{ {
// Static tables and system classloaders must be allocated
// as fixed objects in the heap image so that they can be
// marked as dirty and visited during GC. Otherwise,
// attempts to update references in these objects to point
// to runtime-allocated memory would fail because we don't
// scan non-fixed objects in the heap image during GC.
FixedAllocator allocator FixedAllocator allocator
(t->m->system, reinterpret_cast<uint8_t*>(heap + position), (t->m->system, reinterpret_cast<uint8_t*>(heap + position),
(capacity - position) * BytesPerWord); (capacity - position) * BytesPerWord);
@ -296,40 +376,90 @@ writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
PROTECT(t, constants); PROTECT(t, constants);
const unsigned HeapCapacity = 32 * 1024 * 1024; // this map will not be used when the bootimage is loaded, so
// there's no need to preserve it:
setRoot(t, Machine::ByteArrayMap, makeWeakHashMap(t, 0, 0));
// name all primitive classes so we don't try to update immutable
// references at runtime:
{ object name = makeByteArray(t, "void");
set(t, type(t, Machine::JvoidType), ClassName, name);
name = makeByteArray(t, "boolean");
set(t, type(t, Machine::JbooleanType), ClassName, name);
name = makeByteArray(t, "byte");
set(t, type(t, Machine::JbyteType), ClassName, name);
name = makeByteArray(t, "short");
set(t, type(t, Machine::JshortType), ClassName, name);
name = makeByteArray(t, "char");
set(t, type(t, Machine::JcharType), ClassName, name);
name = makeByteArray(t, "int");
set(t, type(t, Machine::JintType), ClassName, name);
name = makeByteArray(t, "float");
set(t, type(t, Machine::JfloatType), ClassName, name);
name = makeByteArray(t, "long");
set(t, type(t, Machine::JlongType), ClassName, name);
name = makeByteArray(t, "double");
set(t, type(t, Machine::JdoubleType), ClassName, name);
}
collect(t, Heap::MajorCollection);
uintptr_t* heap = static_cast<uintptr_t*> uintptr_t* heap = static_cast<uintptr_t*>
(t->m->heap->allocate(HeapCapacity)); (t->m->heap->allocate(HeapCapacity));
uintptr_t* heapMap = static_cast<uintptr_t*> uintptr_t* heapMap = static_cast<uintptr_t*>
(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);
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->bootClassCount = hashMapSize
unsigned* classTable = static_cast<unsigned*> (t, classLoaderMap(t, root(t, Machine::BootLoader)));
(t->m->heap->allocate(image->classCount * sizeof(unsigned)));
unsigned* bootClassTable = static_cast<unsigned*>
(t->m->heap->allocate(image->bootClassCount * sizeof(unsigned)));
{ unsigned i = 0; { unsigned i = 0;
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) { for (HashMapIterator it
classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next())); (t, classLoaderMap(t, root(t, Machine::BootLoader)));
it.hasMore();)
{
bootClassTable[i++] = heapWalker->map()->find
(tripleSecond(t, it.next()));
} }
} }
image->stringCount = hashMapSize(t, t->m->stringMap); image->appClassCount = hashMapSize
(t, classLoaderMap(t, root(t, Machine::AppLoader)));
unsigned* appClassTable = static_cast<unsigned*>
(t->m->heap->allocate(image->appClassCount * sizeof(unsigned)));
{ unsigned i = 0;
for (HashMapIterator it
(t, classLoaderMap(t, root(t, Machine::AppLoader)));
it.hasMore();)
{
appClassTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
}
}
image->stringCount = hashMapSize(t, root(t, Machine::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, root(t, Machine::StringMap)); it.hasMore();) {
stringTable[i++] = heapWalker->map()->find stringTable[i++] = heapWalker->map()->find
(jreferenceTarget(t, tripleFirst(t, it.next()))); (jreferenceTarget(t, tripleFirst(t, it.next())));
} }
@ -344,17 +474,19 @@ writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_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->bootClassCount, image->stringCount, image->callCount,
image->heapSize, 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(bootClassTable, image->bootClassCount * sizeof(unsigned), 1, out);
fwrite(appClassTable, image->appClassCount * 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->bootClassCount * sizeof(unsigned))
+ (image->appClassCount * sizeof(unsigned))
+ (image->stringCount * sizeof(unsigned)) + (image->stringCount * sizeof(unsigned))
+ (image->callCount * sizeof(unsigned) * 2); + (image->callCount * sizeof(unsigned) * 2);
@ -384,16 +516,18 @@ main(int ac, const char** av)
} }
System* s = makeSystem(0); System* s = makeSystem(0);
Heap* h = makeHeap(s, 128 * 1024 * 1024); Heap* h = makeHeap(s, HeapCapacity * 2);
Finder* f = makeFinder(s, av[1], 0); Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX);
Finder* f = makeFinder(s, h, av[1], 0);
Processor* p = makeProcessor(s, h, false); Processor* p = makeProcessor(s, h, false);
BootImage image; BootImage image;
const unsigned CodeCapacity = 16 * 1024 * 1024; const unsigned CodeCapacity = 128 * 1024 * 1024;
uint8_t* code = static_cast<uint8_t*>(h->allocate(CodeCapacity)); uint8_t* code = static_cast<uint8_t*>(h->allocate(CodeCapacity));
p->initialize(&image, code, 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, 0, p, c, 0, 0);
Thread* t = p->makeThread(m, 0, 0); Thread* t = p->makeThread(m, 0, 0);
enter(t, Thread::ActiveState); enter(t, Thread::ActiveState);

View File

@ -95,7 +95,7 @@ class MyClasspath : public Classpath {
virtual const char* virtual const char*
bootClasspath() bootClasspath()
{ {
return BOOT_CLASSPATH; return AVIAN_CLASSPATH;
} }
virtual void virtual void

View File

@ -209,7 +209,7 @@ class MyClasspath : public Classpath {
sb.append('\0'); sb.append('\0');
this->classpath = sb.pointer; this->classpath = sb.pointer;
sb.append(BOOT_CLASSPATH); sb.append(AVIAN_CLASSPATH);
sb.append(s->pathSeparator()); sb.append(s->pathSeparator());
sb.append(javaHome); sb.append(javaHome);
sb.append("/lib/rt.jar"); sb.append("/lib/rt.jar");
@ -590,7 +590,8 @@ getFileAttributes
} }
} else { } else {
object r = t->m->processor->invoke object r = t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), (t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
reinterpret_cast<object>(arguments[0]), file); reinterpret_cast<object>(arguments[0]), file);
return (r ? intValue(t, r) : 0); return (r ? intValue(t, r) : 0);
@ -631,7 +632,8 @@ getLength
return 0; return 0;
} else { } else {
object r = t->m->processor->invoke object r = t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), (t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
reinterpret_cast<object>(arguments[0]), file); reinterpret_cast<object>(arguments[0]), file);
return (r ? longValue(t, r) : 0); return (r ? longValue(t, r) : 0);
@ -703,7 +705,9 @@ openFile(Thread* t, object method, uintptr_t* arguments)
= index + VirtualFileBase; = index + VirtualFileBase;
} else { } else {
t->m->processor->invoke t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), this_, path); (t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
this_, path);
} }
} }
@ -740,7 +744,9 @@ readByteFromFile(Thread* t, object method, uintptr_t* arguments)
} }
} else { } else {
object r = t->m->processor->invoke object r = t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), this_); (t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
this_);
return r ? intValue(t, r) : 0; return r ? intValue(t, r) : 0;
} }
@ -793,8 +799,9 @@ readBytesFromFile(Thread* t, object method, uintptr_t* arguments)
} }
} else { } else {
object r = t->m->processor->invoke object r = t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), this_, dst, (t, nativeInterceptOriginal
offset, length); (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
this_, dst, offset, length);
return r ? intValue(t, r) : 0; return r ? intValue(t, r) : 0;
} }
@ -837,7 +844,9 @@ skipBytesInFile(Thread* t, object method, uintptr_t* arguments)
} }
} else { } else {
object r = t->m->processor->invoke object r = t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), this_, count); (t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
this_, count);
return r ? longValue(t, r) : 0; return r ? longValue(t, r) : 0;
} }
@ -870,7 +879,9 @@ availableBytesInFile(Thread* t, object method, uintptr_t* arguments)
} }
} else { } else {
object r = t->m->processor->invoke object r = t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), this_); (t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
this_);
return r ? intValue(t, r) : 0; return r ? intValue(t, r) : 0;
} }
@ -901,7 +912,9 @@ closeFile(Thread* t, object method, uintptr_t* arguments)
0); 0);
} else { } else {
t->m->processor->invoke t->m->processor->invoke
(t, nativeInterceptOriginal(t, methodCode(t, method)), this_); (t, nativeInterceptOriginal
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
this_);
} }
} }
@ -926,7 +939,11 @@ intercept(Thread* t, object c, const char* name, const char* spec,
object native = makeNativeIntercept(t, function, true, clone); object native = makeNativeIntercept(t, function, true, clone);
set(t, m, MethodCode, native); PROTECT(t, native);
object runtimeData = getMethodRuntimeData(t, m);
set(t, runtimeData, MethodRuntimeDataNative, native);
} }
} }
@ -1196,7 +1213,7 @@ resolveParameterJTypes(Thread* t, object loader, object spec,
object object
resolveExceptionJTypes(Thread* t, object loader, object addendum) resolveExceptionJTypes(Thread* t, object loader, object addendum)
{ {
if (addendum == 0) { if (addendum == 0 or methodAddendumExceptionTable(t, addendum) == 0) {
return makeObjectArray(t, type(t, Machine::JclassType), 0); return makeObjectArray(t, type(t, Machine::JclassType), 0);
} }
@ -2470,8 +2487,9 @@ EXPORT(JVM_GetClassAnnotations)(Thread* t, jclass c)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
return makeLocalReference object addendum = classAddendum(t, jclassVmClass(t, *c));
(t, addendumAnnotationTable(t, classAddendum(t, jclassVmClass(t, *c)))); return addendum
? makeLocalReference(t, addendumAnnotationTable(t, addendum)) : 0;
} }
extern "C" JNIEXPORT jobjectArray JNICALL extern "C" JNIEXPORT jobjectArray JNICALL
@ -2537,7 +2555,12 @@ EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly)
? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod)); ? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod));
if (annotationTable) { if (annotationTable) {
set(t, classAddendum(t, jclassVmClass(t, *c)), AddendumPool, PROTECT(t, signature);
PROTECT(t, annotationTable);
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
set(t, runtimeData, ClassRuntimeDataPool,
addendumPool(t, methodAddendum(t, vmMethod))); addendumPool(t, methodAddendum(t, vmMethod)));
} }
@ -2607,8 +2630,13 @@ EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly)
? 0 : addendumAnnotationTable(t, fieldAddendum(t, vmField)); ? 0 : addendumAnnotationTable(t, fieldAddendum(t, vmField));
if (annotationTable) { if (annotationTable) {
set(t, classAddendum(t, jclassVmClass(t, *c)), AddendumPool, PROTECT(t, signature);
addendumPool(t, fieldAddendum(t, vmField))); PROTECT(t, annotationTable);
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
set(t, runtimeData, ClassRuntimeDataPool,
addendumPool(t, methodAddendum(t, vmField)));
} }
object field = makeJfield object field = makeJfield
@ -2680,7 +2708,12 @@ EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c,
? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod)); ? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod));
if (annotationTable) { if (annotationTable) {
set(t, classAddendum(t, jclassVmClass(t, *c)), AddendumPool, PROTECT(t, signature);
PROTECT(t, annotationTable);
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
set(t, runtimeData, ClassRuntimeDataPool,
addendumPool(t, methodAddendum(t, vmMethod))); addendumPool(t, methodAddendum(t, vmMethod)));
} }
@ -2766,9 +2799,20 @@ EXPORT(JVM_GetClassConstantPool)(Thread* t, jclass c)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
return makeLocalReference object vmClass = jclassVmClass(t, *c);
(t, makeConstantPool object addendum = classAddendum(t, vmClass);
(t, addendumPool(t, classAddendum(t, jclassVmClass(t, *c))))); object pool;
if (addendum) {
pool = addendumPool(t, addendum);
} else {
pool = 0;
}
if (pool == 0) {
pool = classRuntimeDataPool(t, getClassRuntimeData(t, vmClass));
}
return makeLocalReference(t, makeConstantPool(t, pool));
} }
extern "C" JNIEXPORT jint JNICALL extern "C" JNIEXPORT jint JNICALL

View File

@ -2900,6 +2900,8 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function)
if (methodFlags(t, method) & ACC_SYNCHRONIZED) { if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
Compiler::Operand* lock; Compiler::Operand* lock;
if (methodFlags(t, method) & ACC_STATIC) { if (methodFlags(t, method) & ACC_STATIC) {
PROTECT(t, method);
lock = frame->append(methodClass(t, method)); lock = frame->append(methodClass(t, method));
} else { } else {
lock = loadLocal(frame->context, 1, savedTargetIndex(t, method)); lock = loadLocal(frame->context, 1, savedTargetIndex(t, method));
@ -3716,6 +3718,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
and (fieldCode(t, field) == DoubleField and (fieldCode(t, field) == DoubleField
or fieldCode(t, field) == LongField)) or fieldCode(t, field) == LongField))
{ {
PROTECT(t, field);
c->call c->call
(c->constant (c->constant
(getThunk(t, acquireMonitorForObjectThunk), Compiler::AddressType), (getThunk(t, acquireMonitorForObjectThunk), Compiler::AddressType),
@ -3729,6 +3733,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (instruction == getstatic) { if (instruction == getstatic) {
assert(t, fieldFlags(t, field) & ACC_STATIC); assert(t, fieldFlags(t, field) & ACC_STATIC);
PROTECT(t, field);
if (fieldClass(t, field) != methodClass(t, context->method) if (fieldClass(t, field) != methodClass(t, context->method)
and classNeedsInit(t, fieldClass(t, field))) and classNeedsInit(t, fieldClass(t, field)))
{ {
@ -4127,7 +4133,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
unsigned instance = parameterFootprint - 1; unsigned instance = parameterFootprint - 1;
unsigned rSize = resultSize(t, methodReturnCode(t, target)); int returnCode = methodReturnCode(t, target);
unsigned rSize = resultSize(t, returnCode);
Compiler::Operand* result = c->stackCall Compiler::Operand* result = c->stackCall
(c->call (c->call
@ -4143,13 +4151,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
0, 0,
frame->trace(0, 0), frame->trace(0, 0),
rSize, rSize,
operandTypeForFieldCode(t, methodReturnCode(t, target)), operandTypeForFieldCode(t, returnCode),
parameterFootprint); parameterFootprint);
frame->pop(parameterFootprint); frame->pop(parameterFootprint);
if (rSize) { if (rSize) {
pushReturnValue(t, frame, methodReturnCode(t, target), result); pushReturnValue(t, frame, returnCode, result);
} }
} break; } break;
@ -4385,12 +4393,20 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (singletonIsObject(t, pool, index - 1)) { if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1); object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v) == type(t, Machine::ReferenceType)) { if (objectClass(t, v) == type(t, Machine::ReferenceType)) {
object class_ = resolveClassInPool(t, context->method, index - 1); v = resolveClassInPool(t, context->method, index - 1);
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
}
frame->pushObject(frame->append(getJClass(t, class_))); if (objectClass(t, v) == type(t, Machine::ClassType)) {
} else if (objectClass(t, v) == type(t, Machine::ClassType)) { frame->pushObject
frame->pushObject(frame->append(getJClass(t, v))); (c->call
(c->constant
(getThunk(t, getJClassThunk), Compiler::AddressType),
0,
frame->trace(0, 0),
BytesPerWord,
Compiler::ObjectType,
2, c->register_(t->arch->thread()), frame->append(v)));
} else { } else {
frame->pushObject(frame->append(v)); frame->pushObject(frame->append(v));
} }
@ -4703,6 +4719,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (fieldClass(t, field) != methodClass(t, context->method) if (fieldClass(t, field) != methodClass(t, context->method)
and classNeedsInit(t, fieldClass(t, field))) and classNeedsInit(t, fieldClass(t, field)))
{ {
PROTECT(t, field);
c->call c->call
(c->constant (c->constant
(getThunk(t, tryInitClassThunk), Compiler::AddressType), (getThunk(t, tryInitClassThunk), Compiler::AddressType),
@ -4729,6 +4747,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
and (fieldCode(t, field) == DoubleField and (fieldCode(t, field) == DoubleField
or fieldCode(t, field) == LongField)) or fieldCode(t, field) == LongField))
{ {
PROTECT(t, field);
c->call c->call
(c->constant (c->constant
(getThunk(t, acquireMonitorForObjectThunk), (getThunk(t, acquireMonitorForObjectThunk),
@ -4766,6 +4786,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Compiler::Operand* table; Compiler::Operand* table;
if (instruction == putstatic) { if (instruction == putstatic) {
PROTECT(t, field);
table = frame->append(staticTable); table = frame->append(staticTable);
} else { } else {
table = frame->popObject(); table = frame->popObject();
@ -6308,7 +6330,7 @@ invokeNativeSlow(MyThread* t, object method, void* function)
uint64_t uint64_t
invokeNative2(MyThread* t, object method) invokeNative2(MyThread* t, object method)
{ {
object native = methodCode(t, method); object native = methodRuntimeDataNative(t, getMethodRuntimeData(t, method));
if (nativeFast(t, native)) { if (nativeFast(t, native)) {
return invokeNativeFast(t, method, nativeFunction(t, native)); return invokeNativeFast(t, method, nativeFunction(t, native));
} else { } else {
@ -7276,7 +7298,7 @@ class MyProcessor: public Processor {
return vm::makeMethod return vm::makeMethod
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags, (t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
offset, 0, name, spec, addendum, class_, code); offset, 0, 0, name, spec, addendum, class_, code);
} }
virtual object virtual object
@ -7301,8 +7323,9 @@ class MyProcessor: public Processor {
{ {
return vm::makeClass return vm::makeClass
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions, (t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
objectMask, name, sourceFile, super, interfaceTable, virtualTable, 0, objectMask, name, sourceFile, super, interfaceTable,
fieldTable, methodTable, staticTable, addendum, loader, vtableLength); virtualTable, fieldTable, methodTable, staticTable, addendum, loader,
vtableLength);
} }
virtual void virtual void
@ -7664,11 +7687,11 @@ class MyProcessor: public Processor {
codeAllocator.capacity = ExecutableAreaSizeInBytes; codeAllocator.capacity = ExecutableAreaSizeInBytes;
} }
roots = makeArray(t, RootCount);
if (image) { if (image) {
local::boot(static_cast<MyThread*>(t), image); local::boot(static_cast<MyThread*>(t), image);
} else { } else {
roots = makeArray(t, RootCount);
setRoot(t, CallTable, makeArray(t, 128)); setRoot(t, CallTable, makeArray(t, 128));
setRoot(t, MethodTreeSentinal, makeTreeNode(t, 0, 0, 0)); setRoot(t, MethodTreeSentinal, makeTreeNode(t, 0, 0, 0));
@ -8069,7 +8092,7 @@ fixupMethods(Thread* t, object map, BootImage* image, uint8_t* code)
if (classMethodTable(t, c)) { if (classMethodTable(t, c)) {
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) { for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object method = arrayBody(t, classMethodTable(t, c), i); object method = arrayBody(t, classMethodTable(t, c), i);
if (methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) { if (methodCode(t, method)) {
assert(t, (methodCompiled(t, method) - image->codeBase) assert(t, (methodCompiled(t, method) - image->codeBase)
<= image->codeSize); <= image->codeSize);
@ -8077,7 +8100,7 @@ fixupMethods(Thread* t, object map, BootImage* image, uint8_t* code)
= (methodCompiled(t, method) - image->codeBase) = (methodCompiled(t, method) - image->codeBase)
+ reinterpret_cast<uintptr_t>(code); + reinterpret_cast<uintptr_t>(code);
if (DebugCompile and (methodFlags(t, method) & ACC_NATIVE) == 0) { if (DebugCompile) {
logCompile logCompile
(static_cast<MyThread*>(t), (static_cast<MyThread*>(t),
reinterpret_cast<uint8_t*>(methodCompiled(t, method)), reinterpret_cast<uint8_t*>(methodCompiled(t, method)),
@ -8180,11 +8203,16 @@ boot(MyThread* t, BootImage* image)
t->m->heap->setImmortalHeap(heap, image->heapSize / BytesPerWord); t->m->heap->setImmortalHeap(heap, image->heapSize / BytesPerWord);
setRoot(t, Machine::BootLoader, bootObject(heap, image->bootLoader));
setRoot(t, Machine::AppLoader, bootObject(heap, image->appLoader));
t->m->types = bootObject(heap, image->types); t->m->types = bootObject(heap, image->types);
t->m->roots = makeArray(t, Machine::RootCount);
setRoot(t, Machine::BootLoader, bootObject(heap, image->bootLoader));
setRoot(t, Machine::AppLoader, bootObject(heap, image->appLoader));
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor); MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
p->roots = makeArray(t, RootCount);
setRoot(t, MethodTree, bootObject(heap, image->methodTree)); setRoot(t, MethodTree, bootObject(heap, image->methodTree));
setRoot(t, MethodTreeSentinal, bootObject(heap, image->methodTreeSentinal)); setRoot(t, MethodTreeSentinal, bootObject(heap, image->methodTreeSentinal));
@ -8195,11 +8223,17 @@ boot(MyThread* t, BootImage* image)
syncInstructionCache(code, image->codeSize); syncInstructionCache(code, image->codeSize);
set(t, root(t, Machine::BootLoader), ClassLoaderMap, makeClassMap { object map = makeClassMap(t, bootClassTable, image->bootClassCount, heap);
(t, bootClassTable, image->bootClassCount, heap)); set(t, root(t, Machine::BootLoader), ClassLoaderMap, map);
}
set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap systemClassLoaderFinder(t, root(t, Machine::BootLoader)) = t->m->bootFinder;
(t, appClassTable, image->appClassCount, heap));
{ object map = makeClassMap(t, appClassTable, image->appClassCount, heap);
set(t, root(t, Machine::AppLoader), ClassLoaderMap, map);
}
systemClassLoaderFinder(t, root(t, Machine::AppLoader)) = t->m->appFinder;
setRoot(t, Machine::StringMap, makeStringMap setRoot(t, Machine::StringMap, makeStringMap
(t, stringTable, image->stringCount, heap)); (t, stringTable, image->stringCount, heap));

View File

@ -656,7 +656,7 @@ invokeNative(Thread* t, object method)
return VoidField; return VoidField;
} }
object native = methodCode(t, method); object native = methodRuntimeDataNative(t, getMethodRuntimeData(t, method));
if (nativeFast(t, native)) { if (nativeFast(t, native)) {
pushFrame(t, method); pushFrame(t, method);
@ -3045,7 +3045,7 @@ class MyProcessor: public Processor {
{ {
return vm::makeMethod return vm::makeMethod
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags, (t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
offset, 0, name, spec, addendum, class_, code); offset, 0, 0, name, spec, addendum, class_, code);
} }
virtual object virtual object
@ -3069,7 +3069,7 @@ class MyProcessor: public Processor {
unsigned vtableLength UNUSED) unsigned vtableLength UNUSED)
{ {
return vm::makeClass return vm::makeClass
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions, (t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions, 0,
objectMask, name, sourceFile, super, interfaceTable, virtualTable, objectMask, name, sourceFile, super, interfaceTable, virtualTable,
fieldTable, methodTable, addendum, staticTable, loader, 0); fieldTable, methodTable, addendum, staticTable, loader, 0);
} }

View File

@ -430,7 +430,8 @@ methodID(Thread* t, object method)
if (methodNativeID(t, method) == 0) { if (methodNativeID(t, method) == 0) {
setRoot(t, Machine::JNIMethodTable, vectorAppend setRoot(t, Machine::JNIMethodTable, vectorAppend
(t, root(t, Machine::JNIMethodTable), method)); (t, root(t, Machine::JNIMethodTable), method));
methodNativeID(t, method) = vectorSize(t, root(t, Machine::JNIMethodTable)); methodNativeID(t, method) = vectorSize
(t, root(t, Machine::JNIMethodTable));
} }
} }
@ -2036,6 +2037,27 @@ append(char** p, const char* value, unsigned length, char tail)
} }
} }
void
boot(Thread* t)
{
enter(t, Thread::ActiveState);
if (t->exception == 0) {
setRoot(t, Machine::NullPointerException, t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType));
if (t->exception == 0) {
setRoot(t, Machine::ArrayIndexOutOfBoundsException,
t->m->classpath->makeThrowable
(t, Machine::ArrayIndexOutOfBoundsExceptionType));
}
}
t->m->classpath->boot(t);
enter(t, Thread::IdleState);
}
} // namespace local } // namespace local
} // namespace } // namespace
@ -2349,5 +2371,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
*t = p->makeThread(*m, 0, 0); *t = p->makeThread(*m, 0, 0);
local::boot(*t);
return 0; return 0;
} }

View File

@ -1314,6 +1314,7 @@ addInterfaceMethods(Thread* t, object class_, object virtualMap,
methodFlags(t, method), methodFlags(t, method),
(*virtualCount)++, (*virtualCount)++,
0, 0,
0,
methodName(t, method), methodName(t, method),
methodSpec(t, method), methodSpec(t, method),
0, 0,
@ -1650,7 +1651,7 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
object body = makeByteArray(t, length); object body = makeByteArray(t, length);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), length); s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), length);
object addendum = makeClassAddendum(t, pool, body, 0, 0, 0); object addendum = makeClassAddendum(t, pool, body);
set(t, class_, ClassAddendum, addendum); set(t, class_, ClassAddendum, addendum);
} else { } else {
@ -1839,21 +1840,11 @@ resolveArrayClass(Thread* t, object loader, object spec, bool throw_)
object object
resolveObjectArrayClass(Thread* t, object loader, object elementClass) resolveObjectArrayClass(Thread* t, object loader, object elementClass)
{ {
object addendum = classAddendum(t, elementClass); { object arrayClass = classRuntimeDataArrayClass
if (addendum) { (t, getClassRuntimeData(t, elementClass));
object arrayClass = classAddendumArrayClass(t, addendum);
if (arrayClass) { if (arrayClass) {
return arrayClass; return arrayClass;
} }
} else {
PROTECT(t, loader);
PROTECT(t, elementClass);
ACQUIRE(t, t->m->classLock);
object addendum = makeClassAddendum(t, 0, 0, 0, 0, 0);
set(t, elementClass, ClassAddendum, addendum);
} }
PROTECT(t, loader); PROTECT(t, loader);
@ -1882,7 +1873,7 @@ resolveObjectArrayClass(Thread* t, object loader, object elementClass)
object arrayClass = resolveClass(t, loader, spec); object arrayClass = resolveClass(t, loader, spec);
set(t, classAddendum(t, elementClass), ClassAddendumArrayClass, set(t, getClassRuntimeData(t, elementClass), ClassRuntimeDataArrayClass,
arrayClass); arrayClass);
return arrayClass; return arrayClass;
@ -2104,7 +2095,7 @@ boot(Thread* t)
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1); { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1);
codeBody(t, bootCode, 0) = impdep1; codeBody(t, bootCode, 0) = impdep1;
object bootMethod = makeMethod object bootMethod = makeMethod
(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode); (t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode);
PROTECT(t, bootMethod); PROTECT(t, bootMethod);
#include "type-java-initializations.cpp" #include "type-java-initializations.cpp"
@ -2349,6 +2340,8 @@ Thread::init()
m->unsafe = false; m->unsafe = false;
enter(this, ActiveState);
if (image) { if (image) {
m->processor->boot(this, image); m->processor->boot(this, image);
} else { } else {
@ -2358,6 +2351,8 @@ Thread::init()
setRoot(this, Machine::ByteArrayMap, makeWeakHashMap(this, 0, 0)); setRoot(this, Machine::ByteArrayMap, makeWeakHashMap(this, 0, 0));
setRoot(this, Machine::MonitorMap, makeWeakHashMap(this, 0, 0)); setRoot(this, Machine::MonitorMap, makeWeakHashMap(this, 0, 0));
setRoot(this, Machine::ClassRuntimeDataTable, makeVector(this, 0, 0));
setRoot(this, Machine::MethodRuntimeDataTable, makeVector(this, 0, 0));
setRoot(this, Machine::JNIMethodTable, makeVector(this, 0, 0)); setRoot(this, Machine::JNIMethodTable, makeVector(this, 0, 0));
m->localThread->set(this); m->localThread->set(this);
@ -2373,25 +2368,6 @@ Thread::init()
} }
threadPeer(this, javaThread) = reinterpret_cast<jlong>(this); threadPeer(this, javaThread) = reinterpret_cast<jlong>(this);
if (parent == 0) {
enter(this, Thread::ActiveState);
if (exception == 0) {
setRoot(this, Machine::NullPointerException, m->classpath->makeThrowable
(this, Machine::NullPointerExceptionType));
if (exception == 0) {
setRoot(this, Machine::ArrayIndexOutOfBoundsException,
m->classpath->makeThrowable
(this, Machine::ArrayIndexOutOfBoundsExceptionType));
}
}
m->classpath->boot(this);
enter(this, Thread::IdleState);
}
} }
void void
@ -3151,6 +3127,7 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
0, // fixed size 0, // fixed size
0, // array size 0, // array size
0, // array dimensions 0, // array dimensions
0, // runtime data index
0, // object mask 0, // object mask
referenceName referenceName
(t, singletonObject(t, pool, name - 1)), (t, singletonObject(t, pool, name - 1)),

View File

@ -1194,6 +1194,8 @@ class Machine {
MonitorMap, MonitorMap,
StringMap, StringMap,
ByteArrayMap, ByteArrayMap,
ClassRuntimeDataTable,
MethodRuntimeDataTable,
JNIMethodTable, JNIMethodTable,
ShutdownHooks, ShutdownHooks,
ObjectsToFinalize, ObjectsToFinalize,
@ -3056,28 +3058,70 @@ resolveMethod(Thread* t, object method, unsigned index)
(t, classLoader(t, methodClass(t, method)), method, index); (t, classLoader(t, methodClass(t, method)), method, index);
} }
object
vectorAppend(Thread*, object, object);
inline object inline object
getJClass(Thread* t, object c) getClassRuntimeData(Thread* t, object c)
{ {
if (classAddendum(t, c) == 0) { if (classRuntimeDataIndex(t, c) == 0) {
PROTECT(t, c); PROTECT(t, c);
ACQUIRE(t, t->m->classLock); ACQUIRE(t, t->m->classLock);
object addendum = makeClassAddendum(t, 0, 0, 0, 0, 0); if (classRuntimeDataIndex(t, c) == 0) {
object runtimeData = makeClassRuntimeData(t, 0, 0, 0);
set(t, c, ClassAddendum, addendum);
setRoot(t, Machine::ClassRuntimeDataTable, vectorAppend
(t, root(t, Machine::ClassRuntimeDataTable), runtimeData));
classRuntimeDataIndex(t, c) = vectorSize
(t, root(t, Machine::ClassRuntimeDataTable));
}
} }
object jclass = classAddendumClass(t, classAddendum(t, c)); return vectorBody(t, root(t, Machine::ClassRuntimeDataTable),
classRuntimeDataIndex(t, c) - 1);
}
inline object
getMethodRuntimeData(Thread* t, object method)
{
if (methodRuntimeDataIndex(t, method) == 0) {
PROTECT(t, method);
ACQUIRE(t, t->m->classLock);
if (methodRuntimeDataIndex(t, method) == 0) {
object runtimeData = makeMethodRuntimeData(t, 0);
setRoot(t, Machine::MethodRuntimeDataTable, vectorAppend
(t, root(t, Machine::MethodRuntimeDataTable), runtimeData));
methodRuntimeDataIndex(t, method) = vectorSize
(t, root(t, Machine::MethodRuntimeDataTable));
}
}
return vectorBody(t, root(t, Machine::MethodRuntimeDataTable),
methodRuntimeDataIndex(t, method) - 1);
}
inline object
getJClass(Thread* t, object c)
{
object jclass = classRuntimeDataJclass(t, getClassRuntimeData(t, c));
if (jclass == 0) { if (jclass == 0) {
PROTECT(t, c); PROTECT(t, c);
ACQUIRE(t, t->m->classLock); ACQUIRE(t, t->m->classLock);
jclass = t->m->classpath->makeJclass(t, c); jclass = classRuntimeDataJclass(t, getClassRuntimeData(t, c));
if (jclass == 0) {
jclass = t->m->classpath->makeJclass(t, c);
set(t, classAddendum(t, c), ClassAddendumClass, jclass); set(t, getClassRuntimeData(t, c), ClassRuntimeDataJclass, jclass);
}
} }
return jclass; return jclass;
@ -3111,12 +3155,15 @@ registerNative(Thread* t, object method, void* function)
expect(t, methodFlags(t, method) & ACC_NATIVE); expect(t, methodFlags(t, method) & ACC_NATIVE);
object native = makeNative(t, function, false); object native = makeNative(t, function, false);
PROTECT(t, native);
// ensure other threads only see the methodCode field populated object runtimeData = getMethodRuntimeData(t, method);
// once the object it points to has been populated:
// ensure other threads only see the methodRuntimeDataNative field
// populated once the object it points to has been populated:
storeStoreMemoryBarrier(); storeStoreMemoryBarrier();
set(t, method, MethodCode, native); set(t, runtimeData, MethodRuntimeDataNative, native);
} }
inline void inline void
@ -3126,7 +3173,7 @@ unregisterNatives(Thread* t, object c)
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) { for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object method = arrayBody(t, classMethodTable(t, c), i); object method = arrayBody(t, classMethodTable(t, c), i);
if (methodFlags(t, method) & ACC_NATIVE) { if (methodFlags(t, method) & ACC_NATIVE) {
set(t, method, MethodCode, 0); set(t, getMethodRuntimeData(t, method), MethodRuntimeDataNative, 0);
} }
} }
} }
@ -3152,6 +3199,7 @@ methodClone(Thread* t, object method)
methodFlags(t, method), methodFlags(t, method),
methodOffset(t, method), methodOffset(t, method),
methodNativeID(t, method), methodNativeID(t, method),
methodRuntimeDataIndex(t, method),
methodName(t, method), methodName(t, method),
methodSpec(t, method), methodSpec(t, method),
methodAddendum(t, method), methodAddendum(t, method),

View File

@ -232,7 +232,9 @@ resolveNative(Thread* t, object method)
initClass(t, methodClass(t, method)); initClass(t, methodClass(t, method));
if (LIKELY(t->exception == 0) and methodCode(t, method) == 0) { if (LIKELY(t->exception == 0)
and methodRuntimeDataNative(t, getMethodRuntimeData(t, method)) == 0)
{
object native = resolveNativeMethod(t, method); object native = resolveNativeMethod(t, method);
if (UNLIKELY(native == 0)) { if (UNLIKELY(native == 0)) {
object message = makeString object message = makeString
@ -246,11 +248,15 @@ resolveNative(Thread* t, object method)
return; return;
} }
// ensure other threads only see the methodCode field populated PROTECT(t, native);
// once the object it points do has been populated:
object runtimeData = getMethodRuntimeData(t, method);
// ensure other threads only see the methodRuntimeDataNative field
// populated once the object it points to has been populated:
storeStoreMemoryBarrier(); storeStoreMemoryBarrier();
set(t, method, MethodCode, native); set(t, runtimeData, MethodRuntimeDataNative, native);
} }
} }

View File

@ -48,4 +48,5 @@ THUNK(instanceOf64)
THUNK(makeNewGeneral64) THUNK(makeNewGeneral64)
THUNK(makeNew64) THUNK(makeNew64)
THUNK(set) THUNK(set)
THUNK(getJClass)
THUNK(gcIfNecessary) THUNK(gcIfNecessary)

View File

@ -37,6 +37,14 @@
(type fieldAddendum avian/FieldAddendum) (type fieldAddendum avian/FieldAddendum)
(type classRuntimeData
(object arrayClass)
(object jclass)
(object pool))
(type methodRuntimeData
(object native))
(type pointer (type pointer
(void* value)) (void* value))