mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
generate code in ReturnEvent if and only if the event is preceded by at least one non-tail-call
This commit is contained in:
parent
89221bfcfa
commit
0245a94ab8
@ -2165,26 +2165,48 @@ needsReturnBarrier(MyThread* t, object method)
|
|||||||
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag);
|
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
returnsNext(MyThread* t, object code, unsigned ip)
|
||||||
|
{
|
||||||
|
switch (codeBody(t, code, ip)) {
|
||||||
|
case return_:
|
||||||
|
case areturn:
|
||||||
|
case ireturn:
|
||||||
|
case freturn:
|
||||||
|
case lreturn:
|
||||||
|
case dreturn:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case goto_: {
|
||||||
|
uint32_t offset = codeReadInt16(t, code, ++ip);
|
||||||
|
uint32_t newIp = (ip - 3) + offset;
|
||||||
|
assert(t, newIp < codeLength(t, code));
|
||||||
|
|
||||||
|
return returnsNext(t, code, newIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
case goto_w: {
|
||||||
|
uint32_t offset = codeReadInt32(t, code, ++ip);
|
||||||
|
uint32_t newIp = (ip - 5) + offset;
|
||||||
|
assert(t, newIp < codeLength(t, code));
|
||||||
|
|
||||||
|
return returnsNext(t, code, newIp);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee)
|
isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee)
|
||||||
{
|
{
|
||||||
if (((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0)
|
return (((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0)
|
||||||
and (not inTryBlock(t, code, ip - 1))
|
and (not inTryBlock(t, code, ip - 1))
|
||||||
and (not needsReturnBarrier(t, caller))
|
and (not needsReturnBarrier(t, caller))
|
||||||
and (methodReturnCode(t, caller) == VoidField
|
and (methodReturnCode(t, caller) == VoidField
|
||||||
or methodReturnCode(t, caller) == methodReturnCode(t, callee)))
|
or methodReturnCode(t, caller) == methodReturnCode(t, callee))
|
||||||
{
|
and returnsNext(t, code, ip));
|
||||||
switch (codeBody(t, code, ip)) {
|
|
||||||
case return_:
|
|
||||||
case areturn:
|
|
||||||
case ireturn:
|
|
||||||
case freturn:
|
|
||||||
case lreturn:
|
|
||||||
case dreturn:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2209,7 +2231,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
Frame* frame = &myFrame;
|
Frame* frame = &myFrame;
|
||||||
Compiler* c = frame->c;
|
Compiler* c = frame->c;
|
||||||
Context* context = frame->context;
|
Context* context = frame->context;
|
||||||
bool tailCall = false;
|
|
||||||
|
|
||||||
object code = methodCode(t, context->method);
|
object code = methodCode(t, context->method);
|
||||||
PROTECT(t, code);
|
PROTECT(t, code);
|
||||||
@ -2408,10 +2429,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
case areturn: {
|
case areturn: {
|
||||||
Compiler::Operand* value = frame->popObject();
|
Compiler::Operand* value = frame->popObject();
|
||||||
if (not tailCall) {
|
handleExit(t, frame);
|
||||||
handleExit(t, frame);
|
c->return_(BytesPerWord, value);
|
||||||
c->return_(BytesPerWord, value);
|
|
||||||
}
|
|
||||||
} return;
|
} return;
|
||||||
|
|
||||||
case arraylength: {
|
case arraylength: {
|
||||||
@ -3159,9 +3178,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
||||||
|
|
||||||
tailCall = isTailCall(t, code, ip, context->method, target);
|
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
||||||
|
|
||||||
tailCall = compileDirectInvoke(t, frame, target, tailCall);
|
compileDirectInvoke(t, frame, target, tailCall);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case invokestatic: {
|
case invokestatic: {
|
||||||
@ -3172,9 +3191,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
assert(t, methodFlags(t, target) & ACC_STATIC);
|
assert(t, methodFlags(t, target) & ACC_STATIC);
|
||||||
|
|
||||||
tailCall = isTailCall(t, code, ip, context->method, target);
|
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
||||||
|
|
||||||
tailCall = compileDirectInvoke(t, frame, target, tailCall);
|
compileDirectInvoke(t, frame, target, tailCall);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case invokevirtual: {
|
case invokevirtual: {
|
||||||
@ -3193,7 +3212,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
||||||
|
|
||||||
tailCall = isTailCall(t, code, ip, context->method, target);
|
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
||||||
|
|
||||||
Compiler::Operand* classOperand = c->and_
|
Compiler::Operand* classOperand = c->and_
|
||||||
(BytesPerWord, c->constant(PointerMask),
|
(BytesPerWord, c->constant(PointerMask),
|
||||||
@ -3232,10 +3251,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case ireturn:
|
case ireturn:
|
||||||
case freturn: {
|
case freturn: {
|
||||||
Compiler::Operand* value = frame->popInt();
|
Compiler::Operand* value = frame->popInt();
|
||||||
if (not tailCall) {
|
handleExit(t, frame);
|
||||||
handleExit(t, frame);
|
c->return_(4, value);
|
||||||
c->return_(4, value);
|
|
||||||
}
|
|
||||||
} return;
|
} return;
|
||||||
|
|
||||||
case ishl: {
|
case ishl: {
|
||||||
@ -3529,10 +3546,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case lreturn:
|
case lreturn:
|
||||||
case dreturn: {
|
case dreturn: {
|
||||||
Compiler::Operand* value = frame->popLong();
|
Compiler::Operand* value = frame->popLong();
|
||||||
if (not tailCall) {
|
handleExit(t, frame);
|
||||||
handleExit(t, frame);
|
c->return_(8, value);
|
||||||
c->return_(8, value);
|
|
||||||
}
|
|
||||||
} return;
|
} return;
|
||||||
|
|
||||||
case lshl: {
|
case lshl: {
|
||||||
@ -3827,14 +3842,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case return_:
|
case return_:
|
||||||
if (not tailCall) {
|
if (needsReturnBarrier(t, context->method)) {
|
||||||
if (needsReturnBarrier(t, context->method)) {
|
c->storeStoreBarrier();
|
||||||
c->storeStoreBarrier();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleExit(t, frame);
|
|
||||||
c->return_(0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleExit(t, frame);
|
||||||
|
c->return_(0, 0);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case sipush:
|
case sipush:
|
||||||
|
@ -620,6 +620,8 @@ class Event {
|
|||||||
|
|
||||||
virtual bool isBranch() { return false; }
|
virtual bool isBranch() { return false; }
|
||||||
|
|
||||||
|
virtual bool allTailCalls() { return false; }
|
||||||
|
|
||||||
Event* next;
|
Event* next;
|
||||||
Stack* stackBefore;
|
Stack* stackBefore;
|
||||||
Local* localsBefore;
|
Local* localsBefore;
|
||||||
@ -2510,6 +2512,10 @@ class CallEvent: public Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool allTailCalls() {
|
||||||
|
return (flags & Compiler::TailJump) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
Value* address;
|
Value* address;
|
||||||
TraceHandler* traceHandler;
|
TraceHandler* traceHandler;
|
||||||
Value* result;
|
Value* result;
|
||||||
@ -2535,6 +2541,15 @@ appendCall(Context* c, Value* address, unsigned flags,
|
|||||||
stackArgumentFootprint));
|
stackArgumentFootprint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
followsOnlyTailCalls(Event* event)
|
||||||
|
{
|
||||||
|
for (Link* p = event->predecessors; p; p = p->nextPredecessor) {
|
||||||
|
if (not p->predecessor->allTailCalls()) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class ReturnEvent: public Event {
|
class ReturnEvent: public Event {
|
||||||
public:
|
public:
|
||||||
ReturnEvent(Context* c, unsigned size, Value* value):
|
ReturnEvent(Context* c, unsigned size, Value* value):
|
||||||
@ -2558,8 +2573,10 @@ class ReturnEvent: public Event {
|
|||||||
popRead(c, this, r->value);
|
popRead(c, this, r->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
c->assembler->popFrameAndPopArgumentsAndReturn
|
if (not followsOnlyTailCalls(this)) {
|
||||||
(c->arch->argumentFootprint(c->parameterFootprint));
|
c->assembler->popFrameAndPopArgumentsAndReturn
|
||||||
|
(c->arch->argumentFootprint(c->parameterFootprint));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* value;
|
Value* value;
|
||||||
@ -3739,6 +3756,10 @@ class BranchEvent: public Event {
|
|||||||
|
|
||||||
virtual bool isBranch() { return true; }
|
virtual bool isBranch() { return true; }
|
||||||
|
|
||||||
|
virtual bool allTailCalls() {
|
||||||
|
return type == Jump and followsOnlyTailCalls(this);
|
||||||
|
}
|
||||||
|
|
||||||
UnaryOperation type;
|
UnaryOperation type;
|
||||||
Value* address;
|
Value* address;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user