mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +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;
|
package avian;
|
||||||
|
|
||||||
public class ClassAddendum extends Addendum {
|
public class ClassAddendum extends Addendum { }
|
||||||
public volatile Class class_;
|
|
||||||
public Object[] signers;
|
|
||||||
public volatile Class arrayClass;
|
|
||||||
}
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
16
makefile
16
makefile
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)),
|
||||||
|
@ -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),
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,4 +48,5 @@ THUNK(instanceOf64)
|
|||||||
THUNK(makeNewGeneral64)
|
THUNK(makeNewGeneral64)
|
||||||
THUNK(makeNew64)
|
THUNK(makeNew64)
|
||||||
THUNK(set)
|
THUNK(set)
|
||||||
|
THUNK(getJClass)
|
||||||
THUNK(gcIfNecessary)
|
THUNK(gcIfNecessary)
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user