mirror of
https://github.com/corda/corda.git
synced 2025-01-17 02:09:50 +00:00
more progress towards cross-architecture bootimage builds
This commit fixes a lot of bugs. All tests are now pass for Linux x86_64 to Linux i386 cross builds.
This commit is contained in:
parent
5d55d61c17
commit
e505cbe99d
23
makefile
23
makefile
@ -165,12 +165,13 @@ rdynamic = -rdynamic
|
||||
warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
|
||||
-Wno-non-virtual-dtor
|
||||
|
||||
target-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size)
|
||||
|
||||
common-cflags = $(warnings) -fno-rtti -fno-exceptions \
|
||||
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) $(classpath-cflags) \
|
||||
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
||||
-DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \
|
||||
-DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \
|
||||
-DTARGET_BYTES_PER_WORD=$(pointer-size)
|
||||
-DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags)
|
||||
|
||||
ifneq (,$(filter i386 x86_64,$(arch)))
|
||||
ifeq ($(use-frame-pointer),true)
|
||||
@ -209,9 +210,11 @@ shared = -shared
|
||||
|
||||
openjdk-extra-cflags = -fvisibility=hidden
|
||||
|
||||
bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size)
|
||||
|
||||
ifeq ($(build-arch),powerpc)
|
||||
ifneq ($(arch),$(build-arch))
|
||||
cflags += -DTARGET_OPPOSITE_ENDIAN
|
||||
bootimage-cflags += -DTARGET_OPPOSITE_ENDIAN
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -223,7 +226,7 @@ ifeq ($(arch),powerpc)
|
||||
pointer-size = 4
|
||||
|
||||
ifneq ($(arch),$(build-arch))
|
||||
cflags += -DTARGET_OPPOSITE_ENDIAN
|
||||
bootimage-cflags += -DTARGET_OPPOSITE_ENDIAN
|
||||
endif
|
||||
|
||||
ifneq ($(platform),darwin)
|
||||
@ -264,7 +267,7 @@ endif
|
||||
|
||||
|
||||
ifeq ($(platform),linux)
|
||||
cflags += -DTARGET_PLATFORM_LINUX
|
||||
bootimage-cflags += -DTARGET_PLATFORM_LINUX
|
||||
endif
|
||||
|
||||
ifeq ($(build-platform),darwin)
|
||||
@ -274,7 +277,7 @@ ifeq ($(build-platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(platform),darwin)
|
||||
cflags += -DTARGET_PLATFORM_DARWIN
|
||||
bootimage-cflags += -DTARGET_PLATFORM_DARWIN
|
||||
|
||||
ifeq (${OSX_SDK_SYSROOT},)
|
||||
OSX_SDK_SYSROOT = 10.4u
|
||||
@ -350,7 +353,7 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(platform),windows)
|
||||
cflags += -DTARGET_PLATFORM_WINDOWS
|
||||
bootimage-cflags += -DTARGET_PLATFORM_WINDOWS
|
||||
|
||||
inc = "$(root)/win32/include"
|
||||
lib = "$(root)/win32/lib"
|
||||
@ -520,10 +523,12 @@ vm-sources = \
|
||||
|
||||
vm-asm-sources = $(src)/$(asm).S
|
||||
|
||||
target-asm = $(asm)
|
||||
|
||||
ifeq ($(process),compile)
|
||||
vm-sources += \
|
||||
$(src)/compiler.cpp \
|
||||
$(src)/$(asm).cpp
|
||||
$(src)/$(target-asm).cpp
|
||||
|
||||
vm-asm-sources += $(src)/compile-$(asm).S
|
||||
endif
|
||||
@ -902,6 +907,8 @@ $(bootimage-generator):
|
||||
openjdk-src=$(openjdk-src) \
|
||||
bootimage-generator= \
|
||||
build-bootimage-generator=$(bootimage-generator) \
|
||||
target-cflags="$(bootimage-cflags)" \
|
||||
target-asm=$(asm) \
|
||||
$(bootimage-generator)
|
||||
|
||||
$(build-bootimage-generator): \
|
||||
|
30
src/bootimage-template.cpp
Normal file
30
src/bootimage-template.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
const unsigned NAME(BootMask) = (~static_cast<unsigned>(0))
|
||||
/ NAME(BytesPerWord);
|
||||
|
||||
const unsigned NAME(BootShift) = 32 - log(NAME(BytesPerWord));
|
||||
|
||||
const unsigned NAME(BootFlatConstant) = 1 << NAME(BootShift);
|
||||
const unsigned NAME(BootHeapOffset) = 1 << (NAME(BootShift) + 1);
|
||||
|
||||
inline unsigned
|
||||
LABEL(codeMapSize)(unsigned codeSize)
|
||||
{
|
||||
return ceiling(codeSize, TargetBitsPerWord) * TargetBytesPerWord;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
LABEL(heapMapSize)(unsigned heapSize)
|
||||
{
|
||||
return ceiling(heapSize, TargetBitsPerWord * TargetBytesPerWord)
|
||||
* TargetBytesPerWord;
|
||||
}
|
||||
|
||||
inline object
|
||||
LABEL(bootObject)(LABEL(uintptr_t)* heap, unsigned offset)
|
||||
{
|
||||
if (offset) {
|
||||
return reinterpret_cast<object>(heap + offset - 1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "bootimage.h"
|
||||
#include "heap.h"
|
||||
#include "heapwalk.h"
|
||||
#include "common.h"
|
||||
@ -40,6 +39,7 @@ const bool DebugNativeTarget = false;
|
||||
enum Type {
|
||||
Type_none,
|
||||
Type_object,
|
||||
Type_object_nogc,
|
||||
Type_int8_t,
|
||||
Type_uint8_t,
|
||||
Type_int16_t,
|
||||
@ -60,13 +60,19 @@ enum Type {
|
||||
|
||||
class Field {
|
||||
public:
|
||||
Field(Type type, unsigned offset, unsigned targetOffset):
|
||||
type(type), offset(offset), targetOffset(targetOffset)
|
||||
Field() { }
|
||||
|
||||
Field(Type type, unsigned buildOffset, unsigned buildSize,
|
||||
unsigned targetOffset, unsigned targetSize):
|
||||
type(type), buildOffset(buildOffset), buildSize(buildSize),
|
||||
targetOffset(targetOffset), targetSize(targetSize)
|
||||
{ }
|
||||
|
||||
Type type;
|
||||
unsigned offset;
|
||||
unsigned buildOffset;
|
||||
unsigned buildSize;
|
||||
unsigned targetOffset;
|
||||
unsigned targetSize;
|
||||
};
|
||||
|
||||
class TypeMap {
|
||||
@ -155,6 +161,108 @@ endsWith(const char* suffix, const char* s, unsigned length)
|
||||
and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
|
||||
}
|
||||
|
||||
object
|
||||
getNonStaticFields(Thread* t, object typeMaps, object c, object fields,
|
||||
unsigned* count, object* array)
|
||||
{
|
||||
PROTECT(t, typeMaps);
|
||||
PROTECT(t, c);
|
||||
PROTECT(t, fields);
|
||||
|
||||
*array = hashMapFind(t, typeMaps, c, objectHash, objectEqual);
|
||||
|
||||
if (*array) {
|
||||
*count += reinterpret_cast<TypeMap*>(&byteArrayBody(t, *array, 0))
|
||||
->fixedFieldCount;
|
||||
} else {
|
||||
if (classSuper(t, c)) {
|
||||
fields = getNonStaticFields
|
||||
(t, typeMaps, classSuper(t, c), fields, count, array);
|
||||
}
|
||||
|
||||
if (classFieldTable(t, c)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, classFieldTable(t, c)); ++i) {
|
||||
object field = arrayBody(t, classFieldTable(t, c), i);
|
||||
|
||||
if ((fieldFlags(t, field) & ACC_STATIC) == 0) {
|
||||
++ (*count);
|
||||
fields = vectorAppend(t, fields, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vectorAppend(t, fields, 0);
|
||||
}
|
||||
|
||||
object
|
||||
allFields(Thread* t, object typeMaps, object c, unsigned* count, object* array)
|
||||
{
|
||||
PROTECT(t, typeMaps);
|
||||
PROTECT(t, c);
|
||||
|
||||
object fields = makeVector(t, 0, 0);
|
||||
PROTECT(t, fields);
|
||||
|
||||
*array = hashMapFind(t, typeMaps, c, objectHash, objectEqual);
|
||||
|
||||
bool includeMembers;
|
||||
if (*array) {
|
||||
includeMembers = false;
|
||||
*count += reinterpret_cast<TypeMap*>(&byteArrayBody(t, *array, 0))
|
||||
->fixedFieldCount;
|
||||
} else if (classSuper(t, c)) {
|
||||
includeMembers = true;
|
||||
fields = getNonStaticFields
|
||||
(t, typeMaps, classSuper(t, c), fields, count, array);
|
||||
}
|
||||
|
||||
if (classFieldTable(t, c)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, classFieldTable(t, c)); ++i) {
|
||||
object field = arrayBody(t, classFieldTable(t, c), i);
|
||||
|
||||
if (includeMembers or (fieldFlags(t, field) & ACC_STATIC)) {
|
||||
++ (*count);
|
||||
fields = vectorAppend(t, fields, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
TypeMap*
|
||||
classTypeMap(Thread* t, object typeMaps, object p)
|
||||
{
|
||||
return reinterpret_cast<TypeMap*>
|
||||
(&byteArrayBody
|
||||
(t, hashMapFind(t, typeMaps, p, objectHash, objectEqual), 0));
|
||||
}
|
||||
|
||||
TypeMap*
|
||||
typeMap(Thread* t, object typeMaps, object p)
|
||||
{
|
||||
return reinterpret_cast<TypeMap*>
|
||||
(&byteArrayBody
|
||||
(t, objectClass(t, p) == type(t, Machine::SingletonType)
|
||||
? hashMapFind(t, typeMaps, p, objectHash, objectEqual)
|
||||
: hashMapFind(t, typeMaps, objectClass(t, p), objectHash, objectEqual),
|
||||
0));
|
||||
}
|
||||
|
||||
unsigned
|
||||
targetFieldOffset(Thread* t, object typeMaps, object field)
|
||||
{
|
||||
// if (strcmp(reinterpret_cast<const char*>
|
||||
// (&byteArrayBody(t, className(t, fieldClass(t, field)), 0)),
|
||||
// "java/lang/Throwable") == 0) trap();
|
||||
|
||||
return ((fieldFlags(t, field) & ACC_STATIC)
|
||||
? typeMap(t, typeMaps, classStaticTable(t, fieldClass(t, field)))
|
||||
: classTypeMap(t, typeMaps, fieldClass(t, field)))
|
||||
->targetFixedOffsets()[fieldOffset(t, field)];
|
||||
}
|
||||
|
||||
object
|
||||
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
uintptr_t* codeMap, const char* className,
|
||||
@ -168,8 +276,22 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
object calls = 0;
|
||||
PROTECT(t, calls);
|
||||
|
||||
object methods = 0;
|
||||
PROTECT(t, methods);
|
||||
|
||||
DelayedPromise* addresses = 0;
|
||||
|
||||
class MyOffsetResolver: public OffsetResolver {
|
||||
public:
|
||||
MyOffsetResolver(object* typeMaps): typeMaps(typeMaps) { }
|
||||
|
||||
virtual unsigned fieldOffset(Thread* t, object field) {
|
||||
return targetFieldOffset(t, *typeMaps, field);
|
||||
}
|
||||
|
||||
object* typeMaps;
|
||||
} resolver(&typeMaps);
|
||||
|
||||
Finder* finder = static_cast<Finder*>
|
||||
(systemClassLoaderFinder(t, root(t, Machine::BootLoader)));
|
||||
|
||||
@ -272,7 +394,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
= i * TargetBytesPerWord;
|
||||
|
||||
new (map->fixedFields() + i) Field
|
||||
(types[i], i * BytesPerWord, i * TargetBytesPerWord);
|
||||
(types[i], i * BytesPerWord, BytesPerWord,
|
||||
i * TargetBytesPerWord, TargetBytesPerWord);
|
||||
}
|
||||
|
||||
hashMapInsert
|
||||
@ -282,41 +405,71 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
}
|
||||
}
|
||||
|
||||
if (classFieldTable(t, c)) {
|
||||
unsigned count = arrayLength(t, classFieldTable(t, c));
|
||||
// if (strcmp(name, "java/lang/System$Property.class") == 0) trap();
|
||||
|
||||
Type memberTypes[count + 1];
|
||||
memberTypes[0] = Type_object;
|
||||
unsigned buildMemberOffsets[count + 1];
|
||||
buildMemberOffsets[0] = 0;
|
||||
unsigned targetMemberOffsets[count + 1];
|
||||
targetMemberOffsets[0] = 0;
|
||||
unsigned memberIndex = 1;
|
||||
unsigned buildMemberOffset = BytesPerWord;
|
||||
unsigned targetMemberOffset = TargetBytesPerWord;
|
||||
{ object array = 0;
|
||||
PROTECT(t, array);
|
||||
|
||||
unsigned count = 0;
|
||||
object fields = allFields(t, typeMaps, c, &count, &array);
|
||||
PROTECT(t, fields);
|
||||
|
||||
Field memberFields[count + 1];
|
||||
|
||||
unsigned memberIndex;
|
||||
unsigned buildMemberOffset;
|
||||
unsigned targetMemberOffset;
|
||||
|
||||
if (array) {
|
||||
memberIndex = 0;
|
||||
buildMemberOffset = 0;
|
||||
targetMemberOffset = 0;
|
||||
|
||||
TypeMap* map = reinterpret_cast<TypeMap*>
|
||||
(&byteArrayBody(t, array, 0));
|
||||
|
||||
for (unsigned j = 0; j < map->fixedFieldCount; ++j) {
|
||||
Field* f = map->fixedFields() + j;
|
||||
|
||||
memberFields[memberIndex] = *f;
|
||||
|
||||
targetMemberOffset += f->targetSize;
|
||||
|
||||
++ memberIndex;
|
||||
}
|
||||
} else {
|
||||
new (memberFields) Field
|
||||
(Type_object, 0, BytesPerWord, 0, TargetBytesPerWord);
|
||||
|
||||
memberIndex = 1;
|
||||
buildMemberOffset = BytesPerWord;
|
||||
targetMemberOffset = TargetBytesPerWord;
|
||||
}
|
||||
|
||||
Field staticFields[count + 2];
|
||||
|
||||
new (staticFields) Field
|
||||
(Type_object, 0, BytesPerWord, 0, TargetBytesPerWord);
|
||||
|
||||
new (staticFields + 1) Field
|
||||
(Type_intptr_t, BytesPerWord, BytesPerWord, TargetBytesPerWord,
|
||||
TargetBytesPerWord);
|
||||
|
||||
Type staticTypes[count + 2];
|
||||
staticTypes[0] = Type_object;
|
||||
staticTypes[1] = Type_intptr_t;
|
||||
unsigned buildStaticOffsets[count + 2];
|
||||
buildStaticOffsets[0] = 0;
|
||||
buildStaticOffsets[1] = BytesPerWord;
|
||||
unsigned targetStaticOffsets[count + 2];
|
||||
targetStaticOffsets[0] = 0;
|
||||
targetStaticOffsets[1] = TargetBytesPerWord;
|
||||
unsigned staticIndex = 2;
|
||||
unsigned buildStaticOffset = BytesPerWord * 2;
|
||||
unsigned targetStaticOffset = TargetBytesPerWord * 2;
|
||||
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
object field = arrayBody(t, classFieldTable(t, c), i);
|
||||
unsigned size = fieldSize(t, fieldCode(t, field));
|
||||
for (unsigned i = 0; i < vectorSize(t, fields); ++i) {
|
||||
object field = vectorBody(t, fields, i);
|
||||
if (field) {
|
||||
unsigned buildSize = fieldSize(t, fieldCode(t, field));
|
||||
unsigned targetSize = buildSize;
|
||||
|
||||
Type type;
|
||||
switch (fieldCode(t, field)) {
|
||||
case ObjectField:
|
||||
type = Type_object;
|
||||
size = TargetBytesPerWord;
|
||||
targetSize = TargetBytesPerWord;
|
||||
break;
|
||||
|
||||
case ByteField:
|
||||
@ -343,39 +496,43 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
}
|
||||
|
||||
if (fieldFlags(t, field) & ACC_STATIC) {
|
||||
staticTypes[staticIndex] = type;
|
||||
|
||||
while (targetStaticOffset % size) {
|
||||
while (targetStaticOffset % targetSize) {
|
||||
++ targetStaticOffset;
|
||||
}
|
||||
|
||||
targetStaticOffsets[staticIndex] = targetStaticOffset;
|
||||
|
||||
targetStaticOffset += size;
|
||||
|
||||
buildStaticOffset = fieldOffset(t, field);
|
||||
buildStaticOffsets[staticIndex] = buildStaticOffset;
|
||||
|
||||
new (staticFields + staticIndex) Field
|
||||
(type, buildStaticOffset, buildSize, targetStaticOffset,
|
||||
targetSize);
|
||||
|
||||
targetStaticOffset += targetSize;
|
||||
|
||||
++ staticIndex;
|
||||
} else {
|
||||
memberTypes[memberIndex] = type;
|
||||
|
||||
while (targetMemberOffset % size) {
|
||||
while (targetMemberOffset % targetSize) {
|
||||
++ targetMemberOffset;
|
||||
}
|
||||
|
||||
targetMemberOffsets[memberIndex] = targetMemberOffset;
|
||||
|
||||
targetMemberOffset += size;
|
||||
|
||||
buildMemberOffset = fieldOffset(t, field);
|
||||
buildMemberOffsets[memberIndex] = buildMemberOffset;
|
||||
|
||||
new (memberFields + memberIndex) Field
|
||||
(type, buildMemberOffset, buildSize, targetMemberOffset,
|
||||
targetSize);
|
||||
|
||||
targetMemberOffset += targetSize;
|
||||
|
||||
++ memberIndex;
|
||||
}
|
||||
} else {
|
||||
targetMemberOffset = pad(targetMemberOffset, TargetBytesPerWord);
|
||||
}
|
||||
}
|
||||
|
||||
{ object array = makeByteArray
|
||||
// if (strcmp(name, "avian/VMClass.class") == 0) trap();
|
||||
|
||||
if (hashMapFind(t, typeMaps, c, objectHash, objectEqual) == 0) {
|
||||
object array = makeByteArray
|
||||
(t, TypeMap::sizeInBytes
|
||||
(ceiling(classFixedSize(t, c), BytesPerWord), memberIndex));
|
||||
|
||||
@ -384,14 +541,14 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
ceiling(targetMemberOffset, TargetBytesPerWord), memberIndex);
|
||||
|
||||
for (unsigned i = 0; i < memberIndex; ++i) {
|
||||
expect(t, buildMemberOffsets[i]
|
||||
Field* f = memberFields + i;
|
||||
|
||||
expect(t, f->buildOffset
|
||||
< map->buildFixedSizeInWords * BytesPerWord);
|
||||
|
||||
map->targetFixedOffsets()[buildMemberOffsets[i]]
|
||||
= targetMemberOffsets[i];
|
||||
map->targetFixedOffsets()[f->buildOffset] = f->targetOffset;
|
||||
|
||||
new (map->fixedFields() + i) Field
|
||||
(memberTypes[i], buildMemberOffsets[i], targetMemberOffsets[i]);
|
||||
map->fixedFields()[i] = *f;
|
||||
}
|
||||
|
||||
hashMapInsert(t, typeMaps, c, array, objectHash);
|
||||
@ -408,20 +565,36 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
TypeMap::SingletonKind);
|
||||
|
||||
for (unsigned i = 0; i < staticIndex; ++i) {
|
||||
expect(t, buildStaticOffsets[i]
|
||||
Field* f = staticFields + i;
|
||||
|
||||
expect(t, f->buildOffset
|
||||
< map->buildFixedSizeInWords * BytesPerWord);
|
||||
|
||||
map->targetFixedOffsets()[buildStaticOffsets[i]]
|
||||
= targetStaticOffsets[i];
|
||||
map->targetFixedOffsets()[f->buildOffset] = f->targetOffset;
|
||||
|
||||
new (map->fixedFields() + i) Field
|
||||
(staticTypes[i], buildStaticOffsets[i], targetStaticOffsets[i]);
|
||||
map->fixedFields()[i] = *f;
|
||||
}
|
||||
|
||||
hashMapInsert
|
||||
(t, typeMaps, classStaticTable(t, c), array, objectHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Finder::Iterator it(finder); it.hasMore();) {
|
||||
unsigned nameSize = 0;
|
||||
const char* name = it.next(&nameSize);
|
||||
|
||||
if (endsWith(".class", name, nameSize)
|
||||
and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
|
||||
{
|
||||
// fprintf(stderr, "%.*s\n", nameSize - 6, name);
|
||||
object c = resolveSystemClass
|
||||
(t, root(t, Machine::BootLoader),
|
||||
makeByteArray(t, "%.*s", nameSize - 6, name), true);
|
||||
|
||||
PROTECT(t, c);
|
||||
|
||||
if (classMethodTable(t, c)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||
@ -444,7 +617,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
PROTECT(t, method);
|
||||
|
||||
t->m->processor->compileMethod
|
||||
(t, zone, &constants, &calls, &addresses, method);
|
||||
(t, zone, &constants, &calls, &addresses, method, &resolver);
|
||||
|
||||
if (methodCode(t, method)) {
|
||||
methods = makePair(t, method, methods);
|
||||
}
|
||||
}
|
||||
|
||||
object addendum = methodAddendum(t, method);
|
||||
@ -499,7 +676,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
(reinterpret_cast<int64_t>(code), &location);
|
||||
target_uintptr_t offset = value - code;
|
||||
if (flat) {
|
||||
offset |= BootFlatConstant;
|
||||
offset |= TargetBootFlatConstant;
|
||||
}
|
||||
memcpy(location, &offset, TargetBytesPerWord);
|
||||
|
||||
@ -510,6 +687,13 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
||||
- reinterpret_cast<intptr_t>(code));
|
||||
}
|
||||
|
||||
for (; methods; methods = pairSecond(t, methods)) {
|
||||
codeCompiled(t, methodCode(t, pairFirst(t, methods)))
|
||||
-= reinterpret_cast<uintptr_t>(code);
|
||||
}
|
||||
|
||||
t->m->processor->normalizeVirtualThunks(t);
|
||||
|
||||
return constants;
|
||||
}
|
||||
|
||||
@ -541,17 +725,6 @@ visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
|
||||
}
|
||||
}
|
||||
|
||||
TypeMap*
|
||||
typeMap(Thread* t, object typeMaps, object p)
|
||||
{
|
||||
return reinterpret_cast<TypeMap*>
|
||||
(&byteArrayBody
|
||||
(t, objectClass(t, p) == type(t, Machine::SingletonType)
|
||||
? hashMapFind(t, typeMaps, p, objectHash, objectEqual)
|
||||
: hashMapFind(t, typeMaps, objectClass(t, p), objectHash, objectEqual),
|
||||
0));
|
||||
}
|
||||
|
||||
unsigned
|
||||
targetOffset(Thread* t, object typeMaps, object p, unsigned offset)
|
||||
{
|
||||
@ -602,6 +775,36 @@ targetSize(Thread* t, object typeMaps, object p)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
objectMaskCount(TypeMap* map)
|
||||
{
|
||||
unsigned count = map->targetFixedSizeInWords;
|
||||
|
||||
if (map->targetArrayElementSizeInBytes) {
|
||||
++ count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned
|
||||
targetSize(Thread* t, object typeMaps, object referer, unsigned refererOffset,
|
||||
object p)
|
||||
{
|
||||
if (referer
|
||||
and objectClass(t, referer) == type(t, Machine::ClassType)
|
||||
and (refererOffset * BytesPerWord) == ClassObjectMask)
|
||||
{
|
||||
return (TargetBytesPerWord * 2)
|
||||
+ pad
|
||||
(ceiling
|
||||
(objectMaskCount
|
||||
(classTypeMap(t, typeMaps, referer)), 32) * 4, TargetBytesPerWord);
|
||||
} else {
|
||||
return targetSize(t, typeMaps, p);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
copy(Thread* t, uint8_t* src, uint8_t* dst, Type type)
|
||||
{
|
||||
@ -674,6 +877,7 @@ nonObjectsEqual(uint8_t* src, uint8_t* dst, Type type)
|
||||
return memcmp(dst, src, BytesPerWord) == 0;
|
||||
|
||||
case Type_object:
|
||||
case Type_object_nogc:
|
||||
return true;
|
||||
|
||||
default: abort();
|
||||
@ -686,7 +890,7 @@ nonObjectsEqual(TypeMap* map, uint8_t* src, uint8_t* dst)
|
||||
for (unsigned i = 0; i < map->fixedFieldCount; ++i) {
|
||||
Field* field = map->fixedFields() + i;
|
||||
if (not nonObjectsEqual
|
||||
(src + field->offset, dst + field->targetOffset, field->type))
|
||||
(src + field->buildOffset, dst + field->targetOffset, field->type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -720,7 +924,7 @@ copy(Thread* t, object typeMaps, object p, uint8_t* dst)
|
||||
for (unsigned i = 0; i < map->fixedFieldCount; ++i) {
|
||||
Field* field = map->fixedFields() + i;
|
||||
if (field->type > Type_array) abort(t);
|
||||
copy(t, src + field->offset, dst + field->targetOffset, field->type);
|
||||
copy(t, src + field->buildOffset, dst + field->targetOffset, field->type);
|
||||
}
|
||||
|
||||
if (map->targetArrayElementSizeInBytes) {
|
||||
@ -732,16 +936,59 @@ copy(Thread* t, object typeMaps, object p, uint8_t* dst)
|
||||
dst + (map->targetFixedSizeInWords * TargetBytesPerWord)
|
||||
+ (i * map->targetArrayElementSizeInBytes), map->arrayElementType);
|
||||
}
|
||||
|
||||
if (objectClass(t, p) == type(t, Machine::ClassType)) {
|
||||
uint16_t fixedSize;
|
||||
uint8_t arrayElementSize;
|
||||
object array = hashMapFind(t, typeMaps, p, objectHash, objectEqual);
|
||||
|
||||
if (array) {
|
||||
TypeMap* classMap = reinterpret_cast<TypeMap*>
|
||||
(&byteArrayBody(t, array, 0));
|
||||
|
||||
fixedSize = TARGET_V2
|
||||
(classMap->targetFixedSizeInWords * TargetBytesPerWord);
|
||||
|
||||
arrayElementSize = classMap->targetArrayElementSizeInBytes;
|
||||
} else if (classFixedSize(t, p) == BytesPerWord * 2
|
||||
and classArrayElementSize(t, p) == BytesPerWord)
|
||||
{
|
||||
fixedSize = TARGET_V2(TargetBytesPerWord * 2);
|
||||
|
||||
arrayElementSize = TargetBytesPerWord;
|
||||
} else {
|
||||
fixedSize = 0;
|
||||
arrayElementSize = 0;
|
||||
}
|
||||
|
||||
if (fixedSize) {
|
||||
memcpy(dst + TargetClassFixedSize, &fixedSize, 2);
|
||||
|
||||
memcpy(dst + TargetClassArrayElementSize, &arrayElementSize, 1);
|
||||
}
|
||||
|
||||
// if (strcmp("vm::lineNumberTable",
|
||||
// reinterpret_cast<const char*>(&byteArrayBody(t, className(t, p), 0))) == 0) trap();
|
||||
}
|
||||
} else {
|
||||
switch (map->kind) {
|
||||
case TypeMap::NormalKind:
|
||||
if (objectClass(t, p) == type(t, Machine::FieldType)) {
|
||||
uint16_t offset = TARGET_V2(targetFieldOffset(t, typeMaps, p));
|
||||
memcpy(dst + TargetFieldOffset, &offset, 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case TypeMap::SingletonKind: {
|
||||
unsigned maskSize = singletonMaskSize
|
||||
(map->targetFixedSizeInWords - 2, TargetBitsPerWord);
|
||||
|
||||
target_uintptr_t targetLength = TARGET_VW
|
||||
(map->targetFixedSizeInWords - 2 + maskSize);
|
||||
memcpy(dst + TargetBytesPerWord, &targetLength, TargetBytesPerWord);
|
||||
|
||||
uint8_t* mask = dst + (map->targetFixedSizeInWords * TargetBytesPerWord);
|
||||
memset(mask, 0, singletonMaskSize
|
||||
(map->targetFixedSizeInWords - 2, TargetBitsPerWord)
|
||||
* TargetBytesPerWord);
|
||||
memset(mask, 0, maskSize * TargetBytesPerWord);
|
||||
|
||||
for (unsigned i = 0; i < map->fixedFieldCount; ++i) {
|
||||
Field* field = map->fixedFields() + i;
|
||||
@ -766,6 +1013,13 @@ copy(Thread* t, object typeMaps, object p, uint8_t* dst)
|
||||
unsigned poolMaskSize = vm::poolMaskSize
|
||||
(map->targetFixedSizeInWords - 2, TargetBitsPerWord);
|
||||
|
||||
unsigned objectMaskSize = singletonMaskSize
|
||||
(map->targetFixedSizeInWords - 2 + poolMaskSize, TargetBitsPerWord);
|
||||
|
||||
target_uintptr_t targetLength = TARGET_VW
|
||||
(map->targetFixedSizeInWords - 2 + poolMaskSize + objectMaskSize);
|
||||
memcpy(dst + TargetBytesPerWord, &targetLength, TargetBytesPerWord);
|
||||
|
||||
uint8_t* poolMask = dst
|
||||
+ (map->targetFixedSizeInWords * TargetBytesPerWord);
|
||||
|
||||
@ -774,9 +1028,7 @@ copy(Thread* t, object typeMaps, object p, uint8_t* dst)
|
||||
uint8_t* objectMask = dst
|
||||
+ ((map->targetFixedSizeInWords + poolMaskSize) * TargetBytesPerWord);
|
||||
|
||||
memset(objectMask, 0, singletonMaskSize
|
||||
(map->targetFixedSizeInWords - 2 + poolMaskSize,
|
||||
TargetBitsPerWord) * TargetBytesPerWord);
|
||||
memset(objectMask, 0, objectMaskSize * TargetBytesPerWord);
|
||||
|
||||
for (unsigned i = 0; i < map->fixedFieldCount; ++i) {
|
||||
Field* field = map->fixedFields() + i;
|
||||
@ -812,21 +1064,64 @@ copy(Thread* t, object typeMaps, object p, uint8_t* dst)
|
||||
default: abort(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
copy(Thread* t, object typeMaps, object referer, unsigned refererOffset,
|
||||
object p, uint8_t* dst)
|
||||
{
|
||||
if (referer
|
||||
and objectClass(t, referer) == type(t, Machine::ClassType)
|
||||
and (refererOffset * BytesPerWord) == ClassObjectMask)
|
||||
{
|
||||
TypeMap* map = classTypeMap(t, typeMaps, referer);
|
||||
|
||||
memset(dst, 0, TargetBytesPerWord);
|
||||
|
||||
unsigned length = ceiling(objectMaskCount(map), 32);
|
||||
|
||||
target_uintptr_t targetLength = TARGET_VW(length);
|
||||
|
||||
memcpy(dst + TargetBytesPerWord, &targetLength, TargetBytesPerWord);
|
||||
|
||||
memset(dst + (TargetBytesPerWord * 2), 0, length * 4);
|
||||
|
||||
for (unsigned i = 0; i < map->fixedFieldCount; ++i) {
|
||||
Field* field = map->fixedFields() + i;
|
||||
if (field->type == Type_object) {
|
||||
unsigned offset = field->targetOffset / TargetBytesPerWord;
|
||||
reinterpret_cast<uint32_t*>(dst + (TargetBytesPerWord * 2))
|
||||
[offset / 32] |= static_cast<uint32_t>(1) << (offset % 32);
|
||||
}
|
||||
}
|
||||
|
||||
if (map->targetArrayElementSizeInBytes
|
||||
and map->arrayElementType == Type_object)
|
||||
{
|
||||
unsigned offset = map->targetFixedSizeInWords;
|
||||
reinterpret_cast<uint32_t*>(dst + (TargetBytesPerWord * 2))
|
||||
[offset / 32] |= static_cast<uint32_t>(1) << (offset % 32);
|
||||
}
|
||||
} else {
|
||||
copy(t, typeMaps, p, dst);
|
||||
}
|
||||
|
||||
if (DebugNativeTarget) {
|
||||
expect(t, targetSize(t, typeMaps, p) == baseSize(t, p, objectClass(t, p)));
|
||||
expect(t, nonObjectsEqual(map, src, dst));
|
||||
expect(t, nonObjectsEqual
|
||||
(typeMap(t, typeMaps, p), reinterpret_cast<uint8_t*>(p), dst));
|
||||
}
|
||||
}
|
||||
|
||||
HeapWalker*
|
||||
makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
|
||||
unsigned capacity, object constants, object typeMaps)
|
||||
makeHeapImage(Thread* t, BootImage* image, target_uintptr_t* heap,
|
||||
target_uintptr_t* map, unsigned capacity, object constants,
|
||||
object typeMaps)
|
||||
{
|
||||
class Visitor: public HeapVisitor {
|
||||
public:
|
||||
Visitor(Thread* t, object typeMaps, uintptr_t* heap,
|
||||
uintptr_t* map, unsigned capacity):
|
||||
Visitor(Thread* t, object typeMaps, target_uintptr_t* heap,
|
||||
target_uintptr_t* map, unsigned capacity):
|
||||
t(t), typeMaps(typeMaps), currentObject(0), currentNumber(0),
|
||||
currentOffset(0), heap(heap), map(map), position(0), capacity(capacity)
|
||||
{ }
|
||||
@ -845,8 +1140,8 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
|
||||
(t, typeMaps, currentObject, currentOffset * BytesPerWord)
|
||||
/ TargetBytesPerWord);
|
||||
|
||||
unsigned mark = heap[offset] & (~PointerMask);
|
||||
unsigned value = number | (mark << BootShift);
|
||||
unsigned mark = heap[offset] & (~TargetPointerMask);
|
||||
unsigned value = number | (mark << TargetBootShift);
|
||||
|
||||
if (value) markBit(map, offset);
|
||||
|
||||
@ -860,7 +1155,8 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
|
||||
|
||||
virtual unsigned visitNew(object p) {
|
||||
if (p) {
|
||||
unsigned size = targetSize(t, typeMaps, p);
|
||||
unsigned size = targetSize
|
||||
(t, typeMaps, currentObject, currentOffset, p);
|
||||
|
||||
unsigned number;
|
||||
if ((currentObject
|
||||
@ -877,7 +1173,7 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
|
||||
|
||||
target_uintptr_t* dst = heap + position + TargetFixieSizeInWords;
|
||||
|
||||
unsigned maskSize = ceiling(size, TargetBytesPerWord);
|
||||
unsigned maskSize = ceiling(size, TargetBitsPerWord);
|
||||
|
||||
unsigned total = TargetFixieSizeInWords + size + maskSize;
|
||||
|
||||
@ -897,7 +1193,8 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
|
||||
memcpy(reinterpret_cast<uint8_t*>(heap + position)
|
||||
+ TargetFixieSize, &targetSize, 4);
|
||||
|
||||
copy(t, typeMaps, p, reinterpret_cast<uint8_t*>(dst));
|
||||
copy(t, typeMaps, currentObject, currentOffset, p,
|
||||
reinterpret_cast<uint8_t*>(dst));
|
||||
|
||||
dst[0] |= FixedMark;
|
||||
|
||||
@ -909,7 +1206,8 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
|
||||
} else {
|
||||
expect(t, position + size < capacity);
|
||||
|
||||
copy(t, typeMaps, p, reinterpret_cast<uint8_t*>(heap + position));
|
||||
copy(t, typeMaps, currentObject, currentOffset, p,
|
||||
reinterpret_cast<uint8_t*>(heap + position));
|
||||
|
||||
number = position + 1;
|
||||
position += size;
|
||||
@ -970,15 +1268,21 @@ updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
|
||||
{
|
||||
void* location;
|
||||
bool flat = pl->resolve(0, &location);
|
||||
target_uintptr_t offset = target | BootHeapOffset;
|
||||
target_uintptr_t offset = target | TargetBootHeapOffset;
|
||||
if (flat) {
|
||||
offset |= BootFlatConstant;
|
||||
offset |= TargetBootFlatConstant;
|
||||
}
|
||||
memcpy(location, &offset, TargetBytesPerWord);
|
||||
|
||||
expect(t, reinterpret_cast<intptr_t>(location)
|
||||
>= reinterpret_cast<intptr_t>(code));
|
||||
|
||||
// fprintf(stderr, "mark constant %d %d\n",
|
||||
// static_cast<unsigned>
|
||||
// (reinterpret_cast<intptr_t>(location)
|
||||
// - reinterpret_cast<intptr_t>(code)),
|
||||
// static_cast<unsigned>(offset));
|
||||
|
||||
markBit(codeMap, reinterpret_cast<intptr_t>(location)
|
||||
- reinterpret_cast<intptr_t>(code));
|
||||
}
|
||||
@ -1014,12 +1318,6 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
typeMaps = makeHashMap(t, 0, 0);
|
||||
PROTECT(t, typeMaps);
|
||||
|
||||
constants = makeCodeImage
|
||||
(t, &zone, image, code, codeMap, className, methodName, methodSpec,
|
||||
typeMaps);
|
||||
|
||||
PROTECT(t, constants);
|
||||
|
||||
#include "type-maps.cpp"
|
||||
|
||||
for (unsigned i = 0; i < arrayLength(t, t->m->types); ++i) {
|
||||
@ -1030,21 +1328,26 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
}
|
||||
++ count;
|
||||
|
||||
Type types[count];
|
||||
types[0] = Type_object;
|
||||
unsigned buildOffsets[count];
|
||||
buildOffsets[0] = 0;
|
||||
Field fields[count];
|
||||
|
||||
new (fields) Field(Type_object, 0, BytesPerWord, 0, TargetBytesPerWord);
|
||||
|
||||
unsigned buildOffset = BytesPerWord;
|
||||
unsigned targetOffsets[count];
|
||||
targetOffsets[0] = 0;
|
||||
unsigned targetOffset = TargetBytesPerWord;
|
||||
bool sawArray = false;
|
||||
unsigned buildSize = BytesPerWord;
|
||||
unsigned targetSize = TargetBytesPerWord;
|
||||
Type type;
|
||||
unsigned buildSize;
|
||||
unsigned targetSize;
|
||||
for (unsigned j = 1; j < count; ++j) {
|
||||
switch (source[j - 1]) {
|
||||
case Type_object:
|
||||
types[j] = Type_object;
|
||||
type = Type_object;
|
||||
buildSize = BytesPerWord;
|
||||
targetSize = TargetBytesPerWord;
|
||||
break;
|
||||
|
||||
case Type_object_nogc:
|
||||
type = Type_object_nogc;
|
||||
buildSize = BytesPerWord;
|
||||
targetSize = TargetBytesPerWord;
|
||||
break;
|
||||
@ -1052,39 +1355,39 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
case Type_word:
|
||||
case Type_intptr_t:
|
||||
case Type_uintptr_t:
|
||||
types[j] = Type_intptr_t;
|
||||
type = Type_intptr_t;
|
||||
buildSize = BytesPerWord;
|
||||
targetSize = TargetBytesPerWord;
|
||||
break;
|
||||
|
||||
case Type_int8_t:
|
||||
case Type_uint8_t:
|
||||
types[j] = Type_int8_t;
|
||||
type = Type_int8_t;
|
||||
buildSize = targetSize = 1;
|
||||
break;
|
||||
|
||||
case Type_int16_t:
|
||||
case Type_uint16_t:
|
||||
types[j] = Type_int16_t;
|
||||
type = Type_int16_t;
|
||||
buildSize = targetSize = 2;
|
||||
break;
|
||||
|
||||
case Type_int32_t:
|
||||
case Type_uint32_t:
|
||||
case Type_float:
|
||||
types[j] = Type_int32_t;
|
||||
type = Type_int32_t;
|
||||
buildSize = targetSize = 4;
|
||||
break;
|
||||
|
||||
case Type_int64_t:
|
||||
case Type_uint64_t:
|
||||
case Type_double:
|
||||
types[j] = Type_int64_t;
|
||||
type = Type_int64_t;
|
||||
buildSize = targetSize = 8;
|
||||
break;
|
||||
|
||||
case Type_array:
|
||||
types[j] = Type_none;
|
||||
type = Type_none;
|
||||
buildSize = targetSize = 0;
|
||||
break;
|
||||
|
||||
@ -1100,16 +1403,14 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
++ buildOffset;
|
||||
}
|
||||
|
||||
buildOffsets[j] = buildOffset;
|
||||
|
||||
buildOffset += buildSize;
|
||||
|
||||
while (targetOffset % targetSize) {
|
||||
++ targetOffset;
|
||||
}
|
||||
|
||||
targetOffsets[j] = targetOffset;
|
||||
new (fields + j) Field
|
||||
(type, buildOffset, buildSize, targetOffset, targetSize);
|
||||
|
||||
buildOffset += buildSize;
|
||||
targetOffset += targetSize;
|
||||
}
|
||||
}
|
||||
@ -1120,7 +1421,7 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
unsigned targetArrayElementSize;
|
||||
if (sawArray) {
|
||||
fixedFieldCount = count - 2;
|
||||
arrayElementType = types[count - 1];
|
||||
arrayElementType = type;
|
||||
buildArrayElementSize = buildSize;
|
||||
targetArrayElementSize = targetSize;
|
||||
} else {
|
||||
@ -1141,19 +1442,27 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
targetArrayElementSize, arrayElementType);
|
||||
|
||||
for (unsigned j = 0; j < fixedFieldCount; ++j) {
|
||||
expect(t, buildOffsets[j] < map->buildFixedSizeInWords * BytesPerWord);
|
||||
Field* f = fields + j;
|
||||
|
||||
map->targetFixedOffsets()[buildOffsets[j]] = targetOffsets[j];
|
||||
expect(t, f->buildOffset
|
||||
< map->buildFixedSizeInWords * BytesPerWord);
|
||||
|
||||
new (map->fixedFields() + j) Field
|
||||
(types[j], buildOffsets[j], targetOffsets[j]);
|
||||
map->targetFixedOffsets()[f->buildOffset] = f->targetOffset;
|
||||
|
||||
map->fixedFields()[j] = *f;
|
||||
}
|
||||
|
||||
hashMapInsertOrReplace
|
||||
(t, typeMaps, type(t, static_cast<Machine::Type>(i)), array,
|
||||
objectHash, objectEqual);
|
||||
hashMapInsert
|
||||
(t, typeMaps, vm::type(t, static_cast<Machine::Type>(i)), array,
|
||||
objectHash);
|
||||
}
|
||||
|
||||
constants = makeCodeImage
|
||||
(t, &zone, image, code, codeMap, className, methodName, methodSpec,
|
||||
typeMaps);
|
||||
|
||||
PROTECT(t, constants);
|
||||
|
||||
// these roots will not be used when the bootimage is loaded, so
|
||||
// there's no need to preserve them:
|
||||
setRoot(t, Machine::PoolMap, 0);
|
||||
@ -1217,9 +1526,10 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t* heap = static_cast<uintptr_t*>
|
||||
target_uintptr_t* heap = static_cast<target_uintptr_t*>
|
||||
(t->m->heap->allocate(HeapCapacity));
|
||||
uintptr_t* heapMap = static_cast<uintptr_t*>
|
||||
|
||||
target_uintptr_t* heapMap = static_cast<target_uintptr_t*>
|
||||
(t->m->heap->allocate(heapMapSize(HeapCapacity)));
|
||||
memset(heapMap, 0, heapMapSize(HeapCapacity));
|
||||
|
||||
@ -1275,7 +1585,6 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
heapWalker->dispose();
|
||||
|
||||
image->magic = BootImage::Magic;
|
||||
image->codeBase = reinterpret_cast<uintptr_t>(code);
|
||||
|
||||
fprintf(stderr, "class count %d string count %d call count %d\n"
|
||||
"heap size %d code size %d\n",
|
||||
@ -1301,11 +1610,15 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
|
||||
++ offset;
|
||||
}
|
||||
|
||||
fwrite(heapMap, pad(heapMapSize(image->heapSize)), 1, out);
|
||||
fwrite(heap, pad(image->heapSize), 1, out);
|
||||
fwrite
|
||||
(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord), 1, out);
|
||||
|
||||
fwrite(codeMap, pad(codeMapSize(image->codeSize)), 1, out);
|
||||
fwrite(code, pad(image->codeSize), 1, out);
|
||||
fwrite(heap, pad(image->heapSize, TargetBytesPerWord), 1, out);
|
||||
|
||||
fwrite
|
||||
(codeMap, pad(codeMapSize(image->codeSize), TargetBytesPerWord), 1, out);
|
||||
|
||||
fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
102
src/bootimage.h
102
src/bootimage.h
@ -12,16 +12,11 @@
|
||||
#define BOOTIMAGE_H
|
||||
|
||||
#include "common.h"
|
||||
#include "target.h"
|
||||
#include "machine.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
const unsigned BootMask = (~static_cast<unsigned>(0)) / BytesPerWord;
|
||||
|
||||
const unsigned BootShift = 32 - log(BytesPerWord);
|
||||
|
||||
const unsigned BootFlatConstant = 1 << BootShift;
|
||||
const unsigned BootHeapOffset = 1 << (BootShift + 1);
|
||||
|
||||
class BootImage {
|
||||
public:
|
||||
class Thunk {
|
||||
@ -30,14 +25,14 @@ class BootImage {
|
||||
start(0), frameSavedOffset(0), length(0)
|
||||
{ }
|
||||
|
||||
Thunk(unsigned start, unsigned frameSavedOffset, unsigned length):
|
||||
Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length):
|
||||
start(start), frameSavedOffset(frameSavedOffset), length(length)
|
||||
{ }
|
||||
|
||||
unsigned start;
|
||||
unsigned frameSavedOffset;
|
||||
unsigned length;
|
||||
};
|
||||
uint32_t start;
|
||||
uint32_t frameSavedOffset;
|
||||
uint32_t length;
|
||||
} PACKED;
|
||||
|
||||
class ThunkCollection {
|
||||
public:
|
||||
@ -47,63 +42,56 @@ class BootImage {
|
||||
Thunk aioob;
|
||||
Thunk stackOverflow;
|
||||
Thunk table;
|
||||
};
|
||||
} PACKED;
|
||||
|
||||
static const unsigned Magic = 0x22377322;
|
||||
static const uint32_t Magic = 0x22377322;
|
||||
|
||||
unsigned magic;
|
||||
uint32_t magic;
|
||||
|
||||
unsigned heapSize;
|
||||
unsigned codeSize;
|
||||
uint32_t heapSize;
|
||||
uint32_t codeSize;
|
||||
|
||||
unsigned bootClassCount;
|
||||
unsigned appClassCount;
|
||||
unsigned stringCount;
|
||||
unsigned callCount;
|
||||
uint32_t bootClassCount;
|
||||
uint32_t appClassCount;
|
||||
uint32_t stringCount;
|
||||
uint32_t callCount;
|
||||
|
||||
unsigned bootLoader;
|
||||
unsigned appLoader;
|
||||
unsigned types;
|
||||
unsigned methodTree;
|
||||
unsigned methodTreeSentinal;
|
||||
unsigned virtualThunks;
|
||||
uint32_t bootLoader;
|
||||
uint32_t appLoader;
|
||||
uint32_t types;
|
||||
uint32_t methodTree;
|
||||
uint32_t methodTreeSentinal;
|
||||
uint32_t virtualThunks;
|
||||
|
||||
uintptr_t codeBase;
|
||||
uint32_t compileMethodCall;
|
||||
uint32_t compileVirtualMethodCall;
|
||||
uint32_t invokeNativeCall;
|
||||
uint32_t throwArrayIndexOutOfBoundsCall;
|
||||
uint32_t throwStackOverflowCall;
|
||||
|
||||
ThunkCollection thunks;
|
||||
|
||||
unsigned compileMethodCall;
|
||||
unsigned compileVirtualMethodCall;
|
||||
unsigned invokeNativeCall;
|
||||
unsigned throwArrayIndexOutOfBoundsCall;
|
||||
unsigned throwStackOverflowCall;
|
||||
|
||||
#define THUNK(s) unsigned s##Call;
|
||||
#define THUNK(s) uint32_t s##Call;
|
||||
#include "thunks.cpp"
|
||||
#undef THUNK
|
||||
|
||||
ThunkCollection thunks;
|
||||
} PACKED;
|
||||
|
||||
class OffsetResolver {
|
||||
public:
|
||||
virtual unsigned fieldOffset(Thread*, object) = 0;
|
||||
};
|
||||
|
||||
inline unsigned
|
||||
codeMapSize(unsigned codeSize)
|
||||
{
|
||||
return ceiling(codeSize, BitsPerWord) * BytesPerWord;
|
||||
}
|
||||
#define NAME(x) Target##x
|
||||
#define LABEL(x) target_##x
|
||||
#include "bootimage-template.cpp"
|
||||
#undef LABEL
|
||||
#undef NAME
|
||||
|
||||
inline unsigned
|
||||
heapMapSize(unsigned heapSize)
|
||||
{
|
||||
return ceiling(heapSize, BitsPerWord * BytesPerWord) * BytesPerWord;
|
||||
}
|
||||
|
||||
inline object
|
||||
bootObject(uintptr_t* heap, unsigned offset)
|
||||
{
|
||||
if (offset) {
|
||||
return reinterpret_cast<object>(heap + offset - 1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#define NAME(x) x
|
||||
#define LABEL(x) x
|
||||
#include "bootimage-template.cpp"
|
||||
#undef LABEL
|
||||
#undef NAME
|
||||
|
||||
} // namespace vm
|
||||
|
||||
|
@ -45,6 +45,8 @@ typedef unsigned __int64 uint64_t;
|
||||
|
||||
# define NO_RETURN __declspec(noreturn)
|
||||
|
||||
# define PACKED
|
||||
|
||||
# define PLATFORM_WINDOWS
|
||||
|
||||
# ifdef _M_IX86
|
||||
@ -76,6 +78,8 @@ typedef intptr_t intptr_alias_t;
|
||||
|
||||
# define NO_RETURN __attribute__((noreturn))
|
||||
|
||||
# define PACKED __attribute__((packed))
|
||||
|
||||
# ifdef __MINGW32__
|
||||
# define PLATFORM_WINDOWS
|
||||
# endif
|
||||
|
214
src/compile.cpp
214
src/compile.cpp
@ -336,7 +336,7 @@ setRoot(Thread* t, Root root, object value);
|
||||
unsigned
|
||||
compiledSize(intptr_t address)
|
||||
{
|
||||
return reinterpret_cast<uintptr_t*>(address)[-1];
|
||||
return reinterpret_cast<target_uintptr_t*>(address)[-1];
|
||||
}
|
||||
|
||||
intptr_t
|
||||
@ -956,9 +956,10 @@ class BootContext {
|
||||
};
|
||||
|
||||
BootContext(Thread* t, object constants, object calls,
|
||||
DelayedPromise* addresses, Zone* zone):
|
||||
DelayedPromise* addresses, Zone* zone, OffsetResolver* resolver):
|
||||
protector(t, this), constants(constants), calls(calls),
|
||||
addresses(addresses), addressSentinal(addresses), zone(zone)
|
||||
addresses(addresses), addressSentinal(addresses), zone(zone),
|
||||
resolver(resolver)
|
||||
{ }
|
||||
|
||||
MyProtector protector;
|
||||
@ -967,6 +968,7 @@ class BootContext {
|
||||
DelayedPromise* addresses;
|
||||
DelayedPromise* addressSentinal;
|
||||
Zone* zone;
|
||||
OffsetResolver* resolver;
|
||||
};
|
||||
|
||||
class Context {
|
||||
@ -3309,7 +3311,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall,
|
||||
(TargetBytesPerWord, frame->addressOperand(returnAddressPromise),
|
||||
TargetBytesPerWord, c->memory
|
||||
(c->register_(t->arch->thread()), Compiler::AddressType,
|
||||
difference(&(t->tailAddress), t)));
|
||||
TargetThreadTailAddress));
|
||||
|
||||
c->exit
|
||||
(c->constant
|
||||
@ -3800,6 +3802,16 @@ intrinsic(MyThread* t, Frame* frame, object target)
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned
|
||||
targetFieldOffset(Context* context, object field)
|
||||
{
|
||||
if (context->bootContext) {
|
||||
return context->bootContext->resolver->fieldOffset(context->thread, field);
|
||||
} else {
|
||||
return fieldOffset(context->thread, field);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
int exceptionHandlerStart)
|
||||
@ -3861,7 +3873,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
}
|
||||
|
||||
if (CheckArrayBounds) {
|
||||
c->checkBounds(array, ArrayLength, index, aioobThunk(t));
|
||||
c->checkBounds(array, TargetArrayLength, index, aioobThunk(t));
|
||||
}
|
||||
|
||||
switch (instruction) {
|
||||
@ -3869,7 +3881,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->pushObject
|
||||
(c->load
|
||||
(TargetBytesPerWord, TargetBytesPerWord, c->memory
|
||||
(array, Compiler::ObjectType, ArrayBody, index,
|
||||
(array, Compiler::ObjectType, TargetArrayBody, index,
|
||||
TargetBytesPerWord),
|
||||
TargetBytesPerWord));
|
||||
break;
|
||||
@ -3878,7 +3890,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(4, 4, c->memory
|
||||
(array, Compiler::FloatType, ArrayBody, index, 4),
|
||||
(array, Compiler::FloatType, TargetArrayBody, index, 4),
|
||||
TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
@ -3886,7 +3898,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(4, 4, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 4),
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 4),
|
||||
TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
@ -3894,7 +3906,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(1, 1, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 1),
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 1),
|
||||
TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
@ -3902,7 +3914,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->pushInt
|
||||
(c->loadz
|
||||
(2, 2, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 2),
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 2),
|
||||
TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
@ -3910,21 +3922,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->pushLong
|
||||
(c->load
|
||||
(8, 8, c->memory
|
||||
(array, Compiler::FloatType, ArrayBody, index, 8), 8));
|
||||
(array, Compiler::FloatType, TargetArrayBody, index, 8), 8));
|
||||
break;
|
||||
|
||||
case laload:
|
||||
frame->pushLong
|
||||
(c->load
|
||||
(8, 8, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 8), 8));
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 8), 8));
|
||||
break;
|
||||
|
||||
case saload:
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(2, 2, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 2),
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 2),
|
||||
TargetBytesPerWord));
|
||||
break;
|
||||
}
|
||||
@ -3956,7 +3968,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
}
|
||||
|
||||
if (CheckArrayBounds) {
|
||||
c->checkBounds(array, ArrayLength, index, aioobThunk(t));
|
||||
c->checkBounds(array, TargetArrayLength, index, aioobThunk(t));
|
||||
}
|
||||
|
||||
switch (instruction) {
|
||||
@ -3969,7 +3981,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
Compiler::VoidType,
|
||||
4, c->register_(t->arch->thread()), array,
|
||||
c->add
|
||||
(4, c->constant(ArrayBody, Compiler::IntegerType),
|
||||
(4, c->constant(TargetArrayBody, Compiler::IntegerType),
|
||||
c->shl
|
||||
(4, c->constant(log(TargetBytesPerWord), Compiler::IntegerType),
|
||||
index)),
|
||||
@ -3979,38 +3991,38 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
case fastore:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 4, c->memory
|
||||
(array, Compiler::FloatType, ArrayBody, index, 4));
|
||||
(array, Compiler::FloatType, TargetArrayBody, index, 4));
|
||||
break;
|
||||
|
||||
case iastore:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 4, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 4));
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 4));
|
||||
break;
|
||||
|
||||
case bastore:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 1, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 1));
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 1));
|
||||
break;
|
||||
|
||||
case castore:
|
||||
case sastore:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 2, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 2));
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 2));
|
||||
break;
|
||||
|
||||
case dastore:
|
||||
c->store
|
||||
(8, value, 8, c->memory
|
||||
(array, Compiler::FloatType, ArrayBody, index, 8));
|
||||
(array, Compiler::FloatType, TargetArrayBody, index, 8));
|
||||
break;
|
||||
|
||||
case lastore:
|
||||
c->store
|
||||
(8, value, 8, c->memory
|
||||
(array, Compiler::IntegerType, ArrayBody, index, 8));
|
||||
(array, Compiler::IntegerType, TargetArrayBody, index, 8));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
@ -4082,7 +4094,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
(c->load
|
||||
(TargetBytesPerWord, TargetBytesPerWord,
|
||||
c->memory
|
||||
(frame->popObject(), Compiler::IntegerType, ArrayLength, 0, 1),
|
||||
(frame->popObject(), Compiler::IntegerType,
|
||||
TargetArrayLength, 0, 1),
|
||||
TargetBytesPerWord));
|
||||
} break;
|
||||
|
||||
@ -4425,54 +4438,56 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(1, 1, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1),
|
||||
TargetBytesPerWord));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1), TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
frame->pushInt
|
||||
(c->loadz
|
||||
(2, 2, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1),
|
||||
TargetBytesPerWord));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1), TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
case ShortField:
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(2, 2, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1),
|
||||
TargetBytesPerWord));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1), TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(4, 4, c->memory
|
||||
(table, Compiler::FloatType, fieldOffset(t, field), 0, 1),
|
||||
TargetBytesPerWord));
|
||||
(table, Compiler::FloatType, targetFieldOffset
|
||||
(context, field), 0, 1), TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
case IntField:
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(4, 4, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1),
|
||||
TargetBytesPerWord));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1), TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
frame->pushLong
|
||||
(c->load
|
||||
(8, 8, c->memory
|
||||
(table, Compiler::FloatType, fieldOffset(t, field), 0, 1), 8));
|
||||
(table, Compiler::FloatType, targetFieldOffset
|
||||
(context, field), 0, 1), 8));
|
||||
break;
|
||||
|
||||
case LongField:
|
||||
frame->pushLong
|
||||
(c->load
|
||||
(8, 8, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1), 8));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1), 8));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
@ -4480,8 +4495,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
(c->load
|
||||
(TargetBytesPerWord, TargetBytesPerWord,
|
||||
c->memory
|
||||
(table, Compiler::ObjectType, fieldOffset(t, field), 0, 1),
|
||||
TargetBytesPerWord));
|
||||
(table, Compiler::ObjectType, targetFieldOffset
|
||||
(context, field), 0, 1), TargetBytesPerWord));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -4974,8 +4989,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
if (LIKELY(methodVirtual(t, target))) {
|
||||
unsigned parameterFootprint = methodParameterFootprint(t, target);
|
||||
|
||||
unsigned offset = ClassVtable
|
||||
+ (methodOffset(t, target) * BytesPerWord);
|
||||
unsigned offset = TargetClassVtable
|
||||
+ (methodOffset(t, target) * TargetBytesPerWord);
|
||||
|
||||
Compiler::Operand* instance = c->peek(1, parameterFootprint - 1);
|
||||
|
||||
@ -4985,7 +5000,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
(c->memory
|
||||
(c->and_
|
||||
(TargetBytesPerWord, c->constant
|
||||
(PointerMask, Compiler::IntegerType),
|
||||
(TargetPointerMask, Compiler::IntegerType),
|
||||
c->memory(instance, Compiler::ObjectType, 0, 0, 1)),
|
||||
Compiler::ObjectType, offset, 0, 1),
|
||||
tailCall ? Compiler::TailJump : 0,
|
||||
@ -5635,38 +5650,44 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
case BooleanField:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 1, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1));
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
case ShortField:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 2, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1));
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 4, c->memory
|
||||
(table, Compiler::FloatType, fieldOffset(t, field), 0, 1));
|
||||
(table, Compiler::FloatType, targetFieldOffset
|
||||
(context, field), 0, 1));
|
||||
break;
|
||||
|
||||
case IntField:
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 4, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
c->store
|
||||
(8, value, 8, c->memory
|
||||
(table, Compiler::FloatType, fieldOffset(t, field), 0, 1));
|
||||
(table, Compiler::FloatType, targetFieldOffset
|
||||
(context, field), 0, 1));
|
||||
break;
|
||||
|
||||
case LongField:
|
||||
c->store
|
||||
(8, value, 8, c->memory
|
||||
(table, Compiler::IntegerType, fieldOffset(t, field), 0, 1));
|
||||
(table, Compiler::IntegerType, targetFieldOffset
|
||||
(context, field), 0, 1));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
@ -5679,14 +5700,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
0,
|
||||
Compiler::VoidType,
|
||||
4, c->register_(t->arch->thread()), table,
|
||||
c->constant(fieldOffset(t, field), Compiler::IntegerType),
|
||||
c->constant(targetFieldOffset(context, field),
|
||||
Compiler::IntegerType),
|
||||
value);
|
||||
} else {
|
||||
c->call
|
||||
(c->constant(getThunk(t, setThunk), Compiler::AddressType),
|
||||
0, 0, 0, Compiler::VoidType,
|
||||
4, c->register_(t->arch->thread()), table,
|
||||
c->constant(fieldOffset(t, field), Compiler::IntegerType),
|
||||
c->constant(targetFieldOffset(context, field),
|
||||
Compiler::IntegerType),
|
||||
value);
|
||||
}
|
||||
break;
|
||||
@ -6797,7 +6820,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context)
|
||||
// of cycles if another thread compiles the same method in parallel,
|
||||
// which might be mitigated by fine-grained, per-method locking):
|
||||
c->compile(context->leaf ? 0 : stackOverflowThunk(t),
|
||||
difference(&(t->stackLimit), t));
|
||||
TargetThreadStackLimit);
|
||||
|
||||
// we must acquire the class lock here at the latest
|
||||
|
||||
@ -6806,7 +6829,8 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context)
|
||||
|
||||
unsigned total = pad(codeSize) + pad(c->poolSize()) + TargetBytesPerWord;
|
||||
|
||||
uintptr_t* code = static_cast<uintptr_t*>(allocator->allocate(total));
|
||||
target_uintptr_t* code = static_cast<target_uintptr_t*>
|
||||
(allocator->allocate(total));
|
||||
code[0] = codeSize;
|
||||
uint8_t* start = reinterpret_cast<uint8_t*>(code + 1);
|
||||
|
||||
@ -6817,8 +6841,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context)
|
||||
if (context->objectPool) {
|
||||
object pool = allocate3
|
||||
(t, allocator, Machine::ImmortalAllocation,
|
||||
FixedSizeOfArray
|
||||
+ ((context->objectPoolCount + 1) * TargetBytesPerWord),
|
||||
FixedSizeOfArray + ((context->objectPoolCount + 1) * BytesPerWord),
|
||||
true);
|
||||
|
||||
initArray(t, pool, context->objectPoolCount + 1);
|
||||
@ -6829,7 +6852,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context)
|
||||
|
||||
unsigned i = 1;
|
||||
for (PoolElement* p = context->objectPool; p; p = p->next) {
|
||||
unsigned offset = ArrayBody + ((i++) * TargetBytesPerWord);
|
||||
unsigned offset = ArrayBody + ((i++) * BytesPerWord);
|
||||
|
||||
p->address = reinterpret_cast<uintptr_t>(pool) + offset;
|
||||
|
||||
@ -8318,13 +8341,30 @@ class MyProcessor: public Processor {
|
||||
t->init();
|
||||
|
||||
if (false) {
|
||||
fprintf(stderr, "%d\n", difference(&(t->stack), t));
|
||||
fprintf(stderr, "%d\n", difference(&(t->scratch), t));
|
||||
fprintf(stderr, "%d\n", difference(&(t->continuation), t));
|
||||
fprintf(stderr, "%d\n", difference(&(t->exception), t));
|
||||
fprintf(stderr, "%d\n", difference(&(t->exceptionStackAdjustment), t));
|
||||
fprintf(stderr, "%d\n", difference(&(t->exceptionOffset), t));
|
||||
fprintf(stderr, "%d\n", difference(&(t->exceptionHandler), t));
|
||||
fprintf(stderr, "stack %d\n",
|
||||
difference(&(t->stack), t));
|
||||
fprintf(stderr, "scratch %d\n",
|
||||
difference(&(t->scratch), t));
|
||||
fprintf(stderr, "continuation %d\n",
|
||||
difference(&(t->continuation), t));
|
||||
fprintf(stderr, "exception %d\n",
|
||||
difference(&(t->exception), t));
|
||||
fprintf(stderr, "exceptionStackAdjustment %d\n",
|
||||
difference(&(t->exceptionStackAdjustment), t));
|
||||
fprintf(stderr, "exceptionOffset %d\n",
|
||||
difference(&(t->exceptionOffset), t));
|
||||
fprintf(stderr, "exceptionHandler %d\n",
|
||||
difference(&(t->exceptionHandler), t));
|
||||
fprintf(stderr, "tailAddress %d\n",
|
||||
difference(&(t->tailAddress), t));
|
||||
fprintf(stderr, "stackLimit %d\n",
|
||||
difference(&(t->stackLimit), t));
|
||||
fprintf(stderr, "ip %d\n",
|
||||
difference(&(t->ip), t));
|
||||
fprintf(stderr, "virtualCallTarget %d\n",
|
||||
difference(&(t->virtualCallTarget), t));
|
||||
fprintf(stderr, "virtualCallIndex %d\n",
|
||||
difference(&(t->virtualCallIndex), t));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -8671,10 +8711,10 @@ class MyProcessor: public Processor {
|
||||
|
||||
virtual void compileMethod(Thread* vmt, Zone* zone, object* constants,
|
||||
object* calls, DelayedPromise** addresses,
|
||||
object method)
|
||||
object method, OffsetResolver* resolver)
|
||||
{
|
||||
MyThread* t = static_cast<MyThread*>(vmt);
|
||||
BootContext bootContext(t, *constants, *calls, *addresses, zone);
|
||||
BootContext bootContext(t, *constants, *calls, *addresses, zone, resolver);
|
||||
|
||||
compile(t, &codeAllocator, &bootContext, method);
|
||||
|
||||
@ -8689,6 +8729,17 @@ class MyProcessor: public Processor {
|
||||
bootImage->virtualThunks = w->visitRoot(root(t, VirtualThunks));
|
||||
}
|
||||
|
||||
virtual void normalizeVirtualThunks(Thread* t) {
|
||||
for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks));
|
||||
i += 2)
|
||||
{
|
||||
if (wordArrayBody(t, root(t, VirtualThunks), i)) {
|
||||
wordArrayBody(t, root(t, VirtualThunks), i)
|
||||
-= reinterpret_cast<uintptr_t>(codeAllocator.base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) {
|
||||
bootImage->codeSize = codeAllocator.offset;
|
||||
bootImage->callCount = callTableSize;
|
||||
@ -8704,7 +8755,7 @@ class MyProcessor: public Processor {
|
||||
table[index++] = callNodeAddress(t, p)
|
||||
- reinterpret_cast<uintptr_t>(codeAllocator.base);
|
||||
table[index++] = w->map()->find(callNodeTarget(t, p))
|
||||
| (static_cast<unsigned>(callNodeFlags(t, p)) << BootShift);
|
||||
| (static_cast<unsigned>(callNodeFlags(t, p)) << TargetBootShift);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8989,7 +9040,8 @@ insertCallNode(MyThread* t, object node)
|
||||
}
|
||||
|
||||
object
|
||||
makeClassMap(Thread* t, unsigned* table, unsigned count, uintptr_t* heap)
|
||||
makeClassMap(Thread* t, unsigned* table, unsigned count,
|
||||
uintptr_t* heap)
|
||||
{
|
||||
object array = makeArray(t, nextPowerOfTwo(count));
|
||||
object map = makeHashMap(t, 0, array);
|
||||
@ -9068,6 +9120,7 @@ fixupHeap(MyThread* t UNUSED, uintptr_t* map, unsigned size, uintptr_t* heap)
|
||||
for (unsigned bit = 0; bit < BitsPerWord; ++bit) {
|
||||
if (w & (static_cast<uintptr_t>(1) << bit)) {
|
||||
unsigned index = indexOf(word, bit);
|
||||
|
||||
uintptr_t* p = heap + index;
|
||||
assert(t, *p);
|
||||
|
||||
@ -9103,6 +9156,10 @@ fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
|
||||
if (oldValue & BootHeapOffset) {
|
||||
newValue = reinterpret_cast<uintptr_t>
|
||||
(heap + (oldValue & BootMask) - 1);
|
||||
|
||||
// fprintf(stderr, "constant marked %d %d\n",
|
||||
// index, static_cast<unsigned>(oldValue));
|
||||
|
||||
} else {
|
||||
newValue = reinterpret_cast<uintptr_t>
|
||||
(code + (oldValue & BootMask));
|
||||
@ -9130,12 +9187,11 @@ fixupMethods(Thread* t, object map, BootImage* image, uint8_t* code)
|
||||
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
||||
object method = arrayBody(t, classMethodTable(t, c), i);
|
||||
if (methodCode(t, method)) {
|
||||
assert(t, (methodCompiled(t, method) - image->codeBase)
|
||||
<= image->codeSize);
|
||||
assert(t, methodCompiled(t, method)
|
||||
<= static_cast<int32_t>(image->codeSize));
|
||||
|
||||
codeCompiled(t, methodCode(t, method))
|
||||
= (methodCompiled(t, method) - image->codeBase)
|
||||
+ reinterpret_cast<uintptr_t>(code);
|
||||
= methodCompiled(t, method) + reinterpret_cast<uintptr_t>(code);
|
||||
|
||||
if (DebugCompile) {
|
||||
logCompile
|
||||
@ -9203,13 +9259,13 @@ fixupThunks(MyThread* t, BootImage* image, uint8_t* code)
|
||||
}
|
||||
|
||||
void
|
||||
fixupVirtualThunks(MyThread* t, BootImage* image, uint8_t* code)
|
||||
fixupVirtualThunks(MyThread* t, uint8_t* code)
|
||||
{
|
||||
for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks)); i += 2)
|
||||
{
|
||||
if (wordArrayBody(t, root(t, VirtualThunks), i)) {
|
||||
wordArrayBody(t, root(t, VirtualThunks), i)
|
||||
= (wordArrayBody(t, root(t, VirtualThunks), i) - image->codeBase)
|
||||
= wordArrayBody(t, root(t, VirtualThunks), i)
|
||||
+ reinterpret_cast<uintptr_t>(code);
|
||||
}
|
||||
}
|
||||
@ -9293,7 +9349,7 @@ boot(MyThread* t, BootImage* image)
|
||||
|
||||
fixupThunks(t, image, code);
|
||||
|
||||
fixupVirtualThunks(t, image, code);
|
||||
fixupVirtualThunks(t, code);
|
||||
|
||||
fixupMethods
|
||||
(t, classLoaderMap(t, root(t, Machine::BootLoader)), image, code);
|
||||
@ -9337,7 +9393,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = defaultContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
a->saveFrame(TargetThreadStack, TargetThreadIp);
|
||||
|
||||
p->thunks.default_.frameSavedOffset = a->length();
|
||||
|
||||
@ -9369,19 +9425,19 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
TargetBytesPerWord, RegisterOperand, &class_);
|
||||
|
||||
Assembler::Memory virtualCallTargetDst
|
||||
(t->arch->thread(), difference(&(t->virtualCallTarget), t));
|
||||
(t->arch->thread(), TargetThreadVirtualCallTarget);
|
||||
|
||||
a->apply(Move, TargetBytesPerWord, RegisterOperand, &class_,
|
||||
TargetBytesPerWord, MemoryOperand, &virtualCallTargetDst);
|
||||
|
||||
Assembler::Register index(t->arch->virtualCallIndex());
|
||||
Assembler::Memory virtualCallIndex
|
||||
(t->arch->thread(), difference(&(t->virtualCallIndex), t));
|
||||
(t->arch->thread(), TargetThreadVirtualCallIndex);
|
||||
|
||||
a->apply(Move, TargetBytesPerWord, RegisterOperand, &index,
|
||||
TargetBytesPerWord, MemoryOperand, &virtualCallIndex);
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
a->saveFrame(TargetThreadStack, TargetThreadIp);
|
||||
|
||||
p->thunks.defaultVirtual.frameSavedOffset = a->length();
|
||||
|
||||
@ -9403,7 +9459,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = nativeContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
a->saveFrame(TargetThreadStack, TargetThreadIp);
|
||||
|
||||
p->thunks.native.frameSavedOffset = a->length();
|
||||
|
||||
@ -9414,7 +9470,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
a->apply(LongCall, TargetBytesPerWord, ConstantOperand, &proc);
|
||||
|
||||
a->popFrameAndUpdateStackAndReturn
|
||||
(t->arch->alignFrameSize(1), difference(&(t->stack), t));
|
||||
(t->arch->alignFrameSize(1), TargetThreadStack);
|
||||
|
||||
p->thunks.native.length = a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
@ -9423,7 +9479,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = aioobContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
a->saveFrame(TargetThreadStack, TargetThreadIp);
|
||||
|
||||
p->thunks.aioob.frameSavedOffset = a->length();
|
||||
|
||||
@ -9440,7 +9496,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = stackOverflowContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
a->saveFrame(TargetThreadStack, TargetThreadIp);
|
||||
|
||||
p->thunks.stackOverflow.frameSavedOffset = a->length();
|
||||
|
||||
@ -9457,7 +9513,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = tableContext.context.assembler;
|
||||
|
||||
a->saveFrame(difference(&(t->stack), t), difference(&(t->ip), t));
|
||||
a->saveFrame(TargetThreadStack, TargetThreadIp);
|
||||
|
||||
p->thunks.table.frameSavedOffset = a->length();
|
||||
|
||||
|
@ -469,7 +469,7 @@ class PoolPromise: public Promise {
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<int64_t>
|
||||
(c->machineCode + pad(c->machineCodeSize)
|
||||
(c->machineCode + pad(c->machineCodeSize, TargetBytesPerWord)
|
||||
+ (key * TargetBytesPerWord));
|
||||
}
|
||||
|
||||
@ -6949,15 +6949,15 @@ class MyCompiler: public Compiler {
|
||||
|
||||
int i = 0;
|
||||
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
|
||||
intptr_t* target = reinterpret_cast<intptr_t*>
|
||||
(c.machineCode + pad(c.machineCodeSize) + i);
|
||||
target_intptr_t* target = reinterpret_cast<target_intptr_t*>
|
||||
(c.machineCode + pad(c.machineCodeSize, TargetBytesPerWord) + i);
|
||||
|
||||
if (n->promise->resolved()) {
|
||||
*target = n->promise->value();
|
||||
} else {
|
||||
class Listener: public Promise::Listener {
|
||||
public:
|
||||
Listener(intptr_t* target): target(target){ }
|
||||
Listener(target_intptr_t* target): target(target){ }
|
||||
|
||||
virtual bool resolve(int64_t value, void** location) {
|
||||
*target = value;
|
||||
@ -6965,7 +6965,7 @@ class MyCompiler: public Compiler {
|
||||
return true;
|
||||
}
|
||||
|
||||
intptr_t* target;
|
||||
target_intptr_t* target;
|
||||
};
|
||||
new (n->promise->listen(sizeof(Listener))) Listener(target);
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ class Fixie {
|
||||
}
|
||||
|
||||
static unsigned maskSize(unsigned size, bool hasMask) {
|
||||
return hasMask * ceiling(size, BytesPerWord) * BytesPerWord;
|
||||
return hasMask * ceiling(size, BitsPerWord) * BytesPerWord;
|
||||
}
|
||||
|
||||
static unsigned totalSize(unsigned size, bool hasMask) {
|
||||
|
@ -3067,7 +3067,7 @@ class MyProcessor: public Processor {
|
||||
}
|
||||
|
||||
virtual void compileMethod(vm::Thread*, Zone*, object*, object*,
|
||||
DelayedPromise**, object)
|
||||
DelayedPromise**, object, OffsetResolver*)
|
||||
{
|
||||
abort(s);
|
||||
}
|
||||
@ -3076,6 +3076,10 @@ class MyProcessor: public Processor {
|
||||
abort(s);
|
||||
}
|
||||
|
||||
virtual void normalizeVirtualThunks(vm::Thread*) {
|
||||
abort(s);
|
||||
}
|
||||
|
||||
virtual unsigned* makeCallTable(vm::Thread*, HeapWalker*) {
|
||||
abort(s);
|
||||
}
|
||||
|
@ -122,11 +122,15 @@ class Processor {
|
||||
|
||||
virtual void
|
||||
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
|
||||
DelayedPromise** addresses, object method) = 0;
|
||||
DelayedPromise** addresses, object method,
|
||||
OffsetResolver* resolver) = 0;
|
||||
|
||||
virtual void
|
||||
visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||
|
||||
virtual void
|
||||
normalizeVirtualThunks(Thread* t) = 0;
|
||||
|
||||
virtual unsigned*
|
||||
makeCallTable(Thread* t, HeapWalker* w) = 0;
|
||||
|
||||
|
43
src/target.h
43
src/target.h
@ -42,25 +42,62 @@ namespace vm {
|
||||
#ifdef TARGET_BYTES_PER_WORD
|
||||
# if (TARGET_BYTES_PER_WORD == 8)
|
||||
# define TARGET_VW(v) TARGET_V8(v)
|
||||
|
||||
typedef uint64_t target_uintptr_t;
|
||||
typedef int64_t target_intptr_t;
|
||||
|
||||
const unsigned TargetBytesPerWord = 8;
|
||||
|
||||
const unsigned TargetThreadTailAddress = 2272;
|
||||
const unsigned TargetThreadStackLimit = 2336;
|
||||
const unsigned TargetThreadStack = 2224;
|
||||
const unsigned TargetThreadIp = 2216;
|
||||
const unsigned TargetThreadVirtualCallTarget = 2280;
|
||||
const unsigned TargetThreadVirtualCallIndex = 2288;
|
||||
|
||||
const unsigned TargetClassFixedSize = 12;
|
||||
const unsigned TargetClassArrayElementSize = 14;
|
||||
const unsigned TargetClassVtable = 128;
|
||||
|
||||
const unsigned TargetFieldOffset = 12;
|
||||
|
||||
# elif (TARGET_BYTES_PER_WORD == 4)
|
||||
# define TARGET_VW(v) TARGET_V4(v)
|
||||
|
||||
typedef uint32_t target_uintptr_t;
|
||||
typedef int32_t target_intptr_t;
|
||||
|
||||
const unsigned TargetBytesPerWord = 4;
|
||||
|
||||
const unsigned TargetThreadTailAddress = 2172;
|
||||
const unsigned TargetThreadStackLimit = 2204;
|
||||
const unsigned TargetThreadStack = 2148;
|
||||
const unsigned TargetThreadIp = 2144;
|
||||
const unsigned TargetThreadVirtualCallTarget = 2176;
|
||||
const unsigned TargetThreadVirtualCallIndex = 2180;
|
||||
|
||||
const unsigned TargetClassFixedSize = 8;
|
||||
const unsigned TargetClassArrayElementSize = 10;
|
||||
const unsigned TargetClassVtable = 68;
|
||||
|
||||
const unsigned TargetFieldOffset = 8;
|
||||
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
#else
|
||||
typedef uintptr_t target_uintptr_t;
|
||||
typedef intptr_t target_intptr_t;
|
||||
const unsigned TargetBytesPerWord = BytesPerWord;
|
||||
# error
|
||||
#endif
|
||||
|
||||
const unsigned TargetBitsPerWord = TargetBytesPerWord * 8;
|
||||
|
||||
const uintptr_t TargetPointerMask
|
||||
= ((~static_cast<target_uintptr_t>(0)) / TargetBytesPerWord)
|
||||
* TargetBytesPerWord;
|
||||
|
||||
const unsigned TargetArrayLength = TargetBytesPerWord;
|
||||
const unsigned TargetArrayBody = TargetBytesPerWord * 2;
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//TARGET_H
|
||||
|
@ -2116,6 +2116,9 @@ writeMap(Output* out, Object* type)
|
||||
case Object::Scalar: {
|
||||
out->write("Type_");
|
||||
out->write(memberTypeEnumName(m));
|
||||
if (memberNoGC(m)) {
|
||||
out->write("_nogc");
|
||||
}
|
||||
} break;
|
||||
|
||||
case Object::Array: {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define VECTOR_H
|
||||
|
||||
#include "system.h"
|
||||
#include "target.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
@ -103,6 +104,10 @@ class Vector {
|
||||
append(&v, 4);
|
||||
}
|
||||
|
||||
void appendTargetAddress(target_uintptr_t v) {
|
||||
append(&v, TargetBytesPerWord);
|
||||
}
|
||||
|
||||
void appendAddress(uintptr_t v) {
|
||||
append(&v, BytesPerWord);
|
||||
}
|
||||
|
12
src/x86.cpp
12
src/x86.cpp
@ -74,13 +74,13 @@ const unsigned StackAlignmentInBytes = 16;
|
||||
const unsigned StackAlignmentInWords = StackAlignmentInBytes / TargetBytesPerWord;
|
||||
|
||||
bool
|
||||
isInt8(intptr_t v)
|
||||
isInt8(target_intptr_t v)
|
||||
{
|
||||
return v == static_cast<int8_t>(v);
|
||||
}
|
||||
|
||||
bool
|
||||
isInt32(intptr_t v)
|
||||
isInt32(target_intptr_t v)
|
||||
{
|
||||
return v == static_cast<int32_t>(v);
|
||||
}
|
||||
@ -958,11 +958,11 @@ moveCR2(Context* c, UNUSED unsigned aSize, Assembler::Constant* a,
|
||||
maybeRex(c, TargetBytesPerWord, b);
|
||||
opcode(c, 0xb8 + regCode(b));
|
||||
if (a->value->resolved()) {
|
||||
c->code.appendAddress(a->value->value());
|
||||
c->code.appendTargetAddress(a->value->value());
|
||||
} else {
|
||||
appendImmediateTask
|
||||
(c, a->value, offset(c), TargetBytesPerWord, promiseOffset);
|
||||
c->code.appendAddress(static_cast<uintptr_t>(0));
|
||||
c->code.appendTargetAddress(static_cast<target_uintptr_t>(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3446,7 +3446,7 @@ class MyAssembler: public Assembler {
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand,
|
||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size),
|
||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord),
|
||||
RegisterOperand,
|
||||
&dst);
|
||||
} else {
|
||||
@ -3455,7 +3455,7 @@ class MyAssembler: public Assembler {
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].size,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].type,
|
||||
RUNTIME_ARRAY_BODY(arguments)[i].operand,
|
||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size),
|
||||
pad(RUNTIME_ARRAY_BODY(arguments)[i].size, TargetBytesPerWord),
|
||||
MemoryOperand,
|
||||
&dst);
|
||||
offset += ceiling
|
||||
|
Loading…
Reference in New Issue
Block a user