From 6c7ff9874e6e09ce7a0f72e77ce6da8c0d648c81 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 12 Mar 2015 08:37:49 -0600 Subject: [PATCH] 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. --- src/machine.cpp | 15 +++++--- src/tools/type-generator/io.h | 11 +++++- src/tools/type-generator/main.cpp | 60 +++++++++++++++++++++++++------ 3 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 8a7053e98f..640b189785 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -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(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(objectMask)) { + and super->objectMask()->length() == maskSize + and memcmp(super->objectMask()->body().begin(), + objectMask, + sizeof(uint32_t) * maskSize) == 0) { mask = vm::type(t, static_cast(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; diff --git a/src/tools/type-generator/io.h b/src/tools/type-generator/io.h index f0ae32135f..74a07a2f91 100644 --- a/src/tools/type-generator/io.h +++ b/src/tools/type-generator/io.h @@ -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 { diff --git a/src/tools/type-generator/main.cpp b/src/tools/type-generator/main.cpp index c981d13194..ad58c07139 100644 --- a/src/tools/type-generator/main.cpp +++ b/src/tools/type-generator/main.cpp @@ -25,6 +25,7 @@ #include #include +#include #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& 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 typeObjectMask(Module& module, Class* cl) +{ + std::vector 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& 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& 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 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)