mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
more JNI work
This commit is contained in:
parent
f0bc4dbe76
commit
2057e72956
34
makefile
34
makefile
@ -4,6 +4,14 @@ bld = build
|
|||||||
src = src
|
src = src
|
||||||
classpath = classpath
|
classpath = classpath
|
||||||
|
|
||||||
|
arch = $(shell uname -m)
|
||||||
|
ifeq ($(arch),i586)
|
||||||
|
arch = i386
|
||||||
|
endif
|
||||||
|
ifeq ($(arch),i686)
|
||||||
|
arch = i386
|
||||||
|
endif
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
cc = gcc
|
||||||
vg = nice valgrind --leak-check=full --num-callers=32 --db-attach=yes \
|
vg = nice valgrind --leak-check=full --num-callers=32 --db-attach=yes \
|
||||||
@ -27,6 +35,7 @@ test-cflags = -DDEBUG_MEMORY
|
|||||||
stress-cflags = -DDEBUG_MEMORY -DDEBUG_MEMORY_MAJOR
|
stress-cflags = -DDEBUG_MEMORY -DDEBUG_MEMORY_MAJOR
|
||||||
|
|
||||||
cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(bld)/%.o,$(x)))
|
cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(bld)/%.o,$(x)))
|
||||||
|
assembly-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(bld)/%.o,$(x)))
|
||||||
|
|
||||||
stdcpp-sources = $(src)/stdc++.cpp
|
stdcpp-sources = $(src)/stdc++.cpp
|
||||||
stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src))
|
stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src))
|
||||||
@ -58,7 +67,21 @@ interpreter-sources = \
|
|||||||
$(src)/vm.cpp \
|
$(src)/vm.cpp \
|
||||||
$(src)/heap.cpp \
|
$(src)/heap.cpp \
|
||||||
$(src)/main.cpp
|
$(src)/main.cpp
|
||||||
interpreter-objects = $(call cpp-objects,$(interpreter-sources),$(src))
|
|
||||||
|
ifeq ($(arch),i386)
|
||||||
|
interpreter-assembly-sources = $(src)/cdecl.S
|
||||||
|
endif
|
||||||
|
ifeq ($(arch),x86_64)
|
||||||
|
interpreter-assembly-sources = $(src)/amd64.S
|
||||||
|
endif
|
||||||
|
|
||||||
|
interpreter-cpp-objects = \
|
||||||
|
$(call cpp-objects,$(interpreter-sources),$(src))
|
||||||
|
interpreter-assembly-objects = \
|
||||||
|
$(call assembly-objects,$(interpreter-assembly-sources),$(src))
|
||||||
|
interpreter-objects = \
|
||||||
|
$(interpreter-cpp-objects) \
|
||||||
|
$(interpreter-assembly-objects)
|
||||||
interpreter-cflags = $(slow) $(cflags)
|
interpreter-cflags = $(slow) $(cflags)
|
||||||
|
|
||||||
generator-headers = \
|
generator-headers = \
|
||||||
@ -138,7 +161,7 @@ stress-all: $(stress-executable)
|
|||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@echo "removing $(bld)"
|
@echo "removing $(bld)"
|
||||||
rm -r $(bld)
|
rm -rf $(bld)
|
||||||
|
|
||||||
gen-arg = $(shell echo $(1) | sed -e 's:$(bld)/type-\(.*\)\.cpp:\1:')
|
gen-arg = $(shell echo $(1) | sed -e 's:$(bld)/type-\(.*\)\.cpp:\1:')
|
||||||
$(generated-code): %.cpp: $(src)/types.def $(generator-executable)
|
$(generated-code): %.cpp: $(src)/types.def $(generator-executable)
|
||||||
@ -159,7 +182,12 @@ $(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp
|
|||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(stdcpp-cflags) -c $(<) -o $(@)
|
$(cxx) $(stdcpp-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
$(interpreter-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends)
|
$(interpreter-cpp-objects): $(bld)/%.o: $(src)/%.cpp $(interpreter-depends)
|
||||||
|
@echo "compiling $(@)"
|
||||||
|
@mkdir -p $(dir $(@))
|
||||||
|
$(cxx) $(interpreter-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
|
$(interpreter-assembly-objects): $(bld)/%.o: $(src)/%.S
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(interpreter-cflags) -c $(<) -o $(@)
|
$(cxx) $(interpreter-cflags) -c $(<) -o $(@)
|
||||||
|
107
src/amd64.S
Normal file
107
src/amd64.S
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl amd64Call
|
||||||
|
.type amd64Call, @function
|
||||||
|
|
||||||
|
amd64Call:
|
||||||
|
pushq %rbp
|
||||||
|
|
||||||
|
// %rdi aka 0(%rbp): function
|
||||||
|
// %rsi aka 8(%rbp): stack
|
||||||
|
// %rdx aka 16(%rbp): stackSize
|
||||||
|
// %rcx aka 24(%rbp): gprTable
|
||||||
|
// %r8 aka 32(%rbp): sseTable
|
||||||
|
// %r9 aka 40(%rbp): returnType
|
||||||
|
|
||||||
|
// save our argument registers so we can clobber them
|
||||||
|
pushq %r9
|
||||||
|
pushq %r8
|
||||||
|
pushq %rcx
|
||||||
|
pushq %rdx
|
||||||
|
pushq %rsi
|
||||||
|
pushq %rdi
|
||||||
|
|
||||||
|
movq %rsp,%rbp
|
||||||
|
|
||||||
|
// reserve space for arguments passed via memory
|
||||||
|
subq %rdx,%rsp
|
||||||
|
|
||||||
|
// copy memory arguments into place
|
||||||
|
movq $0,%rcx
|
||||||
|
jmp test
|
||||||
|
|
||||||
|
loop:
|
||||||
|
movq %rcx,%rax
|
||||||
|
movq %rcx,%rdx
|
||||||
|
addq %rsp,%rdx
|
||||||
|
addq 8(%rbp),%rax
|
||||||
|
movq (%rax),%rax
|
||||||
|
movq %rax,(%rdx)
|
||||||
|
addq $8,%rcx
|
||||||
|
|
||||||
|
test:
|
||||||
|
cmpq 16(%rbp),%rcx
|
||||||
|
jb loop
|
||||||
|
|
||||||
|
// do we need to load the general-purpose registers?
|
||||||
|
cmpq $0,24(%rbp)
|
||||||
|
je sse
|
||||||
|
|
||||||
|
// yes, we do
|
||||||
|
movq 24(%rbp),%rax
|
||||||
|
movq 0(%rax),%rdi
|
||||||
|
movq 8(%rax),%rsi
|
||||||
|
movq 16(%rax),%rcx
|
||||||
|
movq 24(%rax),%rdx
|
||||||
|
movq 32(%rax),%r8
|
||||||
|
movq 40(%rax),%r9
|
||||||
|
|
||||||
|
sse:
|
||||||
|
// do we need to load the SSE registers?
|
||||||
|
cmpq $0,32(%rbp)
|
||||||
|
je call
|
||||||
|
|
||||||
|
// yes, we do
|
||||||
|
movq 32(%rbp),%rax
|
||||||
|
movq 0(%rax),%xmm0
|
||||||
|
movq 8(%rax),%xmm1
|
||||||
|
movq 16(%rax),%xmm2
|
||||||
|
movq 24(%rax),%xmm3
|
||||||
|
movq 32(%rax),%xmm4
|
||||||
|
movq 40(%rax),%xmm5
|
||||||
|
movq 48(%rax),%xmm6
|
||||||
|
movq 64(%rax),%xmm7
|
||||||
|
|
||||||
|
call:
|
||||||
|
call *0(%rbp)
|
||||||
|
|
||||||
|
// clear space reserved for memory arguments
|
||||||
|
movq 16(%rbp),%rcx
|
||||||
|
addq %rcx,%rsp
|
||||||
|
|
||||||
|
// handle return value based on expected type
|
||||||
|
movq 40(%rbp),%rcx
|
||||||
|
|
||||||
|
void:
|
||||||
|
cmpq $VOID_TYPE,%rcx
|
||||||
|
jne float
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
float:
|
||||||
|
cmpq $FLOAT_TYPE,%rcx
|
||||||
|
je copy
|
||||||
|
cmpq $DOUBLE_TYPE,%rcx
|
||||||
|
jne exit
|
||||||
|
|
||||||
|
copy:
|
||||||
|
movq %xmm0,%rax
|
||||||
|
|
||||||
|
exit:
|
||||||
|
movq %rbp,%rsp
|
||||||
|
|
||||||
|
// pop our argument registers
|
||||||
|
addq $48,%rsp
|
||||||
|
|
||||||
|
popq %rbp
|
||||||
|
ret
|
78
src/cdecl.S
Normal file
78
src/cdecl.S
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl cdeclCall
|
||||||
|
.type cdeclCall, @function
|
||||||
|
|
||||||
|
cdeclCall:
|
||||||
|
pushl %ebp
|
||||||
|
movl %esp,%ebp
|
||||||
|
|
||||||
|
// 8(%ebp): function
|
||||||
|
// 12(%ebp): stack
|
||||||
|
// 16(%ebp): stackSize
|
||||||
|
// 20(%ebp): returnType
|
||||||
|
|
||||||
|
// reserve space for arguments
|
||||||
|
movl 16(%ebp),%ecx
|
||||||
|
subl %ecx,%esp
|
||||||
|
|
||||||
|
// copy arguments into place
|
||||||
|
movl $0,%ecx
|
||||||
|
jmp test
|
||||||
|
|
||||||
|
loop:
|
||||||
|
movl %ecx,%eax
|
||||||
|
movl %ecx,%edx
|
||||||
|
addl %esp,%edx
|
||||||
|
addl 12(%ebp),%eax
|
||||||
|
movl (%eax),%eax
|
||||||
|
movl %eax,(%edx)
|
||||||
|
addl $4,%ecx
|
||||||
|
|
||||||
|
test:
|
||||||
|
cmpl 16(%ebp),%ecx
|
||||||
|
jb loop
|
||||||
|
|
||||||
|
// call function
|
||||||
|
call *8(%ebp)
|
||||||
|
|
||||||
|
// clear space reserved for arguments
|
||||||
|
movl 16(%ebp),%ecx
|
||||||
|
addl %ecx,%esp
|
||||||
|
|
||||||
|
// handle return value based on expected type
|
||||||
|
movl 20(%ebp),%ecx
|
||||||
|
|
||||||
|
void:
|
||||||
|
cmpl $VOID_TYPE,%ecx
|
||||||
|
jne int64
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
int64:
|
||||||
|
cmpl $INT64_TYPE,%ecx
|
||||||
|
jne float
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
float:
|
||||||
|
cmpl $FLOAT_TYPE,%ecx
|
||||||
|
jne double
|
||||||
|
fstps 8(%ebp)
|
||||||
|
movl 8(%ebp),%eax
|
||||||
|
jmp int32
|
||||||
|
|
||||||
|
double:
|
||||||
|
cmpl $DOUBLE_TYPE,%ecx
|
||||||
|
jne int32
|
||||||
|
fstpl 8(%ebp)
|
||||||
|
movl 8(%ebp),%eax
|
||||||
|
movl 12(%ebp),%edx
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
int32:
|
||||||
|
movl $0,%edx
|
||||||
|
|
||||||
|
exit:
|
||||||
|
movl %ebp,%esp
|
||||||
|
popl %ebp
|
||||||
|
ret
|
@ -6,6 +6,7 @@
|
|||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#define NO_RETURN __attribute__((noreturn))
|
#define NO_RETURN __attribute__((noreturn))
|
||||||
|
|
||||||
|
80
src/main.cpp
80
src/main.cpp
@ -11,6 +11,77 @@
|
|||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
|
||||||
|
extern "C" uint64_t
|
||||||
|
cdeclCall(void* function, void* stack, unsigned stackSize,
|
||||||
|
unsigned returnType);
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
inline uint64_t
|
||||||
|
dynamicCall(void* function, uint32_t* arguments, uint8_t*,
|
||||||
|
unsigned, unsigned argumentsSize, unsigned returnType)
|
||||||
|
{
|
||||||
|
return cdeclCall(function, arguments, argumentsSize, returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#elif defined __x86_64__
|
||||||
|
|
||||||
|
extern "C" uint64_t
|
||||||
|
amd64Call(void* function, void* stack, unsigned stackSize,
|
||||||
|
void* gprTable, void* sseTable, unsigned returnType);
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||||
|
unsigned argumentCount, unsigned, unsigned returnType)
|
||||||
|
{
|
||||||
|
const unsigned GprCount = 6;
|
||||||
|
uint64_t gprTable[GprCount];
|
||||||
|
unsigned gprIndex = 0;
|
||||||
|
|
||||||
|
const unsigned SseCount = 8;
|
||||||
|
uint64_t sseTable[SseCount];
|
||||||
|
unsigned sseIndex = 0;
|
||||||
|
|
||||||
|
uint64_t stack[argumentCount];
|
||||||
|
unsigned stackIndex = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||||
|
switch (argumentTypes[i]) {
|
||||||
|
case FLOAT_TYPE:
|
||||||
|
case DOUBLE_TYPE: {
|
||||||
|
if (sseIndex < SseCount) {
|
||||||
|
sseTable[sseIndex++] = arguments[i];
|
||||||
|
} else {
|
||||||
|
stack[stackIndex++] = arguments[i];
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
if (gprIndex < GprCount) {
|
||||||
|
gprTable[gprIndex++] = arguments[i];
|
||||||
|
} else {
|
||||||
|
stack[stackIndex++] = arguments[i];
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return amd64Call(function, stack, stackIndex * 8, (gprIndex ? gprTable : 0),
|
||||||
|
(sseIndex ? sseTable : 0), returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error unsupported platform
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool Verbose = false;
|
const bool Verbose = false;
|
||||||
@ -115,13 +186,10 @@ class System: public vm::System {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint64_t call(void* ,//function,
|
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||||
unsigned ,//argumentCount,
|
unsigned count, unsigned size, unsigned returnType)
|
||||||
uint32_t* ,//argumentTable,
|
|
||||||
uint8_t* ,//argumentSizeTable,
|
|
||||||
unsigned )//returnSize)
|
|
||||||
{
|
{
|
||||||
::abort();
|
return dynamicCall(function, arguments, types, count, size, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Status load(vm::System::Library** lib,
|
virtual Status load(vm::System::Library** lib,
|
||||||
|
@ -42,9 +42,9 @@ class System {
|
|||||||
virtual void free(const void*) = 0;
|
virtual void free(const void*) = 0;
|
||||||
virtual Status start(Thread*) = 0;
|
virtual Status start(Thread*) = 0;
|
||||||
virtual Status make(Monitor**) = 0;
|
virtual Status make(Monitor**) = 0;
|
||||||
virtual uint64_t call(void* function, unsigned argumentCount,
|
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||||
uint32_t* argumentTable, uint8_t* argumentSizeTable,
|
unsigned count, unsigned size,
|
||||||
unsigned returnSize) = 0;
|
unsigned returnType) = 0;
|
||||||
virtual Status load(Library**, const char* name, Library* next) = 0;
|
virtual Status load(Library**, const char* name, Library* next) = 0;
|
||||||
virtual void abort() = 0;
|
virtual void abort() = 0;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
(uint16_t argumentTableSize)
|
(uint16_t argumentTableSize)
|
||||||
(uint8_t returnCode)
|
(uint8_t returnCode)
|
||||||
(uint8_t builtin)
|
(uint8_t builtin)
|
||||||
(array uint8_t parameterCodes))
|
(array uint8_t parameterTypes))
|
||||||
|
|
||||||
(type pointer
|
(type pointer
|
||||||
(void* value))
|
(void* value))
|
||||||
|
13
src/types.h
Normal file
13
src/types.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef TYPES_H
|
||||||
|
#define TYPES_H
|
||||||
|
|
||||||
|
#define VOID_TYPE 0
|
||||||
|
#define INT8_TYPE 1
|
||||||
|
#define INT16_TYPE 2
|
||||||
|
#define INT32_TYPE 3
|
||||||
|
#define INT64_TYPE 4
|
||||||
|
#define FLOAT_TYPE 5
|
||||||
|
#define DOUBLE_TYPE 6
|
||||||
|
#define POINTER_TYPE 7
|
||||||
|
|
||||||
|
#endif//TYPES_H
|
142
src/vm.cpp
142
src/vm.cpp
@ -17,7 +17,8 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static const bool Debug = true;
|
static const bool Verbose = false;
|
||||||
|
static const bool Debug = false;
|
||||||
|
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
@ -827,7 +828,7 @@ makeRuntimeException(Thread* t, object message)
|
|||||||
{
|
{
|
||||||
PROTECT(t, message);
|
PROTECT(t, message);
|
||||||
object trace = makeTrace(t);
|
object trace = makeTrace(t);
|
||||||
return makeClassCastException(t, message, trace, 0);
|
return makeRuntimeException(t, message, trace, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
@ -935,6 +936,33 @@ fieldCode(Thread* t, unsigned javaCode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
fieldType(Thread* t, unsigned code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case VoidField:
|
||||||
|
return VOID_TYPE;
|
||||||
|
case ByteField:
|
||||||
|
case BooleanField:
|
||||||
|
return INT8_TYPE;
|
||||||
|
case CharField:
|
||||||
|
case ShortField:
|
||||||
|
return INT16_TYPE;
|
||||||
|
case DoubleField:
|
||||||
|
return DOUBLE_TYPE;
|
||||||
|
case FloatField:
|
||||||
|
return FLOAT_TYPE;
|
||||||
|
case IntField:
|
||||||
|
return INT32_TYPE;
|
||||||
|
case LongField:
|
||||||
|
return INT64_TYPE;
|
||||||
|
case ObjectField:
|
||||||
|
return POINTER_TYPE;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
primitiveValue(Thread* t, unsigned code, object o)
|
primitiveValue(Thread* t, unsigned code, object o)
|
||||||
{
|
{
|
||||||
@ -1828,15 +1856,19 @@ resolveClass(Thread* t, object spec)
|
|||||||
(reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0)));
|
(reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0)));
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
fprintf(stderr, "parsing %s\n", &byteArrayBody
|
if (Verbose) {
|
||||||
(t, spec, 0));
|
fprintf(stderr, "parsing %s\n", &byteArrayBody
|
||||||
|
(t, spec, 0));
|
||||||
|
}
|
||||||
|
|
||||||
// parse class file
|
// parse class file
|
||||||
class_ = parseClass(t, data->start(), data->length());
|
class_ = parseClass(t, data->start(), data->length());
|
||||||
data->dispose();
|
data->dispose();
|
||||||
|
|
||||||
fprintf(stderr, "done parsing %s\n", &byteArrayBody
|
if (Verbose) {
|
||||||
(t, className(t, class_), 0));
|
fprintf(stderr, "done parsing %s\n", &byteArrayBody
|
||||||
|
(t, className(t, class_), 0));
|
||||||
|
}
|
||||||
|
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
@ -1929,15 +1961,17 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
|
|||||||
0, // argument table size
|
0, // argument table size
|
||||||
0, // return code,
|
0, // return code,
|
||||||
builtin,
|
builtin,
|
||||||
methodParameterCount(t, method),
|
methodParameterCount(t, method) + 1,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
unsigned argumentTableSize = BytesPerWord / 4;
|
unsigned argumentTableSize = BytesPerWord;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
|
|
||||||
|
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
|
||||||
|
|
||||||
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
||||||
nativeMethodDataParameterCodes(t, data, index++) = ObjectField;
|
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
|
||||||
argumentTableSize += BytesPerWord / 4;
|
argumentTableSize += BytesPerWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* s = reinterpret_cast<const char*>
|
const char* s = reinterpret_cast<const char*>
|
||||||
@ -1945,22 +1979,22 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
|
|||||||
++ s; // skip '('
|
++ s; // skip '('
|
||||||
while (*s and *s != ')') {
|
while (*s and *s != ')') {
|
||||||
unsigned code = fieldCode(t, *s);
|
unsigned code = fieldCode(t, *s);
|
||||||
nativeMethodDataParameterCodes(t, data, index++) = code;
|
nativeMethodDataParameterTypes(t, data, index++) = fieldType(t, code);
|
||||||
|
|
||||||
switch (*s) {
|
switch (*s) {
|
||||||
case 'L':
|
case 'L':
|
||||||
argumentTableSize += BytesPerWord / 4;
|
argumentTableSize += BytesPerWord;
|
||||||
while (*s and *s != ';') ++ s;
|
while (*s and *s != ';') ++ s;
|
||||||
++ s;
|
++ s;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
argumentTableSize += BytesPerWord / 4;
|
argumentTableSize += BytesPerWord;
|
||||||
while (*s == '[') ++ s;
|
while (*s == '[') ++ s;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
argumentTableSize += divide(primitiveSize(t, code), 4);
|
argumentTableSize += pad(primitiveSize(t, code));
|
||||||
++ s;
|
++ s;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2020,44 +2054,50 @@ invokeNative(Thread* t, object method)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned parameterCount = methodParameterCount(t, method);
|
unsigned count = methodParameterCount(t, method);
|
||||||
|
|
||||||
uint32_t args[nativeMethodDataArgumentTableSize(t, data)];
|
unsigned size = nativeMethodDataArgumentTableSize(t, data);
|
||||||
uint8_t sizes[parameterCount + 1];
|
uintptr_t args[size / BytesPerWord];
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
|
|
||||||
sizes[0] = BytesPerWord;
|
args[offset++] = reinterpret_cast<uintptr_t>(t);
|
||||||
memcpy(args + offset, &t, BytesPerWord);
|
|
||||||
offset += BytesPerWord / 4;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < parameterCount; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
unsigned code = nativeMethodDataParameterCodes(t, data, i);
|
unsigned type = nativeMethodDataParameterTypes(t, data, i);
|
||||||
|
unsigned position = (t->sp - count) + i;
|
||||||
|
object o = t->stack[position];
|
||||||
|
|
||||||
if (code == ObjectField) {
|
switch (type) {
|
||||||
sizes[i + 1] = BytesPerWord;
|
case INT8_TYPE:
|
||||||
unsigned position = (t->sp - parameterCount) + i;
|
args[offset++] = cast<uint8_t>(o, BytesPerWord);
|
||||||
if (t->stack[position]) {
|
break;
|
||||||
memcpy(args + offset, t->stack + position, BytesPerWord);
|
|
||||||
} else {
|
case INT16_TYPE:
|
||||||
memset(args + offset, 0, BytesPerWord);
|
args[offset++] = cast<uint16_t>(o, BytesPerWord);
|
||||||
}
|
break;
|
||||||
offset += BytesPerWord / 4;
|
|
||||||
} else {
|
case INT32_TYPE:
|
||||||
sizes[i + 1] = primitiveSize(t, code);
|
case FLOAT_TYPE:
|
||||||
uint64_t v = primitiveValue(t, code, t->stack[t->sp + i]);
|
args[offset++] = cast<uint32_t>(o, BytesPerWord);
|
||||||
if (sizes[i + 1] == 8) {
|
break;
|
||||||
memcpy(args + offset, &v, 8);
|
|
||||||
offset += 2;
|
case INT64_TYPE:
|
||||||
} else {
|
case DOUBLE_TYPE: {
|
||||||
args[offset++] = v;
|
uint64_t v = cast<uint64_t>(o, BytesPerWord);
|
||||||
}
|
memcpy(args + offset, &v, 8);
|
||||||
|
offset += (8 / BytesPerWord);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case POINTER_TYPE:
|
||||||
|
args[offset++] = reinterpret_cast<uintptr_t>(t->stack + position);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned returnCode = nativeMethodDataReturnCode(t, data);
|
unsigned returnCode = nativeMethodDataReturnCode(t, data);
|
||||||
unsigned returnSize
|
unsigned returnType = fieldType(t, returnCode);
|
||||||
= (returnCode == ObjectField ? 4 : primitiveSize(t, returnCode));
|
|
||||||
|
|
||||||
void* function = nativeMethodDataFunction(t, data);
|
void* function = nativeMethodDataFunction(t, data);
|
||||||
|
|
||||||
bool builtin = nativeMethodDataBuiltin(t, data);
|
bool builtin = nativeMethodDataBuiltin(t, data);
|
||||||
@ -2065,11 +2105,13 @@ invokeNative(Thread* t, object method)
|
|||||||
enter(t, Thread::IdleState);
|
enter(t, Thread::IdleState);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rv = t->vm->system->call(function,
|
uint64_t rv = t->vm->system->call
|
||||||
parameterCount,
|
(function,
|
||||||
args,
|
args,
|
||||||
sizes,
|
&nativeMethodDataParameterTypes(t, data, 0),
|
||||||
returnSize);
|
count + 1,
|
||||||
|
size,
|
||||||
|
returnType);
|
||||||
|
|
||||||
if (not builtin) {
|
if (not builtin) {
|
||||||
enter(t, Thread::ActiveState);
|
enter(t, Thread::ActiveState);
|
||||||
@ -3656,6 +3698,8 @@ run(Thread* t)
|
|||||||
if (nativeMethodDataReturnCode(t, methodCode(t, code)) != VoidField) {
|
if (nativeMethodDataReturnCode(t, methodCode(t, code)) != VoidField) {
|
||||||
push(t, r);
|
push(t, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code = methodCode(t, frameMethod(t, frame));
|
||||||
} else {
|
} else {
|
||||||
if (UNLIKELY(codeMaxStack(t, methodCode(t, code)) + base
|
if (UNLIKELY(codeMaxStack(t, methodCode(t, code)) + base
|
||||||
> Thread::StackSizeInWords))
|
> Thread::StackSizeInWords))
|
||||||
@ -3734,7 +3778,7 @@ run(Thread* t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (; p; p = traceNext(t, p)) {
|
for (; p; p = traceNext(t, p)) {
|
||||||
fprintf(stderr, " at %s:%s\n",
|
fprintf(stderr, " at %s.%s\n",
|
||||||
&byteArrayBody
|
&byteArrayBody
|
||||||
(t, className(t, methodClass(t, traceMethod(t, p))), 0),
|
(t, className(t, methodClass(t, traceMethod(t, p))), 0),
|
||||||
&byteArrayBody
|
&byteArrayBody
|
||||||
|
Loading…
Reference in New Issue
Block a user