mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
refactor intrinsic support
This ensures that the low-level, architecture specific code need not be aware of the semantics and names of Java methods.
This commit is contained in:
parent
f702795178
commit
15020d77a6
@ -56,14 +56,14 @@ enum BinaryOperation {
|
||||
Float2Float,
|
||||
Float2Int,
|
||||
Int2Float,
|
||||
FloatSqrt,
|
||||
FloatAbs,
|
||||
Abs,
|
||||
FloatSquareRoot,
|
||||
FloatAbsolute,
|
||||
Absolute,
|
||||
|
||||
NoBinaryOperation = -1
|
||||
};
|
||||
|
||||
const unsigned BinaryOperationCount = Abs + 1;
|
||||
const unsigned BinaryOperationCount = Absolute + 1;
|
||||
|
||||
enum TernaryOperation {
|
||||
Add,
|
||||
@ -343,14 +343,6 @@ class Assembler {
|
||||
virtual int returnAddressOffset() = 0;
|
||||
virtual int framePointerOffset() = 0;
|
||||
virtual void nextFrame(void** stack, void** base) = 0;
|
||||
|
||||
virtual BinaryOperation binaryIntrinsic(const char* className,
|
||||
const char* methodName,
|
||||
const char* parameterSpec) = 0;
|
||||
|
||||
virtual TernaryOperation ternaryIntrinsic(const char* className,
|
||||
const char* methodName,
|
||||
const char* parameterSpec) = 0;
|
||||
|
||||
virtual void plan
|
||||
(UnaryOperation op,
|
||||
|
203
src/compile.cpp
203
src/compile.cpp
@ -783,51 +783,76 @@ class Context {
|
||||
virtual intptr_t getThunk(BinaryOperation op, unsigned size,
|
||||
unsigned resultSize)
|
||||
{
|
||||
switch(op) {
|
||||
case FloatNegate:
|
||||
if (size == 4) {
|
||||
return local::getThunk(t, negateFloatThunk);
|
||||
} else {
|
||||
if (size == 8) {
|
||||
switch(op) {
|
||||
case FloatNegate:
|
||||
assert(t, resultSize == 8);
|
||||
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) {
|
||||
case FloatSquareRoot:
|
||||
assert(t, resultSize == 8);
|
||||
return local::getThunk(t, squareRootDoubleThunk);
|
||||
|
||||
case Float2Float:
|
||||
assert(t, 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) {
|
||||
return local::getThunk(t, floatToLongThunk);
|
||||
} else if (size == 8 and resultSize == 4) {
|
||||
return local::getThunk(t, doubleToIntThunk);
|
||||
} else if (size == 8 and resultSize == 8) {
|
||||
return local::getThunk(t, doubleToLongThunk);
|
||||
}
|
||||
case Float2Int:
|
||||
if (resultSize == 8) {
|
||||
return local::getThunk(t, doubleToLongThunk);
|
||||
} else {
|
||||
assert(t, resultSize == 4);
|
||||
return local::getThunk(t, doubleToIntThunk);
|
||||
}
|
||||
|
||||
case Int2Float:
|
||||
if (size == 4 and resultSize == 4) {
|
||||
return local::getThunk(t, intToFloatThunk);
|
||||
} else if (size == 4 and resultSize == 8) {
|
||||
return local::getThunk(t, intToDoubleThunk);
|
||||
} else if (size == 8 and resultSize == 4) {
|
||||
return local::getThunk(t, longToFloatThunk);
|
||||
} else if (size == 8 and resultSize == 8) {
|
||||
return local::getThunk(t, longToDoubleThunk);
|
||||
}
|
||||
case Int2Float:
|
||||
if (resultSize == 8) {
|
||||
return local::getThunk(t, longToDoubleThunk);
|
||||
} else {
|
||||
assert(t, resultSize == 4);
|
||||
return local::getThunk(t, longToFloatThunk);
|
||||
}
|
||||
|
||||
default: break;
|
||||
default: abort(t);
|
||||
}
|
||||
} else {
|
||||
assert(t, size == 4);
|
||||
|
||||
switch(op) {
|
||||
case FloatNegate:
|
||||
assert(t, size == 4);
|
||||
return local::getThunk(t, negateFloatThunk);
|
||||
|
||||
case FloatAbsolute:
|
||||
assert(t, size == 4);
|
||||
return local::getThunk(t, absoluteFloatThunk);
|
||||
|
||||
case Float2Float:
|
||||
assert(t, resultSize == 8);
|
||||
return local::getThunk(t, floatToDoubleThunk);
|
||||
|
||||
case Float2Int:
|
||||
if (resultSize == 4) {
|
||||
return local::getThunk(t, floatToIntThunk);
|
||||
} else {
|
||||
assert(t, resultSize == 8);
|
||||
return local::getThunk(t, floatToLongThunk);
|
||||
}
|
||||
|
||||
case Int2Float:
|
||||
if (resultSize == 4) {
|
||||
return local::getThunk(t, intToFloatThunk);
|
||||
} else {
|
||||
assert(t, resultSize == 8);
|
||||
return local::getThunk(t, intToDoubleThunk);
|
||||
}
|
||||
|
||||
default: abort(t);
|
||||
}
|
||||
}
|
||||
|
||||
abort(t);
|
||||
}
|
||||
|
||||
virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned)
|
||||
{
|
||||
virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned) {
|
||||
if (size == 8) {
|
||||
switch (op) {
|
||||
case Divide:
|
||||
@ -862,9 +887,10 @@ class Context {
|
||||
case JumpIfFloatLessOrEqualOrUnordered:
|
||||
return local::getThunk(t, compareDoublesLThunk);
|
||||
|
||||
default: break;
|
||||
default: abort(t);
|
||||
}
|
||||
} else if (size == 4) {
|
||||
} else {
|
||||
assert(t, size == 4);
|
||||
switch (op) {
|
||||
case FloatAdd:
|
||||
return local::getThunk(t, addFloatThunk);
|
||||
@ -889,11 +915,9 @@ class Context {
|
||||
case JumpIfFloatLessOrEqualOrUnordered:
|
||||
return local::getThunk(t, compareFloatsLThunk);
|
||||
|
||||
default: break;
|
||||
default: abort(t);
|
||||
}
|
||||
}
|
||||
|
||||
abort(t);
|
||||
}
|
||||
|
||||
MyThread* t;
|
||||
@ -2055,6 +2079,12 @@ negateDouble(uint64_t a)
|
||||
return doubleToBits(- bitsToDouble(a));
|
||||
}
|
||||
|
||||
uint64_t
|
||||
squareRootDouble(uint64_t a)
|
||||
{
|
||||
return doubleToBits(sqrt(bitsToDouble(a)));
|
||||
}
|
||||
|
||||
uint64_t
|
||||
doubleToFloat(int64_t a)
|
||||
{
|
||||
@ -2109,6 +2139,12 @@ negateFloat(uint32_t a)
|
||||
return floatToBits(- bitsToFloat(a));
|
||||
}
|
||||
|
||||
uint64_t
|
||||
absoluteFloat(uint32_t a)
|
||||
{
|
||||
return floatToBits(fabsf(bitsToFloat(a)));
|
||||
}
|
||||
|
||||
int64_t
|
||||
divideLong(int64_t b, int64_t a)
|
||||
{
|
||||
@ -2868,6 +2904,38 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip,
|
||||
return t->exception == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
intrinsic(MyThread* t, Frame* frame, object target)
|
||||
{
|
||||
#define MATCH(name, constant) \
|
||||
(byteArrayLength(t, name) - 1 == sizeof(constant) \
|
||||
and strcmp(reinterpret_cast<char*>(&byteArrayBody(t, name, 0)), \
|
||||
constant) == 0)
|
||||
|
||||
object className = vm::className(t, methodClass(t, target));
|
||||
if (UNLIKELY(MATCH(className, "java/lang/Math"))) {
|
||||
Compiler* c = frame->c;
|
||||
if (MATCH(methodName(t, target), "sqrt")
|
||||
and MATCH(methodSpec(t, target), "(D)D"))
|
||||
{
|
||||
frame->pushLong(c->fsqrt(8, frame->popLong()));
|
||||
return true;
|
||||
} else if (MATCH(methodName(t, target), "abs")) {
|
||||
if (MATCH(methodSpec(t, target), "(I)I")) {
|
||||
frame->pushInt(c->abs(4, frame->popInt()));
|
||||
return true;
|
||||
} else if (MATCH(methodSpec(t, target), "(J)J")) {
|
||||
frame->pushLong(c->abs(8, frame->popLong()));
|
||||
return true;
|
||||
} else if (MATCH(methodSpec(t, target), "(F)F")) {
|
||||
frame->pushInt(c->fabs(4, frame->popInt()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
int exceptionHandlerStart)
|
||||
@ -3878,58 +3946,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
|
||||
assert(t, methodFlags(t, target) & ACC_STATIC);
|
||||
|
||||
bool usedIntrinsic = false;
|
||||
int params = methodParameterCount(t, target);
|
||||
if (params == 1) {
|
||||
BinaryOperation op = t->arch->binaryIntrinsic
|
||||
(reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, className(t, methodClass(t, target)), 0)),
|
||||
reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, methodName(t, target), 0)),
|
||||
reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, methodSpec(t, target), 0)));
|
||||
|
||||
if (op != NoBinaryOperation) {
|
||||
if (DebugIntrinsics) {
|
||||
fprintf(stderr, "Using binary intrinsic %i.\n", op);
|
||||
}
|
||||
int opSize = methodParameterFootprint(t, target) * 4;
|
||||
int resSize = resultSize(t, methodReturnCode(t, target));
|
||||
Compiler::Operand* param;
|
||||
if (opSize == 4) {
|
||||
param = frame->popInt();
|
||||
} else {
|
||||
param = frame->popLong();
|
||||
}
|
||||
Compiler::Operand* operand = c->operation
|
||||
(op, opSize, resSize, operandTypeForFieldCode
|
||||
(t, methodReturnCode(t, target)), param);
|
||||
if (resSize == 4) {
|
||||
frame->pushInt(operand);
|
||||
} else {
|
||||
frame->pushLong(operand);
|
||||
}
|
||||
usedIntrinsic = true;
|
||||
}
|
||||
} else if (params == 2) {
|
||||
TernaryOperation op = t->arch->ternaryIntrinsic
|
||||
(reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, className(t, methodClass(t, target)), 0)),
|
||||
reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, methodName(t, target), 0)),
|
||||
reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, methodSpec(t, target), 0)));
|
||||
|
||||
if (op != NoTernaryOperation) {
|
||||
if (DebugIntrinsics) {
|
||||
fprintf(stderr, "Could use ternary intrinsic %i.\n", op);
|
||||
}
|
||||
//int aSize, bSize;
|
||||
//int resSize = resultSize(t, methodReturnCode(t, target));
|
||||
//TODO: use intrinsic
|
||||
}
|
||||
}
|
||||
if (not usedIntrinsic) {
|
||||
if (not intrinsic(t, frame, target)) {
|
||||
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
||||
compileDirectInvoke(t, frame, target, tailCall);
|
||||
}
|
||||
|
@ -6370,23 +6370,27 @@ class MyCompiler: public Compiler {
|
||||
(&c, FloatNegate, size, static_cast<Value*>(a), size, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual Operand* operation(BinaryOperation op, unsigned aSize,
|
||||
unsigned resSize, OperandType resType, Operand* a)
|
||||
{
|
||||
Value* result = value(&c, valueType(&c, resType));
|
||||
appendTranslate(&c, op, aSize, static_cast<Value*>(a), resSize, result);
|
||||
|
||||
virtual Operand* abs(unsigned size, Operand* a) {
|
||||
assert(&c, static_cast<Value*>(a)->type == ValueGeneral);
|
||||
Value* result = value(&c, ValueGeneral);
|
||||
appendTranslate(&c, Absolute, size, static_cast<Value*>(a), size, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual Operand* operation(TernaryOperation op, unsigned aSize,
|
||||
unsigned bSize, unsigned resSize,
|
||||
OperandType resType, Operand* a, Operand* b)
|
||||
{
|
||||
Value* result = value(&c, valueType(&c, resType));
|
||||
appendCombine
|
||||
(&c, op, aSize, static_cast<Value*>(a), bSize, static_cast<Value*>(b),
|
||||
resSize, result);
|
||||
|
||||
virtual Operand* fabs(unsigned size, Operand* a) {
|
||||
assert(&c, static_cast<Value*>(a)->type == ValueFloat);
|
||||
Value* result = value(&c, ValueFloat);
|
||||
appendTranslate
|
||||
(&c, FloatAbsolute, size, static_cast<Value*>(a), size, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual Operand* fsqrt(unsigned size, Operand* a) {
|
||||
assert(&c, static_cast<Value*>(a)->type == ValueFloat);
|
||||
Value* result = value(&c, ValueFloat);
|
||||
appendTranslate
|
||||
(&c, FloatSquareRoot, size, static_cast<Value*>(a), size, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -176,12 +176,9 @@ class Compiler {
|
||||
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0;
|
||||
virtual Operand* neg(unsigned size, Operand* a) = 0;
|
||||
virtual Operand* fneg(unsigned size, Operand* a) = 0;
|
||||
virtual Operand* operation(BinaryOperation op, unsigned aSize,
|
||||
unsigned resSize, OperandType resType,
|
||||
Operand* a) = 0;
|
||||
virtual Operand* operation(TernaryOperation op, unsigned aSize,
|
||||
unsigned bSize, unsigned resSize,
|
||||
OperandType resType, Operand* a, Operand* b) = 0;
|
||||
virtual Operand* abs(unsigned size, Operand* a) = 0;
|
||||
virtual Operand* fabs(unsigned size, Operand* a) = 0;
|
||||
virtual Operand* fsqrt(unsigned size, Operand* a) = 0;
|
||||
virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
||||
virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
||||
virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
|
||||
|
@ -11,6 +11,7 @@ THUNK(multiplyDouble)
|
||||
THUNK(divideDouble)
|
||||
THUNK(moduloDouble)
|
||||
THUNK(negateDouble)
|
||||
THUNK(squareRootDouble)
|
||||
THUNK(doubleToFloat)
|
||||
THUNK(doubleToInt)
|
||||
THUNK(doubleToLong)
|
||||
@ -20,6 +21,7 @@ THUNK(multiplyFloat)
|
||||
THUNK(divideFloat)
|
||||
THUNK(moduloFloat)
|
||||
THUNK(negateFloat)
|
||||
THUNK(absoluteFloat)
|
||||
THUNK(divideLong)
|
||||
THUNK(moduloLong)
|
||||
THUNK(floatToDouble)
|
||||
|
36
src/x86.cpp
36
src/x86.cpp
@ -2446,7 +2446,7 @@ floatNegateRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||
}
|
||||
|
||||
void
|
||||
floatAbsRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
|
||||
floatAbsoluteRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
|
||||
unsigned bSize UNUSED, Assembler::Register* b)
|
||||
{
|
||||
assert(c, floatReg(a) and floatReg(b));
|
||||
@ -2471,7 +2471,7 @@ floatAbsRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
|
||||
}
|
||||
|
||||
void
|
||||
absRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||
absoluteRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||
unsigned bSize UNUSED, Assembler::Register* b UNUSED)
|
||||
{
|
||||
assert(c, aSize == bSize and a->low == rax and b->low == rax);
|
||||
@ -2533,8 +2533,8 @@ populateTables(ArchitectureContext* c)
|
||||
bo[index(c, Move, C, M)] = CAST2(moveCM);
|
||||
bo[index(c, Move, A, R)] = CAST2(moveAR);
|
||||
|
||||
bo[index(c, FloatSqrt, R, R)] = CAST2(floatSqrtRR);
|
||||
bo[index(c, FloatSqrt, M, R)] = CAST2(floatSqrtMR);
|
||||
bo[index(c, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR);
|
||||
bo[index(c, FloatSquareRoot, M, R)] = CAST2(floatSqrtMR);
|
||||
|
||||
bo[index(c, MoveZ, R, R)] = CAST2(moveZRR);
|
||||
bo[index(c, MoveZ, M, R)] = CAST2(moveZMR);
|
||||
@ -2591,8 +2591,8 @@ populateTables(ArchitectureContext* c)
|
||||
bo[index(c, Int2Float, R, R)] = CAST2(int2FloatRR);
|
||||
bo[index(c, Int2Float, M, R)] = CAST2(int2FloatMR);
|
||||
|
||||
bo[index(c, Abs, R, R)] = CAST2(absRR);
|
||||
bo[index(c, FloatAbs, R, R)] = CAST2(floatAbsRR);
|
||||
bo[index(c, Absolute, R, R)] = CAST2(absoluteRR);
|
||||
bo[index(c, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR);
|
||||
|
||||
bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR);
|
||||
bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR);
|
||||
@ -2839,13 +2839,13 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
case Float2Float:
|
||||
case Float2Int:
|
||||
case Int2Float:
|
||||
case FloatAbs:
|
||||
case FloatAbsolute:
|
||||
case FloatNegate:
|
||||
case FloatSqrt:
|
||||
case FloatSquareRoot:
|
||||
return false;
|
||||
|
||||
case Negate:
|
||||
case Abs:
|
||||
case Absolute:
|
||||
return true;
|
||||
|
||||
default:
|
||||
@ -2892,16 +2892,16 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
and strcmp(methodName, "sqrt") == 0
|
||||
and strcmp(parameterSpec, "(D)D") == 0)
|
||||
{
|
||||
return FloatSqrt;
|
||||
return FloatSquareRoot;
|
||||
} else if (strcmp(methodName, "abs")) {
|
||||
if (strcmp(parameterSpec, "(I)I") == 0
|
||||
or strcmp(parameterSpec, "(J)J") == 0)
|
||||
{
|
||||
return Abs;
|
||||
return Absolute;
|
||||
} else if (useSSE(&c)
|
||||
and strcmp(parameterSpec, "(F)F") == 0)
|
||||
{
|
||||
return FloatAbs;
|
||||
return FloatAbsolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2933,12 +2933,12 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
| (static_cast<uint64_t>(1) << rax);
|
||||
break;
|
||||
|
||||
case Abs:
|
||||
case Absolute:
|
||||
*aTypeMask = (1 << RegisterOperand);
|
||||
*aRegisterMask = (static_cast<uint64_t>(1) << rax);
|
||||
break;
|
||||
|
||||
case FloatAbs:
|
||||
case FloatAbsolute:
|
||||
*aTypeMask = (1 << RegisterOperand);
|
||||
*aRegisterMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
||||
| FloatRegisterMask;
|
||||
@ -2954,7 +2954,7 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
}
|
||||
break;
|
||||
|
||||
case FloatSqrt:
|
||||
case FloatSquareRoot:
|
||||
*aTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
||||
*aRegisterMask = (static_cast<uint64_t>(FloatRegisterMask) << 32)
|
||||
| FloatRegisterMask;
|
||||
@ -3025,12 +3025,12 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
| (static_cast<uint64_t>(GeneralRegisterMask) << 32);
|
||||
|
||||
switch (op) {
|
||||
case Abs:
|
||||
case Absolute:
|
||||
*bTypeMask = (1 << RegisterOperand);
|
||||
*bRegisterMask = (static_cast<uint64_t>(1) << rax);
|
||||
break;
|
||||
|
||||
case FloatAbs:
|
||||
case FloatAbsolute:
|
||||
*bTypeMask = (1 << RegisterOperand);
|
||||
*bRegisterMask = aRegisterMask;
|
||||
break;
|
||||
@ -3041,7 +3041,7 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
break;
|
||||
|
||||
case FloatNegate:
|
||||
case FloatSqrt:
|
||||
case FloatSquareRoot:
|
||||
case Float2Float:
|
||||
case Int2Float:
|
||||
*bTypeMask = (1 << RegisterOperand);
|
||||
|
Loading…
Reference in New Issue
Block a user