mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
handle arbitrary class sizes in type-generator/main.cpp
OpenJDK 8 includes a core class (java.lang.Thread) which so many fields that it exceeds the class size limit in type-generator dictated by the logic responsible for calculating each class's GC object mask, at least on 32-bit systems. There was no fundamental need for this limit -- it just made the code simpler. This commit removes the above limit at the cost of slightly more complicated code. The original motivation for this change is that the platform=macosx arch=i386 openjdk=$jdk8 build was failing. However, there doesn't seem to be a prebuild JDK 8 for 32-bit OS X anywhere on the Internet, nor is there any obvious way to build one on a modern Mac, so it's safe to say we won't be supporting this combination anyway. The problem also occurs on Linux and Windows, though, so it needs to be fixed.
This commit is contained in:
parent
1f8f0b2194
commit
6c7ff9874e
@ -3101,7 +3101,7 @@ void removeString(Thread* t, object o)
|
||||
void bootClass(Thread* t,
|
||||
Gc::Type type,
|
||||
int superType,
|
||||
uint32_t objectMask,
|
||||
uint32_t* objectMask,
|
||||
unsigned fixedSize,
|
||||
unsigned arrayElementSize,
|
||||
unsigned vtableLength)
|
||||
@ -3109,15 +3109,20 @@ void bootClass(Thread* t,
|
||||
GcClass* super
|
||||
= (superType >= 0 ? vm::type(t, static_cast<Gc::Type>(superType)) : 0);
|
||||
|
||||
unsigned maskSize
|
||||
= ceilingDivide(fixedSize + arrayElementSize, 32 * BytesPerWord);
|
||||
|
||||
GcIntArray* mask;
|
||||
if (objectMask) {
|
||||
if (super and super->objectMask()
|
||||
and super->objectMask()->body()[0]
|
||||
== static_cast<int32_t>(objectMask)) {
|
||||
and super->objectMask()->length() == maskSize
|
||||
and memcmp(super->objectMask()->body().begin(),
|
||||
objectMask,
|
||||
sizeof(uint32_t) * maskSize) == 0) {
|
||||
mask = vm::type(t, static_cast<Gc::Type>(superType))->objectMask();
|
||||
} else {
|
||||
mask = makeIntArray(t, 1);
|
||||
mask->body()[0] = objectMask;
|
||||
mask = makeIntArray(t, maskSize);
|
||||
memcpy(mask->body().begin(), objectMask, sizeof(uint32_t) * maskSize);
|
||||
}
|
||||
} else {
|
||||
mask = 0;
|
||||
|
@ -120,7 +120,7 @@ class Output {
|
||||
|
||||
virtual void write(const std::string& s) = 0;
|
||||
|
||||
void write(int i)
|
||||
void write(int32_t i)
|
||||
{
|
||||
static const int Size = 32;
|
||||
char s[Size];
|
||||
@ -128,6 +128,15 @@ class Output {
|
||||
assert(c > 0 and c < Size);
|
||||
write(s);
|
||||
}
|
||||
|
||||
void writeUnsigned(uint32_t i)
|
||||
{
|
||||
static const int Size = 32;
|
||||
char s[Size];
|
||||
int c UNUSED = vm::snprintf(s, Size, "%u", i);
|
||||
assert(c > 0 and c < Size);
|
||||
write(s);
|
||||
}
|
||||
};
|
||||
|
||||
class FileOutput : public Output {
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include <avian/util/arg-parser.h>
|
||||
#include <avian/util/stream.h>
|
||||
#include <avian/util/math.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "sexpr.h"
|
||||
@ -1326,17 +1327,23 @@ void set(uint32_t* mask, unsigned index)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t typeObjectMask(Module& module, Class* cl)
|
||||
void set(std::vector<uint32_t>& mask, unsigned index)
|
||||
{
|
||||
assert(cl->fixedSize + (cl->arrayField ? cl->arrayField->elementSize : 0)
|
||||
< 32 * BytesPerWord);
|
||||
set(&(mask[index / 32]), index % 32);
|
||||
}
|
||||
|
||||
uint32_t mask = 1;
|
||||
std::vector<uint32_t> typeObjectMask(Module& module, Class* cl)
|
||||
{
|
||||
std::vector<uint32_t> mask(ceilingDivide(
|
||||
cl->fixedSize + (cl->arrayField ? cl->arrayField->elementSize : 0),
|
||||
32 * BytesPerWord));
|
||||
|
||||
set(mask, 0);
|
||||
|
||||
for (const auto f : cl->fields) {
|
||||
unsigned offset = f->offset / BytesPerWord;
|
||||
if (isFieldGcVisible(module, f)) {
|
||||
set(&mask, offset);
|
||||
set(mask, offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1344,13 +1351,28 @@ uint32_t typeObjectMask(Module& module, Class* cl)
|
||||
Field* f = cl->arrayField;
|
||||
unsigned offset = f->offset / BytesPerWord;
|
||||
if (isFieldGcVisible(module, f)) {
|
||||
set(&mask, offset);
|
||||
set(mask, offset);
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
bool trivialMask(const std::vector<uint32_t>& mask)
|
||||
{
|
||||
if (mask[0] != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < mask.size(); ++i) {
|
||||
if (mask[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void writeInitialization(Output* out,
|
||||
Module& module,
|
||||
std::set<Class*>& alreadyInited,
|
||||
@ -1363,6 +1385,24 @@ void writeInitialization(Output* out,
|
||||
if (cl->super && cl->name != "intArray" && cl->name != "class") {
|
||||
writeInitialization(out, module, alreadyInited, cl->super);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> mask = typeObjectMask(module, cl);
|
||||
bool trivialMask = local::trivialMask(mask);
|
||||
if (trivialMask) {
|
||||
out->write("{ ");
|
||||
} else {
|
||||
out->write("{ uint32_t mask[");
|
||||
out->write(mask.size());
|
||||
out->write("] = { ");
|
||||
for (size_t i = 0; i < mask.size(); ++i) {
|
||||
out->writeUnsigned(mask[i]);
|
||||
if (i < mask.size() - 1) {
|
||||
out->write(", ");
|
||||
}
|
||||
}
|
||||
out->write(" };\n");
|
||||
}
|
||||
|
||||
out->write("bootClass(t, Gc::");
|
||||
out->write(capitalize(cl->name));
|
||||
out->write("Type, ");
|
||||
@ -1376,10 +1416,10 @@ void writeInitialization(Output* out,
|
||||
}
|
||||
out->write(", ");
|
||||
|
||||
if (typeObjectMask(module, cl) != 1) {
|
||||
out->write(typeObjectMask(module, cl));
|
||||
} else {
|
||||
if (trivialMask) {
|
||||
out->write("0");
|
||||
} else {
|
||||
out->write("mask");
|
||||
}
|
||||
out->write(", ");
|
||||
|
||||
@ -1390,7 +1430,7 @@ void writeInitialization(Output* out,
|
||||
out->write(", ");
|
||||
|
||||
out->write(cl->methods.size());
|
||||
out->write(");\n");
|
||||
out->write("); }\n");
|
||||
}
|
||||
|
||||
void writeInitializations(Output* out, Module& module)
|
||||
|
Loading…
Reference in New Issue
Block a user