disable use of SSE when compiling ahead-of-time

This commit is contained in:
Joel Dice 2009-10-10 17:46:43 -06:00
parent 38bf29300f
commit 44a6620aa1
8 changed files with 184 additions and 131 deletions

View File

@ -428,7 +428,7 @@ class Assembler {
};
Assembler::Architecture*
makeArchitecture(System* system);
makeArchitecture(System* system, bool useNativeFeatures);
Assembler*
makeAssembler(System* system, Allocator* allocator, Zone* zone,

View File

@ -386,7 +386,7 @@ main(int ac, const char** av)
System* s = makeSystem(0);
Heap* h = makeHeap(s, 128 * 1024 * 1024);
Finder* f = makeFinder(s, av[1], 0);
Processor* p = makeProcessor(s, h);
Processor* p = makeProcessor(s, h, false);
BootImage image;
const unsigned CodeCapacity = 32 * 1024 * 1024;

View File

@ -92,7 +92,8 @@ class MyThread: public Thread {
CallTrace* next;
};
MyThread(Machine* m, object javaThread, MyThread* parent):
MyThread(Machine* m, object javaThread, MyThread* parent,
bool useNativeFeatures):
Thread(m, javaThread, parent),
ip(0),
base(0),
@ -106,7 +107,9 @@ class MyThread: public Thread {
virtualCallIndex(0),
trace(0),
reference(0),
arch(parent ? parent->arch : makeArchitecture(m->system))
arch(parent
? parent->arch
: makeArchitecture(m->system, useNativeFeatures))
{
arch->acquire();
}
@ -786,30 +789,33 @@ class Context {
} else {
return local::getThunk(t, negateDoubleThunk);
}
case Float2Float:
if (size == 4 and resultSize == 8) {
return local::getThunk(t, floatToDoubleThunk);
} else if(size == 8 and resultSize == 4) {
} else if (size == 8 and resultSize == 4) {
return local::getThunk(t, doubleToFloatThunk);
}
case Float2Int:
if (size == 4 and resultSize == 4) {
return local::getThunk(t, floatToIntThunk);
} else if(size == 4 and resultSize == 8) {
} else if (size == 4 and resultSize == 8) {
return local::getThunk(t, floatToLongThunk);
} else if(size == 8 and resultSize == 4) {
} else if (size == 8 and resultSize == 4) {
return local::getThunk(t, doubleToIntThunk);
} else if(size == 8 and resultSize == 8) {
} else if (size == 8 and resultSize == 8) {
return local::getThunk(t, doubleToLongThunk);
}
case Int2Float:
if (size == 4 and resultSize == 4) {
return local::getThunk(t, intToFloatThunk);
} else if(size == 4 and resultSize == 8) {
} else if (size == 4 and resultSize == 8) {
return local::getThunk(t, intToDoubleThunk);
} else if(size == 8 and resultSize == 4) {
} else if (size == 8 and resultSize == 4) {
return local::getThunk(t, longToFloatThunk);
} else if(size == 8 and resultSize == 8) {
} else if (size == 8 and resultSize == 8) {
return local::getThunk(t, longToDoubleThunk);
}
@ -819,48 +825,71 @@ class Context {
abort(t);
}
virtual intptr_t getThunk(TernaryOperation op, unsigned size UNUSED,
unsigned resultSize)
virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned)
{
switch (op) {
case Divide:
if (resultSize == 8) {
if (size == 8) {
switch (op) {
case Divide:
return local::getThunk(t, divideLongThunk);
}
break;
case Remainder:
if (resultSize == 8) {
return local::getThunk(t, moduloLongThunk);
}
break;
case FloatAdd:
if(resultSize == 4) {
return local::getThunk(t, addFloatThunk);
} else {
case Remainder:
return local::getThunk(t, moduloLongThunk);
case FloatAdd:
return local::getThunk(t, addDoubleThunk);
}
case FloatSubtract:
if(resultSize == 4) {
return local::getThunk(t, subtractFloatThunk);
} else {
return local::getThunk(t, subtractDoubleThunk);
}
case FloatMultiply:
if(resultSize == 4) {
return local::getThunk(t, multiplyFloatThunk);
} else {
return local::getThunk(t, multiplyDoubleThunk);
}
case FloatDivide:
if(resultSize == 4) {
return local::getThunk(t, divideFloatThunk);
} else {
return local::getThunk(t, divideDoubleThunk);
}
default: break;
case FloatSubtract:
return local::getThunk(t, subtractDoubleThunk);
case FloatMultiply:
return local::getThunk(t, multiplyDoubleThunk);
case FloatDivide:
return local::getThunk(t, divideDoubleThunk);
case JumpIfFloatEqual:
case JumpIfFloatNotEqual:
case JumpIfFloatLess:
case JumpIfFloatGreater:
case JumpIfFloatLessOrEqual:
case JumpIfFloatGreaterOrUnordered:
case JumpIfFloatGreaterOrEqualOrUnordered:
return local::getThunk(t, compareDoublesGThunk);
case JumpIfFloatGreaterOrEqual:
case JumpIfFloatLessOrUnordered:
case JumpIfFloatLessOrEqualOrUnordered:
return local::getThunk(t, compareDoublesLThunk);
default: break;
}
} else if (size == 4) {
switch (op) {
case FloatAdd:
return local::getThunk(t, addFloatThunk);
case FloatSubtract:
return local::getThunk(t, subtractFloatThunk);
case FloatMultiply:
return local::getThunk(t, multiplyFloatThunk);
case FloatDivide:
return local::getThunk(t, divideFloatThunk);
case JumpIfFloatEqual:
case JumpIfFloatNotEqual:
case JumpIfFloatLess:
case JumpIfFloatGreater:
case JumpIfFloatLessOrEqual:
case JumpIfFloatGreaterOrUnordered:
case JumpIfFloatGreaterOrEqualOrUnordered:
return local::getThunk(t, compareFloatsGThunk);
case JumpIfFloatGreaterOrEqual:
case JumpIfFloatLessOrUnordered:
case JumpIfFloatLessOrEqualOrUnordered:
return local::getThunk(t, compareFloatsLThunk);
default: break;
}
}
abort(t);
@ -6784,7 +6813,7 @@ processor(MyThread* t);
class MyProcessor: public Processor {
public:
MyProcessor(System* s, Allocator* allocator):
MyProcessor(System* s, Allocator* allocator, bool useNativeFeatures):
s(s),
allocator(allocator),
defaultThunk(0),
@ -6792,7 +6821,6 @@ class MyProcessor: public Processor {
nativeThunk(0),
aioobThunk(0),
callTable(0),
callTableSize(0),
methodTree(0),
methodTreeSentinal(0),
objectPools(0),
@ -6801,15 +6829,19 @@ class MyProcessor: public Processor {
receiveMethod(0),
windMethod(0),
rewindMethod(0),
bootImage(0),
codeAllocator(s, 0, 0),
bootImage(0)
thunkSize(0),
callTableSize(0),
useNativeFeatures(useNativeFeatures)
{ }
virtual Thread*
makeThread(Machine* m, object javaThread, Thread* parent)
{
MyThread* t = new (m->heap->allocate(sizeof(MyThread)))
MyThread(m, javaThread, static_cast<MyThread*>(parent));
MyThread(m, javaThread, static_cast<MyThread*>(parent),
useNativeFeatures);
t->init();
if (false) {
@ -7275,9 +7307,7 @@ class MyProcessor: public Processor {
uint8_t* nativeThunk;
uint8_t* aioobThunk;
uint8_t* thunkTable;
unsigned thunkSize;
object callTable;
unsigned callTableSize;
object methodTree;
object methodTreeSentinal;
object objectPools;
@ -7286,9 +7316,12 @@ class MyProcessor: public Processor {
object receiveMethod;
object windMethod;
object rewindMethod;
BootImage* bootImage;
SegFaultHandler segFaultHandler;
FixedAllocator codeAllocator;
BootImage* bootImage;
unsigned thunkSize;
unsigned callTableSize;
bool useNativeFeatures;
};
object
@ -7485,7 +7518,7 @@ void
fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
uintptr_t* heap)
{
Assembler::Architecture* arch = makeArchitecture(t->m->system);
Assembler::Architecture* arch = makeArchitecture(t->m->system, false);
arch->acquire();
for (unsigned word = 0; word < size; ++word) {
@ -8092,10 +8125,10 @@ codeAllocator(MyThread* t)
namespace vm {
Processor*
makeProcessor(System* system, Allocator* allocator)
makeProcessor(System* system, Allocator* allocator, bool useNativeFeatures)
{
return new (allocator->allocate(sizeof(local::MyProcessor)))
local::MyProcessor(system, allocator);
local::MyProcessor(system, allocator, useNativeFeatures);
}
} // namespace vm

View File

@ -893,7 +893,7 @@ bool
uniqueSite(Context* c, Value* v, Site* s)
{
SiteIterator it(c, v);
Site* p = it.next();
Site* p UNUSED = it.next();
if (it.hasMore()) {
// the site is not this word's only site, but if the site is
// shared with the next word, it may be that word's only site
@ -1784,7 +1784,7 @@ class RegisterSite: public Site {
}
}
virtual unsigned registerMask(Context* c) {
virtual unsigned registerMask(Context* c UNUSED) {
assert(c, number != NoRegister);
return 1 << number;
@ -4266,6 +4266,37 @@ shouldJump(Context* c, TernaryOperation type, unsigned size, int64_t b,
}
}
TernaryOperation
thunkBranch(Context* c, TernaryOperation type)
{
switch (type) {
case JumpIfFloatEqual:
return JumpIfEqual;
case JumpIfFloatNotEqual:
return JumpIfNotEqual;
case JumpIfFloatLess:
case JumpIfFloatLessOrUnordered:
return JumpIfLess;
case JumpIfFloatGreater:
case JumpIfFloatGreaterOrUnordered:
return JumpIfGreater;
case JumpIfFloatLessOrEqual:
case JumpIfFloatLessOrEqualOrUnordered:
return JumpIfLessOrEqual;
case JumpIfFloatGreaterOrEqual:
case JumpIfFloatGreaterOrEqualOrUnordered:
return JumpIfGreaterOrEqual;
default:
abort(c);
}
}
class BranchEvent: public Event {
public:
BranchEvent(Context* c, TernaryOperation type, unsigned size,
@ -4354,7 +4385,7 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first,
0, 0, result, 4, argumentStack,
ceiling(size, BytesPerWord) * 2, 0);
appendBranch(c, JumpIfEqual, 4, value
appendBranch(c, thunkBranch(c, type), 4, value
(c, ValueGeneral, constantSite(c, static_cast<int64_t>(0))),
result, address);
} else {

View File

@ -3333,7 +3333,7 @@ class MyProcessor: public Processor {
namespace vm {
Processor*
makeProcessor(System* system, Allocator* allocator)
makeProcessor(System* system, Allocator* allocator, bool)
{
return new (allocator->allocate(sizeof(MyProcessor)))
MyProcessor(system, allocator);

View File

@ -2155,7 +2155,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
System* s = makeSystem(crashDumpDirectory);
Heap* h = makeHeap(s, heapLimit);
Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary);
Processor* p = makeProcessor(s, h);
Processor* p = makeProcessor(s, h, true);
const char** properties = static_cast<const char**>
(h->allocate(sizeof(const char*) * propertyCount));

View File

@ -180,7 +180,7 @@ class Processor {
};
Processor*
makeProcessor(System* system, Allocator* allocator);
makeProcessor(System* system, Allocator* allocator, bool useNativeFeatures);
} // namespace vm

View File

@ -15,10 +15,6 @@
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
#define CAST_BRANCH(x) reinterpret_cast<BranchOperationType>(x)
const bool DebugSSE = false;
const bool EnableSSE = true;
const bool EnableSSE2 = true;
using namespace vm;
namespace {
@ -150,9 +146,12 @@ typedef void (*BranchOperationType)
class ArchitectureContext {
public:
ArchitectureContext(System* s): s(s) { }
ArchitectureContext(System* s, bool useNativeFeatures):
s(s), useNativeFeatures(useNativeFeatures)
{ }
System* s;
bool useNativeFeatures;
OperationType operations[OperationCount];
UnaryOperationType unaryOperations[UnaryOperationCount
* OperandTypeCount];
@ -443,33 +442,22 @@ padding(AlignmentPadding* p, unsigned start, unsigned offset,
return padding;
}
extern "C"
bool detectFeature(unsigned ecx, unsigned edx);
extern "C" bool
detectFeature(unsigned ecx, unsigned edx);
bool
supportsSSE()
useSSE(ArchitectureContext* c)
{
static int supported = -1;
if(supported == -1) {
supported = EnableSSE and detectFeature(0, 0x2000000);
if(DebugSSE) {
fprintf(stderr, "sse %sdetected.\n", supported ? "" : "not ");
if (c->useNativeFeatures) {
static int supported = -1;
if (supported == -1) {
supported = detectFeature(0, 0x2000000) // SSE 1
and detectFeature(0, 0x4000000); // SSE 2
}
return supported;
} else {
return false;
}
return supported;
}
bool
supportsSSE2()
{
static int supported = -1;
if(supported == -1) {
supported = EnableSSE2 and detectFeature(0, 0x4000000);
if(DebugSSE) {
fprintf(stderr, "sse2 %sdetected.\n", supported ? "" : "not ");
}
}
return supported;
}
#define REX_W 0x48
@ -481,17 +469,17 @@ supportsSSE2()
void maybeRex(Context* c, unsigned size, int a, int index, int base,
bool always)
{
if(BytesPerWord == 8) {
if (BytesPerWord == 8) {
uint8_t byte;
if(size == 8) {
if (size == 8) {
byte = REX_W;
} else {
byte = REX_NONE;
}
if(a != NoRegister and (a & 8)) byte |= REX_R;
if(index != NoRegister and (index & 8)) byte |= REX_X;
if(base != NoRegister and (base & 8)) byte |= REX_B;
if(always or byte != REX_NONE) c->code.append(byte);
if (a != NoRegister and (a & 8)) byte |= REX_R;
if (index != NoRegister and (index & 8)) byte |= REX_X;
if (base != NoRegister and (base & 8)) byte |= REX_B;
if (always or byte != REX_NONE) c->code.append(byte);
}
}
@ -561,9 +549,9 @@ sib(Context* c, unsigned scale, int index, int base)
void
modrmSib(Context* c, int width, int a, int scale, int index, int base)
{
if(index == NoRegister) {
if (index == NoRegister) {
modrm(c, width, base, a);
if(regCode(base) == rsp) {
if (regCode(base) == rsp) {
sib(c, 0x00, rsp, rsp);
}
} else {
@ -575,9 +563,9 @@ modrmSib(Context* c, int width, int a, int scale, int index, int base)
void
modrmSibImm(Context* c, int a, int scale, int index, int base, int offset)
{
if(offset == 0 and regCode(base) != rbp) {
if (offset == 0 and regCode(base) != rbp) {
modrmSib(c, 0x00, a, scale, index, base);
} else if(isInt8(offset)) {
} else if (isInt8(offset)) {
modrmSib(c, 0x40, a, scale, index, base);
c->code.append(offset);
} else {
@ -985,7 +973,7 @@ void
moveRR(Context* c, unsigned aSize, Assembler::Register* a,
UNUSED unsigned bSize, Assembler::Register* b)
{
if(floatReg(a) or floatReg(b)) {
if (floatReg(a) or floatReg(b)) {
sseMoveRR(c, aSize, a, bSize, b);
return;
}
@ -1084,9 +1072,9 @@ void
moveMR(Context* c, unsigned aSize, Assembler::Memory* a,
unsigned bSize, Assembler::Register* b)
{
if(floatReg(b)) {
sseMoveMR(c, aSize, a, bSize, b);
return;
if (floatReg(b)) {
sseMoveMR(c, aSize, a, bSize, b);
return;
}
switch (aSize) {
@ -1163,9 +1151,9 @@ moveRM(Context* c, unsigned aSize, Assembler::Register* a,
{
assert(c, aSize == bSize);
if(floatReg(a)) {
sseMoveRM(c, aSize, a, bSize, b);
return;
if (floatReg(a)) {
sseMoveRM(c, aSize, a, bSize, b);
return;
}
switch (aSize) {
@ -1195,7 +1183,7 @@ moveRM(Context* c, unsigned aSize, Assembler::Register* a,
break;
case 8:
if(BytesPerWord == 8) {
if (BytesPerWord == 8) {
maybeRex(c, bSize, a, b);
opcode(c, 0x89);
modrmSibImm(c, a, b);
@ -1266,7 +1254,7 @@ moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
case 8: {
if (BytesPerWord == 8) {
if(a->value->resolved() and isInt32(a->value->value())) {
if (a->value->resolved() and isInt32(a->value->value())) {
maybeRex(c, bSize, b);
opcode(c, 0xc7);
modrmSibImm(c, 0, b->scale, b->index, b->base, b->offset);
@ -2354,7 +2342,6 @@ void
float2FloatRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize UNUSED, Assembler::Register* b)
{
assert(c, supportsSSE2());
floatRegOp(c, aSize, a, 4, b, 0x5a);
}
@ -2362,7 +2349,6 @@ void
float2FloatMR(Context* c, unsigned aSize, Assembler::Memory* a,
unsigned bSize UNUSED, Assembler::Register* b)
{
assert(c, supportsSSE2());
floatMemOp(c, aSize, a, 4, b, 0x5a);
}
@ -2370,7 +2356,7 @@ void
float2IntRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, !floatReg(b));
assert(c, not floatReg(b));
floatRegOp(c, aSize, a, bSize, b, 0x2d);
}
@ -2405,7 +2391,7 @@ floatNegateRR(Context* c, unsigned aSize, Assembler::Register* a,
assert(c, aSize == 4);
ResolvedPromise pcon(0x80000000);
Assembler::Constant con(&pcon);
if(a->low == b->low) {
if (a->low == b->low) {
Assembler::Register tmp(c->client->acquireTemporary(FloatRegisterMask));
moveCR(c, 4, &con, 4, &tmp);
maybeRex(c, 4, a, &tmp);
@ -2414,7 +2400,7 @@ floatNegateRR(Context* c, unsigned aSize, Assembler::Register* a,
c->client->releaseTemporary(tmp.low);
} else {
moveCR(c, 4, &con, 4, b);
if(aSize == 8) opcode(c, 0x66);
if (aSize == 8) opcode(c, 0x66);
maybeRex(c, 4, a, b);
opcode(c, 0x0f, 0x57);
modrm(c, 0xc0, a, b);
@ -2431,7 +2417,7 @@ floatAbsRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
assert(c, aSize == 4);
ResolvedPromise pcon(0x7fffffff);
Assembler::Constant con(&pcon);
if(a->low == b->low) {
if (a->low == b->low) {
Assembler::Register tmp(c->client->acquireTemporary(FloatRegisterMask));
moveCR(c, 4, &con, 4, &tmp);
maybeRex(c, 4, a, &tmp);
@ -2571,14 +2557,17 @@ populateTables(ArchitectureContext* c)
bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM);
bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM);
}
class MyArchitecture: public Assembler::Architecture {
public:
MyArchitecture(System* system): c(system), referenceCount(0) {
MyArchitecture(System* system, bool useNativeFeatures):
c(system, useNativeFeatures), referenceCount(0)
{
populateTables(&c);
}
virtual unsigned floatRegisterSize() {
if (supportsSSE()) {
if (useSSE(&c)) {
return 8;
} else {
return 0;
@ -2590,7 +2579,7 @@ class MyArchitecture: public Assembler::Architecture {
}
virtual uint32_t floatRegisterMask() {
return supportsSSE() ? FloatRegisterMask : 0;
return useSSE(&c) ? FloatRegisterMask : 0;
}
virtual int stack() {
@ -2822,7 +2811,7 @@ class MyArchitecture: public Assembler::Architecture {
const char* parameterSpec)
{
if (strcmp(className, "java/lang/Math") == 0) {
if (supportsSSE()
if (useSSE(&c)
and strcmp(methodName, "sqrt") == 0
and strcmp(parameterSpec, "(D)D") == 0)
{
@ -2832,8 +2821,7 @@ class MyArchitecture: public Assembler::Architecture {
or strcmp(parameterSpec, "(J)J") == 0)
{
return Abs;
} else if (supportsSSE()
and supportsSSE2()
} else if (useSSE(&c)
and strcmp(parameterSpec, "(F)F") == 0)
{
return FloatAbs;
@ -2881,7 +2869,7 @@ class MyArchitecture: public Assembler::Architecture {
case FloatNegate:
// floatNegateRR does not support doubles
if (supportsSSE() and aSize == 4 and bSize == 4) {
if (useSSE(&c) and aSize == 4 and bSize == 4) {
*aTypeMask = (1 << RegisterOperand);
*aRegisterMask = FloatRegisterMask;
} else {
@ -2896,7 +2884,7 @@ class MyArchitecture: public Assembler::Architecture {
break;
case Float2Float:
if (supportsSSE() and supportsSSE2()) {
if (useSSE(&c)) {
*aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
*aRegisterMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
| FloatRegisterMask;
@ -2906,7 +2894,7 @@ class MyArchitecture: public Assembler::Architecture {
break;
case Float2Int:
if (supportsSSE() and (bSize <= BytesPerWord)) {
if (useSSE(&c) and (bSize <= BytesPerWord)) {
*aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
*aRegisterMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
| FloatRegisterMask;
@ -2916,7 +2904,7 @@ class MyArchitecture: public Assembler::Architecture {
break;
case Int2Float:
if (supportsSSE()) {
if (useSSE(&c)) {
*aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
*aRegisterMask = GeneralRegisterMask
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
@ -3081,7 +3069,7 @@ class MyArchitecture: public Assembler::Architecture {
case FloatSubtract:
case FloatMultiply:
case FloatDivide:
if (supportsSSE()) {
if (useSSE(&c)) {
*aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
*bTypeMask = (1 << RegisterOperand);
@ -3145,7 +3133,7 @@ class MyArchitecture: public Assembler::Architecture {
case JumpIfFloatGreaterOrUnordered:
case JumpIfFloatLessOrEqualOrUnordered:
case JumpIfFloatGreaterOrEqualOrUnordered:
if (supportsSSE()) {
if (useSSE(&c)) {
*aTypeMask = (1 << RegisterOperand);
*aRegisterMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
| FloatRegisterMask;
@ -3400,7 +3388,8 @@ class MyAssembler: public Assembler {
virtual void apply(TernaryOperation op,
unsigned aSize, OperandType aType, Operand* aOperand,
unsigned bSize, OperandType bType, Operand* bOperand,
unsigned cSize, OperandType cType, Operand* cOperand)
unsigned cSize UNUSED, OperandType cType UNUSED,
Operand* cOperand)
{
if (isBranch(op)) {
assert(&c, aSize == bSize);
@ -3484,10 +3473,10 @@ class MyAssembler: public Assembler {
namespace vm {
Assembler::Architecture*
makeArchitecture(System* system)
makeArchitecture(System* system, bool useNativeFeatures)
{
return new (allocate(system, sizeof(local::MyArchitecture)))
local::MyArchitecture(system);
local::MyArchitecture(system, useNativeFeatures);
}
Assembler*