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:
Joel Dice 2015-03-12 08:37:49 -06:00
parent 1f8f0b2194
commit 6c7ff9874e
3 changed files with 70 additions and 16 deletions

View File

@ -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;

View File

@ -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 {

View File

@ -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)