mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
support tail calls and continuations as build options
This commit is contained in:
parent
deefc47b1a
commit
31eb75a736
14
makefile
14
makefile
@ -35,6 +35,12 @@ endif
|
|||||||
ifeq ($(heapdump),true)
|
ifeq ($(heapdump),true)
|
||||||
options := $(options)-heapdump
|
options := $(options)-heapdump
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(tails),true)
|
||||||
|
options := $(options)-tails
|
||||||
|
endif
|
||||||
|
ifeq ($(continuations),true)
|
||||||
|
options := $(options)-continuations
|
||||||
|
endif
|
||||||
|
|
||||||
root = $(shell (cd .. && pwd))
|
root = $(shell (cd .. && pwd))
|
||||||
build = build
|
build = build
|
||||||
@ -254,6 +260,14 @@ ifeq ($(heapdump),true)
|
|||||||
cflags += -DAVIAN_HEAPDUMP
|
cflags += -DAVIAN_HEAPDUMP
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(tails),true)
|
||||||
|
cflags += -DAVIAN_TAILS
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(continuations),true)
|
||||||
|
cflags += -DAVIAN_CONTINUATIONS
|
||||||
|
endif
|
||||||
|
|
||||||
bootimage-generator-sources = $(src)/bootimage.cpp
|
bootimage-generator-sources = $(src)/bootimage.cpp
|
||||||
bootimage-generator-objects = \
|
bootimage-generator-objects = \
|
||||||
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(native-build))
|
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(native-build))
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
#ifdef AVIAN_TAILS
|
||||||
|
const bool TailCalls = true;
|
||||||
|
#else
|
||||||
|
const bool TailCalls = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
enum Operation {
|
enum Operation {
|
||||||
Return,
|
Return,
|
||||||
LoadBarrier,
|
LoadBarrier,
|
||||||
|
277
src/compile.cpp
277
src/compile.cpp
@ -39,6 +39,12 @@ const bool DebugFrameMaps = false;
|
|||||||
|
|
||||||
const bool CheckArrayBounds = true;
|
const bool CheckArrayBounds = true;
|
||||||
|
|
||||||
|
#ifdef AVIAN_CONTINUATIONS
|
||||||
|
const bool Continuations = true;
|
||||||
|
#else
|
||||||
|
const bool Continuations = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
const unsigned MaxNativeCallFootprint = 4;
|
const unsigned MaxNativeCallFootprint = 4;
|
||||||
|
|
||||||
const unsigned InitialZoneCapacityInBytes = 64 * 1024;
|
const unsigned InitialZoneCapacityInBytes = 64 * 1024;
|
||||||
@ -1425,7 +1431,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetBase,
|
|||||||
= t->arch->argumentFootprint(methodParameterFootprint(t, target));
|
= t->arch->argumentFootprint(methodParameterFootprint(t, target));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (t->continuation) {
|
while (Continuations and t->continuation) {
|
||||||
object c = t->continuation;
|
object c = t->continuation;
|
||||||
|
|
||||||
object method = continuationMethod(t, c);
|
object method = continuationMethod(t, c);
|
||||||
@ -1495,7 +1501,7 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetBase,
|
|||||||
unsigned argumentFootprint
|
unsigned argumentFootprint
|
||||||
= t->arch->argumentFootprint(methodParameterFootprint(t, target));
|
= t->arch->argumentFootprint(methodParameterFootprint(t, target));
|
||||||
unsigned alignment = t->arch->stackAlignmentInWords();
|
unsigned alignment = t->arch->stackAlignmentInWords();
|
||||||
if (argumentFootprint > alignment) {
|
if (TailCalls and argumentFootprint > alignment) {
|
||||||
top += argumentFootprint - alignment;
|
top += argumentFootprint - alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1559,9 +1565,15 @@ unwind(MyThread* t)
|
|||||||
object&
|
object&
|
||||||
objectPools(MyThread* t);
|
objectPools(MyThread* t);
|
||||||
|
|
||||||
|
object&
|
||||||
|
windMethod(MyThread* t);
|
||||||
|
|
||||||
object&
|
object&
|
||||||
rewindMethod(MyThread* t);
|
rewindMethod(MyThread* t);
|
||||||
|
|
||||||
|
object&
|
||||||
|
receiveMethod(MyThread* t);
|
||||||
|
|
||||||
uintptr_t
|
uintptr_t
|
||||||
defaultThunk(MyThread* t);
|
defaultThunk(MyThread* t);
|
||||||
|
|
||||||
@ -2144,7 +2156,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall,
|
|||||||
unsigned flags = (tailCall ? Compiler::TailJump : 0);
|
unsigned flags = (tailCall ? Compiler::TailJump : 0);
|
||||||
|
|
||||||
if (useThunk or (tailCall and (methodFlags(t, target) & ACC_NATIVE))) {
|
if (useThunk or (tailCall and (methodFlags(t, target) & ACC_NATIVE))) {
|
||||||
if (tailCall) {
|
if (TailCalls and tailCall) {
|
||||||
TraceElement* trace = frame->trace(target, TraceElement::TailCall);
|
TraceElement* trace = frame->trace(target, TraceElement::TailCall);
|
||||||
Compiler::Operand* returnAddress = c->promiseConstant
|
Compiler::Operand* returnAddress = c->promiseConstant
|
||||||
(new (frame->context->zone.allocate(sizeof(TraceElementPromise)))
|
(new (frame->context->zone.allocate(sizeof(TraceElementPromise)))
|
||||||
@ -2409,12 +2421,13 @@ returnsNext(MyThread* t, object code, unsigned ip)
|
|||||||
bool
|
bool
|
||||||
isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee)
|
isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee)
|
||||||
{
|
{
|
||||||
return (((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0)
|
return TailCalls
|
||||||
|
and ((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));
|
and returnsNext(t, code, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -5111,7 +5124,8 @@ invokeNative(MyThread* t)
|
|||||||
if (UNLIKELY(t->exception)) {
|
if (UNLIKELY(t->exception)) {
|
||||||
unwind(t);
|
unwind(t);
|
||||||
} else {
|
} else {
|
||||||
if (t->arch->argumentFootprint(parameterFootprint)
|
if (TailCalls
|
||||||
|
and t->arch->argumentFootprint(parameterFootprint)
|
||||||
> t->arch->stackAlignmentInWords())
|
> t->arch->stackAlignmentInWords())
|
||||||
{
|
{
|
||||||
t->stack = static_cast<uintptr_t*>(t->stack)
|
t->stack = static_cast<uintptr_t*>(t->stack)
|
||||||
@ -5542,6 +5556,117 @@ callContinuation(MyThread* t, object continuation, object result,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
callWithCurrentContinuation(MyThread* t, object receiver)
|
||||||
|
{
|
||||||
|
object method = 0;
|
||||||
|
void* ip = 0;
|
||||||
|
void* base = 0;
|
||||||
|
void* stack = 0;
|
||||||
|
unsigned oldArgumentFootprint = 0;
|
||||||
|
|
||||||
|
{ PROTECT(t, receiver);
|
||||||
|
|
||||||
|
if (receiveMethod(t) == 0) {
|
||||||
|
const char* const className = "avian/CallbackReceiver";
|
||||||
|
const char* const methodName = "receive";
|
||||||
|
const char* const methodSpec = "(Lavian/Callback;)Ljava/lang/Object;";
|
||||||
|
|
||||||
|
object m = resolveMethod(t, className, methodName, methodSpec);
|
||||||
|
|
||||||
|
if (m) {
|
||||||
|
receiveMethod(t) = m;
|
||||||
|
} else {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s %s not found in %s", methodName, methodSpec, className);
|
||||||
|
t->exception = makeNoSuchMethodError(t, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
object continuationClass = arrayBody
|
||||||
|
(t, t->m->types, Machine::ContinuationType);
|
||||||
|
|
||||||
|
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
|
||||||
|
resolveClass(t, vm::className(t, continuationClass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
method = findInterfaceMethod
|
||||||
|
(t, receiveMethod(t), objectClass(t, receiver));
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
compile(t, ::codeAllocator(t), 0, method);
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
t->continuation = makeCurrentContinuation
|
||||||
|
(t, &ip, &base, &stack, &oldArgumentFootprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
jumpAndInvoke
|
||||||
|
(t, method, base, stack, oldArgumentFootprint, receiver,
|
||||||
|
t->continuation);
|
||||||
|
} else {
|
||||||
|
unwind(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dynamicWind(MyThread* t, object before, object thunk, object after)
|
||||||
|
{
|
||||||
|
void* ip = 0;
|
||||||
|
void* base = 0;
|
||||||
|
void* stack = 0;
|
||||||
|
unsigned oldArgumentFootprint = 0;
|
||||||
|
|
||||||
|
{ PROTECT(t, before);
|
||||||
|
PROTECT(t, thunk);
|
||||||
|
PROTECT(t, after);
|
||||||
|
|
||||||
|
if (windMethod(t) == 0) {
|
||||||
|
const char* const className = "avian/Continuations";
|
||||||
|
const char* const methodName = "wind";
|
||||||
|
const char* const methodSpec
|
||||||
|
= "(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;"
|
||||||
|
"Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;";
|
||||||
|
|
||||||
|
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||||
|
|
||||||
|
if (method) {
|
||||||
|
windMethod(t) = method;
|
||||||
|
compile(t, ::codeAllocator(t), 0, method);
|
||||||
|
} else {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s %s not found in %s", methodName, methodSpec, className);
|
||||||
|
t->exception = makeNoSuchMethodError(t, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
t->continuation = makeCurrentContinuation
|
||||||
|
(t, &ip, &base, &stack, &oldArgumentFootprint);
|
||||||
|
|
||||||
|
object newContext = makeContinuationContext
|
||||||
|
(t, continuationContext(t, t->continuation), before, after,
|
||||||
|
t->continuation, t->trace->originalMethod);
|
||||||
|
|
||||||
|
set(t, t->continuation, ContinuationContext, newContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
jumpAndInvoke
|
||||||
|
(t, windMethod(t), base, stack, oldArgumentFootprint, before, thunk,
|
||||||
|
after);
|
||||||
|
} else {
|
||||||
|
unwind(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ArgumentList {
|
class ArgumentList {
|
||||||
public:
|
public:
|
||||||
ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask,
|
ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask,
|
||||||
@ -6213,132 +6338,52 @@ class MyProcessor: public Processor {
|
|||||||
(t->m->system->handleSegFault(&segFaultHandler)));
|
(t->m->system->handleSegFault(&segFaultHandler)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void callWithCurrentContinuation(Thread* vmt, object receiver) {
|
virtual void callWithCurrentContinuation(Thread* t, object receiver) {
|
||||||
MyThread* t = static_cast<MyThread*>(vmt);
|
if (Continuations) {
|
||||||
|
::callWithCurrentContinuation(static_cast<MyThread*>(t), receiver);
|
||||||
object method = 0;
|
|
||||||
void* ip = 0;
|
|
||||||
void* base = 0;
|
|
||||||
void* stack = 0;
|
|
||||||
unsigned oldArgumentFootprint = 0;
|
|
||||||
|
|
||||||
{ PROTECT(t, receiver);
|
|
||||||
|
|
||||||
if (receiveMethod == 0) {
|
|
||||||
const char* const className = "avian/CallbackReceiver";
|
|
||||||
const char* const methodName = "receive";
|
|
||||||
const char* const methodSpec = "(Lavian/Callback;)Ljava/lang/Object;";
|
|
||||||
|
|
||||||
receiveMethod = resolveMethod(t, className, methodName, methodSpec);
|
|
||||||
|
|
||||||
if (receiveMethod == 0) {
|
|
||||||
object message = makeString
|
|
||||||
(t, "%s %s not found in %s", methodName, methodSpec, className);
|
|
||||||
t->exception = makeNoSuchMethodError(t, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
|
||||||
object continuationClass = arrayBody
|
|
||||||
(t, t->m->types, Machine::ContinuationType);
|
|
||||||
|
|
||||||
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
|
|
||||||
resolveClass(t, vm::className(t, continuationClass));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
|
||||||
method = findInterfaceMethod
|
|
||||||
(t, receiveMethod, objectClass(t, receiver));
|
|
||||||
PROTECT(t, method);
|
|
||||||
|
|
||||||
compile(t, ::codeAllocator(t), 0, method);
|
|
||||||
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
|
||||||
t->continuation = makeCurrentContinuation
|
|
||||||
(t, &ip, &base, &stack, &oldArgumentFootprint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
|
||||||
jumpAndInvoke
|
|
||||||
(t, method, base, stack, oldArgumentFootprint, receiver,
|
|
||||||
t->continuation);
|
|
||||||
} else {
|
} else {
|
||||||
unwind(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dynamicWind(Thread* vmt, object before, object thunk,
|
virtual void dynamicWind(Thread* t, object before, object thunk,
|
||||||
object after)
|
object after)
|
||||||
{
|
{
|
||||||
MyThread* t = static_cast<MyThread*>(vmt);
|
if (Continuations) {
|
||||||
|
::dynamicWind(static_cast<MyThread*>(t), before, thunk, after);
|
||||||
void* ip = 0;
|
|
||||||
void* base = 0;
|
|
||||||
void* stack = 0;
|
|
||||||
unsigned oldArgumentFootprint = 0;
|
|
||||||
|
|
||||||
{ PROTECT(t, before);
|
|
||||||
PROTECT(t, thunk);
|
|
||||||
PROTECT(t, after);
|
|
||||||
|
|
||||||
if (windMethod == 0) {
|
|
||||||
const char* const className = "avian/Continuations";
|
|
||||||
const char* const methodName = "wind";
|
|
||||||
const char* const methodSpec
|
|
||||||
= "(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;"
|
|
||||||
"Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;";
|
|
||||||
|
|
||||||
windMethod = resolveMethod(t, className, methodName, methodSpec);
|
|
||||||
|
|
||||||
if (windMethod) {
|
|
||||||
compile(t, ::codeAllocator(t), 0, windMethod);
|
|
||||||
} else {
|
} else {
|
||||||
object message = makeString
|
abort(t);
|
||||||
(t, "%s %s not found in %s", methodName, methodSpec, className);
|
|
||||||
t->exception = makeNoSuchMethodError(t, message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
virtual void feedResultToContinuation(Thread* t, object continuation,
|
||||||
t->continuation = makeCurrentContinuation
|
|
||||||
(t, &ip, &base, &stack, &oldArgumentFootprint);
|
|
||||||
|
|
||||||
object newContext = makeContinuationContext
|
|
||||||
(t, continuationContext(t, t->continuation), before, after,
|
|
||||||
t->continuation, t->trace->originalMethod);
|
|
||||||
|
|
||||||
set(t, t->continuation, ContinuationContext, newContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
|
||||||
jumpAndInvoke
|
|
||||||
(t, windMethod, base, stack, oldArgumentFootprint, before, thunk,
|
|
||||||
after);
|
|
||||||
} else {
|
|
||||||
unwind(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void feedResultToContinuation(Thread* vmt, object continuation,
|
|
||||||
object result)
|
object result)
|
||||||
{
|
{
|
||||||
callContinuation(static_cast<MyThread*>(vmt), continuation, result, 0);
|
if (Continuations) {
|
||||||
|
callContinuation(static_cast<MyThread*>(t), continuation, result, 0);
|
||||||
|
} else {
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void feedExceptionToContinuation(Thread* vmt, object continuation,
|
virtual void feedExceptionToContinuation(Thread* t, object continuation,
|
||||||
object exception)
|
object exception)
|
||||||
{
|
{
|
||||||
callContinuation(static_cast<MyThread*>(vmt), continuation, 0, exception);
|
if (Continuations) {
|
||||||
|
callContinuation(static_cast<MyThread*>(t), continuation, 0, exception);
|
||||||
|
} else {
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void walkContinuationBody(Thread* t, Heap::Walker* w, object o,
|
virtual void walkContinuationBody(Thread* t, Heap::Walker* w, object o,
|
||||||
unsigned start)
|
unsigned start)
|
||||||
{
|
{
|
||||||
|
if (Continuations) {
|
||||||
::walkContinuationBody(static_cast<MyThread*>(t), w, o, start);
|
::walkContinuationBody(static_cast<MyThread*>(t), w, o, start);
|
||||||
|
} else {
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
@ -6969,12 +7014,24 @@ objectPools(MyThread* t)
|
|||||||
return processor(t)->objectPools;
|
return processor(t)->objectPools;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object&
|
||||||
|
windMethod(MyThread* t)
|
||||||
|
{
|
||||||
|
return processor(t)->windMethod;
|
||||||
|
}
|
||||||
|
|
||||||
object&
|
object&
|
||||||
rewindMethod(MyThread* t)
|
rewindMethod(MyThread* t)
|
||||||
{
|
{
|
||||||
return processor(t)->rewindMethod;
|
return processor(t)->rewindMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object&
|
||||||
|
receiveMethod(MyThread* t)
|
||||||
|
{
|
||||||
|
return processor(t)->receiveMethod;
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t
|
uintptr_t
|
||||||
defaultThunk(MyThread* t)
|
defaultThunk(MyThread* t)
|
||||||
{
|
{
|
||||||
|
@ -2392,7 +2392,7 @@ class CallEvent: public Event {
|
|||||||
int framePointerIndex;
|
int framePointerIndex;
|
||||||
int frameOffset;
|
int frameOffset;
|
||||||
|
|
||||||
if (flags & Compiler::TailJump) {
|
if (TailCalls and (flags & Compiler::TailJump)) {
|
||||||
assert(c, argumentCount == 0);
|
assert(c, argumentCount == 0);
|
||||||
|
|
||||||
int base = frameBase(c);
|
int base = frameBase(c);
|
||||||
@ -2433,7 +2433,7 @@ class CallEvent: public Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & Compiler::TailJump) == 0) {
|
if ((not TailCalls) or (flags & Compiler::TailJump) == 0) {
|
||||||
stackArgumentIndex = c->localFootprint;
|
stackArgumentIndex = c->localFootprint;
|
||||||
if (stackBefore) {
|
if (stackBefore) {
|
||||||
stackArgumentIndex += stackBefore->index + 1 - stackArgumentFootprint;
|
stackArgumentIndex += stackBefore->index + 1 - stackArgumentFootprint;
|
||||||
@ -2475,7 +2475,7 @@ class CallEvent: public Event {
|
|||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
UnaryOperation op;
|
UnaryOperation op;
|
||||||
|
|
||||||
if (flags & Compiler::TailJump) {
|
if (TailCalls and (flags & Compiler::TailJump)) {
|
||||||
if (flags & Compiler::Aligned) {
|
if (flags & Compiler::Aligned) {
|
||||||
op = AlignedJump;
|
op = AlignedJump;
|
||||||
} else {
|
} else {
|
||||||
@ -2525,6 +2525,7 @@ class CallEvent: public Event {
|
|||||||
stackArgumentIndex);
|
stackArgumentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TailCalls) {
|
||||||
if (flags & Compiler::TailJump) {
|
if (flags & Compiler::TailJump) {
|
||||||
if (returnAddressSurrogate) {
|
if (returnAddressSurrogate) {
|
||||||
returnAddressSurrogate->source->thaw(c, returnAddressSurrogate);
|
returnAddressSurrogate->source->thaw(c, returnAddressSurrogate);
|
||||||
@ -2534,7 +2535,9 @@ class CallEvent: public Event {
|
|||||||
framePointerSurrogate->source->thaw(c, framePointerSurrogate);
|
framePointerSurrogate->source->thaw(c, framePointerSurrogate);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned footprint = c->arch->argumentFootprint(stackArgumentFootprint);
|
unsigned footprint = c->arch->argumentFootprint
|
||||||
|
(stackArgumentFootprint);
|
||||||
|
|
||||||
if (footprint > c->arch->stackAlignmentInWords()) {
|
if (footprint > c->arch->stackAlignmentInWords()) {
|
||||||
Assembler::Register stack(c->arch->stack());
|
Assembler::Register stack(c->arch->stack());
|
||||||
ResolvedPromise adjustmentPromise
|
ResolvedPromise adjustmentPromise
|
||||||
@ -2546,6 +2549,7 @@ class CallEvent: public Event {
|
|||||||
BytesPerWord, RegisterOperand, &stack);
|
BytesPerWord, RegisterOperand, &stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clean(c, this, stackBefore, localsBefore, reads, popIndex);
|
clean(c, this, stackBefore, localsBefore, reads, popIndex);
|
||||||
|
|
||||||
|
@ -2412,6 +2412,7 @@ class MyAssembler: public Assembler {
|
|||||||
int returnAddressSurrogate,
|
int returnAddressSurrogate,
|
||||||
int framePointerSurrogate)
|
int framePointerSurrogate)
|
||||||
{
|
{
|
||||||
|
if (TailCalls) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
Register tmp(c.client->acquireTemporary());
|
Register tmp(c.client->acquireTemporary());
|
||||||
|
|
||||||
@ -2450,6 +2451,9 @@ class MyAssembler: public Assembler {
|
|||||||
} else {
|
} else {
|
||||||
popFrame();
|
popFrame();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
abort(&c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint) {
|
virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint) {
|
||||||
@ -2458,7 +2462,7 @@ class MyAssembler: public Assembler {
|
|||||||
assert(&c, argumentFootprint >= StackAlignmentInWords);
|
assert(&c, argumentFootprint >= StackAlignmentInWords);
|
||||||
assert(&c, (argumentFootprint % StackAlignmentInWords) == 0);
|
assert(&c, (argumentFootprint % StackAlignmentInWords) == 0);
|
||||||
|
|
||||||
if (argumentFootprint > StackAlignmentInWords) {
|
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
|
||||||
Register returnAddress(rcx);
|
Register returnAddress(rcx);
|
||||||
popR(&c, BytesPerWord, &returnAddress);
|
popR(&c, BytesPerWord, &returnAddress);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user