mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
ensure stack alignment in compile-x86.S and update vmInvoke to accept frame size parameter
This commit is contained in:
parent
17b4c20435
commit
c88e3fa230
@ -14,8 +14,7 @@
|
|||||||
|
|
||||||
#define BYTES_PER_WORD 4
|
#define BYTES_PER_WORD 4
|
||||||
#define LINKAGE_AREA 6
|
#define LINKAGE_AREA 6
|
||||||
#define GPR_COUNT 8
|
#define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA
|
||||||
#define MEMORY_BASE BYTES_PER_WORD * (LINKAGE_AREA + GPR_COUNT)
|
|
||||||
|
|
||||||
#define LOCAL(x) L##x
|
#define LOCAL(x) L##x
|
||||||
|
|
||||||
@ -32,13 +31,16 @@ vmInvoke:
|
|||||||
|
|
||||||
// r3: thread
|
// r3: thread
|
||||||
// r4: function
|
// r4: function
|
||||||
// r5: parameters
|
// r5: arguments
|
||||||
// r6: parameterCount
|
// r6: argumentFootprint
|
||||||
// r7: frameSize
|
// r7: frameSize
|
||||||
// r8: returnType (ignored)
|
// r8: returnType
|
||||||
|
|
||||||
// r9: temporary
|
// r9: temporary
|
||||||
|
|
||||||
|
// save return type
|
||||||
|
stw r8,44(r1)
|
||||||
|
|
||||||
// allocate stack space, adding room for callee-saved registers
|
// allocate stack space, adding room for callee-saved registers
|
||||||
addi r9,r7,80
|
addi r9,r7,80
|
||||||
stwux r1,r1,r9
|
stwux r1,r1,r9
|
||||||
@ -75,7 +77,7 @@ vmInvoke:
|
|||||||
|
|
||||||
LOCAL(loop):
|
LOCAL(loop):
|
||||||
lwzx r17,r16,r5
|
lwzx r17,r16,r5
|
||||||
addi r18,r16,MEMORY_BASE
|
addi r18,r16,ARGUMENT_BASE
|
||||||
stwx r17,r18,r1
|
stwx r17,r18,r1
|
||||||
addi r16,r16,BYTES_PER_WORD
|
addi r16,r16,BYTES_PER_WORD
|
||||||
|
|
||||||
@ -113,6 +115,24 @@ LOCAL(test):
|
|||||||
lwz r30,68(r9)
|
lwz r30,68(r9)
|
||||||
lwz r31,72(r9)
|
lwz r31,72(r9)
|
||||||
|
|
||||||
|
// handle return value based on expected type
|
||||||
|
lwz r8,44(r1)
|
||||||
|
|
||||||
|
LOCAL(void):
|
||||||
|
cmplw VOID_TYPE,r8
|
||||||
|
bne LOCAL(int64)
|
||||||
|
b LOCAL(exit)
|
||||||
|
|
||||||
|
LOCAL(int64):
|
||||||
|
cmplw INT64_TYPE,r8
|
||||||
|
bne LOCAL(int32)
|
||||||
|
b LOCAL(exit)
|
||||||
|
|
||||||
|
LOCAL(int32):
|
||||||
|
mr r3,r4
|
||||||
|
li r3,0
|
||||||
|
|
||||||
|
LOCAL(exit):
|
||||||
// load return address
|
// load return address
|
||||||
lwz r0,8(r1)
|
lwz r0,8(r1)
|
||||||
mtlr r0
|
mtlr r0
|
||||||
|
@ -21,30 +21,38 @@ vmInvoke:
|
|||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp,%rbp
|
movq %rsp,%rbp
|
||||||
|
|
||||||
// push callee-saved registers
|
|
||||||
pushq %rbx
|
|
||||||
pushq %r12
|
|
||||||
pushq %r13
|
|
||||||
pushq %r14
|
|
||||||
pushq %r15
|
|
||||||
|
|
||||||
// %rdi: thread
|
// %rdi: thread
|
||||||
// %rsi: function
|
// %rsi: function
|
||||||
// %rdx: stack
|
// %rdx: arguments
|
||||||
// %rcx: stackSize
|
// %rcx: argumentFootprint
|
||||||
// %r8 : returnType
|
// %r8 : frameSize
|
||||||
|
// %r9 : returnType (ignored)
|
||||||
|
|
||||||
|
// allocate stack space, adding room for callee-saved registers
|
||||||
|
subq %r8,%rsp
|
||||||
|
subq $48,%rsp
|
||||||
|
|
||||||
|
// save callee-saved registers
|
||||||
|
movq %rsp,%r9
|
||||||
|
addq %r8,%r9
|
||||||
|
|
||||||
|
movq %rbx,0(%r9)
|
||||||
|
movq %r12,8(%r9)
|
||||||
|
movq %r13,16(%r9)
|
||||||
|
movq %r14,24(%r9)
|
||||||
|
movq %r15,32(%r9)
|
||||||
|
|
||||||
// we use rbx to hold the thread pointer, by convention
|
// we use rbx to hold the thread pointer, by convention
|
||||||
mov %rdi,%rbx
|
mov %rdi,%rbx
|
||||||
|
|
||||||
// copy arguments into place
|
// copy arguments into place
|
||||||
pushq %rcx
|
|
||||||
movq $0,%r9
|
movq $0,%r9
|
||||||
jmp LOCAL(test)
|
jmp LOCAL(test)
|
||||||
|
|
||||||
LOCAL(loop):
|
LOCAL(loop):
|
||||||
push (%rdx,%r9,8)
|
movq (%rdx,%r9,1),%r8
|
||||||
inc %r9
|
movq %r8,(%rsp,%r9,1)
|
||||||
|
addq $8,%r9
|
||||||
|
|
||||||
LOCAL(test):
|
LOCAL(test):
|
||||||
cmpq %rcx,%r9
|
cmpq %rcx,%r9
|
||||||
@ -53,22 +61,20 @@ LOCAL(test):
|
|||||||
// call function
|
// call function
|
||||||
call *%rsi
|
call *%rsi
|
||||||
|
|
||||||
// pop arguments
|
// restore stack pointer
|
||||||
mov -48(%rbp),%rcx
|
|
||||||
sal $3,%rcx
|
|
||||||
addq %rcx,%rsp
|
|
||||||
|
|
||||||
// pop argument stack size
|
|
||||||
addq $8,%rsp
|
|
||||||
|
|
||||||
// pop callee-saved registers
|
|
||||||
popq %r15
|
|
||||||
popq %r14
|
|
||||||
popq %r13
|
|
||||||
popq %r12
|
|
||||||
popq %rbx
|
|
||||||
|
|
||||||
movq %rbp,%rsp
|
movq %rbp,%rsp
|
||||||
|
|
||||||
|
// restore callee-saved registers
|
||||||
|
movq %rsp,%r9
|
||||||
|
subq $48,%r9
|
||||||
|
|
||||||
|
movq 0(%r9),%rbx
|
||||||
|
movq 8(%r9),%r12
|
||||||
|
movq 16(%r9),%r13
|
||||||
|
movq 24(%r9),%r14
|
||||||
|
movq 32(%r9),%r15
|
||||||
|
|
||||||
|
// return
|
||||||
popq %rbp
|
popq %rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -84,28 +90,37 @@ vmInvoke:
|
|||||||
pushl %ebp
|
pushl %ebp
|
||||||
movl %esp,%ebp
|
movl %esp,%ebp
|
||||||
|
|
||||||
// ebx, esi and edi are callee-saved registers
|
|
||||||
pushl %ebx
|
|
||||||
pushl %esi
|
|
||||||
pushl %edi
|
|
||||||
|
|
||||||
// 8(%ebp): thread
|
// 8(%ebp): thread
|
||||||
// 12(%ebp): function
|
// 12(%ebp): function
|
||||||
// 16(%ebp): stack
|
// 16(%ebp): arguments
|
||||||
// 20(%ebp): stackSize
|
// 20(%ebp): argumentFootprint
|
||||||
// 24(%ebp): returnType
|
// 24(%ebp): frameSize
|
||||||
|
// 28(%ebp): returnType
|
||||||
|
|
||||||
|
// allocate stack space, adding room for callee-saved registers
|
||||||
|
subl 24(%ebp),%esp
|
||||||
|
subl $16,%esp
|
||||||
|
|
||||||
|
// save callee-saved registers
|
||||||
|
movl %esp,%ecx
|
||||||
|
addl 24(%ebp),%ecx
|
||||||
|
|
||||||
|
movl %ebx,0(%ecx)
|
||||||
|
movl %esi,4(%ecx)
|
||||||
|
movl %edi,8(%ecx)
|
||||||
|
|
||||||
// we use ebx to hold the thread pointer, by convention
|
// we use ebx to hold the thread pointer, by convention
|
||||||
mov 8(%ebp),%ebx
|
mov 8(%ebp),%ebx
|
||||||
|
|
||||||
// copy arguments into place
|
// copy arguments into place
|
||||||
movl $0,%ecx
|
movl $0,%ecx
|
||||||
mov 16(%ebp),%edx
|
movl 16(%ebp),%edx
|
||||||
jmp LOCAL(test)
|
jmp LOCAL(test)
|
||||||
|
|
||||||
LOCAL(loop):
|
LOCAL(loop):
|
||||||
push (%edx,%ecx,4)
|
movl (%edx,%ecx,1),%eax
|
||||||
inc %ecx
|
movl %eax,(%esp,%ecx,1)
|
||||||
|
addl $4,%ecx
|
||||||
|
|
||||||
LOCAL(test):
|
LOCAL(test):
|
||||||
cmpl 20(%ebp),%ecx
|
cmpl 20(%ebp),%ecx
|
||||||
@ -114,13 +129,19 @@ LOCAL(test):
|
|||||||
// call function
|
// call function
|
||||||
call *12(%ebp)
|
call *12(%ebp)
|
||||||
|
|
||||||
// pop arguments
|
// restore stack pointer
|
||||||
mov 20(%ebp),%ecx
|
movl %ebp,%esp
|
||||||
sal $2,%ecx
|
|
||||||
addl %ecx,%esp
|
// restore callee-saved registers
|
||||||
|
movl %esp,%ecx
|
||||||
|
subl $16,%ecx
|
||||||
|
|
||||||
|
movl 0(%ecx),%ebx
|
||||||
|
movl 4(%ecx),%esi
|
||||||
|
movl 8(%ecx),%edi
|
||||||
|
|
||||||
// handle return value based on expected type
|
// handle return value based on expected type
|
||||||
movl 24(%ebp),%ecx
|
movl 28(%ebp),%ecx
|
||||||
|
|
||||||
LOCAL(void):
|
LOCAL(void):
|
||||||
cmpl $VOID_TYPE,%ecx
|
cmpl $VOID_TYPE,%ecx
|
||||||
@ -136,10 +157,6 @@ LOCAL(int32):
|
|||||||
movl $0,%edx
|
movl $0,%edx
|
||||||
|
|
||||||
LOCAL(exit):
|
LOCAL(exit):
|
||||||
popl %edi
|
|
||||||
popl %esi
|
|
||||||
popl %ebx
|
|
||||||
movl %ebp,%esp
|
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -19,15 +19,15 @@
|
|||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
extern "C" uint64_t
|
extern "C" uint64_t
|
||||||
vmInvoke(void* thread, void* function, void* stack, unsigned stackSize,
|
vmInvoke(void* thread, void* function, void* arguments,
|
||||||
unsigned returnType);
|
unsigned argumentFootprint, unsigned frameSize, unsigned returnType);
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
vmCall();
|
vmCall();
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool DebugCompile = true;
|
const bool DebugCompile = false;
|
||||||
const bool DebugNatives = false;
|
const bool DebugNatives = false;
|
||||||
const bool DebugCallTable = false;
|
const bool DebugCallTable = false;
|
||||||
const bool DebugMethodTree = false;
|
const bool DebugMethodTree = false;
|
||||||
@ -4649,12 +4649,14 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
|||||||
|
|
||||||
class ArgumentList {
|
class ArgumentList {
|
||||||
public:
|
public:
|
||||||
ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_,
|
ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask,
|
||||||
const char* spec, bool indirectObjects, va_list arguments):
|
object this_, const char* spec, bool indirectObjects,
|
||||||
|
va_list arguments):
|
||||||
t(static_cast<MyThread*>(t)),
|
t(static_cast<MyThread*>(t)),
|
||||||
array(array),
|
array(array),
|
||||||
objectMask(objectMask),
|
objectMask(objectMask),
|
||||||
position(0),
|
size(size),
|
||||||
|
position(size),
|
||||||
protector(this)
|
protector(this)
|
||||||
{
|
{
|
||||||
if (this_) {
|
if (this_) {
|
||||||
@ -4685,12 +4687,13 @@ class ArgumentList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_,
|
ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask,
|
||||||
const char* spec, object arguments):
|
object this_, const char* spec, object arguments):
|
||||||
t(static_cast<MyThread*>(t)),
|
t(static_cast<MyThread*>(t)),
|
||||||
array(array),
|
array(array),
|
||||||
objectMask(objectMask),
|
objectMask(objectMask),
|
||||||
position(0),
|
size(size),
|
||||||
|
position(size),
|
||||||
protector(this)
|
protector(this)
|
||||||
{
|
{
|
||||||
if (this_) {
|
if (this_) {
|
||||||
@ -4720,34 +4723,41 @@ class ArgumentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addObject(object v) {
|
void addObject(object v) {
|
||||||
|
assert(t, position);
|
||||||
|
|
||||||
|
-- position;
|
||||||
array[position] = reinterpret_cast<uintptr_t>(v);
|
array[position] = reinterpret_cast<uintptr_t>(v);
|
||||||
objectMask[position] = true;
|
objectMask[position] = true;
|
||||||
++ position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addInt(uintptr_t v) {
|
void addInt(uintptr_t v) {
|
||||||
|
assert(t, position);
|
||||||
|
|
||||||
|
-- position;
|
||||||
array[position] = v;
|
array[position] = v;
|
||||||
objectMask[position] = false;
|
objectMask[position] = false;
|
||||||
++ position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLong(uint64_t v) {
|
void addLong(uint64_t v) {
|
||||||
|
assert(t, position >= 2);
|
||||||
|
|
||||||
|
position -= 2;
|
||||||
|
|
||||||
if (BytesPerWord == 8) {
|
if (BytesPerWord == 8) {
|
||||||
memcpy(array + position + 1, &v, 8);
|
memcpy(array + position, &v, 8);
|
||||||
} else {
|
} else {
|
||||||
// push words in reverse order, since they will be switched back
|
array[position] = v;
|
||||||
// when pushed on the stack:
|
array[position + 1] = v >> 32;
|
||||||
array[position] = v >> 32;
|
|
||||||
array[position + 1] = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
objectMask[position] = false;
|
objectMask[position] = false;
|
||||||
objectMask[position + 1] = false;
|
objectMask[position + 1] = false;
|
||||||
position += 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MyThread* t;
|
MyThread* t;
|
||||||
uintptr_t* array;
|
uintptr_t* array;
|
||||||
bool* objectMask;
|
bool* objectMask;
|
||||||
|
unsigned size;
|
||||||
unsigned position;
|
unsigned position;
|
||||||
|
|
||||||
class MyProtector: public Thread::Protector {
|
class MyProtector: public Thread::Protector {
|
||||||
@ -4755,7 +4765,7 @@ class ArgumentList {
|
|||||||
MyProtector(ArgumentList* list): Protector(list->t), list(list) { }
|
MyProtector(ArgumentList* list): Protector(list->t), list(list) { }
|
||||||
|
|
||||||
virtual void visit(Heap::Visitor* v) {
|
virtual void visit(Heap::Visitor* v) {
|
||||||
for (unsigned i = 0; i < list->position; ++i) {
|
for (unsigned i = list->position; i < list->size; ++i) {
|
||||||
if (list->objectMask[i]) {
|
if (list->objectMask[i]) {
|
||||||
v->visit(reinterpret_cast<object*>(list->array + i));
|
v->visit(reinterpret_cast<object*>(list->array + i));
|
||||||
}
|
}
|
||||||
@ -4782,9 +4792,14 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
|
|||||||
trace.nativeMethod = method;
|
trace.nativeMethod = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned count = arguments->size - arguments->position;
|
||||||
|
|
||||||
result = vmInvoke
|
result = vmInvoke
|
||||||
(t, reinterpret_cast<void*>(methodAddress(t, method)),
|
(t, reinterpret_cast<void*>(methodAddress(t, method)),
|
||||||
arguments->array, arguments->position, returnType);
|
arguments->array + arguments->position,
|
||||||
|
count * BytesPerWord,
|
||||||
|
t->arch->alignFrameSize(count) * BytesPerWord,
|
||||||
|
returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->exception) {
|
if (t->exception) {
|
||||||
@ -5076,7 +5091,7 @@ class MyProcessor: public Processor {
|
|||||||
unsigned size = methodParameterFootprint(t, method);
|
unsigned size = methodParameterFootprint(t, method);
|
||||||
uintptr_t array[size];
|
uintptr_t array[size];
|
||||||
bool objectMask[size];
|
bool objectMask[size];
|
||||||
ArgumentList list(t, array, objectMask, this_, spec, arguments);
|
ArgumentList list(t, array, size, objectMask, this_, spec, arguments);
|
||||||
|
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -5107,7 +5122,7 @@ class MyProcessor: public Processor {
|
|||||||
uintptr_t array[size];
|
uintptr_t array[size];
|
||||||
bool objectMask[size];
|
bool objectMask[size];
|
||||||
ArgumentList list
|
ArgumentList list
|
||||||
(t, array, objectMask, this_, spec, indirectObjects, arguments);
|
(t, array, size, objectMask, this_, spec, indirectObjects, arguments);
|
||||||
|
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -5133,7 +5148,7 @@ class MyProcessor: public Processor {
|
|||||||
uintptr_t array[size];
|
uintptr_t array[size];
|
||||||
bool objectMask[size];
|
bool objectMask[size];
|
||||||
ArgumentList list
|
ArgumentList list
|
||||||
(t, array, objectMask, this_, methodSpec, false, arguments);
|
(t, array, size, objectMask, this_, methodSpec, false, arguments);
|
||||||
|
|
||||||
object method = resolveMethod(t, className, methodName, methodSpec);
|
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user