generate code in ReturnEvent if and only if the event is preceded by at least one non-tail-call

This commit is contained in:
Joel Dice 2009-04-25 19:51:33 -06:00
parent 89221bfcfa
commit 0245a94ab8
2 changed files with 78 additions and 44 deletions

View File

@ -2165,26 +2165,48 @@ needsReturnBarrier(MyThread* t, object method)
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
isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee)
{
if (((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0)
and (not inTryBlock(t, code, ip - 1))
and (not needsReturnBarrier(t, caller))
and (methodReturnCode(t, caller) == VoidField
or methodReturnCode(t, caller) == methodReturnCode(t, callee)))
{
switch (codeBody(t, code, ip)) {
case return_:
case areturn:
case ireturn:
case freturn:
case lreturn:
case dreturn:
return true;
}
}
return false;
return (((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0)
and (not inTryBlock(t, code, ip - 1))
and (not needsReturnBarrier(t, caller))
and (methodReturnCode(t, caller) == VoidField
or methodReturnCode(t, caller) == methodReturnCode(t, callee))
and returnsNext(t, code, ip));
}
void
@ -2209,7 +2231,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Frame* frame = &myFrame;
Compiler* c = frame->c;
Context* context = frame->context;
bool tailCall = false;
object code = methodCode(t, context->method);
PROTECT(t, code);
@ -2408,10 +2429,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case areturn: {
Compiler::Operand* value = frame->popObject();
if (not tailCall) {
handleExit(t, frame);
c->return_(BytesPerWord, value);
}
handleExit(t, frame);
c->return_(BytesPerWord, value);
} return;
case arraylength: {
@ -3159,9 +3178,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
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;
case invokestatic: {
@ -3172,9 +3191,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
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;
case invokevirtual: {
@ -3193,7 +3212,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
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_
(BytesPerWord, c->constant(PointerMask),
@ -3232,10 +3251,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case ireturn:
case freturn: {
Compiler::Operand* value = frame->popInt();
if (not tailCall) {
handleExit(t, frame);
c->return_(4, value);
}
handleExit(t, frame);
c->return_(4, value);
} return;
case ishl: {
@ -3529,10 +3546,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case lreturn:
case dreturn: {
Compiler::Operand* value = frame->popLong();
if (not tailCall) {
handleExit(t, frame);
c->return_(8, value);
}
handleExit(t, frame);
c->return_(8, value);
} return;
case lshl: {
@ -3827,14 +3842,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
return;
case return_:
if (not tailCall) {
if (needsReturnBarrier(t, context->method)) {
c->storeStoreBarrier();
}
handleExit(t, frame);
c->return_(0, 0);
if (needsReturnBarrier(t, context->method)) {
c->storeStoreBarrier();
}
handleExit(t, frame);
c->return_(0, 0);
return;
case sipush:

View File

@ -620,6 +620,8 @@ class Event {
virtual bool isBranch() { return false; }
virtual bool allTailCalls() { return false; }
Event* next;
Stack* stackBefore;
Local* localsBefore;
@ -2510,6 +2512,10 @@ class CallEvent: public Event {
}
}
virtual bool allTailCalls() {
return (flags & Compiler::TailJump) != 0;
}
Value* address;
TraceHandler* traceHandler;
Value* result;
@ -2535,6 +2541,15 @@ appendCall(Context* c, Value* address, unsigned flags,
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 {
public:
ReturnEvent(Context* c, unsigned size, Value* value):
@ -2558,8 +2573,10 @@ class ReturnEvent: public Event {
popRead(c, this, r->value);
}
c->assembler->popFrameAndPopArgumentsAndReturn
(c->arch->argumentFootprint(c->parameterFootprint));
if (not followsOnlyTailCalls(this)) {
c->assembler->popFrameAndPopArgumentsAndReturn
(c->arch->argumentFootprint(c->parameterFootprint));
}
}
Value* value;
@ -3739,6 +3756,10 @@ class BranchEvent: public Event {
virtual bool isBranch() { return true; }
virtual bool allTailCalls() {
return type == Jump and followsOnlyTailCalls(this);
}
UnaryOperation type;
Value* address;
};