mirror of
https://github.com/corda/corda.git
synced 2025-01-01 02:36:44 +00:00
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:
parent
4f23601b56
commit
459f4d5194
@ -10,8 +10,4 @@
|
||||
|
||||
package avian;
|
||||
|
||||
public class ClassAddendum extends Addendum {
|
||||
public volatile Class class_;
|
||||
public Object[] signers;
|
||||
public volatile Class arrayClass;
|
||||
}
|
||||
public class ClassAddendum extends Addendum { }
|
||||
|
@ -16,6 +16,7 @@ public class VMClass {
|
||||
public short fixedSize;
|
||||
public byte arrayElementSize;
|
||||
public byte arrayDimensions;
|
||||
public int runtimeDataIndex;
|
||||
public int[] objectMask;
|
||||
public byte[] name;
|
||||
public byte[] sourceFile;
|
||||
@ -24,7 +25,7 @@ public class VMClass {
|
||||
public VMMethod[] virtualTable;
|
||||
public VMField[] fieldTable;
|
||||
public VMMethod[] methodTable;
|
||||
public volatile avian.ClassAddendum addendum;
|
||||
public avian.ClassAddendum addendum;
|
||||
public Object staticTable;
|
||||
public ClassLoader loader;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ public class VMMethod {
|
||||
public short flags;
|
||||
public short offset;
|
||||
public int nativeID;
|
||||
public int runtimeDataIndex;
|
||||
public byte[] name;
|
||||
public byte[] spec;
|
||||
public MethodAddendum addendum;
|
||||
|
@ -572,10 +572,6 @@ public final class Class <T> implements Type, AnnotatedElement {
|
||||
return (T) o;
|
||||
}
|
||||
|
||||
public Object[] getSigners() {
|
||||
return vmClass.addendum.signers;
|
||||
}
|
||||
|
||||
public Package getPackage() {
|
||||
if ((vmClass.vmFlags & PrimitiveFlag) != 0 || isArray()) {
|
||||
return null;
|
||||
|
16
makefile
16
makefile
@ -72,13 +72,13 @@ ifeq ($(build-platform),darwin)
|
||||
library-path-variable = DYLD_LIBRARY_PATH
|
||||
endif
|
||||
|
||||
ifdef openjdk
|
||||
ifneq ($(openjdk),)
|
||||
openjdk-arch = $(arch)
|
||||
ifeq ($(arch),x86_64)
|
||||
openjdk-arch = amd64
|
||||
endif
|
||||
|
||||
ifdef openjdk-src
|
||||
ifneq ($(openjdk-src),)
|
||||
include openjdk-src.mk
|
||||
options := $(options)-openjdk-src
|
||||
classpath-objects = $(openjdk-objects)
|
||||
@ -436,8 +436,7 @@ endif
|
||||
bootimage-generator-sources = $(src)/bootimage.cpp
|
||||
bootimage-generator-objects = \
|
||||
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(build))
|
||||
bootimage-generator = \
|
||||
$(build)/$(bootimage-platform)-$(build-arch)$(options)/bootimage-generator
|
||||
bootimage-generator = $(build)/bootimage-generator
|
||||
|
||||
bootimage-bin = $(build)/bootimage.bin
|
||||
bootimage-object = $(build)/bootimage-bin.o
|
||||
@ -454,10 +453,11 @@ $(error "bootimage cross-builds not yet supported")
|
||||
endif
|
||||
|
||||
vm-classpath-object = $(bootimage-object)
|
||||
cflags += -DBOOT_IMAGE=\"bootimageBin\"
|
||||
cflags += -DBOOT_IMAGE=\"bootimageBin\" -DAVIAN_CLASSPATH=\"\"
|
||||
else
|
||||
vm-classpath-object = $(classpath-object)
|
||||
cflags += -DBOOT_CLASSPATH=\"[classpathJar]\"
|
||||
cflags += -DBOOT_CLASSPATH=\"[classpathJar]\" \
|
||||
-DAVIAN_CLASSPATH=\"[classpathJar]\"
|
||||
endif
|
||||
|
||||
driver-source = $(src)/main.cpp
|
||||
@ -509,7 +509,7 @@ ifneq ($(classpath),avian)
|
||||
$(classpath-src)/avian/VMMethod.java \
|
||||
$(classpath-src)/avian/resource/Handler.java
|
||||
|
||||
ifdef openjdk
|
||||
ifneq ($(openjdk),)
|
||||
classpath-sources := $(classpath-sources) \
|
||||
$(classpath-src)/avian/OpenJDK.java
|
||||
endif
|
||||
@ -759,6 +759,8 @@ $(bootimage-generator):
|
||||
$(MAKE) mode=$(mode) \
|
||||
arch=$(build-arch) \
|
||||
platform=$(bootimage-platform) \
|
||||
openjdk=$(openjdk) \
|
||||
openjdk-src=$(openjdk-src) \
|
||||
bootimage-generator= \
|
||||
build-bootimage-generator=$(bootimage-generator) \
|
||||
$(bootimage-generator)
|
||||
|
@ -23,6 +23,38 @@ using namespace vm;
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
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;
|
||||
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);
|
||||
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;
|
||||
|
||||
@ -62,21 +99,53 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
if (classMethodTable(t, c)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||
object method = arrayBody(t, classMethodTable(t, c), i);
|
||||
if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE))
|
||||
and ((methodName == 0
|
||||
if (((methodName == 0
|
||||
or ::strcmp
|
||||
(reinterpret_cast<char*>
|
||||
(&byteArrayBody
|
||||
(t, vm::methodName(t, method), 0)), methodName) == 0)
|
||||
and (methodSpec == 0
|
||||
or ::strcmp
|
||||
(reinterpret_cast<char*>
|
||||
(&byteArrayBody
|
||||
(t, vm::methodName(t, method), 0)), methodName) == 0)
|
||||
and (methodSpec == 0
|
||||
or ::strcmp
|
||||
(reinterpret_cast<char*>
|
||||
(&byteArrayBody
|
||||
(t, vm::methodSpec(t, method), 0)), methodSpec)
|
||||
== 0)))
|
||||
(t, vm::methodSpec(t, method), 0)), methodSpec)
|
||||
== 0)))
|
||||
{
|
||||
t->m->processor->compileMethod
|
||||
(t, zone, &constants, &calls, &addresses, method);
|
||||
if (methodCode(t, 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) {
|
||||
address = reinterpret_cast<uintptr_t>(code + image->thunks.native.start);
|
||||
} else {
|
||||
address = methodCompiled(t, method);
|
||||
address = codeCompiled(t, methodCode(t, method));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
m->processor->visitRoots(w);
|
||||
m->processor->visitRoots(t, w);
|
||||
|
||||
for (; constants; constants = tripleThird(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 number;
|
||||
if (currentObject
|
||||
and (currentOffset * BytesPerWord) == ClassStaticTable)
|
||||
if ((currentObject
|
||||
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
|
||||
(t->m->system, reinterpret_cast<uint8_t*>(heap + position),
|
||||
(capacity - position) * BytesPerWord);
|
||||
@ -296,40 +376,90 @@ writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
|
||||
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*>
|
||||
(t->m->heap->allocate(HeapCapacity));
|
||||
uintptr_t* heapMap = static_cast<uintptr_t*>
|
||||
(t->m->heap->allocate(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
|
||||
(t, image, heap, heapMap, HeapCapacity, constants);
|
||||
|
||||
updateConstants(t, constants, code, codeMap, heapWalker->map());
|
||||
|
||||
image->classCount = hashMapSize(t, t->m->classMap);
|
||||
unsigned* classTable = static_cast<unsigned*>
|
||||
(t->m->heap->allocate(image->classCount * sizeof(unsigned)));
|
||||
image->bootClassCount = hashMapSize
|
||||
(t, classLoaderMap(t, root(t, Machine::BootLoader)));
|
||||
|
||||
unsigned* bootClassTable = static_cast<unsigned*>
|
||||
(t->m->heap->allocate(image->bootClassCount * sizeof(unsigned)));
|
||||
|
||||
{ unsigned i = 0;
|
||||
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
|
||||
classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
|
||||
for (HashMapIterator it
|
||||
(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*>
|
||||
(t->m->heap->allocate(image->stringCount * sizeof(unsigned)));
|
||||
|
||||
{ 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
|
||||
(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"
|
||||
"heap size %d code size %d\n",
|
||||
image->classCount, image->stringCount, image->callCount,
|
||||
image->bootClassCount, image->stringCount, image->callCount,
|
||||
image->heapSize, image->codeSize);
|
||||
|
||||
if (true) {
|
||||
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(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->callCount * sizeof(unsigned) * 2);
|
||||
|
||||
@ -384,16 +516,18 @@ main(int ac, const char** av)
|
||||
}
|
||||
|
||||
System* s = makeSystem(0);
|
||||
Heap* h = makeHeap(s, 128 * 1024 * 1024);
|
||||
Finder* f = makeFinder(s, av[1], 0);
|
||||
Heap* h = makeHeap(s, HeapCapacity * 2);
|
||||
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);
|
||||
|
||||
BootImage image;
|
||||
const unsigned CodeCapacity = 16 * 1024 * 1024;
|
||||
const unsigned CodeCapacity = 128 * 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, 0, p, c, 0, 0);
|
||||
Thread* t = p->makeThread(m, 0, 0);
|
||||
|
||||
enter(t, Thread::ActiveState);
|
||||
|
@ -95,7 +95,7 @@ class MyClasspath : public Classpath {
|
||||
virtual const char*
|
||||
bootClasspath()
|
||||
{
|
||||
return BOOT_CLASSPATH;
|
||||
return AVIAN_CLASSPATH;
|
||||
}
|
||||
|
||||
virtual void
|
||||
|
@ -209,7 +209,7 @@ class MyClasspath : public Classpath {
|
||||
sb.append('\0');
|
||||
|
||||
this->classpath = sb.pointer;
|
||||
sb.append(BOOT_CLASSPATH);
|
||||
sb.append(AVIAN_CLASSPATH);
|
||||
sb.append(s->pathSeparator());
|
||||
sb.append(javaHome);
|
||||
sb.append("/lib/rt.jar");
|
||||
@ -590,7 +590,8 @@ getFileAttributes
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
|
||||
return (r ? intValue(t, r) : 0);
|
||||
@ -631,7 +632,8 @@ getLength
|
||||
return 0;
|
||||
} else {
|
||||
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);
|
||||
|
||||
return (r ? longValue(t, r) : 0);
|
||||
@ -703,7 +705,9 @@ openFile(Thread* t, object method, uintptr_t* arguments)
|
||||
= index + VirtualFileBase;
|
||||
} else {
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
@ -793,8 +799,9 @@ readBytesFromFile(Thread* t, object method, uintptr_t* arguments)
|
||||
}
|
||||
} else {
|
||||
object r = t->m->processor->invoke
|
||||
(t, nativeInterceptOriginal(t, methodCode(t, method)), this_, dst,
|
||||
offset, length);
|
||||
(t, nativeInterceptOriginal
|
||||
(t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))),
|
||||
this_, dst, offset, length);
|
||||
|
||||
return r ? intValue(t, r) : 0;
|
||||
}
|
||||
@ -837,7 +844,9 @@ skipBytesInFile(Thread* t, object method, uintptr_t* arguments)
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
@ -870,7 +879,9 @@ availableBytesInFile(Thread* t, object method, uintptr_t* arguments)
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
@ -901,7 +912,9 @@ closeFile(Thread* t, object method, uintptr_t* arguments)
|
||||
0);
|
||||
} else {
|
||||
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);
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2470,8 +2487,9 @@ EXPORT(JVM_GetClassAnnotations)(Thread* t, jclass c)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return makeLocalReference
|
||||
(t, addendumAnnotationTable(t, classAddendum(t, jclassVmClass(t, *c))));
|
||||
object addendum = classAddendum(t, jclassVmClass(t, *c));
|
||||
return addendum
|
||||
? makeLocalReference(t, addendumAnnotationTable(t, addendum)) : 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobjectArray JNICALL
|
||||
@ -2537,7 +2555,12 @@ EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly)
|
||||
? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod));
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
@ -2607,8 +2630,13 @@ EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly)
|
||||
? 0 : addendumAnnotationTable(t, fieldAddendum(t, vmField));
|
||||
|
||||
if (annotationTable) {
|
||||
set(t, classAddendum(t, jclassVmClass(t, *c)), AddendumPool,
|
||||
addendumPool(t, fieldAddendum(t, vmField)));
|
||||
PROTECT(t, signature);
|
||||
PROTECT(t, annotationTable);
|
||||
|
||||
object runtimeData = getClassRuntimeData(t, jclassVmClass(t, *c));
|
||||
|
||||
set(t, runtimeData, ClassRuntimeDataPool,
|
||||
addendumPool(t, methodAddendum(t, vmField)));
|
||||
}
|
||||
|
||||
object field = makeJfield
|
||||
@ -2680,7 +2708,12 @@ EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c,
|
||||
? 0 : addendumAnnotationTable(t, methodAddendum(t, vmMethod));
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
@ -2766,9 +2799,20 @@ EXPORT(JVM_GetClassConstantPool)(Thread* t, jclass c)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return makeLocalReference
|
||||
(t, makeConstantPool
|
||||
(t, addendumPool(t, classAddendum(t, jclassVmClass(t, *c)))));
|
||||
object vmClass = jclassVmClass(t, *c);
|
||||
object addendum = classAddendum(t, vmClass);
|
||||
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
|
||||
|
@ -2900,6 +2900,8 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function)
|
||||
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
||||
Compiler::Operand* lock;
|
||||
if (methodFlags(t, method) & ACC_STATIC) {
|
||||
PROTECT(t, method);
|
||||
|
||||
lock = frame->append(methodClass(t, method));
|
||||
} else {
|
||||
lock = loadLocal(frame->context, 1, savedTargetIndex(t, method));
|
||||
@ -3716,6 +3718,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
and (fieldCode(t, field) == DoubleField
|
||||
or fieldCode(t, field) == LongField))
|
||||
{
|
||||
PROTECT(t, field);
|
||||
|
||||
c->call
|
||||
(c->constant
|
||||
(getThunk(t, acquireMonitorForObjectThunk), Compiler::AddressType),
|
||||
@ -3729,6 +3733,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
if (instruction == getstatic) {
|
||||
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
||||
|
||||
PROTECT(t, field);
|
||||
|
||||
if (fieldClass(t, field) != methodClass(t, context->method)
|
||||
and classNeedsInit(t, fieldClass(t, field)))
|
||||
{
|
||||
@ -4127,7 +4133,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
|
||||
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
|
||||
(c->call
|
||||
@ -4143,13 +4151,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
0,
|
||||
frame->trace(0, 0),
|
||||
rSize,
|
||||
operandTypeForFieldCode(t, methodReturnCode(t, target)),
|
||||
operandTypeForFieldCode(t, returnCode),
|
||||
parameterFootprint);
|
||||
|
||||
frame->pop(parameterFootprint);
|
||||
|
||||
if (rSize) {
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
||||
pushReturnValue(t, frame, returnCode, result);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -4385,12 +4393,20 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
if (singletonIsObject(t, pool, index - 1)) {
|
||||
object v = singletonObject(t, pool, index - 1);
|
||||
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;
|
||||
}
|
||||
|
||||
frame->pushObject(frame->append(getJClass(t, class_)));
|
||||
} else if (objectClass(t, v) == type(t, Machine::ClassType)) {
|
||||
frame->pushObject(frame->append(getJClass(t, v)));
|
||||
if (objectClass(t, v) == type(t, Machine::ClassType)) {
|
||||
frame->pushObject
|
||||
(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 {
|
||||
frame->pushObject(frame->append(v));
|
||||
}
|
||||
@ -4703,6 +4719,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
if (fieldClass(t, field) != methodClass(t, context->method)
|
||||
and classNeedsInit(t, fieldClass(t, field)))
|
||||
{
|
||||
PROTECT(t, field);
|
||||
|
||||
c->call
|
||||
(c->constant
|
||||
(getThunk(t, tryInitClassThunk), Compiler::AddressType),
|
||||
@ -4729,6 +4747,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
and (fieldCode(t, field) == DoubleField
|
||||
or fieldCode(t, field) == LongField))
|
||||
{
|
||||
PROTECT(t, field);
|
||||
|
||||
c->call
|
||||
(c->constant
|
||||
(getThunk(t, acquireMonitorForObjectThunk),
|
||||
@ -4766,6 +4786,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
Compiler::Operand* table;
|
||||
|
||||
if (instruction == putstatic) {
|
||||
PROTECT(t, field);
|
||||
|
||||
table = frame->append(staticTable);
|
||||
} else {
|
||||
table = frame->popObject();
|
||||
@ -6308,7 +6330,7 @@ invokeNativeSlow(MyThread* t, object method, void* function)
|
||||
uint64_t
|
||||
invokeNative2(MyThread* t, object method)
|
||||
{
|
||||
object native = methodCode(t, method);
|
||||
object native = methodRuntimeDataNative(t, getMethodRuntimeData(t, method));
|
||||
if (nativeFast(t, native)) {
|
||||
return invokeNativeFast(t, method, nativeFunction(t, native));
|
||||
} else {
|
||||
@ -7276,7 +7298,7 @@ class MyProcessor: public Processor {
|
||||
|
||||
return vm::makeMethod
|
||||
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
|
||||
offset, 0, name, spec, addendum, class_, code);
|
||||
offset, 0, 0, name, spec, addendum, class_, code);
|
||||
}
|
||||
|
||||
virtual object
|
||||
@ -7301,8 +7323,9 @@ class MyProcessor: public Processor {
|
||||
{
|
||||
return vm::makeClass
|
||||
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
|
||||
objectMask, name, sourceFile, super, interfaceTable, virtualTable,
|
||||
fieldTable, methodTable, staticTable, addendum, loader, vtableLength);
|
||||
0, objectMask, name, sourceFile, super, interfaceTable,
|
||||
virtualTable, fieldTable, methodTable, staticTable, addendum, loader,
|
||||
vtableLength);
|
||||
}
|
||||
|
||||
virtual void
|
||||
@ -7664,11 +7687,11 @@ class MyProcessor: public Processor {
|
||||
codeAllocator.capacity = ExecutableAreaSizeInBytes;
|
||||
}
|
||||
|
||||
roots = makeArray(t, RootCount);
|
||||
|
||||
if (image) {
|
||||
local::boot(static_cast<MyThread*>(t), image);
|
||||
} else {
|
||||
roots = makeArray(t, RootCount);
|
||||
|
||||
setRoot(t, CallTable, makeArray(t, 128));
|
||||
|
||||
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)) {
|
||||
for (unsigned i = 0; i < arrayLength(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)
|
||||
<= image->codeSize);
|
||||
|
||||
@ -8077,7 +8100,7 @@ fixupMethods(Thread* t, object map, BootImage* image, uint8_t* code)
|
||||
= (methodCompiled(t, method) - image->codeBase)
|
||||
+ reinterpret_cast<uintptr_t>(code);
|
||||
|
||||
if (DebugCompile and (methodFlags(t, method) & ACC_NATIVE) == 0) {
|
||||
if (DebugCompile) {
|
||||
logCompile
|
||||
(static_cast<MyThread*>(t),
|
||||
reinterpret_cast<uint8_t*>(methodCompiled(t, method)),
|
||||
@ -8180,11 +8203,16 @@ boot(MyThread* t, BootImage* image)
|
||||
|
||||
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->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);
|
||||
|
||||
p->roots = makeArray(t, RootCount);
|
||||
|
||||
setRoot(t, MethodTree, bootObject(heap, image->methodTree));
|
||||
setRoot(t, MethodTreeSentinal, bootObject(heap, image->methodTreeSentinal));
|
||||
@ -8195,11 +8223,17 @@ boot(MyThread* t, BootImage* image)
|
||||
|
||||
syncInstructionCache(code, image->codeSize);
|
||||
|
||||
set(t, root(t, Machine::BootLoader), ClassLoaderMap, makeClassMap
|
||||
(t, bootClassTable, image->bootClassCount, heap));
|
||||
{ object map = makeClassMap(t, bootClassTable, image->bootClassCount, heap);
|
||||
set(t, root(t, Machine::BootLoader), ClassLoaderMap, map);
|
||||
}
|
||||
|
||||
set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap
|
||||
(t, appClassTable, image->appClassCount, heap));
|
||||
systemClassLoaderFinder(t, root(t, Machine::BootLoader)) = t->m->bootFinder;
|
||||
|
||||
{ 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
|
||||
(t, stringTable, image->stringCount, heap));
|
||||
|
@ -656,7 +656,7 @@ invokeNative(Thread* t, object method)
|
||||
return VoidField;
|
||||
}
|
||||
|
||||
object native = methodCode(t, method);
|
||||
object native = methodRuntimeDataNative(t, getMethodRuntimeData(t, method));
|
||||
if (nativeFast(t, native)) {
|
||||
pushFrame(t, method);
|
||||
|
||||
@ -3045,7 +3045,7 @@ class MyProcessor: public Processor {
|
||||
{
|
||||
return vm::makeMethod
|
||||
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
|
||||
offset, 0, name, spec, addendum, class_, code);
|
||||
offset, 0, 0, name, spec, addendum, class_, code);
|
||||
}
|
||||
|
||||
virtual object
|
||||
@ -3069,7 +3069,7 @@ class MyProcessor: public Processor {
|
||||
unsigned vtableLength UNUSED)
|
||||
{
|
||||
return vm::makeClass
|
||||
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions,
|
||||
(t, flags, vmFlags, fixedSize, arrayElementSize, arrayDimensions, 0,
|
||||
objectMask, name, sourceFile, super, interfaceTable, virtualTable,
|
||||
fieldTable, methodTable, addendum, staticTable, loader, 0);
|
||||
}
|
||||
|
@ -430,7 +430,8 @@ methodID(Thread* t, object method)
|
||||
if (methodNativeID(t, method) == 0) {
|
||||
setRoot(t, Machine::JNIMethodTable, vectorAppend
|
||||
(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
|
||||
@ -2349,5 +2371,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
|
||||
*t = p->makeThread(*m, 0, 0);
|
||||
|
||||
local::boot(*t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1314,6 +1314,7 @@ addInterfaceMethods(Thread* t, object class_, object virtualMap,
|
||||
methodFlags(t, method),
|
||||
(*virtualCount)++,
|
||||
0,
|
||||
0,
|
||||
methodName(t, method),
|
||||
methodSpec(t, method),
|
||||
0,
|
||||
@ -1650,7 +1651,7 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
|
||||
object body = makeByteArray(t, 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);
|
||||
} else {
|
||||
@ -1839,21 +1840,11 @@ resolveArrayClass(Thread* t, object loader, object spec, bool throw_)
|
||||
object
|
||||
resolveObjectArrayClass(Thread* t, object loader, object elementClass)
|
||||
{
|
||||
object addendum = classAddendum(t, elementClass);
|
||||
if (addendum) {
|
||||
object arrayClass = classAddendumArrayClass(t, addendum);
|
||||
{ object arrayClass = classRuntimeDataArrayClass
|
||||
(t, getClassRuntimeData(t, elementClass));
|
||||
if (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);
|
||||
@ -1882,7 +1873,7 @@ resolveObjectArrayClass(Thread* t, object loader, object elementClass)
|
||||
|
||||
object arrayClass = resolveClass(t, loader, spec);
|
||||
|
||||
set(t, classAddendum(t, elementClass), ClassAddendumArrayClass,
|
||||
set(t, getClassRuntimeData(t, elementClass), ClassRuntimeDataArrayClass,
|
||||
arrayClass);
|
||||
|
||||
return arrayClass;
|
||||
@ -2104,7 +2095,7 @@ boot(Thread* t)
|
||||
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1);
|
||||
codeBody(t, bootCode, 0) = impdep1;
|
||||
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);
|
||||
|
||||
#include "type-java-initializations.cpp"
|
||||
@ -2349,6 +2340,8 @@ Thread::init()
|
||||
|
||||
m->unsafe = false;
|
||||
|
||||
enter(this, ActiveState);
|
||||
|
||||
if (image) {
|
||||
m->processor->boot(this, image);
|
||||
} else {
|
||||
@ -2358,6 +2351,8 @@ Thread::init()
|
||||
setRoot(this, Machine::ByteArrayMap, 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));
|
||||
|
||||
m->localThread->set(this);
|
||||
@ -2373,25 +2368,6 @@ Thread::init()
|
||||
}
|
||||
|
||||
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
|
||||
@ -3151,6 +3127,7 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size)
|
||||
0, // fixed size
|
||||
0, // array size
|
||||
0, // array dimensions
|
||||
0, // runtime data index
|
||||
0, // object mask
|
||||
referenceName
|
||||
(t, singletonObject(t, pool, name - 1)),
|
||||
|
@ -1194,6 +1194,8 @@ class Machine {
|
||||
MonitorMap,
|
||||
StringMap,
|
||||
ByteArrayMap,
|
||||
ClassRuntimeDataTable,
|
||||
MethodRuntimeDataTable,
|
||||
JNIMethodTable,
|
||||
ShutdownHooks,
|
||||
ObjectsToFinalize,
|
||||
@ -3056,28 +3058,70 @@ resolveMethod(Thread* t, object method, unsigned index)
|
||||
(t, classLoader(t, methodClass(t, method)), method, index);
|
||||
}
|
||||
|
||||
object
|
||||
vectorAppend(Thread*, object, 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);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
object addendum = makeClassAddendum(t, 0, 0, 0, 0, 0);
|
||||
|
||||
set(t, c, ClassAddendum, addendum);
|
||||
if (classRuntimeDataIndex(t, c) == 0) {
|
||||
object runtimeData = makeClassRuntimeData(t, 0, 0, 0);
|
||||
|
||||
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) {
|
||||
PROTECT(t, c);
|
||||
|
||||
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;
|
||||
@ -3111,12 +3155,15 @@ registerNative(Thread* t, object method, void* function)
|
||||
expect(t, methodFlags(t, method) & ACC_NATIVE);
|
||||
|
||||
object native = makeNative(t, function, false);
|
||||
PROTECT(t, native);
|
||||
|
||||
// ensure other threads only see the methodCode field populated
|
||||
// once the object it points to 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();
|
||||
|
||||
set(t, method, MethodCode, native);
|
||||
set(t, runtimeData, MethodRuntimeDataNative, native);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -3126,7 +3173,7 @@ unregisterNatives(Thread* t, object c)
|
||||
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||
object method = arrayBody(t, classMethodTable(t, c), i);
|
||||
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),
|
||||
methodOffset(t, method),
|
||||
methodNativeID(t, method),
|
||||
methodRuntimeDataIndex(t, method),
|
||||
methodName(t, method),
|
||||
methodSpec(t, method),
|
||||
methodAddendum(t, method),
|
||||
|
@ -232,7 +232,9 @@ resolveNative(Thread* t, object 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);
|
||||
if (UNLIKELY(native == 0)) {
|
||||
object message = makeString
|
||||
@ -246,11 +248,15 @@ resolveNative(Thread* t, object method)
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure other threads only see the methodCode field populated
|
||||
// once the object it points do has been populated:
|
||||
PROTECT(t, native);
|
||||
|
||||
object runtimeData = getMethodRuntimeData(t, method);
|
||||
|
||||
// ensure other threads only see the methodRuntimeDataNative field
|
||||
// populated once the object it points to has been populated:
|
||||
storeStoreMemoryBarrier();
|
||||
|
||||
set(t, method, MethodCode, native);
|
||||
set(t, runtimeData, MethodRuntimeDataNative, native);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,4 +48,5 @@ THUNK(instanceOf64)
|
||||
THUNK(makeNewGeneral64)
|
||||
THUNK(makeNew64)
|
||||
THUNK(set)
|
||||
THUNK(getJClass)
|
||||
THUNK(gcIfNecessary)
|
||||
|
@ -37,6 +37,14 @@
|
||||
|
||||
(type fieldAddendum avian/FieldAddendum)
|
||||
|
||||
(type classRuntimeData
|
||||
(object arrayClass)
|
||||
(object jclass)
|
||||
(object pool))
|
||||
|
||||
(type methodRuntimeData
|
||||
(object native))
|
||||
|
||||
(type pointer
|
||||
(void* value))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user