mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
reformat changes since master
This commit is contained in:
parent
cbad6931af
commit
7642b94308
@ -58,21 +58,23 @@ Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock) {
|
|||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(t, reinterpret_cast<vm::object>(arguments[2]));
|
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||||
|
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||||
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
|
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT int64_t JNICALL
|
extern "C" JNIEXPORT int64_t JNICALL
|
||||||
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||||
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(t, reinterpret_cast<vm::object>(arguments[2]));
|
vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
|
||||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
t, reinterpret_cast<vm::object>(arguments[2]));
|
||||||
|
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||||
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
|
||||||
return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
|
return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
|
@ -160,4 +160,4 @@ class DelayedPromise: public ListenPromise {
|
|||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
|
||||||
#endif // AVIAN_CODEGEN_PROMISE_H
|
#endif // AVIAN_CODEGEN_PROMISE_H
|
||||||
|
@ -70,4 +70,4 @@ public:
|
|||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
|
||||||
#endif // AVIAN_CODEGEN_REGISTERS_H
|
#endif // AVIAN_CODEGEN_REGISTERS_H
|
||||||
|
@ -75,7 +75,7 @@ class Heap : public avian::util::Allocator {
|
|||||||
virtual void pad(void* p) = 0;
|
virtual void pad(void* p) = 0;
|
||||||
virtual void* follow(void* p) = 0;
|
virtual void* follow(void* p) = 0;
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
T* follow(T* p)
|
T* follow(T* p)
|
||||||
{
|
{
|
||||||
return static_cast<T*>(follow((void*)p));
|
return static_cast<T*>(follow((void*)p));
|
||||||
|
@ -44,8 +44,9 @@ inline void expect(T t, bool v) {
|
|||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define assertT(t, v)
|
#define assertT(t, v)
|
||||||
#else
|
#else
|
||||||
template<class T>
|
template <class T>
|
||||||
inline void assertT(T t, bool v) {
|
inline void assertT(T t, bool v)
|
||||||
|
{
|
||||||
expect(t, v);
|
expect(t, v);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,4 +46,4 @@ public:
|
|||||||
} // namespace avian
|
} // namespace avian
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
#endif // AVIAN_UTIL_ARG_PARSER_H
|
#endif // AVIAN_UTIL_ARG_PARSER_H
|
||||||
|
@ -37,8 +37,8 @@ inline uint32_t hash(Slice<const uint8_t> data)
|
|||||||
|
|
||||||
inline uint32_t hash(Slice<const int8_t> data)
|
inline uint32_t hash(Slice<const int8_t> data)
|
||||||
{
|
{
|
||||||
return hash(
|
return hash(Slice<const uint8_t>(
|
||||||
Slice<const uint8_t>(reinterpret_cast<const uint8_t*>(data.begin()), data.count));
|
reinterpret_cast<const uint8_t*>(data.begin()), data.count));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t hash(Slice<const uint16_t> data)
|
inline uint32_t hash(Slice<const uint16_t> data)
|
||||||
|
@ -21,7 +21,6 @@ namespace util {
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct NonConst;
|
struct NonConst;
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct NonConst<const T> {
|
struct NonConst<const T> {
|
||||||
typedef T Type;
|
typedef T Type;
|
||||||
@ -42,7 +41,8 @@ class Slice {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Slice(const Slice<typename NonConst<T>::Type>& copy) : items(copy.items), count(copy.count)
|
inline Slice(const Slice<typename NonConst<T>::Type>& copy)
|
||||||
|
: items(copy.items), count(copy.count)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,12 +30,9 @@ getTrace(Thread* t, unsigned skipCount)
|
|||||||
virtual bool visit(Processor::StackWalker* walker) {
|
virtual bool visit(Processor::StackWalker* walker) {
|
||||||
if (skipCount == 0) {
|
if (skipCount == 0) {
|
||||||
GcMethod* method = walker->method();
|
GcMethod* method = walker->method();
|
||||||
if (isAssignableFrom
|
if (isAssignableFrom(t, type(t, GcThrowable::Type), method->class_())
|
||||||
(t, type(t, GcThrowable::Type), method->class_())
|
|
||||||
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
and vm::strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||||
method->name()->body().begin())
|
method->name()->body().begin()) == 0) {
|
||||||
== 0)
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
trace = makeTrace(t, walker);
|
trace = makeTrace(t, walker);
|
||||||
@ -59,14 +56,11 @@ getTrace(Thread* t, unsigned skipCount)
|
|||||||
return v.trace;
|
return v.trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool compatibleArrayTypes(Thread* t UNUSED, GcClass* a, GcClass* b)
|
||||||
compatibleArrayTypes(Thread* t UNUSED, GcClass* a, GcClass* b)
|
|
||||||
{
|
{
|
||||||
return a->arrayElementSize()
|
return a->arrayElementSize() and b->arrayElementSize()
|
||||||
and b->arrayElementSize()
|
and (a == b or (not((a->vmFlags() & PrimitiveFlag)
|
||||||
and (a == b
|
or (b->vmFlags() & PrimitiveFlag))));
|
||||||
or (not ((a->vmFlags() & PrimitiveFlag)
|
|
||||||
or (b->vmFlags() & PrimitiveFlag))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -239,8 +233,11 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName,
|
|||||||
runOnLoadIfFound(t, lib);
|
runOnLoadIfFound(t, lib);
|
||||||
}
|
}
|
||||||
} else if (throw_) {
|
} else if (throw_) {
|
||||||
throwNew(t, GcUnsatisfiedLinkError::Type,
|
throwNew(t,
|
||||||
"library not found in %s: %s", path, name);
|
GcUnsatisfiedLinkError::Type,
|
||||||
|
"library not found in %s: %s",
|
||||||
|
path,
|
||||||
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lib;
|
return lib;
|
||||||
@ -268,17 +265,20 @@ clone(Thread* t, object o)
|
|||||||
} else {
|
} else {
|
||||||
GcByteArray* classNameSlash = objectClass(t, o)->name();
|
GcByteArray* classNameSlash = objectClass(t, o)->name();
|
||||||
THREAD_RUNTIME_ARRAY(t, char, classNameDot, classNameSlash->length());
|
THREAD_RUNTIME_ARRAY(t, char, classNameDot, classNameSlash->length());
|
||||||
replace('/', '.', RUNTIME_ARRAY_BODY(classNameDot),
|
replace('/',
|
||||||
|
'.',
|
||||||
|
RUNTIME_ARRAY_BODY(classNameDot),
|
||||||
reinterpret_cast<char*>(classNameSlash->body().begin()));
|
reinterpret_cast<char*>(classNameSlash->body().begin()));
|
||||||
throwNew(t, GcCloneNotSupportedException::Type, "%s",
|
throwNew(t,
|
||||||
|
GcCloneNotSupportedException::Type,
|
||||||
|
"%s",
|
||||||
RUNTIME_ARRAY_BODY(classNameDot));
|
RUNTIME_ARRAY_BODY(classNameDot));
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcStackTraceElement*
|
GcStackTraceElement* makeStackTraceElement(Thread* t, GcTraceElement* e)
|
||||||
makeStackTraceElement(Thread* t, GcTraceElement* e)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, e);
|
PROTECT(t, e);
|
||||||
|
|
||||||
@ -289,7 +289,9 @@ makeStackTraceElement(Thread* t, GcTraceElement* e)
|
|||||||
PROTECT(t, class_name);
|
PROTECT(t, class_name);
|
||||||
|
|
||||||
THREAD_RUNTIME_ARRAY(t, char, s, class_name->length());
|
THREAD_RUNTIME_ARRAY(t, char, s, class_name->length());
|
||||||
replace('/', '.', RUNTIME_ARRAY_BODY(s),
|
replace('/',
|
||||||
|
'.',
|
||||||
|
RUNTIME_ARRAY_BODY(s),
|
||||||
reinterpret_cast<char*>(class_name->body().begin()));
|
reinterpret_cast<char*>(class_name->body().begin()));
|
||||||
GcString* class_name_string = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
|
GcString* class_name_string = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
|
||||||
PROTECT(t, class_name_string);
|
PROTECT(t, class_name_string);
|
||||||
@ -297,22 +299,21 @@ makeStackTraceElement(Thread* t, GcTraceElement* e)
|
|||||||
GcByteArray* method_name = method->name();
|
GcByteArray* method_name = method->name();
|
||||||
PROTECT(t, method_name);
|
PROTECT(t, method_name);
|
||||||
|
|
||||||
GcString* method_name_string = t->m->classpath->makeString
|
GcString* method_name_string = t->m->classpath->makeString(
|
||||||
(t, method_name, 0, method_name->length() - 1);
|
t, method_name, 0, method_name->length() - 1);
|
||||||
PROTECT(t, method_name_string);
|
PROTECT(t, method_name_string);
|
||||||
|
|
||||||
unsigned line = t->m->processor->lineNumber
|
unsigned line = t->m->processor->lineNumber(t, method, e->ip());
|
||||||
(t, method, e->ip());
|
|
||||||
|
|
||||||
GcByteArray* file = method->class_()->sourceFile();
|
GcByteArray* file = method->class_()->sourceFile();
|
||||||
GcString* file_string = file ? t->m->classpath->makeString
|
GcString* file_string
|
||||||
(t, file, 0, file->length() - 1) : 0;
|
= file ? t->m->classpath->makeString(t, file, 0, file->length() - 1) : 0;
|
||||||
|
|
||||||
return makeStackTraceElement(t, class_name_string, method_name_string, file_string, line);
|
return makeStackTraceElement(
|
||||||
|
t, class_name_string, method_name_string, file_string, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcObject*
|
GcObject* translateInvokeResult(Thread* t, unsigned returnCode, object o)
|
||||||
translateInvokeResult(Thread* t, unsigned returnCode, object o)
|
|
||||||
{
|
{
|
||||||
switch (returnCode) {
|
switch (returnCode) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
@ -344,9 +345,10 @@ translateInvokeResult(Thread* t, unsigned returnCode, object o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GcClass*
|
GcClass* resolveClassBySpec(Thread* t,
|
||||||
resolveClassBySpec(Thread* t, GcClassLoader* loader, const char* spec,
|
GcClassLoader* loader,
|
||||||
unsigned specLength)
|
const char* spec,
|
||||||
|
unsigned specLength)
|
||||||
{
|
{
|
||||||
switch (*spec) {
|
switch (*spec) {
|
||||||
case 'L': {
|
case 'L': {
|
||||||
@ -368,15 +370,19 @@ resolveClassBySpec(Thread* t, GcClassLoader* loader, const char* spec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GcJclass*
|
GcJclass* resolveJType(Thread* t,
|
||||||
resolveJType(Thread* t, GcClassLoader* loader, const char* spec, unsigned specLength)
|
GcClassLoader* loader,
|
||||||
|
const char* spec,
|
||||||
|
unsigned specLength)
|
||||||
{
|
{
|
||||||
return getJClass(t, resolveClassBySpec(t, loader, spec, specLength));
|
return getJClass(t, resolveClassBySpec(t, loader, spec, specLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
GcPair*
|
GcPair* resolveParameterTypes(Thread* t,
|
||||||
resolveParameterTypes(Thread* t, GcClassLoader* loader, GcByteArray* spec,
|
GcClassLoader* loader,
|
||||||
unsigned* parameterCount, unsigned* returnTypeSpec)
|
GcByteArray* spec,
|
||||||
|
unsigned* parameterCount,
|
||||||
|
unsigned* returnTypeSpec)
|
||||||
{
|
{
|
||||||
PROTECT(t, loader);
|
PROTECT(t, loader);
|
||||||
PROTECT(t, spec);
|
PROTECT(t, spec);
|
||||||
@ -391,12 +397,15 @@ resolveParameterTypes(Thread* t, GcClassLoader* loader, GcByteArray* spec,
|
|||||||
case 'L': {
|
case 'L': {
|
||||||
unsigned start = offset;
|
unsigned start = offset;
|
||||||
++ offset;
|
++ offset;
|
||||||
while (spec->body()[offset] != ';') ++ offset;
|
while (spec->body()[offset] != ';')
|
||||||
|
++offset;
|
||||||
++ offset;
|
++ offset;
|
||||||
|
|
||||||
GcClass* type = resolveClassBySpec
|
GcClass* type
|
||||||
(t, loader, reinterpret_cast<char*>(&spec->body()[start]),
|
= resolveClassBySpec(t,
|
||||||
offset - start);
|
loader,
|
||||||
|
reinterpret_cast<char*>(&spec->body()[start]),
|
||||||
|
offset - start);
|
||||||
|
|
||||||
list = makePair(t, type, list);
|
list = makePair(t, type, list);
|
||||||
|
|
||||||
@ -405,11 +414,13 @@ resolveParameterTypes(Thread* t, GcClassLoader* loader, GcByteArray* spec,
|
|||||||
|
|
||||||
case '[': {
|
case '[': {
|
||||||
unsigned start = offset;
|
unsigned start = offset;
|
||||||
while (spec->body()[offset] == '[') ++ offset;
|
while (spec->body()[offset] == '[')
|
||||||
|
++offset;
|
||||||
switch (spec->body()[offset]) {
|
switch (spec->body()[offset]) {
|
||||||
case 'L':
|
case 'L':
|
||||||
++ offset;
|
++ offset;
|
||||||
while (spec->body()[offset] != ';') ++ offset;
|
while (spec->body()[offset] != ';')
|
||||||
|
++offset;
|
||||||
++ offset;
|
++ offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -418,17 +429,18 @@ resolveParameterTypes(Thread* t, GcClassLoader* loader, GcByteArray* spec,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcClass* type = resolveClassBySpec
|
GcClass* type
|
||||||
(t, loader, reinterpret_cast<char*>(&spec->body()[start]),
|
= resolveClassBySpec(t,
|
||||||
offset - start);
|
loader,
|
||||||
|
reinterpret_cast<char*>(&spec->body()[start]),
|
||||||
|
offset - start);
|
||||||
|
|
||||||
list = makePair(t, type, list);
|
list = makePair(t, type, list);
|
||||||
++ count;
|
++ count;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
list = makePair
|
list = makePair(t, primitiveClass(t, spec->body()[offset]), list);
|
||||||
(t, primitiveClass(t, spec->body()[offset]), list);
|
|
||||||
++ offset;
|
++ offset;
|
||||||
++ count;
|
++ count;
|
||||||
break;
|
break;
|
||||||
@ -440,17 +452,18 @@ resolveParameterTypes(Thread* t, GcClassLoader* loader, GcByteArray* spec,
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object resolveParameterJTypes(Thread* t,
|
||||||
resolveParameterJTypes(Thread* t, GcClassLoader* loader, GcByteArray* spec,
|
GcClassLoader* loader,
|
||||||
unsigned* parameterCount, unsigned* returnTypeSpec)
|
GcByteArray* spec,
|
||||||
|
unsigned* parameterCount,
|
||||||
|
unsigned* returnTypeSpec)
|
||||||
{
|
{
|
||||||
GcPair* list = resolveParameterTypes
|
GcPair* list
|
||||||
(t, loader, spec, parameterCount, returnTypeSpec);
|
= resolveParameterTypes(t, loader, spec, parameterCount, returnTypeSpec);
|
||||||
|
|
||||||
PROTECT(t, list);
|
PROTECT(t, list);
|
||||||
|
|
||||||
object array = makeObjectArray
|
object array = makeObjectArray(t, type(t, GcJclass::Type), *parameterCount);
|
||||||
(t, type(t, GcJclass::Type), *parameterCount);
|
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
for (int i = *parameterCount - 1; i >= 0; --i) {
|
for (int i = *parameterCount - 1; i >= 0; --i) {
|
||||||
@ -462,8 +475,9 @@ resolveParameterJTypes(Thread* t, GcClassLoader* loader, GcByteArray* spec,
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object resolveExceptionJTypes(Thread* t,
|
||||||
resolveExceptionJTypes(Thread* t, GcClassLoader* loader, GcMethodAddendum* addendum)
|
GcClassLoader* loader,
|
||||||
|
GcMethodAddendum* addendum)
|
||||||
{
|
{
|
||||||
if (addendum == 0 or addendum->exceptionTable() == 0) {
|
if (addendum == 0 or addendum->exceptionTable() == 0) {
|
||||||
return makeObjectArray(t, type(t, GcJclass::Type), 0);
|
return makeObjectArray(t, type(t, GcJclass::Type), 0);
|
||||||
@ -472,16 +486,15 @@ resolveExceptionJTypes(Thread* t, GcClassLoader* loader, GcMethodAddendum* adden
|
|||||||
PROTECT(t, loader);
|
PROTECT(t, loader);
|
||||||
PROTECT(t, addendum);
|
PROTECT(t, addendum);
|
||||||
|
|
||||||
GcShortArray* exceptionTable = cast<GcShortArray>(t, addendum->exceptionTable());
|
GcShortArray* exceptionTable
|
||||||
|
= cast<GcShortArray>(t, addendum->exceptionTable());
|
||||||
PROTECT(t, exceptionTable);
|
PROTECT(t, exceptionTable);
|
||||||
|
|
||||||
object array = makeObjectArray
|
object array
|
||||||
(t, type(t, GcJclass::Type),
|
= makeObjectArray(t, type(t, GcJclass::Type), exceptionTable->length());
|
||||||
exceptionTable->length());
|
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
for (unsigned i = 0; i < exceptionTable->length(); ++i)
|
for (unsigned i = 0; i < exceptionTable->length(); ++i) {
|
||||||
{
|
|
||||||
uint16_t index = exceptionTable->body()[i] - 1;
|
uint16_t index = exceptionTable->body()[i] - 1;
|
||||||
|
|
||||||
object o = singletonObject(t, addendum->pool()->as<GcSingleton>(t), index);
|
object o = singletonObject(t, addendum->pool()->as<GcSingleton>(t), index);
|
||||||
@ -489,7 +502,8 @@ resolveExceptionJTypes(Thread* t, GcClassLoader* loader, GcMethodAddendum* adden
|
|||||||
if (objectClass(t, o) == type(t, GcReference::Type)) {
|
if (objectClass(t, o) == type(t, GcReference::Type)) {
|
||||||
o = resolveClass(t, loader, cast<GcReference>(t, o)->name());
|
o = resolveClass(t, loader, cast<GcReference>(t, o)->name());
|
||||||
|
|
||||||
addendum->pool()->setBodyElement(t, index, reinterpret_cast<uintptr_t>(o));
|
addendum->pool()->setBodyElement(
|
||||||
|
t, index, reinterpret_cast<uintptr_t>(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
o = getJClass(t, cast<GcClass>(t, o));
|
o = getJClass(t, cast<GcClass>(t, o));
|
||||||
@ -500,8 +514,7 @@ resolveExceptionJTypes(Thread* t, GcClassLoader* loader, GcMethodAddendum* adden
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object invoke(Thread* t, GcMethod* method, object instance, object args)
|
||||||
invoke(Thread* t, GcMethod* method, object instance, object args)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
PROTECT(t, instance);
|
PROTECT(t, instance);
|
||||||
@ -512,30 +525,45 @@ invoke(Thread* t, GcMethod* method, object instance, object args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((args == 0 ? 0 : objectArrayLength(t, args))
|
if ((args == 0 ? 0 : objectArrayLength(t, args))
|
||||||
!= method->parameterCount())
|
!= method->parameterCount()) {
|
||||||
{
|
|
||||||
throwNew(t, GcIllegalArgumentException::Type);
|
throwNew(t, GcIllegalArgumentException::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method->parameterCount()) {
|
if (method->parameterCount()) {
|
||||||
unsigned specLength = method->spec()->length();
|
unsigned specLength = method->spec()->length();
|
||||||
THREAD_RUNTIME_ARRAY(t, char, spec, specLength);
|
THREAD_RUNTIME_ARRAY(t, char, spec, specLength);
|
||||||
memcpy(RUNTIME_ARRAY_BODY(spec),
|
memcpy(
|
||||||
method->spec()->body().begin(), specLength);
|
RUNTIME_ARRAY_BODY(spec), method->spec()->body().begin(), specLength);
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) {
|
for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) {
|
||||||
GcClass* type;
|
GcClass* type;
|
||||||
bool objectType = false;
|
bool objectType = false;
|
||||||
const char* p = it.next();
|
const char* p = it.next();
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'Z': type = vm::type(t, GcBoolean::Type); break;
|
case 'Z':
|
||||||
case 'B': type = vm::type(t, GcByte::Type); break;
|
type = vm::type(t, GcBoolean::Type);
|
||||||
case 'S': type = vm::type(t, GcShort::Type); break;
|
break;
|
||||||
case 'C': type = vm::type(t, GcChar::Type); break;
|
case 'B':
|
||||||
case 'I': type = vm::type(t, GcInt::Type); break;
|
type = vm::type(t, GcByte::Type);
|
||||||
case 'F': type = vm::type(t, GcFloat::Type); break;
|
break;
|
||||||
case 'J': type = vm::type(t, GcLong::Type); break;
|
case 'S':
|
||||||
case 'D': type = vm::type(t, GcDouble::Type); break;
|
type = vm::type(t, GcShort::Type);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
type = vm::type(t, GcChar::Type);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
type = vm::type(t, GcInt::Type);
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
type = vm::type(t, GcFloat::Type);
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
type = vm::type(t, GcLong::Type);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
type = vm::type(t, GcDouble::Type);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
case '[': {
|
case '[': {
|
||||||
@ -550,9 +578,8 @@ invoke(Thread* t, GcMethod* method, object instance, object args)
|
|||||||
THREAD_RUNTIME_ARRAY(t, char, name, nameLength);
|
THREAD_RUNTIME_ARRAY(t, char, name, nameLength);
|
||||||
memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1);
|
memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1);
|
||||||
RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0;
|
RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0;
|
||||||
type = resolveClass
|
type = resolveClass(
|
||||||
(t, method->class_()->loader(),
|
t, method->class_()->loader(), RUNTIME_ARRAY_BODY(name));
|
||||||
RUNTIME_ARRAY_BODY(name));
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -576,10 +603,11 @@ invoke(Thread* t, GcMethod* method, object instance, object args)
|
|||||||
|
|
||||||
THREAD_RESOURCE0(t, {
|
THREAD_RESOURCE0(t, {
|
||||||
if (t->exception) {
|
if (t->exception) {
|
||||||
t->exception = makeThrowable
|
t->exception = makeThrowable(
|
||||||
(t, GcInvocationTargetException::Type, 0, 0, t->exception);
|
t, GcInvocationTargetException::Type, 0, 0, t->exception);
|
||||||
|
|
||||||
t->exception->as<GcInvocationTargetException>(t)->setTarget(t, t->exception->cause());
|
t->exception->as<GcInvocationTargetException>(t)
|
||||||
|
->setTarget(t, t->exception->cause());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -595,9 +623,12 @@ invoke(Thread* t, GcMethod* method, object instance, object args)
|
|||||||
|
|
||||||
// only safe to call during bootstrap when there's only one thread
|
// only safe to call during bootstrap when there's only one thread
|
||||||
// running:
|
// running:
|
||||||
void
|
void intercept(Thread* t,
|
||||||
intercept(Thread* t, GcClass* c, const char* name, const char* spec,
|
GcClass* c,
|
||||||
void* function, bool updateRuntimeData)
|
const char* name,
|
||||||
|
const char* spec,
|
||||||
|
void* function,
|
||||||
|
bool updateRuntimeData)
|
||||||
{
|
{
|
||||||
GcMethod* m = findMethodOrNull(t, c, name, spec);
|
GcMethod* m = findMethodOrNull(t, c, name, spec);
|
||||||
if (m) {
|
if (m) {
|
||||||
@ -638,14 +669,11 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
|
|||||||
{
|
{
|
||||||
ACQUIRE(t, t->m->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
for (GcFinder* p = roots(t)->virtualFileFinders();
|
for (GcFinder* p = roots(t)->virtualFileFinders(); p; p = p->next()) {
|
||||||
p; p = p->next())
|
|
||||||
{
|
|
||||||
if (p->name()->length() == nameLength
|
if (p->name()->length() == nameLength
|
||||||
and strncmp(reinterpret_cast<const char*>
|
and strncmp(reinterpret_cast<const char*>(p->name()->body().begin()),
|
||||||
(p->name()->body().begin()),
|
name,
|
||||||
name, nameLength))
|
nameLength)) {
|
||||||
{
|
|
||||||
return static_cast<Finder*>(p->finder());
|
return static_cast<Finder*>(p->finder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -653,8 +681,8 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
|
|||||||
GcByteArray* n = makeByteArray(t, nameLength + 1);
|
GcByteArray* n = makeByteArray(t, nameLength + 1);
|
||||||
memcpy(n->body().begin(), name, nameLength);
|
memcpy(n->body().begin(), name, nameLength);
|
||||||
|
|
||||||
void* p = t->m->libraries->resolve
|
void* p = t->m->libraries->resolve(
|
||||||
(reinterpret_cast<const char*>(n->body().begin()));
|
reinterpret_cast<const char*>(n->body().begin()));
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
uint8_t* (*function)(unsigned*);
|
uint8_t* (*function)(unsigned*);
|
||||||
@ -664,8 +692,7 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
|
|||||||
uint8_t* data = function(&size);
|
uint8_t* data = function(&size);
|
||||||
if (data) {
|
if (data) {
|
||||||
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
|
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
|
||||||
GcFinder* finder = makeFinder
|
GcFinder* finder = makeFinder(t, f, n, roots(t)->virtualFileFinders());
|
||||||
(t, f, n, roots(t)->virtualFileFinders());
|
|
||||||
|
|
||||||
roots(t)->setVirtualFileFinders(t, finder);
|
roots(t)->setVirtualFileFinders(t, finder);
|
||||||
|
|
||||||
@ -676,8 +703,7 @@ getFinder(Thread* t, const char* name, unsigned nameLength)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
||||||
getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
|
||||||
{
|
{
|
||||||
GcClassAddendum* addendum = c->addendum();
|
GcClassAddendum* addendum = c->addendum();
|
||||||
if (addendum) {
|
if (addendum) {
|
||||||
@ -687,12 +713,11 @@ getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
|||||||
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
for (unsigned i = 0; i < table->length(); ++i) {
|
for (unsigned i = 0; i < table->length(); ++i) {
|
||||||
GcInnerClassReference* reference = cast<GcInnerClassReference>(t, table->body()[i]);
|
GcInnerClassReference* reference
|
||||||
|
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||||
GcByteArray* outer = reference->outer();
|
GcByteArray* outer = reference->outer();
|
||||||
if (outer and byteArrayEqual(t, outer, c->name())
|
if (outer and byteArrayEqual(t, outer, c->name())
|
||||||
and ((not publicOnly)
|
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
|
||||||
or (reference->flags() & ACC_PUBLIC)))
|
|
||||||
{
|
|
||||||
++ count;
|
++ count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -701,18 +726,13 @@ getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
|||||||
PROTECT(t, result);
|
PROTECT(t, result);
|
||||||
|
|
||||||
for (unsigned i = 0; i < table->length(); ++i) {
|
for (unsigned i = 0; i < table->length(); ++i) {
|
||||||
GcInnerClassReference* reference = cast<GcInnerClassReference>(t, table->body()[i]);
|
GcInnerClassReference* reference
|
||||||
|
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||||
GcByteArray* outer = reference->outer();
|
GcByteArray* outer = reference->outer();
|
||||||
if (outer and byteArrayEqual(t, outer, c->name())
|
if (outer and byteArrayEqual(t, outer, c->name())
|
||||||
and ((not publicOnly)
|
and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) {
|
||||||
or (reference->flags() & ACC_PUBLIC)))
|
object inner
|
||||||
{
|
= getJClass(t, resolveClass(t, c->loader(), reference->inner()));
|
||||||
object inner = getJClass(
|
|
||||||
t,
|
|
||||||
resolveClass(
|
|
||||||
t,
|
|
||||||
c->loader(),
|
|
||||||
reference->inner()));
|
|
||||||
|
|
||||||
-- count;
|
-- count;
|
||||||
reinterpret_cast<GcArray*>(result)->setBodyElement(t, count, inner);
|
reinterpret_cast<GcArray*>(result)->setBodyElement(t, count, inner);
|
||||||
@ -726,24 +746,19 @@ getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly)
|
|||||||
return makeObjectArray(t, type(t, GcJclass::Type), 0);
|
return makeObjectArray(t, type(t, GcJclass::Type), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcJclass*
|
GcJclass* getDeclaringClass(Thread* t, GcClass* c)
|
||||||
getDeclaringClass(Thread* t, GcClass* c)
|
|
||||||
{
|
{
|
||||||
GcClassAddendum* addendum = c->addendum();
|
GcClassAddendum* addendum = c->addendum();
|
||||||
if (addendum) {
|
if (addendum) {
|
||||||
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
|
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
|
||||||
if (table) {
|
if (table) {
|
||||||
for (unsigned i = 0; i < table->length(); ++i) {
|
for (unsigned i = 0; i < table->length(); ++i) {
|
||||||
GcInnerClassReference* reference = cast<GcInnerClassReference>(t, table->body()[i]);
|
GcInnerClassReference* reference
|
||||||
if (reference->outer() and strcmp
|
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||||
(reference->inner()->body().begin(),
|
if (reference->outer()
|
||||||
c->name()->body().begin()) == 0)
|
and strcmp(reference->inner()->body().begin(),
|
||||||
{
|
c->name()->body().begin()) == 0) {
|
||||||
return getJClass(
|
return getJClass(t, resolveClass(t, c->loader(), reference->outer()));
|
||||||
t,
|
|
||||||
resolveClass(t,
|
|
||||||
c->loader(),
|
|
||||||
reference->outer()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -752,19 +767,17 @@ getDeclaringClass(Thread* t, GcClass* c)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned classModifiers(Thread* t, GcClass* c)
|
||||||
classModifiers(Thread* t, GcClass* c)
|
|
||||||
{
|
{
|
||||||
GcClassAddendum* addendum = c->addendum();
|
GcClassAddendum* addendum = c->addendum();
|
||||||
if (addendum) {
|
if (addendum) {
|
||||||
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
|
GcArray* table = cast<GcArray>(t, addendum->innerClassTable());
|
||||||
if (table) {
|
if (table) {
|
||||||
for (unsigned i = 0; i < table->length(); ++i) {
|
for (unsigned i = 0; i < table->length(); ++i) {
|
||||||
GcInnerClassReference* reference = cast<GcInnerClassReference>(t, table->body()[i]);
|
GcInnerClassReference* reference
|
||||||
if (0 == strcmp
|
= cast<GcInnerClassReference>(t, table->body()[i]);
|
||||||
(c->name()->body().begin(),
|
if (0 == strcmp(c->name()->body().begin(),
|
||||||
reference->inner()->body().begin()))
|
reference->inner()->body().begin())) {
|
||||||
{
|
|
||||||
return reference->flags();
|
return reference->flags();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ namespace vm {
|
|||||||
class Machine;
|
class Machine;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
class GcObject;;
|
class GcObject;
|
||||||
|
;
|
||||||
|
|
||||||
typedef GcObject* object;
|
typedef GcObject* object;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -18,16 +18,14 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
inline int16_t
|
inline int16_t codeReadInt16(Thread* t UNUSED, GcCode* code, unsigned& ip)
|
||||||
codeReadInt16(Thread* t UNUSED, GcCode* code, unsigned& ip)
|
|
||||||
{
|
{
|
||||||
uint8_t v1 = code->body()[ip++];
|
uint8_t v1 = code->body()[ip++];
|
||||||
uint8_t v2 = code->body()[ip++];
|
uint8_t v2 = code->body()[ip++];
|
||||||
return ((v1 << 8) | v2);
|
return ((v1 << 8) | v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32_t
|
inline int32_t codeReadInt32(Thread* t UNUSED, GcCode* code, unsigned& ip)
|
||||||
codeReadInt32(Thread* t UNUSED, GcCode* code, unsigned& ip)
|
|
||||||
{
|
{
|
||||||
uint8_t v1 = code->body()[ip++];
|
uint8_t v1 = code->body()[ip++];
|
||||||
uint8_t v2 = code->body()[ip++];
|
uint8_t v2 = code->body()[ip++];
|
||||||
@ -36,8 +34,7 @@ codeReadInt32(Thread* t UNUSED, GcCode* code, unsigned& ip)
|
|||||||
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
|
return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool isSuperclass(Thread* t UNUSED, GcClass* class_, GcClass* base)
|
||||||
isSuperclass(Thread* t UNUSED, GcClass* class_, GcClass* base)
|
|
||||||
{
|
{
|
||||||
for (GcClass* oc = base->super(); oc; oc = oc->super()) {
|
for (GcClass* oc = base->super(); oc; oc = oc->super()) {
|
||||||
if (oc == class_) {
|
if (oc == class_) {
|
||||||
@ -47,20 +44,17 @@ isSuperclass(Thread* t UNUSED, GcClass* class_, GcClass* base)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool isSpecialMethod(Thread* t, GcMethod* method, GcClass* class_)
|
||||||
isSpecialMethod(Thread* t, GcMethod* method, GcClass* class_)
|
|
||||||
{
|
{
|
||||||
return (class_->flags() & ACC_SUPER)
|
return (class_->flags() & ACC_SUPER)
|
||||||
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||||
method->name()->body().begin()) != 0
|
method->name()->body().begin()) != 0
|
||||||
and isSuperclass(t, method->class_(), class_);
|
and isSuperclass(t, method->class_(), class_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void resolveNative(Thread* t, GcMethod* method);
|
||||||
resolveNative(Thread* t, GcMethod* method);
|
|
||||||
|
|
||||||
int
|
int findLineNumber(Thread* t, GcMethod* method, unsigned ip);
|
||||||
findLineNumber(Thread* t, GcMethod* method, unsigned ip);
|
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
|
@ -74,46 +74,43 @@ class Processor {
|
|||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual Thread*
|
virtual Thread* makeThread(Machine* m, GcThread* javaThread, Thread* parent)
|
||||||
makeThread(Machine* m, GcThread* javaThread, Thread* parent) = 0;
|
= 0;
|
||||||
|
|
||||||
virtual GcMethod*
|
virtual GcMethod* makeMethod(Thread* t,
|
||||||
makeMethod(Thread* t,
|
uint8_t vmFlags,
|
||||||
uint8_t vmFlags,
|
uint8_t returnCode,
|
||||||
uint8_t returnCode,
|
uint8_t parameterCount,
|
||||||
uint8_t parameterCount,
|
uint8_t parameterFootprint,
|
||||||
uint8_t parameterFootprint,
|
uint16_t flags,
|
||||||
uint16_t flags,
|
uint16_t offset,
|
||||||
uint16_t offset,
|
GcByteArray* name,
|
||||||
GcByteArray* name,
|
GcByteArray* spec,
|
||||||
GcByteArray* spec,
|
GcMethodAddendum* addendum,
|
||||||
GcMethodAddendum* addendum,
|
GcClass* class_,
|
||||||
GcClass* class_,
|
GcCode* code) = 0;
|
||||||
GcCode* code) = 0;
|
|
||||||
|
|
||||||
virtual GcClass*
|
virtual GcClass* makeClass(Thread* t,
|
||||||
makeClass(Thread* t,
|
uint16_t flags,
|
||||||
uint16_t flags,
|
uint16_t vmFlags,
|
||||||
uint16_t vmFlags,
|
uint16_t fixedSize,
|
||||||
uint16_t fixedSize,
|
uint8_t arrayElementSize,
|
||||||
uint8_t arrayElementSize,
|
uint8_t arrayDimensions,
|
||||||
uint8_t arrayDimensions,
|
GcClass* arrayElementClass,
|
||||||
GcClass* arrayElementClass,
|
GcIntArray* objectMask,
|
||||||
GcIntArray* objectMask,
|
GcByteArray* name,
|
||||||
GcByteArray* name,
|
GcByteArray* sourceFile,
|
||||||
GcByteArray* sourceFile,
|
GcClass* super,
|
||||||
GcClass* super,
|
object interfaceTable,
|
||||||
object interfaceTable,
|
object virtualTable,
|
||||||
object virtualTable,
|
object fieldTable,
|
||||||
object fieldTable,
|
object methodTable,
|
||||||
object methodTable,
|
GcClassAddendum* addendum,
|
||||||
GcClassAddendum* addendum,
|
GcSingleton* staticTable,
|
||||||
GcSingleton* staticTable,
|
GcClassLoader* loader,
|
||||||
GcClassLoader* loader,
|
unsigned vtableLength) = 0;
|
||||||
unsigned vtableLength) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void initVtable(Thread* t, GcClass* c) = 0;
|
||||||
initVtable(Thread* t, GcClass* c) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||||
@ -121,8 +118,7 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
walkStack(Thread* t, StackVisitor* v) = 0;
|
walkStack(Thread* t, StackVisitor* v) = 0;
|
||||||
|
|
||||||
virtual int
|
virtual int lineNumber(Thread* t, GcMethod* method, int ip) = 0;
|
||||||
lineNumber(Thread* t, GcMethod* method, int ip) = 0;
|
|
||||||
|
|
||||||
virtual object*
|
virtual object*
|
||||||
makeLocalReference(Thread* t, object o) = 0;
|
makeLocalReference(Thread* t, object o) = 0;
|
||||||
@ -136,21 +132,29 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
popLocalFrame(Thread* t) = 0;
|
popLocalFrame(Thread* t) = 0;
|
||||||
|
|
||||||
virtual object
|
virtual object invokeArray(Thread* t,
|
||||||
invokeArray(Thread* t, GcMethod* method, object this_, object arguments) = 0;
|
GcMethod* method,
|
||||||
|
object this_,
|
||||||
|
object arguments) = 0;
|
||||||
|
|
||||||
virtual object
|
virtual object invokeArray(Thread* t,
|
||||||
invokeArray(Thread* t, GcMethod* method, object this_, const jvalue* arguments)
|
GcMethod* method,
|
||||||
= 0;
|
object this_,
|
||||||
|
const jvalue* arguments) = 0;
|
||||||
|
|
||||||
virtual object
|
virtual object invokeList(Thread* t,
|
||||||
invokeList(Thread* t, GcMethod* method, object this_, bool indirectObjects,
|
GcMethod* method,
|
||||||
va_list arguments) = 0;
|
object this_,
|
||||||
|
bool indirectObjects,
|
||||||
|
va_list arguments) = 0;
|
||||||
|
|
||||||
virtual object
|
virtual object invokeList(Thread* t,
|
||||||
invokeList(Thread* t, GcClassLoader* loader, const char* className,
|
GcClassLoader* loader,
|
||||||
const char* methodName, const char* methodSpec,
|
const char* className,
|
||||||
object this_, va_list arguments) = 0;
|
const char* methodName,
|
||||||
|
const char* methodSpec,
|
||||||
|
object this_,
|
||||||
|
va_list arguments) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
dispose(Thread* t) = 0;
|
dispose(Thread* t) = 0;
|
||||||
@ -167,10 +171,13 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
addCompilationHandler(CompilationHandler* handler) = 0;
|
addCompilationHandler(CompilationHandler* handler) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void compileMethod(Thread* t,
|
||||||
compileMethod(Thread* t, Zone* zone, GcTriple** constants, GcTriple** calls,
|
Zone* zone,
|
||||||
avian::codegen::DelayedPromise** addresses, GcMethod* method,
|
GcTriple** constants,
|
||||||
OffsetResolver* resolver) = 0;
|
GcTriple** calls,
|
||||||
|
avian::codegen::DelayedPromise** addresses,
|
||||||
|
GcMethod* method,
|
||||||
|
OffsetResolver* resolver) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitRoots(Thread* t, HeapWalker* w) = 0;
|
visitRoots(Thread* t, HeapWalker* w) = 0;
|
||||||
@ -190,19 +197,19 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
dynamicWind(Thread* t, object before, object thunk, object after) = 0;
|
dynamicWind(Thread* t, object before, object thunk, object after) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void feedResultToContinuation(Thread* t,
|
||||||
feedResultToContinuation(Thread* t, GcContinuation* continuation, object result) = 0;
|
GcContinuation* continuation,
|
||||||
|
object result) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void feedExceptionToContinuation(Thread* t,
|
||||||
feedExceptionToContinuation(Thread* t, GcContinuation* continuation,
|
GcContinuation* continuation,
|
||||||
GcThrowable* exception) = 0;
|
GcThrowable* exception) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
|
walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start)
|
||||||
= 0;
|
= 0;
|
||||||
|
|
||||||
object
|
object invoke(Thread* t, GcMethod* method, object this_, ...)
|
||||||
invoke(Thread* t, GcMethod* method, object this_, ...)
|
|
||||||
{
|
{
|
||||||
va_list a;
|
va_list a;
|
||||||
va_start(a, this_);
|
va_start(a, this_);
|
||||||
@ -214,9 +221,13 @@ class Processor {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object invoke(Thread* t,
|
||||||
invoke(Thread* t, GcClassLoader* loader, const char* className,
|
GcClassLoader* loader,
|
||||||
const char* methodName, const char* methodSpec, object this_, ...)
|
const char* className,
|
||||||
|
const char* methodName,
|
||||||
|
const char* methodSpec,
|
||||||
|
object this_,
|
||||||
|
...)
|
||||||
{
|
{
|
||||||
va_list a;
|
va_list a;
|
||||||
va_start(a, this_);
|
va_start(a, this_);
|
||||||
|
106
src/avian/util.h
106
src/avian/util.h
@ -16,32 +16,39 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
GcTriple*
|
GcTriple* hashMapFindNode(Thread* t,
|
||||||
hashMapFindNode(Thread* t, GcHashMap* map, object key,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object),
|
object key,
|
||||||
bool (*equal)(Thread*, object, object));
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object));
|
||||||
|
|
||||||
inline object
|
inline object hashMapFind(Thread* t,
|
||||||
hashMapFind(Thread* t, GcHashMap* map, object key,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object),
|
object key,
|
||||||
bool (*equal)(Thread*, object, object))
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object))
|
||||||
{
|
{
|
||||||
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
||||||
return (n ? n->second() : 0);
|
return (n ? n->second() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void hashMapResize(Thread* t,
|
||||||
hashMapResize(Thread* t, GcHashMap* map, uint32_t (*hash)(Thread*, object),
|
GcHashMap* map,
|
||||||
unsigned size);
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
unsigned size);
|
||||||
|
|
||||||
void
|
void hashMapInsert(Thread* t,
|
||||||
hashMapInsert(Thread* t, GcHashMap* map, object key, object value,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object));
|
object key,
|
||||||
|
object value,
|
||||||
|
uint32_t (*hash)(Thread*, object));
|
||||||
|
|
||||||
inline bool
|
inline bool hashMapInsertOrReplace(Thread* t,
|
||||||
hashMapInsertOrReplace(Thread* t, GcHashMap* map, object key, object value,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object),
|
object key,
|
||||||
bool (*equal)(Thread*, object, object))
|
object value,
|
||||||
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object))
|
||||||
{
|
{
|
||||||
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
@ -53,10 +60,12 @@ hashMapInsertOrReplace(Thread* t, GcHashMap* map, object key, object value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool hashMapInsertMaybe(Thread* t,
|
||||||
hashMapInsertMaybe(Thread* t, GcHashMap* map, object key, object value,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object),
|
object key,
|
||||||
bool (*equal)(Thread*, object, object))
|
object value,
|
||||||
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object))
|
||||||
{
|
{
|
||||||
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
GcTriple* n = hashMapFindNode(t, map, key, hash, equal);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
@ -67,43 +76,49 @@ hashMapInsertMaybe(Thread* t, GcHashMap* map, object key, object value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object hashMapRemove(Thread* t,
|
||||||
hashMapRemove(Thread* t, GcHashMap* map, object key,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object),
|
object key,
|
||||||
bool (*equal)(Thread*, object, object));
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object));
|
||||||
|
|
||||||
object
|
object hashMapIterator(Thread* t, GcHashMap* map);
|
||||||
hashMapIterator(Thread* t, GcHashMap* map);
|
|
||||||
|
|
||||||
object
|
object
|
||||||
hashMapIteratorNext(Thread* t, object it);
|
hashMapIteratorNext(Thread* t, object it);
|
||||||
|
|
||||||
void
|
void listAppend(Thread* t, GcList* list, object value);
|
||||||
listAppend(Thread* t, GcList* list, object value);
|
|
||||||
|
|
||||||
GcVector*
|
GcVector* vectorAppend(Thread* t, GcVector* vector, object value);
|
||||||
vectorAppend(Thread* t, GcVector* vector, object value);
|
|
||||||
|
|
||||||
object
|
object
|
||||||
growArray(Thread* t, object array);
|
growArray(Thread* t, object array);
|
||||||
|
|
||||||
object
|
object treeQuery(Thread* t,
|
||||||
treeQuery(Thread* t, GcTreeNode* tree, intptr_t key, GcTreeNode* sentinal,
|
GcTreeNode* tree,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
intptr_t key,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||||
|
|
||||||
GcTreeNode*
|
GcTreeNode* treeInsert(Thread* t,
|
||||||
treeInsert(Thread* t, Zone* zone, GcTreeNode* tree, intptr_t key, object value,
|
Zone* zone,
|
||||||
GcTreeNode* sentinal,
|
GcTreeNode* tree,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
intptr_t key,
|
||||||
|
object value,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||||
|
|
||||||
void
|
void treeUpdate(Thread* t,
|
||||||
treeUpdate(Thread* t, GcTreeNode* tree, intptr_t key, object value, GcTreeNode* sentinal,
|
GcTreeNode* tree,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
intptr_t key,
|
||||||
|
object value,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||||
|
|
||||||
class HashMapIterator: public Thread::Protector {
|
class HashMapIterator: public Thread::Protector {
|
||||||
public:
|
public:
|
||||||
HashMapIterator(Thread* t, GcHashMap* map):
|
HashMapIterator(Thread* t, GcHashMap* map)
|
||||||
Protector(t), map(map), node(0), index(0)
|
: Protector(t), map(map), node(0), index(0)
|
||||||
{
|
{
|
||||||
find();
|
find();
|
||||||
}
|
}
|
||||||
@ -126,7 +141,8 @@ class HashMapIterator: public Thread::Protector {
|
|||||||
return node != 0;
|
return node != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTriple* next() {
|
GcTriple* next()
|
||||||
|
{
|
||||||
if (node) {
|
if (node) {
|
||||||
GcTriple* n = node;
|
GcTriple* n = node;
|
||||||
if (node->third()) {
|
if (node->third()) {
|
||||||
|
170
src/builtin.cpp
170
src/builtin.cpp
@ -19,9 +19,11 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
int64_t
|
int64_t search(Thread* t,
|
||||||
search(Thread* t, GcClassLoader* loader, GcString* name,
|
GcClassLoader* loader,
|
||||||
GcClass* (*op)(Thread*, GcClassLoader*, GcByteArray*), bool replaceDots)
|
GcString* name,
|
||||||
|
GcClass* (*op)(Thread*, GcClassLoader*, GcByteArray*),
|
||||||
|
bool replaceDots)
|
||||||
{
|
{
|
||||||
if (LIKELY(name)) {
|
if (LIKELY(name)) {
|
||||||
PROTECT(t, loader);
|
PROTECT(t, loader);
|
||||||
@ -41,15 +43,15 @@ search(Thread* t, GcClassLoader* loader, GcString* name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GcClass*
|
GcClass* resolveSystemClassThrow(Thread* t,
|
||||||
resolveSystemClassThrow(Thread* t, GcClassLoader* loader, GcByteArray* spec)
|
GcClassLoader* loader,
|
||||||
|
GcByteArray* spec)
|
||||||
{
|
{
|
||||||
return resolveSystemClass
|
return resolveSystemClass(
|
||||||
(t, loader, spec, true, GcClassNotFoundException::Type);
|
t, loader, spec, true, GcClassNotFoundException::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcField*
|
GcField* fieldForOffsetInClass(Thread* t, GcClass* c, unsigned offset)
|
||||||
fieldForOffsetInClass(Thread* t, GcClass* c, unsigned offset)
|
|
||||||
{
|
{
|
||||||
GcClass* super = c->super();
|
GcClass* super = c->super();
|
||||||
if (super) {
|
if (super) {
|
||||||
@ -63,9 +65,7 @@ fieldForOffsetInClass(Thread* t, GcClass* c, unsigned offset)
|
|||||||
if (table) {
|
if (table) {
|
||||||
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
||||||
GcField* field = cast<GcField>(t, objectArrayBody(t, table, i));
|
GcField* field = cast<GcField>(t, objectArrayBody(t, table, i));
|
||||||
if ((field->flags() & ACC_STATIC) == 0
|
if ((field->flags() & ACC_STATIC) == 0 and field->offset() == offset) {
|
||||||
and field->offset() == offset)
|
|
||||||
{
|
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,8 +74,7 @@ fieldForOffsetInClass(Thread* t, GcClass* c, unsigned offset)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcField*
|
GcField* fieldForOffset(Thread* t, GcSingleton* o, unsigned offset)
|
||||||
fieldForOffset(Thread* t, GcSingleton* o, unsigned offset)
|
|
||||||
{
|
{
|
||||||
GcClass* c = objectClass(t, o);
|
GcClass* c = objectClass(t, o);
|
||||||
if (c->vmFlags() & SingletonFlag) {
|
if (c->vmFlags() & SingletonFlag) {
|
||||||
@ -84,9 +83,7 @@ fieldForOffset(Thread* t, GcSingleton* o, unsigned offset)
|
|||||||
if (table) {
|
if (table) {
|
||||||
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
for (unsigned i = 0; i < objectArrayLength(t, table); ++i) {
|
||||||
GcField* field = cast<GcField>(t, objectArrayBody(t, table, i));
|
GcField* field = cast<GcField>(t, objectArrayBody(t, table, i));
|
||||||
if ((field->flags() & ACC_STATIC)
|
if ((field->flags() & ACC_STATIC) and field->offset() == offset) {
|
||||||
and field->offset() == offset)
|
|
||||||
{
|
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,18 +128,21 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_Classes_resolveVMClass
|
Avian_avian_Classes_resolveVMClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClassLoader* loader = cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
GcClassLoader* loader
|
||||||
GcByteArray* spec = cast<GcByteArray>(t, reinterpret_cast<object>(arguments[1]));
|
= cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
|
GcByteArray* spec
|
||||||
|
= cast<GcByteArray>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(resolveClass(t, loader, spec, true, GcClassNotFoundException::Type));
|
resolveClass(t, loader, spec, true, GcClassNotFoundException::Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_Classes_defineVMClass
|
Avian_avian_Classes_defineVMClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClassLoader* loader = cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
GcClassLoader* loader
|
||||||
|
= cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
GcByteArray* b = cast<GcByteArray>(t, reinterpret_cast<object>(arguments[1]));
|
GcByteArray* b = cast<GcByteArray>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
int offset = arguments[2];
|
int offset = arguments[2];
|
||||||
int length = arguments[3];
|
int length = arguments[3];
|
||||||
@ -162,7 +162,8 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_SystemClassLoader_findLoadedVMClass
|
Avian_avian_SystemClassLoader_findLoadedVMClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClassLoader* loader = cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
GcClassLoader* loader
|
||||||
|
= cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[1]));
|
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
|
|
||||||
return search(t, loader, name, findLoadedClass, true);
|
return search(t, loader, name, findLoadedClass, true);
|
||||||
@ -172,15 +173,16 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_SystemClassLoader_vmClass
|
Avian_avian_SystemClassLoader_vmClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]))->vmClass());
|
cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]))->vmClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_SystemClassLoader_findVMClass
|
Avian_avian_SystemClassLoader_findVMClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClassLoader* loader = cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
GcClassLoader* loader
|
||||||
|
= cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[1]));
|
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
|
|
||||||
return search(t, loader, name, resolveSystemClassThrow, true);
|
return search(t, loader, name, resolveSystemClassThrow, true);
|
||||||
@ -190,15 +192,17 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_SystemClassLoader_resourceURLPrefix
|
Avian_avian_SystemClassLoader_resourceURLPrefix
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClassLoader* loader = cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
GcClassLoader* loader
|
||||||
|
= cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[1]));
|
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
|
|
||||||
if (LIKELY(name)) {
|
if (LIKELY(name)) {
|
||||||
THREAD_RUNTIME_ARRAY(t, char, n, name->length(t) + 1);
|
THREAD_RUNTIME_ARRAY(t, char, n, name->length(t) + 1);
|
||||||
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
const char* name = static_cast<Finder*>
|
const char* name
|
||||||
(loader->as<GcSystemClassLoader>(t)->finder())->urlPrefix(RUNTIME_ARRAY_BODY(n));
|
= static_cast<Finder*>(loader->as<GcSystemClassLoader>(t)->finder())
|
||||||
|
->urlPrefix(RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
return name ? reinterpret_cast<uintptr_t>(makeString(t, "%s", name)) : 0;
|
return name ? reinterpret_cast<uintptr_t>(makeString(t, "%s", name)) : 0;
|
||||||
} else {
|
} else {
|
||||||
@ -210,18 +214,21 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_SystemClassLoader_00024ResourceEnumeration_nextResourceURLPrefix
|
Avian_avian_SystemClassLoader_00024ResourceEnumeration_nextResourceURLPrefix
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClassLoader* loader = cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[1]));
|
GcClassLoader* loader
|
||||||
|
= cast<GcClassLoader>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[2]));
|
GcString* name = cast<GcString>(t, reinterpret_cast<object>(arguments[2]));
|
||||||
GcLongArray* finderElementPtrPtr = cast<GcLongArray>(t, reinterpret_cast<object>(arguments[3]));
|
GcLongArray* finderElementPtrPtr
|
||||||
|
= cast<GcLongArray>(t, reinterpret_cast<object>(arguments[3]));
|
||||||
|
|
||||||
if (LIKELY(name) && LIKELY(finderElementPtrPtr)) {
|
if (LIKELY(name) && LIKELY(finderElementPtrPtr)) {
|
||||||
THREAD_RUNTIME_ARRAY(t, char, n, name->length(t) + 1);
|
THREAD_RUNTIME_ARRAY(t, char, n, name->length(t) + 1);
|
||||||
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
void *&finderElementPtr = reinterpret_cast<void *&>(finderElementPtrPtr->body()[0]);
|
void*& finderElementPtr
|
||||||
const char* name = static_cast<Finder*>
|
= reinterpret_cast<void*&>(finderElementPtrPtr->body()[0]);
|
||||||
(loader->as<GcSystemClassLoader>(t)->finder())->nextUrlPrefix(RUNTIME_ARRAY_BODY(n),
|
const char* name
|
||||||
finderElementPtr);
|
= static_cast<Finder*>(loader->as<GcSystemClassLoader>(t)->finder())
|
||||||
|
->nextUrlPrefix(RUNTIME_ARRAY_BODY(n), finderElementPtr);
|
||||||
|
|
||||||
return name ? reinterpret_cast<uintptr_t>(makeString(t, "%s", name)) : 0;
|
return name ? reinterpret_cast<uintptr_t>(makeString(t, "%s", name)) : 0;
|
||||||
} else {
|
} else {
|
||||||
@ -233,8 +240,8 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_SystemClassLoader_getClass
|
Avian_avian_SystemClassLoader_getClass
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(getJClass(t, cast<GcClass>(t, reinterpret_cast<object>(arguments[0]))));
|
getJClass(t, cast<GcClass>(t, reinterpret_cast<object>(arguments[0]))));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
@ -254,14 +261,14 @@ Avian_avian_SystemClassLoader_getPackageSource
|
|||||||
|
|
||||||
GcByteArray* key = makeByteArray(t, RUNTIME_ARRAY_BODY(chars));
|
GcByteArray* key = makeByteArray(t, RUNTIME_ARRAY_BODY(chars));
|
||||||
|
|
||||||
GcByteArray* array = cast<GcByteArray>(t, hashMapFind
|
GcByteArray* array = cast<GcByteArray>(
|
||||||
(t, roots(t)->packageMap(), key, byteArrayHash, byteArrayEqual));
|
t,
|
||||||
|
hashMapFind(
|
||||||
|
t, roots(t)->packageMap(), key, byteArrayHash, byteArrayEqual));
|
||||||
|
|
||||||
if (array) {
|
if (array) {
|
||||||
return reinterpret_cast<uintptr_t>(makeLocalReference(
|
return reinterpret_cast<uintptr_t>(makeLocalReference(
|
||||||
t,
|
t, t->m->classpath->makeString(t, array, 0, array->length())));
|
||||||
t->m->classpath->makeString(
|
|
||||||
t, array, 0, array->length())));
|
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -285,7 +292,9 @@ Avian_avian_Machine_dumpHeap
|
|||||||
}
|
}
|
||||||
fclose(out);
|
fclose(out);
|
||||||
} else {
|
} else {
|
||||||
throwNew(t, GcRuntimeException::Type, "file not found: %s",
|
throwNew(t,
|
||||||
|
GcRuntimeException::Type,
|
||||||
|
"file not found: %s",
|
||||||
RUNTIME_ARRAY_BODY(n));
|
RUNTIME_ARRAY_BODY(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,7 +401,8 @@ Avian_avian_avianvmresource_Handler_00024ResourceInputStream_read__JI_3BII
|
|||||||
{
|
{
|
||||||
int64_t peer; memcpy(&peer, arguments, 8);
|
int64_t peer; memcpy(&peer, arguments, 8);
|
||||||
int32_t position = arguments[2];
|
int32_t position = arguments[2];
|
||||||
GcByteArray* buffer = cast<GcByteArray>(t, reinterpret_cast<object>(arguments[3]));
|
GcByteArray* buffer
|
||||||
|
= cast<GcByteArray>(t, reinterpret_cast<object>(arguments[3]));
|
||||||
int32_t offset = arguments[4];
|
int32_t offset = arguments[4];
|
||||||
int32_t length = arguments[5];
|
int32_t length = arguments[5];
|
||||||
|
|
||||||
@ -405,8 +415,7 @@ Avian_avian_avianvmresource_Handler_00024ResourceInputStream_read__JI_3BII
|
|||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
memcpy(&buffer->body()[offset], region->start() + position,
|
memcpy(&buffer->body()[offset], region->start() + position, length);
|
||||||
length);
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -445,9 +454,10 @@ extern "C" AVIAN_EXPORT void JNICALL
|
|||||||
Avian_avian_Continuations_00024Continuation_handleResult
|
Avian_avian_Continuations_00024Continuation_handleResult
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
t->m->processor->feedResultToContinuation
|
t->m->processor->feedResultToContinuation(
|
||||||
(t, cast<GcContinuation>(t, reinterpret_cast<object>(arguments[0])),
|
t,
|
||||||
reinterpret_cast<object>(arguments[1]));
|
cast<GcContinuation>(t, reinterpret_cast<object>(arguments[0])),
|
||||||
|
reinterpret_cast<object>(arguments[1]));
|
||||||
|
|
||||||
abort(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
@ -456,9 +466,10 @@ extern "C" AVIAN_EXPORT void JNICALL
|
|||||||
Avian_avian_Continuations_00024Continuation_handleException
|
Avian_avian_Continuations_00024Continuation_handleException
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
t->m->processor->feedExceptionToContinuation
|
t->m->processor->feedExceptionToContinuation(
|
||||||
(t, cast<GcContinuation>(t, reinterpret_cast<object>(arguments[0])),
|
t,
|
||||||
cast<GcThrowable>(t, reinterpret_cast<object>(arguments[1])));
|
cast<GcContinuation>(t, reinterpret_cast<object>(arguments[0])),
|
||||||
|
cast<GcThrowable>(t, reinterpret_cast<object>(arguments[1])));
|
||||||
|
|
||||||
abort(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
@ -467,16 +478,20 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_Singleton_getObject
|
Avian_avian_Singleton_getObject
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(singletonObject(
|
||||||
(singletonObject(t, cast<GcSingleton>(t, reinterpret_cast<object>(arguments[0])), arguments[1]));
|
t,
|
||||||
|
cast<GcSingleton>(t, reinterpret_cast<object>(arguments[0])),
|
||||||
|
arguments[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_avian_Singleton_getInt
|
Avian_avian_Singleton_getInt
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return singletonValue
|
return singletonValue(
|
||||||
(t, cast<GcSingleton>(t, reinterpret_cast<object>(arguments[0])), arguments[1]);
|
t,
|
||||||
|
cast<GcSingleton>(t, reinterpret_cast<object>(arguments[0])),
|
||||||
|
arguments[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
@ -484,8 +499,12 @@ Avian_avian_Singleton_getLong
|
|||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int64_t v;
|
int64_t v;
|
||||||
memcpy(&v, &singletonValue
|
memcpy(&v,
|
||||||
(t, cast<GcSingleton>(t, reinterpret_cast<object>(arguments[0])), arguments[1]), 8);
|
&singletonValue(
|
||||||
|
t,
|
||||||
|
cast<GcSingleton>(t, reinterpret_cast<object>(arguments[0])),
|
||||||
|
arguments[1]),
|
||||||
|
8);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,19 +729,16 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_sun_misc_Unsafe_arrayIndexScale
|
Avian_sun_misc_Unsafe_arrayIndexScale
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcClass* c = cast<GcJclass>(t, reinterpret_cast<object>(arguments[1]))->vmClass();
|
GcClass* c
|
||||||
|
= cast<GcJclass>(t, reinterpret_cast<object>(arguments[1]))->vmClass();
|
||||||
|
|
||||||
if (c == type(t, GcBooleanArray::Type)
|
if (c == type(t, GcBooleanArray::Type) || c == type(t, GcByteArray::Type))
|
||||||
|| c == type(t, GcByteArray::Type))
|
|
||||||
return 1;
|
return 1;
|
||||||
else if (c == type(t, GcShortArray::Type)
|
else if (c == type(t, GcShortArray::Type) || c == type(t, GcCharArray::Type))
|
||||||
|| c == type(t, GcCharArray::Type))
|
|
||||||
return 2;
|
return 2;
|
||||||
else if (c == type(t, GcIntArray::Type)
|
else if (c == type(t, GcIntArray::Type) || c == type(t, GcFloatArray::Type))
|
||||||
|| c == type(t, GcFloatArray::Type))
|
|
||||||
return 4;
|
return 4;
|
||||||
else if (c == type(t, GcLongArray::Type)
|
else if (c == type(t, GcLongArray::Type) || c == type(t, GcDoubleArray::Type))
|
||||||
|| c == type(t, GcDoubleArray::Type))
|
|
||||||
return 8;
|
return 8;
|
||||||
else
|
else
|
||||||
return BytesPerWord;
|
return BytesPerWord;
|
||||||
@ -733,13 +749,15 @@ Avian_java_nio_FixedArrayByteBuffer_allocateFixed
|
|||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
int capacity = arguments[0];
|
int capacity = arguments[0];
|
||||||
GcLongArray* address = cast<GcLongArray>(t, reinterpret_cast<object>(arguments[1]));
|
GcLongArray* address
|
||||||
|
= cast<GcLongArray>(t, reinterpret_cast<object>(arguments[1]));
|
||||||
PROTECT(t, address);
|
PROTECT(t, address);
|
||||||
|
|
||||||
GcArray* array = reinterpret_cast<GcArray*>(allocate3
|
GcArray* array = reinterpret_cast<GcArray*>(allocate3(
|
||||||
(t, t->m->heap, Machine::FixedAllocation, ArrayBody + capacity, false));
|
t, t->m->heap, Machine::FixedAllocation, ArrayBody + capacity, false));
|
||||||
|
|
||||||
setObjectClass(t, reinterpret_cast<object>(array), type(t, GcByteArray::Type));
|
setObjectClass(
|
||||||
|
t, reinterpret_cast<object>(array), type(t, GcByteArray::Type));
|
||||||
array->length() = capacity;
|
array->length() = capacity;
|
||||||
|
|
||||||
address->body()[0] = reinterpret_cast<intptr_t>(array) + ArrayBody;
|
address->body()[0] = reinterpret_cast<intptr_t>(array) + ArrayBody;
|
||||||
@ -964,11 +982,11 @@ Avian_sun_misc_Unsafe_park
|
|||||||
monitorAcquire(t, cast<GcMonitor>(t, interruptLock(t, t->javaThread)));
|
monitorAcquire(t, cast<GcMonitor>(t, interruptLock(t, t->javaThread)));
|
||||||
bool interrupted = false;
|
bool interrupted = false;
|
||||||
while (time >= 0
|
while (time >= 0
|
||||||
and (not (t->javaThread->unparked()
|
and (not(t->javaThread->unparked() or t->javaThread->interrupted()
|
||||||
or t->javaThread->interrupted()
|
or (interrupted = monitorWait(
|
||||||
or (interrupted = monitorWait
|
t,
|
||||||
(t, cast<GcMonitor>(t, interruptLock(t, t->javaThread)), time)))))
|
cast<GcMonitor>(t, interruptLock(t, t->javaThread)),
|
||||||
{
|
time))))) {
|
||||||
int64_t now = t->m->system->now();
|
int64_t now = t->m->system->now();
|
||||||
time -= now - then;
|
time -= now - then;
|
||||||
then = now;
|
then = now;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -26,20 +26,20 @@ class MyClasspath : public Classpath {
|
|||||||
allocator(allocator)
|
allocator(allocator)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual GcJclass*
|
virtual GcJclass* makeJclass(Thread* t, GcClass* class_)
|
||||||
makeJclass(Thread* t, GcClass* class_)
|
|
||||||
{
|
{
|
||||||
return vm::makeJclass(t, class_);
|
return vm::makeJclass(t, class_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcString*
|
virtual GcString* makeString(Thread* t,
|
||||||
makeString(Thread* t, object array, int32_t offset, int32_t length)
|
object array,
|
||||||
|
int32_t offset,
|
||||||
|
int32_t length)
|
||||||
{
|
{
|
||||||
return vm::makeString(t, array, offset, length, 0);
|
return vm::makeString(t, array, offset, length, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcThread*
|
virtual GcThread* makeThread(Thread* t, Thread* parent)
|
||||||
makeThread(Thread* t, Thread* parent)
|
|
||||||
{
|
{
|
||||||
GcThreadGroup* group;
|
GcThreadGroup* group;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
@ -51,38 +51,48 @@ class MyClasspath : public Classpath {
|
|||||||
const unsigned NewState = 0;
|
const unsigned NewState = 0;
|
||||||
const unsigned NormalPriority = 5;
|
const unsigned NormalPriority = 5;
|
||||||
|
|
||||||
return vm::makeThread
|
return vm::makeThread(t,
|
||||||
(t, 0, 0, 0, 0, 0, NewState, NormalPriority, 0, 0, 0,
|
0,
|
||||||
roots(t)->appLoader(), 0, 0, group, 0);
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NewState,
|
||||||
|
NormalPriority,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
roots(t)->appLoader(),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
group,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object makeJMethod(Thread* t, GcMethod* vmMethod)
|
||||||
makeJMethod(Thread* t, GcMethod* vmMethod)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, vmMethod);
|
PROTECT(t, vmMethod);
|
||||||
|
|
||||||
GcJmethod* jmethod = makeJmethod(t, vmMethod, false);
|
GcJmethod* jmethod = makeJmethod(t, vmMethod, false);
|
||||||
|
|
||||||
return vmMethod->name()->body()[0] == '<'
|
return vmMethod->name()->body()[0] == '<'
|
||||||
? (object)makeJconstructor(t, jmethod) : (object)jmethod;
|
? (object)makeJconstructor(t, jmethod)
|
||||||
|
: (object)jmethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcMethod*
|
virtual GcMethod* getVMMethod(Thread* t, object jmethod)
|
||||||
getVMMethod(Thread* t, object jmethod)
|
|
||||||
{
|
{
|
||||||
return objectClass(t, jmethod) == type(t, GcJmethod::Type)
|
return objectClass(t, jmethod) == type(t, GcJmethod::Type)
|
||||||
? cast<GcJmethod>(t, jmethod)->vmMethod()
|
? cast<GcJmethod>(t, jmethod)->vmMethod()
|
||||||
: cast<GcJconstructor>(t, jmethod)->method()->vmMethod();
|
: cast<GcJconstructor>(t, jmethod)->method()->vmMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object makeJField(Thread* t, GcField* vmField)
|
||||||
makeJField(Thread* t, GcField* vmField)
|
|
||||||
{
|
{
|
||||||
return makeJfield(t, vmField, false);
|
return makeJfield(t, vmField, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcField*
|
virtual GcField* getVMField(Thread* t UNUSED, GcJfield* jfield)
|
||||||
getVMField(Thread* t UNUSED, GcJfield* jfield)
|
|
||||||
{
|
{
|
||||||
return jfield->vmField();
|
return jfield->vmField();
|
||||||
}
|
}
|
||||||
@ -96,15 +106,16 @@ class MyClasspath : public Classpath {
|
|||||||
virtual void
|
virtual void
|
||||||
runThread(Thread* t)
|
runThread(Thread* t)
|
||||||
{
|
{
|
||||||
GcMethod* method = resolveMethod
|
GcMethod* method = resolveMethod(t,
|
||||||
(t, roots(t)->bootLoader(), "java/lang/Thread", "run",
|
roots(t)->bootLoader(),
|
||||||
"(Ljava/lang/Thread;)V");
|
"java/lang/Thread",
|
||||||
|
"run",
|
||||||
|
"(Ljava/lang/Thread;)V");
|
||||||
|
|
||||||
t->m->processor->invoke(t, method, 0, t->javaThread);
|
t->m->processor->invoke(t, method, 0, t->javaThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void resolveNative(Thread* t, GcMethod* method)
|
||||||
resolveNative(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
vm::resolveNative(t, method);
|
vm::resolveNative(t, method);
|
||||||
}
|
}
|
||||||
@ -141,8 +152,8 @@ class MyClasspath : public Classpath {
|
|||||||
virtual object
|
virtual object
|
||||||
makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
makeDirectByteBuffer(Thread* t, void* p, jlong capacity)
|
||||||
{
|
{
|
||||||
GcClass* c = resolveClass
|
GcClass* c
|
||||||
(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer");
|
= resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer");
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
object instance = makeNew(t, c);
|
object instance = makeNew(t, c);
|
||||||
@ -164,8 +175,7 @@ class MyClasspath : public Classpath {
|
|||||||
|
|
||||||
GcField* field = resolveField(t, objectClass(t, b), "address", "J");
|
GcField* field = resolveField(t, objectClass(t, b), "address", "J");
|
||||||
|
|
||||||
return reinterpret_cast<void*>
|
return reinterpret_cast<void*>(fieldAtOffset<int64_t>(b, field->offset()));
|
||||||
(fieldAtOffset<int64_t>(b, field->offset()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int64_t
|
virtual int64_t
|
||||||
@ -173,8 +183,7 @@ class MyClasspath : public Classpath {
|
|||||||
{
|
{
|
||||||
PROTECT(t, b);
|
PROTECT(t, b);
|
||||||
|
|
||||||
GcField* field = resolveField
|
GcField* field = resolveField(t, objectClass(t, b), "capacity", "I");
|
||||||
(t, objectClass(t, b), "capacity", "I");
|
|
||||||
|
|
||||||
return fieldAtOffset<int32_t>(b, field->offset());
|
return fieldAtOffset<int32_t>(b, field->offset());
|
||||||
}
|
}
|
||||||
@ -194,14 +203,12 @@ class MyClasspath : public Classpath {
|
|||||||
(strcmp("loadLibrary",
|
(strcmp("loadLibrary",
|
||||||
reinterpret_cast<char*>(calleeMethodName->body().begin()))
|
reinterpret_cast<char*>(calleeMethodName->body().begin()))
|
||||||
and strcmp("load",
|
and strcmp("load",
|
||||||
reinterpret_cast<char*>(
|
reinterpret_cast<char*>(calleeMethodName->body().begin())))
|
||||||
calleeMethodName->body().begin())))
|
or (strcmp("java/lang/System",
|
||||||
or (strcmp(
|
reinterpret_cast<char*>(calleeClassName->body().begin()))
|
||||||
"java/lang/System",
|
and strcmp(
|
||||||
reinterpret_cast<char*>(calleeClassName->body().begin()))
|
"java/lang/Runtime",
|
||||||
and strcmp("java/lang/Runtime",
|
reinterpret_cast<char*>(calleeClassName->body().begin()))));
|
||||||
reinterpret_cast<char*>(
|
|
||||||
calleeClassName->body().begin()))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcClassLoader* libraryClassLoader(Thread* t, GcMethod* caller)
|
virtual GcClassLoader* libraryClassLoader(Thread* t, GcMethod* caller)
|
||||||
@ -227,9 +234,11 @@ class MyClasspath : public Classpath {
|
|||||||
Allocator* allocator;
|
Allocator* allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void enumerateThreads(Thread* t,
|
||||||
enumerateThreads(Thread* t, Thread* x, GcArray* array, unsigned* index,
|
Thread* x,
|
||||||
unsigned limit)
|
GcArray* array,
|
||||||
|
unsigned* index,
|
||||||
|
unsigned limit)
|
||||||
{
|
{
|
||||||
if (*index < limit) {
|
if (*index < limit) {
|
||||||
array->setBodyElement(t, *index, x->javaThread);
|
array->setBodyElement(t, *index, x->javaThread);
|
||||||
@ -263,10 +272,8 @@ Avian_java_lang_Object_toString
|
|||||||
object this_ = reinterpret_cast<object>(arguments[0]);
|
object this_ = reinterpret_cast<object>(arguments[0]);
|
||||||
|
|
||||||
unsigned hash = objectHash(t, this_);
|
unsigned hash = objectHash(t, this_);
|
||||||
GcString* s = makeString
|
GcString* s = makeString(
|
||||||
(t, "%s@0x%x",
|
t, "%s@0x%x", objectClass(t, this_)->name()->body().begin(), hash);
|
||||||
objectClass(t, this_)->name()->body().begin(),
|
|
||||||
hash);
|
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>(s);
|
return reinterpret_cast<int64_t>(s);
|
||||||
}
|
}
|
||||||
@ -457,8 +464,8 @@ Avian_java_lang_reflect_Method_invoke
|
|||||||
THREAD_RESOURCE0(t, {
|
THREAD_RESOURCE0(t, {
|
||||||
if (t->exception) {
|
if (t->exception) {
|
||||||
GcThrowable* exception = t->exception;
|
GcThrowable* exception = t->exception;
|
||||||
t->exception = makeThrowable
|
t->exception = makeThrowable(
|
||||||
(t, GcInvocationTargetException::Type, 0, 0, exception);
|
t, GcInvocationTargetException::Type, 0, 0, exception);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -492,11 +499,12 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_java_lang_reflect_Array_makeObjectArray
|
Avian_java_lang_reflect_Array_makeObjectArray
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
GcJclass* elementType = cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]));
|
GcJclass* elementType
|
||||||
|
= cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]));
|
||||||
int length = arguments[1];
|
int length = arguments[1];
|
||||||
|
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(makeObjectArray(t, elementType->vmClass(), length));
|
makeObjectArray(t, elementType->vmClass(), length));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
@ -580,8 +588,7 @@ Avian_java_lang_System_identityHashCode
|
|||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_java_lang_ClassLoader_getCaller(Thread* t, object, uintptr_t*)
|
Avian_java_lang_ClassLoader_getCaller(Thread* t, object, uintptr_t*)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>(
|
return reinterpret_cast<int64_t>(getJClass(t, getCaller(t, 2)->class_()));
|
||||||
getJClass(t, getCaller(t, 2)->class_()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
@ -591,7 +598,9 @@ extern "C" AVIAN_EXPORT void JNICALL
|
|||||||
|
|
||||||
Thread::LibraryLoadStack stack(
|
Thread::LibraryLoadStack stack(
|
||||||
t,
|
t,
|
||||||
cast<GcJclass>(t, reinterpret_cast<object>(arguments[1]))->vmClass()->loader());
|
cast<GcJclass>(t, reinterpret_cast<object>(arguments[1]))
|
||||||
|
->vmClass()
|
||||||
|
->loader());
|
||||||
|
|
||||||
bool mapName = arguments[2];
|
bool mapName = arguments[2];
|
||||||
|
|
||||||
@ -643,7 +652,8 @@ Avian_java_lang_Throwable_resolveTrace
|
|||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
for (unsigned i = 0; i < length; ++i) {
|
for (unsigned i = 0; i < length; ++i) {
|
||||||
GcStackTraceElement* ste = makeStackTraceElement(t, cast<GcTraceElement>(t, objectArrayBody(t, trace, i)));
|
GcStackTraceElement* ste = makeStackTraceElement(
|
||||||
|
t, cast<GcTraceElement>(t, objectArrayBody(t, trace, i)));
|
||||||
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, ste);
|
reinterpret_cast<GcArray*>(array)->setBodyElement(t, i, ste);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,8 +671,8 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_java_lang_Thread_doStart
|
Avian_java_lang_Thread_doStart
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<int64_t>
|
return reinterpret_cast<int64_t>(
|
||||||
(startThread(t, cast<GcThread>(t, reinterpret_cast<object>(*arguments))));
|
startThread(t, cast<GcThread>(t, reinterpret_cast<object>(*arguments))));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT void JNICALL
|
extern "C" AVIAN_EXPORT void JNICALL
|
||||||
@ -713,7 +723,8 @@ Avian_java_lang_Thread_enumerate
|
|||||||
|
|
||||||
ACQUIRE_RAW(t, t->m->stateLock);
|
ACQUIRE_RAW(t, t->m->stateLock);
|
||||||
|
|
||||||
unsigned count = min(t->m->liveCount, objectArrayLength(t, reinterpret_cast<object>(array)));
|
unsigned count = min(t->m->liveCount,
|
||||||
|
objectArrayLength(t, reinterpret_cast<object>(array)));
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
local::enumerateThreads(t, t->m->rootThread, array, &index, count);
|
local::enumerateThreads(t, t->m->rootThread, array, &index, count);
|
||||||
return count;
|
return count;
|
||||||
@ -730,14 +741,18 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
|||||||
Avian_avian_Atomic_getOffset
|
Avian_avian_Atomic_getOffset
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[0]))->vmField()->offset();
|
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[0]))
|
||||||
|
->vmField()
|
||||||
|
->offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
Avian_sun_misc_Unsafe_objectFieldOffset
|
Avian_sun_misc_Unsafe_objectFieldOffset
|
||||||
(Thread* t, object, uintptr_t* arguments)
|
(Thread* t, object, uintptr_t* arguments)
|
||||||
{
|
{
|
||||||
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[1]))->vmField()->offset();
|
return cast<GcJfield>(t, reinterpret_cast<object>(arguments[1]))
|
||||||
|
->vmField()
|
||||||
|
->offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||||
@ -793,8 +808,8 @@ Avian_avian_Classes_makeMethod
|
|||||||
->methodTable())->body()[arguments[1]]);
|
->methodTable())->body()[arguments[1]]);
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
GcClass* c = resolveClass
|
GcClass* c
|
||||||
(t, roots(t)->bootLoader(), "java/lang/reflect/Method");
|
= resolveClass(t, roots(t)->bootLoader(), "java/lang/reflect/Method");
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
object instance = makeNew(t, c);
|
object instance = makeNew(t, c);
|
||||||
@ -807,13 +822,13 @@ Avian_avian_Classes_makeMethod
|
|||||||
if (method->name()->body()[0] == '<') {
|
if (method->name()->body()[0] == '<') {
|
||||||
object oldInstance = instance;
|
object oldInstance = instance;
|
||||||
|
|
||||||
c = resolveClass
|
c = resolveClass(
|
||||||
(t, roots(t)->bootLoader(), "java/lang/reflect/Constructor");
|
t, roots(t)->bootLoader(), "java/lang/reflect/Constructor");
|
||||||
|
|
||||||
object instance = makeNew(t, c);
|
object instance = makeNew(t, c);
|
||||||
|
|
||||||
GcMethod* constructor = resolveMethod
|
GcMethod* constructor
|
||||||
(t, c, "<init>", "(Ljava/lang/Method;)V");
|
= resolveMethod(t, c, "<init>", "(Ljava/lang/Method;)V");
|
||||||
|
|
||||||
t->m->processor->invoke(t, constructor, instance, oldInstance);
|
t->m->processor->invoke(t, constructor, instance, oldInstance);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -586,7 +586,8 @@ acceptForResolve(Context* c, Site* s, Read* read, const SiteMask& mask)
|
|||||||
if (s->type(c) == lir::RegisterOperand) {
|
if (s->type(c) == lir::RegisterOperand) {
|
||||||
return c->availableGeneralRegisterCount > ResolveRegisterReserveCount;
|
return c->availableGeneralRegisterCount > ResolveRegisterReserveCount;
|
||||||
} else {
|
} else {
|
||||||
assertT(c, s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex)));
|
assertT(c,
|
||||||
|
s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex)));
|
||||||
|
|
||||||
return isHome(read->value, offsetToFrameIndex
|
return isHome(read->value, offsetToFrameIndex
|
||||||
(c, static_cast<MemorySite*>(s)->offset));
|
(c, static_cast<MemorySite*>(s)->offset));
|
||||||
@ -1138,9 +1139,11 @@ pop(Context* c, unsigned footprint)
|
|||||||
high = low->next;
|
high = low->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertT(c, (TargetBytesPerWord == 8
|
assertT(
|
||||||
and low->value->nextWord == low->value and high->value == 0)
|
c,
|
||||||
or (TargetBytesPerWord == 4 and low->value->nextWord == high->value));
|
(TargetBytesPerWord == 8 and low->value->nextWord == low->value
|
||||||
|
and high->value == 0)
|
||||||
|
or (TargetBytesPerWord == 4 and low->value->nextWord == high->value));
|
||||||
#endif // not NDEBUG
|
#endif // not NDEBUG
|
||||||
|
|
||||||
popWord(c);
|
popWord(c);
|
||||||
@ -2379,10 +2382,11 @@ class MyCompiler: public Compiler {
|
|||||||
high = s->next;
|
high = s->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertT(&c, (TargetBytesPerWord == 8
|
assertT(
|
||||||
and low->value->nextWord == low->value and high->value == 0)
|
&c,
|
||||||
or (TargetBytesPerWord == 4
|
(TargetBytesPerWord == 8 and low->value->nextWord == low->value
|
||||||
and low->value->nextWord == high->value));
|
and high->value == 0)
|
||||||
|
or (TargetBytesPerWord == 4 and low->value->nextWord == high->value));
|
||||||
#endif // not NDEBUG
|
#endif // not NDEBUG
|
||||||
|
|
||||||
if (bigEndian) {
|
if (bigEndian) {
|
||||||
@ -2649,8 +2653,8 @@ class MyCompiler: public Compiler {
|
|||||||
ir::Value* addr)
|
ir::Value* addr)
|
||||||
{
|
{
|
||||||
assertT(&c,
|
assertT(&c,
|
||||||
(isGeneralBranch(op) and isGeneralValue(a) and isGeneralValue(b))or(
|
(isGeneralBranch(op) and isGeneralValue(a) and isGeneralValue(b))
|
||||||
isFloatBranch(op) and isFloatValue(a) and isFloatValue(b)));
|
or (isFloatBranch(op) and isFloatValue(a) and isFloatValue(b)));
|
||||||
|
|
||||||
assertT(&c, a->type == b->type);
|
assertT(&c, a->type == b->type);
|
||||||
assertT(&c, addr->type == ir::Type::iptr());
|
assertT(&c, addr->type == ir::Type::iptr());
|
||||||
@ -2678,8 +2682,8 @@ class MyCompiler: public Compiler {
|
|||||||
ir::Value* b)
|
ir::Value* b)
|
||||||
{
|
{
|
||||||
assertT(&c,
|
assertT(&c,
|
||||||
(isGeneralBinaryOp(op) and isGeneralValue(a) and isGeneralValue(b))
|
(isGeneralBinaryOp(op) and isGeneralValue(a) and isGeneralValue(b))
|
||||||
or(isFloatBinaryOp(op) and isFloatValue(a) and isFloatValue(b)));
|
or (isFloatBinaryOp(op) and isFloatValue(a) and isFloatValue(b)));
|
||||||
|
|
||||||
Value* result = value(&c, type);
|
Value* result = value(&c, type);
|
||||||
|
|
||||||
@ -2695,8 +2699,8 @@ class MyCompiler: public Compiler {
|
|||||||
ir::Value* a)
|
ir::Value* a)
|
||||||
{
|
{
|
||||||
assertT(&c,
|
assertT(&c,
|
||||||
(isGeneralUnaryOp(op) and isGeneralValue(a))or(isFloatUnaryOp(op)
|
(isGeneralUnaryOp(op) and isGeneralValue(a))
|
||||||
and isFloatValue(a)));
|
or (isFloatUnaryOp(op) and isFloatValue(a)));
|
||||||
Value* result = value(&c, a->type);
|
Value* result = value(&c, a->type);
|
||||||
appendTranslate(
|
appendTranslate(
|
||||||
&c, op, static_cast<Value*>(a), result);
|
&c, op, static_cast<Value*>(a), result);
|
||||||
|
@ -400,8 +400,8 @@ class CallEvent: public Event {
|
|||||||
&& (v == 0 || (i >= 1 && arguments[i - 1] == 0)))
|
&& (v == 0 || (i >= 1 && arguments[i - 1] == 0)))
|
||||||
|| (c->targetInfo.pointerSize == 4 && v->nextWord != v)) {
|
|| (c->targetInfo.pointerSize == 4 && v->nextWord != v)) {
|
||||||
assertT(c,
|
assertT(c,
|
||||||
c->targetInfo.pointerSize == 8
|
c->targetInfo.pointerSize == 8
|
||||||
or v->nextWord == arguments[i - 1]);
|
or v->nextWord == arguments[i - 1]);
|
||||||
|
|
||||||
arguments[i] = arguments[i - 1];
|
arguments[i] = arguments[i - 1];
|
||||||
--i;
|
--i;
|
||||||
@ -512,10 +512,14 @@ class CallEvent: public Event {
|
|||||||
op = lir::Jump;
|
op = lir::Jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertT(c, returnAddressSurrogate == 0
|
assertT(
|
||||||
or returnAddressSurrogate->source->type(c) == lir::RegisterOperand);
|
c,
|
||||||
assertT(c, framePointerSurrogate == 0
|
returnAddressSurrogate == 0
|
||||||
or framePointerSurrogate->source->type(c) == lir::RegisterOperand);
|
or returnAddressSurrogate->source->type(c) == lir::RegisterOperand);
|
||||||
|
assertT(
|
||||||
|
c,
|
||||||
|
framePointerSurrogate == 0
|
||||||
|
or framePointerSurrogate->source->type(c) == lir::RegisterOperand);
|
||||||
|
|
||||||
int ras;
|
int ras;
|
||||||
if (returnAddressSurrogate) {
|
if (returnAddressSurrogate) {
|
||||||
@ -1004,7 +1008,9 @@ class CombineEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
assertT(c, firstValue->source->type(c) == firstValue->nextWord->source->type(c));
|
assertT(
|
||||||
|
c,
|
||||||
|
firstValue->source->type(c) == firstValue->nextWord->source->type(c));
|
||||||
|
|
||||||
// if (secondValue->source->type(c) != secondValue->nextWord->source->type(c)) {
|
// if (secondValue->source->type(c) != secondValue->nextWord->source->type(c)) {
|
||||||
// fprintf(stderr, "%p %p %d : %p %p %d\n",
|
// fprintf(stderr, "%p %p %d : %p %p %d\n",
|
||||||
@ -1013,7 +1019,9 @@ class CombineEvent: public Event {
|
|||||||
// secondValue->nextWord->source->type(c));
|
// secondValue->nextWord->source->type(c));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
assertT(c, secondValue->source->type(c) == secondValue->nextWord->source->type(c));
|
assertT(
|
||||||
|
c,
|
||||||
|
secondValue->source->type(c) == secondValue->nextWord->source->type(c));
|
||||||
|
|
||||||
freezeSource(c, firstValue->type.size(c->targetInfo), firstValue);
|
freezeSource(c, firstValue->type.size(c->targetInfo), firstValue);
|
||||||
|
|
||||||
@ -1197,7 +1205,9 @@ class TranslateEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
assertT(c, firstValue->source->type(c) == firstValue->nextWord->source->type(c));
|
assertT(
|
||||||
|
c,
|
||||||
|
firstValue->source->type(c) == firstValue->nextWord->source->type(c));
|
||||||
|
|
||||||
OperandMask bMask;
|
OperandMask bMask;
|
||||||
|
|
||||||
@ -1266,11 +1276,11 @@ void appendTranslate(Context* c,
|
|||||||
Value* resultValue)
|
Value* resultValue)
|
||||||
{
|
{
|
||||||
assertT(c,
|
assertT(c,
|
||||||
firstValue->type.size(c->targetInfo)
|
firstValue->type.size(c->targetInfo)
|
||||||
== firstValue->type.size(c->targetInfo));
|
== firstValue->type.size(c->targetInfo));
|
||||||
assertT(c,
|
assertT(c,
|
||||||
resultValue->type.size(c->targetInfo)
|
resultValue->type.size(c->targetInfo)
|
||||||
== resultValue->type.size(c->targetInfo));
|
== resultValue->type.size(c->targetInfo));
|
||||||
|
|
||||||
bool thunk;
|
bool thunk;
|
||||||
OperandMask first;
|
OperandMask first;
|
||||||
|
@ -50,11 +50,11 @@ unsigned frameIndexToOffset(Context* c, unsigned frameIndex) {
|
|||||||
|
|
||||||
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
|
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
|
||||||
assertT(c,
|
assertT(c,
|
||||||
static_cast<int>((offset / c->targetInfo.pointerSize)
|
static_cast<int>((offset / c->targetInfo.pointerSize)
|
||||||
- c->arch->frameFooterSize()) >= 0);
|
- c->arch->frameFooterSize()) >= 0);
|
||||||
assertT(c,
|
assertT(c,
|
||||||
((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize())
|
((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize())
|
||||||
< totalFrameSize(c));
|
< totalFrameSize(c));
|
||||||
|
|
||||||
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
|
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,8 @@ Read* StubRead::next(Context*) {
|
|||||||
|
|
||||||
|
|
||||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
|
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
|
||||||
assertT(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
assertT(c,
|
||||||
|
(mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
||||||
|
|
||||||
return new(c->zone) SingleRead(mask, successor);
|
return new(c->zone) SingleRead(mask, successor);
|
||||||
}
|
}
|
||||||
|
@ -223,4 +223,4 @@ void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNU
|
|||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -378,8 +378,9 @@ unsigned RegisterSite::registerMask(Context* c UNUSED) {
|
|||||||
|
|
||||||
Site* registerSite(Context* c, int number) {
|
Site* registerSite(Context* c, int number) {
|
||||||
assertT(c, number >= 0);
|
assertT(c, number >= 0);
|
||||||
assertT(c, (1 << number) & (c->regFile->generalRegisters.mask
|
assertT(c,
|
||||||
| c->regFile->floatRegisters.mask));
|
(1 << number) & (c->regFile->generalRegisters.mask
|
||||||
|
| c->regFile->floatRegisters.mask));
|
||||||
|
|
||||||
return new(c->zone) RegisterSite(1 << number, number);
|
return new(c->zone) RegisterSite(1 << number, number);
|
||||||
}
|
}
|
||||||
@ -488,8 +489,7 @@ void MemorySite::acquire(Context* c, Value* v) {
|
|||||||
|
|
||||||
if (base == c->arch->stack()) {
|
if (base == c->arch->stack()) {
|
||||||
assertT(c, index == lir::NoRegister);
|
assertT(c, index == lir::NoRegister);
|
||||||
assertT
|
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
|
||||||
|
|
||||||
compiler::acquire
|
compiler::acquire
|
||||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||||
@ -501,8 +501,7 @@ void MemorySite::acquire(Context* c, Value* v) {
|
|||||||
void MemorySite::release(Context* c, Value* v) {
|
void MemorySite::release(Context* c, Value* v) {
|
||||||
if (base == c->arch->stack()) {
|
if (base == c->arch->stack()) {
|
||||||
assertT(c, index == lir::NoRegister);
|
assertT(c, index == lir::NoRegister);
|
||||||
assertT
|
assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
|
||||||
|
|
||||||
compiler::release
|
compiler::release
|
||||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||||
@ -552,12 +551,12 @@ void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
|||||||
{
|
{
|
||||||
// todo: endianness?
|
// todo: endianness?
|
||||||
assertT(c,
|
assertT(c,
|
||||||
high == this
|
high == this
|
||||||
or (static_cast<MemorySite*>(high)->base == base
|
or (static_cast<MemorySite*>(high)->base == base
|
||||||
and static_cast<MemorySite*>(high)->offset
|
and static_cast<MemorySite*>(high)->offset
|
||||||
== static_cast<int>(offset + c->targetInfo.pointerSize)
|
== static_cast<int>(offset + c->targetInfo.pointerSize)
|
||||||
and static_cast<MemorySite*>(high)->index == index
|
and static_cast<MemorySite*>(high)->index == index
|
||||||
and static_cast<MemorySite*>(high)->scale == scale));
|
and static_cast<MemorySite*>(high)->scale == scale));
|
||||||
|
|
||||||
assertT(c, acquired);
|
assertT(c, acquired);
|
||||||
|
|
||||||
|
@ -884,11 +884,11 @@ void moveAR(Context* con, unsigned srcSize, lir::Address* src,
|
|||||||
void compareRR(Context* con, unsigned aSize, lir::Register* a,
|
void compareRR(Context* con, unsigned aSize, lir::Register* a,
|
||||||
unsigned bSize UNUSED, lir::Register* b)
|
unsigned bSize UNUSED, lir::Register* b)
|
||||||
{
|
{
|
||||||
assertT(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type
|
assertT(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type
|
||||||
|
|
||||||
if (!isFpr(a)) { // GPR compare
|
if (!isFpr(a)) { // GPR compare
|
||||||
assertT(con, aSize == 4 && bSize == 4);
|
assertT(con, aSize == 4 && bSize == 4);
|
||||||
/**///assertT(con, b->low != a->low);
|
/**/ // assertT(con, b->low != a->low);
|
||||||
emit(con, cmp(b->low, a->low));
|
emit(con, cmp(b->low, a->low));
|
||||||
} else { // FPR compare
|
} else { // FPR compare
|
||||||
assertT(con, aSize == bSize);
|
assertT(con, aSize == bSize);
|
||||||
|
@ -143,11 +143,13 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (UseFramePointer and not mostRecent) {
|
if (UseFramePointer and not mostRecent) {
|
||||||
assertT(c, static_cast<void***>(*stack)[-1] + 1
|
assertT(c,
|
||||||
== static_cast<void**>(*stack) + offset);
|
static_cast<void***>(*stack)[-1] + 1
|
||||||
|
== static_cast<void**>(*stack) + offset);
|
||||||
|
|
||||||
assertT(c, static_cast<void***>(*stack)[-1][1]
|
assertT(c,
|
||||||
== static_cast<void**>(*stack)[offset]);
|
static_cast<void***>(*stack)[-1][1]
|
||||||
|
== static_cast<void**>(*stack)[offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
*ip = static_cast<void**>(*stack)[offset];
|
*ip = static_cast<void**>(*stack)[offset];
|
||||||
@ -341,11 +343,15 @@ class MyArchitecture: public Architecture {
|
|||||||
if (TargetBytesPerWord == 4 or op == lir::Call or op == lir::Jump) {
|
if (TargetBytesPerWord == 4 or op == lir::Call or op == lir::Jump) {
|
||||||
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
||||||
|
|
||||||
assertT(&c, ((op == lir::Call or op == lir::LongCall) and *instruction == 0xE8)
|
assertT(
|
||||||
or ((op == lir::Jump or op == lir::LongJump) and *instruction == 0xE9));
|
&c,
|
||||||
|
((op == lir::Call or op == lir::LongCall) and *instruction == 0xE8)
|
||||||
|
or ((op == lir::Jump or op == lir::LongJump)
|
||||||
|
and *instruction == 0xE9));
|
||||||
|
|
||||||
assertT(&c, (not assertTAlignment)
|
assertT(&c,
|
||||||
or reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
|
(not assertTAlignment)
|
||||||
|
or reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
|
||||||
|
|
||||||
intptr_t v = static_cast<uint8_t*>(newTarget)
|
intptr_t v = static_cast<uint8_t*>(newTarget)
|
||||||
- static_cast<uint8_t*>(returnAddress);
|
- static_cast<uint8_t*>(returnAddress);
|
||||||
@ -360,11 +366,13 @@ class MyArchitecture: public Architecture {
|
|||||||
|
|
||||||
assertT(&c, instruction[0] == 0x49 and instruction[1] == 0xBA);
|
assertT(&c, instruction[0] == 0x49 and instruction[1] == 0xBA);
|
||||||
assertT(&c, instruction[10] == 0x41 and instruction[11] == 0xFF);
|
assertT(&c, instruction[10] == 0x41 and instruction[11] == 0xFF);
|
||||||
assertT(&c, (op == lir::LongCall and instruction[12] == 0xD2)
|
assertT(&c,
|
||||||
or (op == lir::LongJump and instruction[12] == 0xE2));
|
(op == lir::LongCall and instruction[12] == 0xD2)
|
||||||
|
or (op == lir::LongJump and instruction[12] == 0xE2));
|
||||||
|
|
||||||
assertT(&c, (not assertTAlignment)
|
assertT(&c,
|
||||||
or reinterpret_cast<uintptr_t>(instruction + 2) % 8 == 0);
|
(not assertTAlignment)
|
||||||
|
or reinterpret_cast<uintptr_t>(instruction + 2) % 8 == 0);
|
||||||
|
|
||||||
memcpy(instruction + 2, &newTarget, 8);
|
memcpy(instruction + 2, &newTarget, 8);
|
||||||
}
|
}
|
||||||
|
@ -708,7 +708,6 @@ void andRR(Context* c, unsigned aSize, lir::Register* a,
|
|||||||
{
|
{
|
||||||
assertT(c, aSize == bSize);
|
assertT(c, aSize == bSize);
|
||||||
|
|
||||||
|
|
||||||
if (vm::TargetBytesPerWord == 4 and aSize == 8) {
|
if (vm::TargetBytesPerWord == 4 and aSize == 8) {
|
||||||
lir::Register ah(a->high);
|
lir::Register ah(a->high);
|
||||||
lir::Register bh(b->high);
|
lir::Register bh(b->high);
|
||||||
@ -877,7 +876,6 @@ void multiplyRR(Context* c, unsigned aSize, lir::Register* a,
|
|||||||
{
|
{
|
||||||
assertT(c, aSize == bSize);
|
assertT(c, aSize == bSize);
|
||||||
|
|
||||||
|
|
||||||
if (vm::TargetBytesPerWord == 4 and aSize == 8) {
|
if (vm::TargetBytesPerWord == 4 and aSize == 8) {
|
||||||
assertT(c, b->high == rdx);
|
assertT(c, b->high == rdx);
|
||||||
assertT(c, b->low != rax);
|
assertT(c, b->low != rax);
|
||||||
|
1964
src/compile.cpp
1964
src/compile.cpp
File diff suppressed because it is too large
Load Diff
@ -284,7 +284,8 @@ class JarIndex {
|
|||||||
|
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
if (signature(p) == EntrySignature) {
|
if (signature(p) == EntrySignature) {
|
||||||
index = index->add(Entry(hash(Slice<const uint8_t>(fileName(p), fileNameLength(p))), p));
|
index = index->add(Entry(
|
||||||
|
hash(Slice<const uint8_t>(fileName(p), fileNameLength(p))), p));
|
||||||
|
|
||||||
p = endOfEntry(p);
|
p = endOfEntry(p);
|
||||||
} else {
|
} else {
|
||||||
|
@ -34,14 +34,13 @@ const unsigned FrameFootprint = 4;
|
|||||||
|
|
||||||
class Thread: public vm::Thread {
|
class Thread: public vm::Thread {
|
||||||
public:
|
public:
|
||||||
|
Thread(Machine* m, GcThread* javaThread, vm::Thread* parent)
|
||||||
Thread(Machine* m, GcThread* javaThread, vm::Thread* parent):
|
: vm::Thread(m, javaThread, parent),
|
||||||
vm::Thread(m, javaThread, parent),
|
ip(0),
|
||||||
ip(0),
|
sp(0),
|
||||||
sp(0),
|
frame(-1),
|
||||||
frame(-1),
|
code(0),
|
||||||
code(0),
|
stackPointers(0)
|
||||||
stackPointers(0)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned ip;
|
unsigned ip;
|
||||||
@ -249,8 +248,7 @@ frameNext(Thread* t, int frame)
|
|||||||
return peekInt(t, frame + FrameNextOffset);
|
return peekInt(t, frame + FrameNextOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GcMethod*
|
inline GcMethod* frameMethod(Thread* t, int frame)
|
||||||
frameMethod(Thread* t, int frame)
|
|
||||||
{
|
{
|
||||||
return cast<GcMethod>(t, peekObject(t, frame + FrameMethodOffset));
|
return cast<GcMethod>(t, peekObject(t, frame + FrameMethodOffset));
|
||||||
}
|
}
|
||||||
@ -303,8 +301,7 @@ setLocalLong(Thread* t, unsigned index, uint64_t value)
|
|||||||
pokeLong(t, frameBase(t, t->frame) + index, value);
|
pokeLong(t, frameBase(t, t->frame) + index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void pushFrame(Thread* t, GcMethod* method)
|
||||||
pushFrame(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -386,7 +383,8 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcMethod* method() {
|
virtual GcMethod* method()
|
||||||
|
{
|
||||||
return frameMethod(t, frame);
|
return frameMethod(t, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,16 +404,11 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
int frame;
|
int frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void
|
inline void checkStack(Thread* t, GcMethod* method)
|
||||||
checkStack(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
if (UNLIKELY(t->sp
|
if (UNLIKELY(t->sp + method->parameterFootprint()
|
||||||
+ method->parameterFootprint()
|
+ method->code()->maxLocals() + FrameFootprint
|
||||||
+ method->code()->maxLocals()
|
+ method->code()->maxStack() > stackSizeInWords(t) / 2)) {
|
||||||
+ FrameFootprint
|
|
||||||
+ method->code()->maxStack()
|
|
||||||
> stackSizeInWords(t) / 2))
|
|
||||||
{
|
|
||||||
throwNew(t, GcStackOverflowError::Type);
|
throwNew(t, GcStackOverflowError::Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,13 +481,15 @@ pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void marshalArguments(Thread* t,
|
||||||
marshalArguments(Thread* t, uintptr_t* args, uint8_t* types, unsigned sp,
|
uintptr_t* args,
|
||||||
GcMethod* method, bool fastCallingConvention)
|
uint8_t* types,
|
||||||
|
unsigned sp,
|
||||||
|
GcMethod* method,
|
||||||
|
bool fastCallingConvention)
|
||||||
{
|
{
|
||||||
MethodSpecIterator it
|
MethodSpecIterator it(
|
||||||
(t, reinterpret_cast<const char*>
|
t, reinterpret_cast<const char*>(method->spec()->body().begin()));
|
||||||
(method->spec()->body().begin()));
|
|
||||||
|
|
||||||
unsigned argOffset = 0;
|
unsigned argOffset = 0;
|
||||||
unsigned typeOffset = 0;
|
unsigned typeOffset = 0;
|
||||||
@ -538,8 +533,7 @@ marshalArguments(Thread* t, uintptr_t* args, uint8_t* types, unsigned sp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned invokeNativeSlow(Thread* t, GcMethod* method, void* function)
|
||||||
invokeNativeSlow(Thread* t, GcMethod* method, void* function)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -587,7 +581,8 @@ invokeNativeSlow(Thread* t, GcMethod* method, void* function)
|
|||||||
uint64_t result;
|
uint64_t result;
|
||||||
|
|
||||||
if (DebugRun) {
|
if (DebugRun) {
|
||||||
fprintf(stderr, "invoke native method %s.%s\n",
|
fprintf(stderr,
|
||||||
|
"invoke native method %s.%s\n",
|
||||||
method->class_()->name()->body().begin(),
|
method->class_()->name()->body().begin(),
|
||||||
method->name()->body().begin());
|
method->name()->body().begin());
|
||||||
}
|
}
|
||||||
@ -607,7 +602,8 @@ invokeNativeSlow(Thread* t, GcMethod* method, void* function)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DebugRun) {
|
if (DebugRun) {
|
||||||
fprintf(stderr, "return from native method %s.%s\n",
|
fprintf(stderr,
|
||||||
|
"return from native method %s.%s\n",
|
||||||
frameMethod(t, t->frame)->class_()->name()->body().begin(),
|
frameMethod(t, t->frame)->class_()->name()->body().begin(),
|
||||||
frameMethod(t, t->frame)->name()->body().begin());
|
frameMethod(t, t->frame)->name()->body().begin());
|
||||||
}
|
}
|
||||||
@ -625,8 +621,7 @@ invokeNativeSlow(Thread* t, GcMethod* method, void* function)
|
|||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned invokeNative(Thread* t, GcMethod* method)
|
||||||
invokeNative(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -651,8 +646,8 @@ invokeNative(Thread* t, GcMethod* method)
|
|||||||
marshalArguments
|
marshalArguments
|
||||||
(t, RUNTIME_ARRAY_BODY(args) + argOffset, 0, sp, method, true);
|
(t, RUNTIME_ARRAY_BODY(args) + argOffset, 0, sp, method, true);
|
||||||
|
|
||||||
result = reinterpret_cast<FastNativeFunction>
|
result = reinterpret_cast<FastNativeFunction>(native->function())(
|
||||||
(native->function())(t, method, RUNTIME_ARRAY_BODY(args));
|
t, method, RUNTIME_ARRAY_BODY(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
pushResult(t, method->returnCode(), result, false);
|
pushResult(t, method->returnCode(), result, false);
|
||||||
@ -683,12 +678,12 @@ isNaN(float v)
|
|||||||
return fpclassify(v) == FP_NAN;
|
return fpclassify(v) == FP_NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t findExceptionHandler(Thread* t, GcMethod* method, unsigned ip)
|
||||||
findExceptionHandler(Thread* t, GcMethod* method, unsigned ip)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
GcExceptionHandlerTable* eht = cast<GcExceptionHandlerTable>(t, method->code()->exceptionHandlerTable());
|
GcExceptionHandlerTable* eht = cast<GcExceptionHandlerTable>(
|
||||||
|
t, method->code()->exceptionHandlerTable());
|
||||||
|
|
||||||
if (eht) {
|
if (eht) {
|
||||||
for (unsigned i = 0; i < eht->length(); ++i) {
|
for (unsigned i = 0; i < eht->length(); ++i) {
|
||||||
@ -732,8 +727,7 @@ findExceptionHandler(Thread* t, int frame)
|
|||||||
return findExceptionHandler(t, frameMethod(t, frame), frameIp(t, frame));
|
return findExceptionHandler(t, frameMethod(t, frame), frameIp(t, frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void pushField(Thread* t, object target, GcField* field)
|
||||||
pushField(Thread* t, object target, GcField* field)
|
|
||||||
{
|
{
|
||||||
switch (field->code()) {
|
switch (field->code()) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
@ -791,10 +785,11 @@ interpret3(Thread* t, const int base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
instruction = code->body()[ip++];
|
instruction = code->body()[ip++];
|
||||||
|
|
||||||
if (DebugRun) {
|
if (DebugRun) {
|
||||||
fprintf(stderr, "ip: %d; instruction: 0x%x in %s.%s ",
|
fprintf(stderr,
|
||||||
|
"ip: %d; instruction: 0x%x in %s.%s ",
|
||||||
ip - 1,
|
ip - 1,
|
||||||
instruction,
|
instruction,
|
||||||
frameMethod(t, frame)->class_()->name()->body().begin(),
|
frameMethod(t, frame)->class_()->name()->body().begin(),
|
||||||
@ -824,9 +819,11 @@ interpret3(Thread* t, const int base)
|
|||||||
{
|
{
|
||||||
pushObject(t, objectArrayBody(t, array, index));
|
pushObject(t, objectArrayBody(t, array, index));
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, objectArrayLength(t, array));
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
objectArrayLength(t, array));
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -846,9 +843,11 @@ interpret3(Thread* t, const int base)
|
|||||||
{
|
{
|
||||||
setField(t, array, ArrayBody + (index * BytesPerWord), value);
|
setField(t, array, ArrayBody + (index * BytesPerWord), value);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, objectArrayLength(t, array));
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
objectArrayLength(t, array));
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -891,8 +890,8 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
pushObject(t, makeObjectArray(t, class_, count));
|
pushObject(t, makeObjectArray(t, class_, count));
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception
|
||||||
(t, GcNegativeArraySizeException::Type, "%d", count);
|
= makeThrowable(t, GcNegativeArraySizeException::Type, "%d", count);
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
@ -952,28 +951,28 @@ interpret3(Thread* t, const int base)
|
|||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
if (objectClass(t, array) == type(t, GcBooleanArray::Type)) {
|
if (objectClass(t, array) == type(t, GcBooleanArray::Type)) {
|
||||||
GcBooleanArray* a = cast<GcBooleanArray>(t, array);
|
GcBooleanArray* a = cast<GcBooleanArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0
|
||||||
static_cast<uintptr_t>(index)
|
and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
< a->length()))
|
|
||||||
{
|
|
||||||
pushInt(t, a->body()[index]);
|
pushInt(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type,
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
"%d not in [0,%d)", index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GcByteArray* a = cast<GcByteArray>(t, array);
|
GcByteArray* a = cast<GcByteArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0
|
||||||
static_cast<uintptr_t>(index)
|
and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
< a->length()))
|
|
||||||
{
|
|
||||||
pushInt(t, a->body()[index]);
|
pushInt(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type,
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
"%d not in [0,%d)", index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -991,27 +990,28 @@ interpret3(Thread* t, const int base)
|
|||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
if (objectClass(t, array) == type(t, GcBooleanArray::Type)) {
|
if (objectClass(t, array) == type(t, GcBooleanArray::Type)) {
|
||||||
GcBooleanArray* a = cast<GcBooleanArray>(t, array);
|
GcBooleanArray* a = cast<GcBooleanArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0
|
||||||
static_cast<uintptr_t>(index)
|
and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
< a->length()))
|
|
||||||
{
|
|
||||||
a->body()[index] = value;
|
a->body()[index] = value;
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type,
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
"%d not in [0,%d)", index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GcByteArray* a = cast<GcByteArray>(t, array);
|
GcByteArray* a = cast<GcByteArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
{
|
|
||||||
a->body()[index] = value;
|
a->body()[index] = value;
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type,
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
"%d not in [0,%d)", index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1031,14 +1031,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcCharArray* a = cast<GcCharArray>(t, array);
|
GcCharArray* a = cast<GcCharArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
pushInt(t, a->body()[index]);
|
pushInt(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1054,14 +1054,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcCharArray* a = cast<GcCharArray>(t, array);
|
GcCharArray* a = cast<GcCharArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
a->body()[index] = value;
|
a->body()[index] = value;
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1078,10 +1078,12 @@ interpret3(Thread* t, const int base)
|
|||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (not instanceOf(t, class_, peekObject(t, sp - 1))) {
|
if (not instanceOf(t, class_, peekObject(t, sp - 1))) {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(
|
||||||
(t, GcClassCastException::Type, "%s as %s",
|
t,
|
||||||
objectClass(t, peekObject(t, sp - 1))->name()->body().begin(),
|
GcClassCastException::Type,
|
||||||
class_->name()->body().begin());
|
"%s as %s",
|
||||||
|
objectClass(t, peekObject(t, sp - 1))->name()->body().begin(),
|
||||||
|
class_->name()->body().begin());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1128,14 +1130,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcDoubleArray* a = cast<GcDoubleArray>(t, array);
|
GcDoubleArray* a = cast<GcDoubleArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
pushLong(t, a->body()[index]);
|
pushLong(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1151,14 +1153,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcDoubleArray* a = cast<GcDoubleArray>(t, array);
|
GcDoubleArray* a = cast<GcDoubleArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
memcpy(&a->body()[index], &value, sizeof(uint64_t));
|
memcpy(&a->body()[index], &value, sizeof(uint64_t));
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1347,14 +1349,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcFloatArray* a = cast<GcFloatArray>(t, array);
|
GcFloatArray* a = cast<GcFloatArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
pushInt(t, a->body()[index]);
|
pushInt(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1370,14 +1372,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcFloatArray* a = cast<GcFloatArray>(t, array);
|
GcFloatArray* a = cast<GcFloatArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
memcpy(&a->body()[index], &value, sizeof(uint32_t));
|
memcpy(&a->body()[index], &value, sizeof(uint32_t));
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1548,14 +1550,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcIntArray* a = cast<GcIntArray>(t, array);
|
GcIntArray* a = cast<GcIntArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
pushInt(t, a->body()[index]);
|
pushInt(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1578,14 +1580,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcIntArray* a = cast<GcIntArray>(t, array);
|
GcIntArray* a = cast<GcIntArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
a->body()[index] = value;
|
a->body()[index] = value;
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1855,8 +1857,8 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
unsigned parameterFootprint = m->parameterFootprint();
|
unsigned parameterFootprint = m->parameterFootprint();
|
||||||
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
||||||
method = findInterfaceMethod
|
method = findInterfaceMethod(
|
||||||
(t, m, objectClass(t, peekObject(t, sp - parameterFootprint)));
|
t, m, objectClass(t, peekObject(t, sp - parameterFootprint)));
|
||||||
goto invoke;
|
goto invoke;
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable(t, GcNullPointerException::Type);
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
||||||
@ -2051,14 +2053,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcLongArray* a = cast<GcLongArray>(t, array);
|
GcLongArray* a = cast<GcLongArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
pushLong(t, a->body()[index]);
|
pushLong(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2081,14 +2083,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcLongArray* a = cast<GcLongArray>(t, array);
|
GcLongArray* a = cast<GcLongArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
a->body()[index] = value;
|
a->body()[index] = value;
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2127,12 +2129,13 @@ interpret3(Thread* t, const int base)
|
|||||||
if (singletonIsObject(t, pool, index - 1)) {
|
if (singletonIsObject(t, pool, index - 1)) {
|
||||||
object v = singletonObject(t, pool, index - 1);
|
object v = singletonObject(t, pool, index - 1);
|
||||||
if (objectClass(t, v) == type(t, GcReference::Type)) {
|
if (objectClass(t, v) == type(t, GcReference::Type)) {
|
||||||
GcClass* class_ = resolveClassInPool
|
GcClass* class_
|
||||||
(t, frameMethod(t, frame), index - 1);
|
= resolveClassInPool(t, frameMethod(t, frame), index - 1);
|
||||||
|
|
||||||
pushObject(t, reinterpret_cast<object>(getJClass(t, class_)));
|
pushObject(t, reinterpret_cast<object>(getJClass(t, class_)));
|
||||||
} else if (objectClass(t, v) == type(t, GcClass::Type)) {
|
} else if (objectClass(t, v) == type(t, GcClass::Type)) {
|
||||||
pushObject(t, reinterpret_cast<object>(getJClass(t, cast<GcClass>(t, v))));
|
pushObject(t,
|
||||||
|
reinterpret_cast<object>(getJClass(t, cast<GcClass>(t, v))));
|
||||||
} else {
|
} else {
|
||||||
pushObject(t, v);
|
pushObject(t, v);
|
||||||
}
|
}
|
||||||
@ -2353,9 +2356,10 @@ interpret3(Thread* t, const int base)
|
|||||||
for (int i = dimensions - 1; i >= 0; --i) {
|
for (int i = dimensions - 1; i >= 0; --i) {
|
||||||
RUNTIME_ARRAY_BODY(counts)[i] = popInt(t);
|
RUNTIME_ARRAY_BODY(counts)[i] = popInt(t);
|
||||||
if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) {
|
if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcNegativeArraySizeException::Type, "%d",
|
GcNegativeArraySizeException::Type,
|
||||||
RUNTIME_ARRAY_BODY(counts)[i]);
|
"%d",
|
||||||
|
RUNTIME_ARRAY_BODY(counts)[i]);
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2426,8 +2430,8 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
pushObject(t, array);
|
pushObject(t, array);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception
|
||||||
(t, GcNegativeArraySizeException::Type, "%d", count);
|
= makeThrowable(t, GcNegativeArraySizeException::Type, "%d", count);
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
@ -2574,8 +2578,7 @@ interpret3(Thread* t, const int base)
|
|||||||
case return_: {
|
case return_: {
|
||||||
GcMethod* method = frameMethod(t, frame);
|
GcMethod* method = frameMethod(t, frame);
|
||||||
if ((method->flags() & ConstructorFlag)
|
if ((method->flags() & ConstructorFlag)
|
||||||
and (method->class_()->vmFlags() & HasFinalMemberFlag))
|
and (method->class_()->vmFlags() & HasFinalMemberFlag)) {
|
||||||
{
|
|
||||||
storeStoreMemoryBarrier();
|
storeStoreMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2593,14 +2596,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcShortArray* a = cast<GcShortArray>(t, array);
|
GcShortArray* a = cast<GcShortArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
pushInt(t, a->body()[index]);
|
pushInt(t, a->body()[index]);
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2616,14 +2619,14 @@ interpret3(Thread* t, const int base)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
GcShortArray* a = cast<GcShortArray>(t, array);
|
GcShortArray* a = cast<GcShortArray>(t, array);
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and static_cast<uintptr_t>(index) < a->length())) {
|
||||||
static_cast<uintptr_t>(index) < a->length()))
|
|
||||||
{
|
|
||||||
a->body()[index] = value;
|
a->body()[index] = value;
|
||||||
} else {
|
} else {
|
||||||
exception = makeThrowable
|
exception = makeThrowable(t,
|
||||||
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
GcArrayIndexOutOfBoundsException::Type,
|
||||||
index, a->length());
|
"%d not in [0,%d)",
|
||||||
|
index,
|
||||||
|
a->length());
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2683,8 +2686,7 @@ interpret3(Thread* t, const int base)
|
|||||||
GcClass* class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
|
GcClass* class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
|
||||||
assertT(t, class_->vmFlags() & BootstrapFlag);
|
assertT(t, class_->vmFlags() & BootstrapFlag);
|
||||||
|
|
||||||
resolveClass(t, frameMethod(t, frame)->class_()->loader(),
|
resolveClass(t, frameMethod(t, frame)->class_()->loader(), class_->name());
|
||||||
class_->name());
|
|
||||||
|
|
||||||
ip -= 3;
|
ip -= 3;
|
||||||
} goto loop;
|
} goto loop;
|
||||||
@ -2693,7 +2695,7 @@ interpret3(Thread* t, const int base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wide:
|
wide:
|
||||||
switch (code->body()[ip++]) {
|
switch (code->body()[ip++]) {
|
||||||
case aload: {
|
case aload: {
|
||||||
pushObject(t, localObject(t, codeReadInt16(t, code, ip)));
|
pushObject(t, localObject(t, codeReadInt16(t, code, ip)));
|
||||||
} goto loop;
|
} goto loop;
|
||||||
@ -2737,8 +2739,8 @@ interpret3(Thread* t, const int base)
|
|||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
invoke: {
|
invoke: {
|
||||||
if (method->flags() & ACC_NATIVE) {
|
if (method->flags() & ACC_NATIVE) {
|
||||||
invokeNative(t, method);
|
invokeNative(t, method);
|
||||||
} else {
|
} else {
|
||||||
checkStack(t, method);
|
checkStack(t, method);
|
||||||
pushFrame(t, method);
|
pushFrame(t, method);
|
||||||
@ -2896,8 +2898,7 @@ pushArguments(Thread* t, object this_, const char* spec, object a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object invoke(Thread* t, GcMethod* method)
|
||||||
invoke(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -2982,8 +2983,9 @@ class MyProcessor: public Processor {
|
|||||||
signals.setCrashDumpDirectory(crashDumpDirectory);
|
signals.setCrashDumpDirectory(crashDumpDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual vm::Thread*
|
virtual vm::Thread* makeThread(Machine* m,
|
||||||
makeThread(Machine* m, GcThread* javaThread, vm::Thread* parent)
|
GcThread* javaThread,
|
||||||
|
vm::Thread* parent)
|
||||||
{
|
{
|
||||||
Thread* t = new (m->heap->allocate(sizeof(Thread) + m->stackSizeInBytes))
|
Thread* t = new (m->heap->allocate(sizeof(Thread) + m->stackSizeInBytes))
|
||||||
Thread(m, javaThread, parent);
|
Thread(m, javaThread, parent);
|
||||||
@ -2991,19 +2993,18 @@ class MyProcessor: public Processor {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcMethod*
|
virtual GcMethod* makeMethod(vm::Thread* t,
|
||||||
makeMethod(vm::Thread* t,
|
uint8_t vmFlags,
|
||||||
uint8_t vmFlags,
|
uint8_t returnCode,
|
||||||
uint8_t returnCode,
|
uint8_t parameterCount,
|
||||||
uint8_t parameterCount,
|
uint8_t parameterFootprint,
|
||||||
uint8_t parameterFootprint,
|
uint16_t flags,
|
||||||
uint16_t flags,
|
uint16_t offset,
|
||||||
uint16_t offset,
|
GcByteArray* name,
|
||||||
GcByteArray* name,
|
GcByteArray* spec,
|
||||||
GcByteArray* spec,
|
GcMethodAddendum* addendum,
|
||||||
GcMethodAddendum* addendum,
|
GcClass* class_,
|
||||||
GcClass* class_,
|
GcCode* code)
|
||||||
GcCode* code)
|
|
||||||
{
|
{
|
||||||
return vm::makeMethod(t,
|
return vm::makeMethod(t,
|
||||||
vmFlags,
|
vmFlags,
|
||||||
@ -3021,26 +3022,25 @@ class MyProcessor: public Processor {
|
|||||||
code);
|
code);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GcClass*
|
virtual GcClass* makeClass(vm::Thread* t,
|
||||||
makeClass(vm::Thread* t,
|
uint16_t flags,
|
||||||
uint16_t flags,
|
uint16_t vmFlags,
|
||||||
uint16_t vmFlags,
|
uint16_t fixedSize,
|
||||||
uint16_t fixedSize,
|
uint8_t arrayElementSize,
|
||||||
uint8_t arrayElementSize,
|
uint8_t arrayDimensions,
|
||||||
uint8_t arrayDimensions,
|
GcClass* arrayElementClass,
|
||||||
GcClass* arrayElementClass,
|
GcIntArray* objectMask,
|
||||||
GcIntArray* objectMask,
|
GcByteArray* name,
|
||||||
GcByteArray* name,
|
GcByteArray* sourceFile,
|
||||||
GcByteArray* sourceFile,
|
GcClass* super,
|
||||||
GcClass* super,
|
object interfaceTable,
|
||||||
object interfaceTable,
|
object virtualTable,
|
||||||
object virtualTable,
|
object fieldTable,
|
||||||
object fieldTable,
|
object methodTable,
|
||||||
object methodTable,
|
GcClassAddendum* addendum,
|
||||||
GcClassAddendum* addendum,
|
GcSingleton* staticTable,
|
||||||
GcSingleton* staticTable,
|
GcClassLoader* loader,
|
||||||
GcClassLoader* loader,
|
unsigned vtableLength UNUSED)
|
||||||
unsigned vtableLength UNUSED)
|
|
||||||
{
|
{
|
||||||
return vm::makeClass(t,
|
return vm::makeClass(t,
|
||||||
flags,
|
flags,
|
||||||
@ -3065,8 +3065,7 @@ class MyProcessor: public Processor {
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void initVtable(vm::Thread*, GcClass*)
|
||||||
initVtable(vm::Thread*, GcClass*)
|
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
@ -3098,8 +3097,7 @@ class MyProcessor: public Processor {
|
|||||||
walker.walk(v);
|
walker.walk(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int
|
virtual int lineNumber(vm::Thread* t, GcMethod* method, int ip)
|
||||||
lineNumber(vm::Thread* t, GcMethod* method, int ip)
|
|
||||||
{
|
{
|
||||||
return findLineNumber(static_cast<Thread*>(t), method, ip);
|
return findLineNumber(static_cast<Thread*>(t), method, ip);
|
||||||
}
|
}
|
||||||
@ -3147,86 +3145,92 @@ class MyProcessor: public Processor {
|
|||||||
t->m->heap->free(f, sizeof(List<unsigned>));
|
t->m->heap->free(f, sizeof(List<unsigned>));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object invokeArray(vm::Thread* vmt,
|
||||||
invokeArray(vm::Thread* vmt, GcMethod* method, object this_, object arguments)
|
GcMethod* method,
|
||||||
|
object this_,
|
||||||
|
object arguments)
|
||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
|
|
||||||
assertT(t, t->state == Thread::ActiveState
|
assertT(
|
||||||
or t->state == Thread::ExclusiveState);
|
t,
|
||||||
|
t->state == Thread::ActiveState or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
if (UNLIKELY(t->sp + method->parameterFootprint() + 1
|
if (UNLIKELY(t->sp + method->parameterFootprint() + 1 > stackSizeInWords(t)
|
||||||
> stackSizeInWords(t) / 2))
|
/ 2)) {
|
||||||
{
|
|
||||||
throwNew(t, GcStackOverflowError::Type);
|
throwNew(t, GcStackOverflowError::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* spec = reinterpret_cast<char*>
|
const char* spec = reinterpret_cast<char*>(method->spec()->body().begin());
|
||||||
(method->spec()->body().begin());
|
|
||||||
pushArguments(t, this_, spec, arguments);
|
pushArguments(t, this_, spec, arguments);
|
||||||
|
|
||||||
return local::invoke(t, method);
|
return local::invoke(t, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object invokeArray(vm::Thread* vmt,
|
||||||
invokeArray(vm::Thread* vmt, GcMethod* method, object this_,
|
GcMethod* method,
|
||||||
const jvalue* arguments)
|
object this_,
|
||||||
|
const jvalue* arguments)
|
||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
|
|
||||||
assertT(t, t->state == Thread::ActiveState
|
assertT(
|
||||||
or t->state == Thread::ExclusiveState);
|
t,
|
||||||
|
t->state == Thread::ActiveState or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
if (UNLIKELY(t->sp + method->parameterFootprint() + 1
|
if (UNLIKELY(t->sp + method->parameterFootprint() + 1 > stackSizeInWords(t)
|
||||||
> stackSizeInWords(t) / 2))
|
/ 2)) {
|
||||||
{
|
|
||||||
throwNew(t, GcStackOverflowError::Type);
|
throwNew(t, GcStackOverflowError::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* spec = reinterpret_cast<char*>
|
const char* spec = reinterpret_cast<char*>(method->spec()->body().begin());
|
||||||
(method->spec()->body().begin());
|
|
||||||
pushArguments(t, this_, spec, arguments);
|
pushArguments(t, this_, spec, arguments);
|
||||||
|
|
||||||
return local::invoke(t, method);
|
return local::invoke(t, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object invokeList(vm::Thread* vmt,
|
||||||
invokeList(vm::Thread* vmt, GcMethod* method, object this_,
|
GcMethod* method,
|
||||||
bool indirectObjects, va_list arguments)
|
object this_,
|
||||||
|
bool indirectObjects,
|
||||||
|
va_list arguments)
|
||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
|
|
||||||
assertT(t, t->state == Thread::ActiveState
|
assertT(
|
||||||
or t->state == Thread::ExclusiveState);
|
t,
|
||||||
|
t->state == Thread::ActiveState or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
if (UNLIKELY(t->sp + method->parameterFootprint() + 1
|
if (UNLIKELY(t->sp + method->parameterFootprint() + 1 > stackSizeInWords(t)
|
||||||
> stackSizeInWords(t) / 2))
|
/ 2)) {
|
||||||
{
|
|
||||||
throwNew(t, GcStackOverflowError::Type);
|
throwNew(t, GcStackOverflowError::Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* spec = reinterpret_cast<char*>
|
const char* spec = reinterpret_cast<char*>(method->spec()->body().begin());
|
||||||
(method->spec()->body().begin());
|
|
||||||
pushArguments(t, this_, spec, indirectObjects, arguments);
|
pushArguments(t, this_, spec, indirectObjects, arguments);
|
||||||
|
|
||||||
return local::invoke(t, method);
|
return local::invoke(t, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object invokeList(vm::Thread* vmt,
|
||||||
invokeList(vm::Thread* vmt, GcClassLoader* loader, const char* className,
|
GcClassLoader* loader,
|
||||||
const char* methodName, const char* methodSpec, object this_,
|
const char* className,
|
||||||
va_list arguments)
|
const char* methodName,
|
||||||
|
const char* methodSpec,
|
||||||
|
object this_,
|
||||||
|
va_list arguments)
|
||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
|
|
||||||
assertT(t, t->state == Thread::ActiveState
|
assertT(
|
||||||
or t->state == Thread::ExclusiveState);
|
t,
|
||||||
|
t->state == Thread::ActiveState or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false)
|
if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false)
|
||||||
> stackSizeInWords(t) / 2))
|
> stackSizeInWords(t) / 2))
|
||||||
@ -3236,8 +3240,8 @@ class MyProcessor: public Processor {
|
|||||||
|
|
||||||
pushArguments(t, this_, methodSpec, false, arguments);
|
pushArguments(t, this_, methodSpec, false, arguments);
|
||||||
|
|
||||||
GcMethod* method = resolveMethod
|
GcMethod* method
|
||||||
(t, loader, className, methodName, methodSpec);
|
= resolveMethod(t, loader, className, methodName, methodSpec);
|
||||||
|
|
||||||
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
@ -3258,8 +3262,13 @@ class MyProcessor: public Processor {
|
|||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void compileMethod(vm::Thread*, Zone*, GcTriple**, GcTriple**,
|
virtual void compileMethod(vm::Thread*,
|
||||||
avian::codegen::DelayedPromise**, GcMethod*, OffsetResolver*)
|
Zone*,
|
||||||
|
GcTriple**,
|
||||||
|
GcTriple**,
|
||||||
|
avian::codegen::DelayedPromise**,
|
||||||
|
GcMethod*,
|
||||||
|
OffsetResolver*)
|
||||||
{
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
@ -3288,11 +3297,15 @@ class MyProcessor: public Processor {
|
|||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void feedResultToContinuation(vm::Thread*, GcContinuation*, object){
|
virtual void feedResultToContinuation(vm::Thread*, GcContinuation*, object)
|
||||||
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void feedExceptionToContinuation(vm::Thread*, GcContinuation*, GcThrowable*) {
|
virtual void feedExceptionToContinuation(vm::Thread*,
|
||||||
|
GcContinuation*,
|
||||||
|
GcThrowable*)
|
||||||
|
{
|
||||||
abort(s);
|
abort(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
253
src/jnienv.cpp
253
src/jnienv.cpp
@ -150,8 +150,8 @@ GetStringChars(Thread* t, jstring s, jboolean* isCopy)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
jchar* chars = static_cast<jchar*>
|
jchar* chars = static_cast<jchar*>(
|
||||||
(t->m->heap->allocate(((*s)->length(t) + 1) * sizeof(jchar)));
|
t->m->heap->allocate(((*s)->length(t) + 1) * sizeof(jchar)));
|
||||||
stringChars(t, *s, chars);
|
stringChars(t, *s, chars);
|
||||||
|
|
||||||
if (isCopy) *isCopy = true;
|
if (isCopy) *isCopy = true;
|
||||||
@ -266,9 +266,7 @@ newString(Thread* t, uintptr_t* arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return reinterpret_cast<uint64_t>(
|
return reinterpret_cast<uint64_t>(
|
||||||
makeLocalReference(t,
|
makeLocalReference(t, t->m->classpath->makeString(t, a, 0, size)));
|
||||||
t->m->classpath->makeString(
|
|
||||||
t, a, 0, size)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring JNICALL
|
jstring JNICALL
|
||||||
@ -325,14 +323,14 @@ defineClass(Thread* t, uintptr_t* arguments)
|
|||||||
|
|
||||||
return reinterpret_cast<uint64_t>(makeLocalReference(
|
return reinterpret_cast<uint64_t>(makeLocalReference(
|
||||||
t,
|
t,
|
||||||
getJClass(t,
|
getJClass(
|
||||||
cast<GcClass>(
|
t,
|
||||||
t,
|
cast<GcClass>(t,
|
||||||
defineClass(t,
|
defineClass(t,
|
||||||
loader ? cast<GcClassLoader>(t, *loader)
|
loader ? cast<GcClassLoader>(t, *loader)
|
||||||
: roots(t)->bootLoader(),
|
: roots(t)->bootLoader(),
|
||||||
buffer,
|
buffer,
|
||||||
length)))));
|
length)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass JNICALL
|
jclass JNICALL
|
||||||
@ -456,8 +454,8 @@ getObjectClass(Thread* t, uintptr_t* arguments)
|
|||||||
{
|
{
|
||||||
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
jobject o = reinterpret_cast<jobject>(arguments[0]);
|
||||||
|
|
||||||
return reinterpret_cast<uint64_t>(makeLocalReference(
|
return reinterpret_cast<uint64_t>(
|
||||||
t, getJClass(t, objectClass(t, *o))));
|
makeLocalReference(t, getJClass(t, objectClass(t, *o))));
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass JNICALL
|
jclass JNICALL
|
||||||
@ -525,8 +523,7 @@ IsAssignableFrom(Thread* t, jclass b, jclass a)
|
|||||||
return run(t, isAssignableFrom, arguments);
|
return run(t, isAssignableFrom, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcMethod*
|
GcMethod* findMethod(Thread* t, jclass c, const char* name, const char* spec)
|
||||||
findMethod(Thread* t, jclass c, const char* name, const char* spec)
|
|
||||||
{
|
{
|
||||||
GcByteArray* n = makeByteArray(t, "%s", name);
|
GcByteArray* n = makeByteArray(t, "%s", name);
|
||||||
PROTECT(t, n);
|
PROTECT(t, n);
|
||||||
@ -535,8 +532,7 @@ findMethod(Thread* t, jclass c, const char* name, const char* spec)
|
|||||||
return vm::findMethod(t, (*c)->vmClass(), n, s);
|
return vm::findMethod(t, (*c)->vmClass(), n, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint methodID(Thread* t, GcMethod* method)
|
||||||
methodID(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
int id = method->nativeID();
|
int id = method->nativeID();
|
||||||
|
|
||||||
@ -548,8 +544,7 @@ methodID(Thread* t, GcMethod* method)
|
|||||||
ACQUIRE(t, t->m->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
if (method->nativeID() == 0) {
|
if (method->nativeID() == 0) {
|
||||||
GcVector* v = vectorAppend(
|
GcVector* v = vectorAppend(t, roots(t)->jNIMethodTable(), method);
|
||||||
t, roots(t)->jNIMethodTable(), method);
|
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
roots(t)->setJNIMethodTable(t, v);
|
roots(t)->setJNIMethodTable(t, v);
|
||||||
|
|
||||||
@ -610,12 +605,12 @@ GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
|||||||
return run(t, getStaticMethodID, arguments);
|
return run(t, getStaticMethodID, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcMethod*
|
GcMethod* getMethod(Thread* t, jmethodID m)
|
||||||
getMethod(Thread* t, jmethodID m)
|
|
||||||
{
|
{
|
||||||
assertT(t, m);
|
assertT(t, m);
|
||||||
|
|
||||||
GcMethod* method = cast<GcMethod>(t, roots(t)->jNIMethodTable()->body()[m - 1]);
|
GcMethod* method
|
||||||
|
= cast<GcMethod>(t, roots(t)->jNIMethodTable()->body()[m - 1]);
|
||||||
|
|
||||||
assertT(t, (method->flags() & ACC_STATIC) == 0);
|
assertT(t, (method->flags() & ACC_STATIC) == 0);
|
||||||
|
|
||||||
@ -675,12 +670,10 @@ newObjectA(Thread* t, uintptr_t* arguments)
|
|||||||
return reinterpret_cast<uint64_t>(makeLocalReference(t, o));
|
return reinterpret_cast<uint64_t>(makeLocalReference(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject JNICALL
|
jobject JNICALL NewObjectA(Thread* t, jclass c, jmethodID m, const jvalue* a)
|
||||||
NewObjectA(Thread* t, jclass c, jmethodID m, const jvalue* a)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[]
|
||||||
m,
|
= {reinterpret_cast<uintptr_t>(c), m, reinterpret_cast<uintptr_t>(a)};
|
||||||
reinterpret_cast<uintptr_t>(a) };
|
|
||||||
|
|
||||||
return reinterpret_cast<jobject>(run(t, newObjectA, arguments));
|
return reinterpret_cast<jobject>(run(t, newObjectA, arguments));
|
||||||
}
|
}
|
||||||
@ -749,8 +742,9 @@ callIntMethodV(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[1];
|
jmethodID m = arguments[1];
|
||||||
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
|
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
|
||||||
|
|
||||||
return cast<GcInt>
|
return cast<GcInt>(
|
||||||
(t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))->value();
|
t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))
|
||||||
|
->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -783,8 +777,8 @@ callIntMethodA(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[1];
|
jmethodID m = arguments[1];
|
||||||
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
||||||
|
|
||||||
return cast<GcInt>
|
return cast<GcInt>(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a))
|
||||||
(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a))->value();
|
->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -936,8 +930,9 @@ callLongMethodV(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[1];
|
jmethodID m = arguments[1];
|
||||||
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
|
va_list* a = reinterpret_cast<va_list*>(arguments[2]);
|
||||||
|
|
||||||
return cast<GcLong>
|
return cast<GcLong>(
|
||||||
(t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))->value();
|
t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))
|
||||||
|
->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong JNICALL
|
jlong JNICALL
|
||||||
@ -970,8 +965,9 @@ callLongMethodA(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[1];
|
jmethodID m = arguments[1];
|
||||||
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[2]);
|
||||||
|
|
||||||
return cast<GcLong>
|
return cast<GcLong>(t,
|
||||||
(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a))->value();
|
t->m->processor->invokeArray(t, getMethod(t, m), *o, a))
|
||||||
|
->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong JNICALL
|
jlong JNICALL
|
||||||
@ -1105,12 +1101,12 @@ CallVoidMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a)
|
|||||||
run(t, callVoidMethodA, arguments);
|
run(t, callVoidMethodA, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcMethod*
|
GcMethod* getStaticMethod(Thread* t, jmethodID m)
|
||||||
getStaticMethod(Thread* t, jmethodID m)
|
|
||||||
{
|
{
|
||||||
assertT(t, m);
|
assertT(t, m);
|
||||||
|
|
||||||
GcMethod* method = cast<GcMethod>(t, roots(t)->jNIMethodTable()->body()[m - 1]);
|
GcMethod* method
|
||||||
|
= cast<GcMethod>(t, roots(t)->jNIMethodTable()->body()[m - 1]);
|
||||||
|
|
||||||
assertT(t, method->flags() & ACC_STATIC);
|
assertT(t, method->flags() & ACC_STATIC);
|
||||||
|
|
||||||
@ -1174,8 +1170,9 @@ callStaticIntMethodV(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[0];
|
jmethodID m = arguments[0];
|
||||||
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
|
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
|
||||||
|
|
||||||
return cast<GcInt>
|
return cast<GcInt>(t,
|
||||||
(t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a))->value();
|
t->m->processor->invokeList(
|
||||||
|
t, getStaticMethod(t, m), 0, true, *a))->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -1205,8 +1202,9 @@ callStaticIntMethodA(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[0];
|
jmethodID m = arguments[0];
|
||||||
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
|
||||||
|
|
||||||
return cast<GcInt>
|
return cast<GcInt>(
|
||||||
(t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))->value();
|
t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))
|
||||||
|
->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -1339,8 +1337,9 @@ callStaticLongMethodV(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[0];
|
jmethodID m = arguments[0];
|
||||||
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
|
va_list* a = reinterpret_cast<va_list*>(arguments[1]);
|
||||||
|
|
||||||
return cast<GcLong>
|
return cast<GcLong>(t,
|
||||||
(t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a))->value();
|
t->m->processor->invokeList(
|
||||||
|
t, getStaticMethod(t, m), 0, true, *a))->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong JNICALL
|
jlong JNICALL
|
||||||
@ -1370,8 +1369,9 @@ callStaticLongMethodA(Thread* t, uintptr_t* arguments)
|
|||||||
jmethodID m = arguments[0];
|
jmethodID m = arguments[0];
|
||||||
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
|
const jvalue* a = reinterpret_cast<const jvalue*>(arguments[1]);
|
||||||
|
|
||||||
return cast<GcLong>
|
return cast<GcLong>(
|
||||||
(t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))->value();
|
t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))
|
||||||
|
->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong JNICALL
|
jlong JNICALL
|
||||||
@ -1489,8 +1489,7 @@ CallStaticVoidMethodA(Thread* t, jclass, jmethodID m, const jvalue* a)
|
|||||||
run(t, callStaticVoidMethodA, arguments);
|
run(t, callStaticVoidMethodA, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint fieldID(Thread* t, GcField* field)
|
||||||
fieldID(Thread* t, GcField* field)
|
|
||||||
{
|
{
|
||||||
int id = field->nativeID();
|
int id = field->nativeID();
|
||||||
|
|
||||||
@ -1502,8 +1501,7 @@ fieldID(Thread* t, GcField* field)
|
|||||||
ACQUIRE(t, t->m->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
if (field->nativeID() == 0) {
|
if (field->nativeID() == 0) {
|
||||||
GcVector* v = vectorAppend(
|
GcVector* v = vectorAppend(t, roots(t)->jNIFieldTable(), field);
|
||||||
t, roots(t)->jNIFieldTable(), field);
|
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
roots(t)->setJNIFieldTable(t, v);
|
roots(t)->setJNIFieldTable(t, v);
|
||||||
|
|
||||||
@ -1546,8 +1544,7 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
|||||||
return run(t, getFieldID, arguments);
|
return run(t, getFieldID, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcField*
|
GcField* getField(Thread* t, jfieldID f)
|
||||||
getField(Thread* t, jfieldID f)
|
|
||||||
{
|
{
|
||||||
assertT(t, f);
|
assertT(t, f);
|
||||||
|
|
||||||
@ -1567,8 +1564,8 @@ getObjectField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return reinterpret_cast<uintptr_t>
|
return reinterpret_cast<uintptr_t>(
|
||||||
(makeLocalReference(t, fieldAtOffset<object>(*o, field->offset())));
|
makeLocalReference(t, fieldAtOffset<object>(*o, field->offset())));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject JNICALL
|
jobject JNICALL
|
||||||
@ -1975,8 +1972,7 @@ SetDoubleField(Thread* t, jobject o, jfieldID field, jdouble v)
|
|||||||
run(t, setDoubleField, arguments);
|
run(t, setDoubleField, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcField*
|
GcField* getStaticField(Thread* t, jfieldID f)
|
||||||
getStaticField(Thread* t, jfieldID f)
|
|
||||||
{
|
{
|
||||||
assertT(t, f);
|
assertT(t, f);
|
||||||
|
|
||||||
@ -1999,14 +1995,11 @@ getStaticObjectField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return reinterpret_cast<uintptr_t>
|
return reinterpret_cast<uintptr_t>(makeLocalReference(
|
||||||
(makeLocalReference
|
t, fieldAtOffset<object>(c->vmClass()->staticTable(), field->offset())));
|
||||||
(t, fieldAtOffset<object>
|
|
||||||
(c->vmClass()->staticTable(), field->offset())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject JNICALL
|
jobject JNICALL GetStaticObjectField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticObjectField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2026,12 +2019,10 @@ getStaticBooleanField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return fieldAtOffset<jboolean>
|
return fieldAtOffset<jboolean>(c->vmClass()->staticTable(), field->offset());
|
||||||
(c->vmClass()->staticTable(), field->offset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL GetStaticBooleanField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticBooleanField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2051,12 +2042,10 @@ getStaticByteField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return fieldAtOffset<jbyte>
|
return fieldAtOffset<jbyte>(c->vmClass()->staticTable(), field->offset());
|
||||||
(c->vmClass()->staticTable(), field->offset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jbyte JNICALL
|
jbyte JNICALL GetStaticByteField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticByteField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2076,12 +2065,10 @@ getStaticCharField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return fieldAtOffset<jchar>
|
return fieldAtOffset<jchar>(c->vmClass()->staticTable(), field->offset());
|
||||||
(c->vmClass()->staticTable(), field->offset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jchar JNICALL
|
jchar JNICALL GetStaticCharField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticCharField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2101,12 +2088,10 @@ getStaticShortField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return fieldAtOffset<jshort>
|
return fieldAtOffset<jshort>(c->vmClass()->staticTable(), field->offset());
|
||||||
(c->vmClass()->staticTable(), field->offset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jshort JNICALL
|
jshort JNICALL GetStaticShortField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticShortField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2126,12 +2111,10 @@ getStaticIntField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return fieldAtOffset<jint>
|
return fieldAtOffset<jint>(c->vmClass()->staticTable(), field->offset());
|
||||||
(c->vmClass()->staticTable(), field->offset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jint JNICALL
|
jint JNICALL GetStaticIntField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticIntField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2151,12 +2134,10 @@ getStaticLongField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return fieldAtOffset<jlong>
|
return fieldAtOffset<jlong>(c->vmClass()->staticTable(), field->offset());
|
||||||
(c->vmClass()->staticTable(), field->offset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong JNICALL
|
jlong JNICALL GetStaticLongField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticLongField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2176,13 +2157,11 @@ getStaticFloatField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return floatToBits
|
return floatToBits(
|
||||||
(fieldAtOffset<jfloat>
|
fieldAtOffset<jfloat>(c->vmClass()->staticTable(), field->offset()));
|
||||||
(c->vmClass()->staticTable(), field->offset()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jfloat JNICALL
|
jfloat JNICALL GetStaticFloatField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticFloatField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2202,13 +2181,11 @@ getStaticDoubleField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_READ(t, field);
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
||||||
|
|
||||||
return doubleToBits
|
return doubleToBits(
|
||||||
(fieldAtOffset<jdouble>
|
fieldAtOffset<jdouble>(c->vmClass()->staticTable(), field->offset()));
|
||||||
(c->vmClass()->staticTable(), field->offset()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jdouble JNICALL
|
jdouble JNICALL GetStaticDoubleField(Thread* t, jclass c, jfieldID field)
|
||||||
GetStaticDoubleField(Thread* t, jclass c, jfieldID field)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field };
|
field };
|
||||||
@ -2229,14 +2206,13 @@ setStaticObjectField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
setField(t, c->vmClass()->staticTable(), field->offset(),
|
setField(t, c->vmClass()->staticTable(), field->offset(), (v ? *v : 0));
|
||||||
(v ? *v : 0));
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v)
|
SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v)
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field,
|
field,
|
||||||
@ -2258,14 +2234,13 @@ setStaticBooleanField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jboolean>
|
fieldAtOffset<jboolean>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v)
|
SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v)
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field,
|
field,
|
||||||
@ -2287,14 +2262,12 @@ setStaticByteField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jbyte>
|
fieldAtOffset<jbyte>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v)
|
||||||
SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field,
|
field,
|
||||||
@ -2316,14 +2289,12 @@ setStaticCharField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jchar>
|
fieldAtOffset<jchar>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v)
|
||||||
SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field,
|
field,
|
||||||
@ -2345,14 +2316,12 @@ setStaticShortField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jshort>
|
fieldAtOffset<jshort>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v)
|
||||||
SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field,
|
field,
|
||||||
@ -2374,14 +2343,12 @@ setStaticIntField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jint>
|
fieldAtOffset<jint>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v)
|
||||||
SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field,
|
field,
|
||||||
@ -2403,14 +2370,12 @@ setStaticLongField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jlong>
|
fieldAtOffset<jlong>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v)
|
||||||
SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[2 + (sizeof(jlong) / BytesPerWord)];
|
uintptr_t arguments[2 + (sizeof(jlong) / BytesPerWord)];
|
||||||
arguments[0] = reinterpret_cast<uintptr_t>(c);
|
arguments[0] = reinterpret_cast<uintptr_t>(c);
|
||||||
@ -2433,14 +2398,12 @@ setStaticFloatField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jfloat>
|
fieldAtOffset<jfloat>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v)
|
||||||
SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v)
|
|
||||||
{
|
{
|
||||||
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(c),
|
||||||
field,
|
field,
|
||||||
@ -2462,14 +2425,13 @@ setStaticDoubleField(Thread* t, uintptr_t* arguments)
|
|||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
||||||
|
|
||||||
fieldAtOffset<jdouble>
|
fieldAtOffset<jdouble>(c->vmClass()->staticTable(), field->offset()) = v;
|
||||||
(c->vmClass()->staticTable(), field->offset()) = v;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v)
|
SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v)
|
||||||
{
|
{
|
||||||
uintptr_t arguments[2 + (sizeof(jdouble) / BytesPerWord)];
|
uintptr_t arguments[2 + (sizeof(jdouble) / BytesPerWord)];
|
||||||
arguments[0] = reinterpret_cast<uintptr_t>(c);
|
arguments[0] = reinterpret_cast<uintptr_t>(c);
|
||||||
@ -2596,7 +2558,8 @@ GetObjectArrayElement(Thread* t, jobjectArray array, jsize index)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return makeLocalReference(t, objectArrayBody(t, reinterpret_cast<object>(*array), index));
|
return makeLocalReference(
|
||||||
|
t, objectArrayBody(t, reinterpret_cast<object>(*array), index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -2605,7 +2568,10 @@ SetObjectArrayElement(Thread* t, jobjectArray array, jsize index,
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
setField(t, reinterpret_cast<object>(*array), ArrayBody + (index * BytesPerWord), (value ? *value : 0));
|
setField(t,
|
||||||
|
reinterpret_cast<object>(*array),
|
||||||
|
ArrayBody + (index * BytesPerWord),
|
||||||
|
(value ? *value : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
@ -3003,8 +2969,7 @@ GetBooleanArrayRegion(Thread* t, jbooleanArray array, jint offset, jint length,
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
if (length) {
|
if (length) {
|
||||||
memcpy(dst, &(*array)->body()[offset],
|
memcpy(dst, &(*array)->body()[offset], length * sizeof(jboolean));
|
||||||
length * sizeof(jboolean));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3092,8 +3057,7 @@ SetBooleanArrayRegion(Thread* t, jbooleanArray array, jint offset, jint length,
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
if (length) {
|
if (length) {
|
||||||
memcpy(&(*array)->body()[offset], src,
|
memcpy(&(*array)->body()[offset], src, length * sizeof(jboolean));
|
||||||
length * sizeof(jboolean));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3291,15 +3255,16 @@ registerNatives(Thread* t, uintptr_t* arguments)
|
|||||||
const char* sig = methods[i].signature;
|
const char* sig = methods[i].signature;
|
||||||
if (*sig == '!') ++ sig;
|
if (*sig == '!') ++ sig;
|
||||||
|
|
||||||
GcMethod* method = findMethodOrNull
|
GcMethod* method
|
||||||
(t, (*c)->vmClass(), methods[i].name, sig);
|
= findMethodOrNull(t, (*c)->vmClass(), methods[i].name, sig);
|
||||||
|
|
||||||
if (method == 0 or (method->flags() & ACC_NATIVE) == 0) {
|
if (method == 0 or (method->flags() & ACC_NATIVE) == 0) {
|
||||||
// The JNI spec says we must throw a NoSuchMethodError in this
|
// The JNI spec says we must throw a NoSuchMethodError in this
|
||||||
// case, but that would prevent using a code shrinker like
|
// case, but that would prevent using a code shrinker like
|
||||||
// ProGuard effectively. Instead, we just ignore it.
|
// ProGuard effectively. Instead, we just ignore it.
|
||||||
|
|
||||||
// fprintf(stderr, "not found: %s.%s%s\n", &byteArrayBody(t, className(t, (*c)->vmClass()), 0), methods[i].name, sig);
|
// fprintf(stderr, "not found: %s.%s%s\n", &byteArrayBody(t,
|
||||||
|
// className(t, (*c)->vmClass()), 0), methods[i].name, sig);
|
||||||
// abort(t);
|
// abort(t);
|
||||||
} else {
|
} else {
|
||||||
registerNative(t, method, methods[i].function);
|
registerNative(t, method, methods[i].function);
|
||||||
@ -3578,9 +3543,11 @@ boot(Thread* t, uintptr_t*)
|
|||||||
GcString* host = makeString(t, "0.0.0.0");
|
GcString* host = makeString(t, "0.0.0.0");
|
||||||
PROTECT(t, host);
|
PROTECT(t, host);
|
||||||
|
|
||||||
GcMethod* method = resolveMethod
|
GcMethod* method = resolveMethod(t,
|
||||||
(t, roots(t)->bootLoader(), "avian/Traces", "startTraceListener",
|
roots(t)->bootLoader(),
|
||||||
"(Ljava/lang/String;I)V");
|
"avian/Traces",
|
||||||
|
"startTraceListener",
|
||||||
|
"(Ljava/lang/String;I)V");
|
||||||
|
|
||||||
t->m->processor->invoke(t, method, 0, host, atoi(port));
|
t->m->processor->invoke(t, method, 0, host, atoi(port));
|
||||||
}
|
}
|
||||||
|
1493
src/machine.cpp
1493
src/machine.cpp
File diff suppressed because it is too large
Load Diff
@ -66,8 +66,7 @@ mangle(int8_t c, char* dst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned jniNameLength(Thread* t UNUSED, GcMethod* method, bool decorate)
|
||||||
jniNameLength(Thread* t UNUSED, GcMethod* method, bool decorate)
|
|
||||||
{
|
{
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
|
|
||||||
@ -87,9 +86,9 @@ jniNameLength(Thread* t UNUSED, GcMethod* method, bool decorate)
|
|||||||
size += 2;
|
size += 2;
|
||||||
|
|
||||||
GcByteArray* methodSpec = method->spec();
|
GcByteArray* methodSpec = method->spec();
|
||||||
for (unsigned i = 1; i < methodSpec->length() - 1
|
for (unsigned i = 1;
|
||||||
and methodSpec->body()[i] != ')'; ++i)
|
i < methodSpec->length() - 1 and methodSpec->body()[i] != ')';
|
||||||
{
|
++i) {
|
||||||
size += mangledSize(methodSpec->body()[i]);
|
size += mangledSize(methodSpec->body()[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,9 +96,12 @@ jniNameLength(Thread* t UNUSED, GcMethod* method, bool decorate)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void makeJNIName(Thread* t UNUSED,
|
||||||
makeJNIName(Thread* t UNUSED, const char* prefix, unsigned prefixLength, char* name,
|
const char* prefix,
|
||||||
GcMethod* method, bool decorate)
|
unsigned prefixLength,
|
||||||
|
char* name,
|
||||||
|
GcMethod* method,
|
||||||
|
bool decorate)
|
||||||
{
|
{
|
||||||
memcpy(name, prefix, prefixLength);
|
memcpy(name, prefix, prefixLength);
|
||||||
name += prefixLength;
|
name += prefixLength;
|
||||||
@ -121,9 +123,9 @@ makeJNIName(Thread* t UNUSED, const char* prefix, unsigned prefixLength, char* n
|
|||||||
*(name++) = '_';
|
*(name++) = '_';
|
||||||
|
|
||||||
GcByteArray* methodSpec = method->spec();
|
GcByteArray* methodSpec = method->spec();
|
||||||
for (unsigned i = 1; i < methodSpec->length() - 1
|
for (unsigned i = 1;
|
||||||
and methodSpec->body()[i] != ')'; ++i)
|
i < methodSpec->length() - 1 and methodSpec->body()[i] != ')';
|
||||||
{
|
++i) {
|
||||||
name += mangle(methodSpec->body()[i], name);
|
name += mangle(methodSpec->body()[i], name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,9 +151,11 @@ resolveNativeMethod(Thread* t, const char* undecorated, const char* decorated)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void* resolveNativeMethod(Thread* t,
|
||||||
resolveNativeMethod(Thread* t, GcMethod* method, const char* prefix,
|
GcMethod* method,
|
||||||
unsigned prefixLength, int footprint UNUSED)
|
const char* prefix,
|
||||||
|
unsigned prefixLength,
|
||||||
|
int footprint UNUSED)
|
||||||
{
|
{
|
||||||
unsigned undecoratedSize = prefixLength + jniNameLength(t, method, false);
|
unsigned undecoratedSize = prefixLength + jniNameLength(t, method, false);
|
||||||
// extra 6 is for code below:
|
// extra 6 is for code below:
|
||||||
@ -205,8 +209,7 @@ resolveNativeMethod(Thread* t, GcMethod* method, const char* prefix,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcNative*
|
GcNative* resolveNativeMethod(Thread* t, GcMethod* method)
|
||||||
resolveNativeMethod(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
void* p = resolveNativeMethod(t, method, "Avian_", 6, 3);
|
void* p = resolveNativeMethod(t, method, "Avian_", 6, 3);
|
||||||
if (p) {
|
if (p) {
|
||||||
@ -225,8 +228,7 @@ resolveNativeMethod(Thread* t, GcMethod* method)
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
void
|
void resolveNative(Thread* t, GcMethod* method)
|
||||||
resolveNative(Thread* t, GcMethod* method)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
@ -237,7 +239,9 @@ resolveNative(Thread* t, GcMethod* method)
|
|||||||
if (getMethodRuntimeData(t, method)->native() == 0) {
|
if (getMethodRuntimeData(t, method)->native() == 0) {
|
||||||
GcNative* native = resolveNativeMethod(t, method);
|
GcNative* native = resolveNativeMethod(t, method);
|
||||||
if (UNLIKELY(native == 0)) {
|
if (UNLIKELY(native == 0)) {
|
||||||
throwNew(t, GcUnsatisfiedLinkError::Type, "%s.%s%s",
|
throwNew(t,
|
||||||
|
GcUnsatisfiedLinkError::Type,
|
||||||
|
"%s.%s%s",
|
||||||
method->class_()->name()->body().begin(),
|
method->class_()->name()->body().begin(),
|
||||||
method->name()->body().begin(),
|
method->name()->body().begin(),
|
||||||
method->spec()->body().begin());
|
method->spec()->body().begin());
|
||||||
@ -255,8 +259,7 @@ resolveNative(Thread* t, GcMethod* method)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int findLineNumber(Thread* t UNUSED, GcMethod* method, unsigned ip)
|
||||||
findLineNumber(Thread* t UNUSED, GcMethod* method, unsigned ip)
|
|
||||||
{
|
{
|
||||||
if (method->flags() & ACC_NATIVE) {
|
if (method->flags() & ACC_NATIVE) {
|
||||||
return NativeLine;
|
return NativeLine;
|
||||||
@ -276,8 +279,7 @@ findLineNumber(Thread* t UNUSED, GcMethod* method, unsigned ip)
|
|||||||
|
|
||||||
if (ip >= lineNumberIp(ln)
|
if (ip >= lineNumberIp(ln)
|
||||||
and (middle + 1 == lnt->length()
|
and (middle + 1 == lnt->length()
|
||||||
or ip < lineNumberIp(lnt->body()[middle + 1])))
|
or ip < lineNumberIp(lnt->body()[middle + 1]))) {
|
||||||
{
|
|
||||||
return lineNumberLine(ln);
|
return lineNumberLine(ln);
|
||||||
} else if (ip < lineNumberIp(ln)) {
|
} else if (ip < lineNumberIp(ln)) {
|
||||||
top = middle;
|
top = middle;
|
||||||
|
@ -175,23 +175,29 @@ endsWith(const char* suffix, const char* s, unsigned length)
|
|||||||
and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
|
and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcVector*
|
GcVector* getNonStaticFields(Thread* t,
|
||||||
getNonStaticFields(Thread* t, GcHashMap* typeMaps, GcClass* c, GcVector* fields,
|
GcHashMap* typeMaps,
|
||||||
unsigned* count, GcByteArray** array)
|
GcClass* c,
|
||||||
|
GcVector* fields,
|
||||||
|
unsigned* count,
|
||||||
|
GcByteArray** array)
|
||||||
{
|
{
|
||||||
PROTECT(t, typeMaps);
|
PROTECT(t, typeMaps);
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
PROTECT(t, fields);
|
PROTECT(t, fields);
|
||||||
|
|
||||||
*array = cast<GcByteArray>(t, hashMapFind(t, typeMaps, reinterpret_cast<object>(c), objectHash, objectEqual));
|
*array = cast<GcByteArray>(
|
||||||
|
t,
|
||||||
|
hashMapFind(
|
||||||
|
t, typeMaps, reinterpret_cast<object>(c), objectHash, objectEqual));
|
||||||
|
|
||||||
if (*array) {
|
if (*array) {
|
||||||
*count += reinterpret_cast<TypeMap*>((*array)->body().begin())
|
*count += reinterpret_cast<TypeMap*>((*array)->body().begin())
|
||||||
->fixedFieldCount;
|
->fixedFieldCount;
|
||||||
} else {
|
} else {
|
||||||
if (c->super()) {
|
if (c->super()) {
|
||||||
fields = getNonStaticFields
|
fields
|
||||||
(t, typeMaps, c->super(), fields, count, array);
|
= getNonStaticFields(t, typeMaps, c->super(), fields, count, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GcArray* ftable = cast<GcArray>(t, c->fieldTable())) {
|
if (GcArray* ftable = cast<GcArray>(t, c->fieldTable())) {
|
||||||
@ -210,8 +216,11 @@ getNonStaticFields(Thread* t, GcHashMap* typeMaps, GcClass* c, GcVector* fields,
|
|||||||
return vectorAppend(t, fields, 0);
|
return vectorAppend(t, fields, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcVector*
|
GcVector* allFields(Thread* t,
|
||||||
allFields(Thread* t, GcHashMap* typeMaps, GcClass* c, unsigned* count, GcByteArray** array)
|
GcHashMap* typeMaps,
|
||||||
|
GcClass* c,
|
||||||
|
unsigned* count,
|
||||||
|
GcByteArray** array)
|
||||||
{
|
{
|
||||||
PROTECT(t, typeMaps);
|
PROTECT(t, typeMaps);
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
@ -219,18 +228,21 @@ allFields(Thread* t, GcHashMap* typeMaps, GcClass* c, unsigned* count, GcByteArr
|
|||||||
GcVector* fields = makeVector(t, 0, 0);
|
GcVector* fields = makeVector(t, 0, 0);
|
||||||
PROTECT(t, fields);
|
PROTECT(t, fields);
|
||||||
|
|
||||||
*array = cast<GcByteArray>(t, hashMapFind(t, typeMaps, reinterpret_cast<object>(c), objectHash, objectEqual));
|
*array = cast<GcByteArray>(
|
||||||
|
t,
|
||||||
|
hashMapFind(
|
||||||
|
t, typeMaps, reinterpret_cast<object>(c), objectHash, objectEqual));
|
||||||
|
|
||||||
bool includeMembers;
|
bool includeMembers;
|
||||||
if (*array) {
|
if (*array) {
|
||||||
includeMembers = false;
|
includeMembers = false;
|
||||||
*count += reinterpret_cast<TypeMap*>((*array)->body().begin())
|
*count += reinterpret_cast<TypeMap*>((*array)->body().begin())
|
||||||
->fixedFieldCount;
|
->fixedFieldCount;
|
||||||
} else {
|
} else {
|
||||||
includeMembers = true;
|
includeMembers = true;
|
||||||
if (c->super()) {
|
if (c->super()) {
|
||||||
fields = getNonStaticFields
|
fields
|
||||||
(t, typeMaps, c->super(), fields, count, array);
|
= getNonStaticFields(t, typeMaps, c->super(), fields, count, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,41 +261,54 @@ allFields(Thread* t, GcHashMap* typeMaps, GcClass* c, unsigned* count, GcByteArr
|
|||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeMap*
|
TypeMap* classTypeMap(Thread* t, GcHashMap* typeMaps, object p)
|
||||||
classTypeMap(Thread* t, GcHashMap* typeMaps, object p)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<TypeMap*>
|
return reinterpret_cast<TypeMap*>(
|
||||||
(cast<GcByteArray>
|
cast<GcByteArray>(t, hashMapFind(t, typeMaps, p, objectHash, objectEqual))
|
||||||
(t, hashMapFind(t, typeMaps, p, objectHash, objectEqual))->body().begin());
|
->body()
|
||||||
|
.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeMap*
|
TypeMap* typeMap(Thread* t, GcHashMap* typeMaps, object p)
|
||||||
typeMap(Thread* t, GcHashMap* typeMaps, object p)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<TypeMap*>
|
return reinterpret_cast<TypeMap*>(
|
||||||
(cast<GcByteArray>
|
cast<GcByteArray>(
|
||||||
(t, objectClass(t, p) == type(t, GcSingleton::Type)
|
t,
|
||||||
? hashMapFind(t, typeMaps, p, objectHash, objectEqual)
|
objectClass(t, p) == type(t, GcSingleton::Type)
|
||||||
: hashMapFind(t, typeMaps, reinterpret_cast<object>(objectClass(t, p)), objectHash, objectEqual))->body().begin());
|
? hashMapFind(t, typeMaps, p, objectHash, objectEqual)
|
||||||
|
: hashMapFind(t,
|
||||||
|
typeMaps,
|
||||||
|
reinterpret_cast<object>(objectClass(t, p)),
|
||||||
|
objectHash,
|
||||||
|
objectEqual))
|
||||||
|
->body()
|
||||||
|
.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned targetFieldOffset(Thread* t, GcHashMap* typeMaps, GcField* field)
|
||||||
targetFieldOffset(Thread* t, GcHashMap* typeMaps, GcField* field)
|
|
||||||
{
|
{
|
||||||
// if (strcmp(reinterpret_cast<const char*>
|
// if (strcmp(reinterpret_cast<const char*>
|
||||||
// (&byteArrayBody(t, className(t, field->class_()), 0)),
|
// (&byteArrayBody(t, className(t, field->class_()), 0)),
|
||||||
// "java/lang/Throwable") == 0) trap();
|
// "java/lang/Throwable") == 0) trap();
|
||||||
|
|
||||||
return ((field->flags() & ACC_STATIC)
|
return ((field->flags() & ACC_STATIC)
|
||||||
? typeMap(t, typeMaps, reinterpret_cast<object>(field->class_()->staticTable()))
|
? typeMap(
|
||||||
: classTypeMap(t, typeMaps, reinterpret_cast<object>(field->class_())))
|
t,
|
||||||
->targetFixedOffsets()[field->offset()];
|
typeMaps,
|
||||||
|
reinterpret_cast<object>(field->class_()->staticTable()))
|
||||||
|
: classTypeMap(
|
||||||
|
t, typeMaps, reinterpret_cast<object>(field->class_())))
|
||||||
|
->targetFixedOffsets()[field->offset()];
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTriple*
|
GcTriple* makeCodeImage(Thread* t,
|
||||||
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
Zone* zone,
|
||||||
const char* className, const char* methodName,
|
BootImage* image,
|
||||||
const char* methodSpec, GcHashMap* typeMaps)
|
uint8_t* code,
|
||||||
|
const char* className,
|
||||||
|
const char* methodName,
|
||||||
|
const char* methodSpec,
|
||||||
|
GcHashMap* typeMaps)
|
||||||
{
|
{
|
||||||
PROTECT(t, typeMaps);
|
PROTECT(t, typeMaps);
|
||||||
|
|
||||||
@ -302,17 +327,20 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
|
|
||||||
class MyOffsetResolver: public OffsetResolver {
|
class MyOffsetResolver: public OffsetResolver {
|
||||||
public:
|
public:
|
||||||
MyOffsetResolver(GcHashMap** typeMaps): typeMaps(typeMaps) { }
|
MyOffsetResolver(GcHashMap** typeMaps) : typeMaps(typeMaps)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned fieldOffset(Thread* t, GcField* field) {
|
virtual unsigned fieldOffset(Thread* t, GcField* field)
|
||||||
|
{
|
||||||
return targetFieldOffset(t, *typeMaps, field);
|
return targetFieldOffset(t, *typeMaps, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcHashMap** typeMaps;
|
GcHashMap** typeMaps;
|
||||||
} resolver(&typeMaps);
|
} resolver(&typeMaps);
|
||||||
|
|
||||||
Finder* finder = static_cast<Finder*>
|
Finder* finder = static_cast<Finder*>(
|
||||||
(roots(t)->bootLoader()->as<GcSystemClassLoader>(t)->finder());
|
roots(t)->bootLoader()->as<GcSystemClassLoader>(t)->finder());
|
||||||
|
|
||||||
for (Finder::Iterator it(finder); it.hasMore();) {
|
for (Finder::Iterator it(finder); it.hasMore();) {
|
||||||
unsigned nameSize = 0;
|
unsigned nameSize = 0;
|
||||||
@ -322,9 +350,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
|
and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
|
||||||
{
|
{
|
||||||
// fprintf(stderr, "pass 1 %.*s\n", nameSize - 6, name);
|
// fprintf(stderr, "pass 1 %.*s\n", nameSize - 6, name);
|
||||||
GcClass* c = resolveSystemClass
|
GcClass* c
|
||||||
(t, roots(t)->bootLoader(),
|
= resolveSystemClass(t,
|
||||||
makeByteArray(t, "%.*s", nameSize - 6, name), true);
|
roots(t)->bootLoader(),
|
||||||
|
makeByteArray(t, "%.*s", nameSize - 6, name),
|
||||||
|
true);
|
||||||
|
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
@ -400,11 +430,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GcByteArray* array = makeByteArray
|
GcByteArray* array
|
||||||
(t, TypeMap::sizeInBytes(count + 2, count + 2));
|
= makeByteArray(t, TypeMap::sizeInBytes(count + 2, count + 2));
|
||||||
|
|
||||||
TypeMap* map = new (array->body().begin()) TypeMap
|
TypeMap* map = new (array->body().begin())
|
||||||
(count + 2, count + 2, count + 2, TypeMap::PoolKind);
|
TypeMap(count + 2, count + 2, count + 2, TypeMap::PoolKind);
|
||||||
|
|
||||||
for (unsigned i = 0; i < count + 2; ++i) {
|
for (unsigned i = 0; i < count + 2; ++i) {
|
||||||
expect(t, i < map->buildFixedSizeInWords);
|
expect(t, i < map->buildFixedSizeInWords);
|
||||||
@ -417,14 +447,21 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
TargetBytesPerWord);
|
TargetBytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
hashMapInsert
|
hashMapInsert(
|
||||||
(t, typeMaps, reinterpret_cast<object>(hashMapFind
|
t,
|
||||||
(t, roots(t)->poolMap(), reinterpret_cast<object>(c), objectHash, objectEqual)), reinterpret_cast<object>(array),
|
typeMaps,
|
||||||
objectHash);
|
reinterpret_cast<object>(hashMapFind(t,
|
||||||
|
roots(t)->poolMap(),
|
||||||
|
reinterpret_cast<object>(c),
|
||||||
|
objectHash,
|
||||||
|
objectEqual)),
|
||||||
|
reinterpret_cast<object>(array),
|
||||||
|
objectHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ GcByteArray* array = 0;
|
{
|
||||||
|
GcByteArray* array = 0;
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
@ -442,8 +479,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
buildMemberOffset = 0;
|
buildMemberOffset = 0;
|
||||||
targetMemberOffset = 0;
|
targetMemberOffset = 0;
|
||||||
|
|
||||||
TypeMap* map = reinterpret_cast<TypeMap*>
|
TypeMap* map = reinterpret_cast<TypeMap*>(array->body().begin());
|
||||||
(array->body().begin());
|
|
||||||
|
|
||||||
for (unsigned j = 0; j < map->fixedFieldCount; ++j) {
|
for (unsigned j = 0; j < map->fixedFieldCount; ++j) {
|
||||||
Field* f = map->fixedFields() + j;
|
Field* f = map->fixedFields() + j;
|
||||||
@ -548,14 +584,20 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashMapFind(t, typeMaps, reinterpret_cast<object>(c), objectHash, objectEqual) == 0) {
|
if (hashMapFind(t,
|
||||||
GcByteArray* array = makeByteArray
|
typeMaps,
|
||||||
(t, TypeMap::sizeInBytes
|
reinterpret_cast<object>(c),
|
||||||
(ceilingDivide(c->fixedSize(), BytesPerWord), memberIndex));
|
objectHash,
|
||||||
|
objectEqual) == 0) {
|
||||||
|
GcByteArray* array = makeByteArray(
|
||||||
|
t,
|
||||||
|
TypeMap::sizeInBytes(ceilingDivide(c->fixedSize(), BytesPerWord),
|
||||||
|
memberIndex));
|
||||||
|
|
||||||
TypeMap* map = new (array->body().begin()) TypeMap
|
TypeMap* map = new (array->body().begin())
|
||||||
(ceilingDivide(c->fixedSize(), BytesPerWord),
|
TypeMap(ceilingDivide(c->fixedSize(), BytesPerWord),
|
||||||
ceilingDivide(targetMemberOffset, TargetBytesPerWord), memberIndex);
|
ceilingDivide(targetMemberOffset, TargetBytesPerWord),
|
||||||
|
memberIndex);
|
||||||
|
|
||||||
for (unsigned i = 0; i < memberIndex; ++i) {
|
for (unsigned i = 0; i < memberIndex; ++i) {
|
||||||
Field* f = RUNTIME_ARRAY_BODY(memberFields) + i;
|
Field* f = RUNTIME_ARRAY_BODY(memberFields) + i;
|
||||||
@ -568,18 +610,24 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
map->fixedFields()[i] = *f;
|
map->fixedFields()[i] = *f;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashMapInsert(t, typeMaps, reinterpret_cast<object>(c), reinterpret_cast<object>(array), objectHash);
|
hashMapInsert(t,
|
||||||
|
typeMaps,
|
||||||
|
reinterpret_cast<object>(c),
|
||||||
|
reinterpret_cast<object>(array),
|
||||||
|
objectHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->staticTable()) {
|
if (c->staticTable()) {
|
||||||
GcByteArray* array = makeByteArray
|
GcByteArray* array = makeByteArray(
|
||||||
(t, TypeMap::sizeInBytes
|
t,
|
||||||
(singletonCount(t, c->staticTable()) + 2, staticIndex));
|
TypeMap::sizeInBytes(singletonCount(t, c->staticTable()) + 2,
|
||||||
|
staticIndex));
|
||||||
|
|
||||||
TypeMap* map = new (array->body().begin()) TypeMap
|
TypeMap* map = new (array->body().begin())
|
||||||
(singletonCount(t, c->staticTable()) + 2,
|
TypeMap(singletonCount(t, c->staticTable()) + 2,
|
||||||
ceilingDivide(targetStaticOffset, TargetBytesPerWord), staticIndex,
|
ceilingDivide(targetStaticOffset, TargetBytesPerWord),
|
||||||
TypeMap::SingletonKind);
|
staticIndex,
|
||||||
|
TypeMap::SingletonKind);
|
||||||
|
|
||||||
for (unsigned i = 0; i < staticIndex; ++i) {
|
for (unsigned i = 0; i < staticIndex; ++i) {
|
||||||
Field* f = RUNTIME_ARRAY_BODY(staticFields) + i;
|
Field* f = RUNTIME_ARRAY_BODY(staticFields) + i;
|
||||||
@ -592,8 +640,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
map->fixedFields()[i] = *f;
|
map->fixedFields()[i] = *f;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashMapInsert
|
hashMapInsert(t,
|
||||||
(t, typeMaps, reinterpret_cast<object>(c->staticTable()), reinterpret_cast<object>(array), objectHash);
|
typeMaps,
|
||||||
|
reinterpret_cast<object>(c->staticTable()),
|
||||||
|
reinterpret_cast<object>(array),
|
||||||
|
objectHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -610,56 +661,64 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
GcClass* c = 0;
|
GcClass* c = 0;
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
c = resolveSystemClass
|
c = resolveSystemClass(t,
|
||||||
(t, roots(t)->bootLoader(),
|
roots(t)->bootLoader(),
|
||||||
makeByteArray(t, "%.*s", nameSize - 6, name), true);
|
makeByteArray(t, "%.*s", nameSize - 6, name),
|
||||||
|
true);
|
||||||
|
|
||||||
if (GcArray* mtable = cast<GcArray>(t, c->methodTable())) {
|
if (GcArray* mtable = cast<GcArray>(t, c->methodTable())) {
|
||||||
PROTECT(t, mtable);
|
PROTECT(t, mtable);
|
||||||
for (unsigned i = 0; i < mtable->length(); ++i) {
|
for (unsigned i = 0; i < mtable->length(); ++i) {
|
||||||
GcMethod* method = cast<GcMethod>(t, mtable->body()[i]);
|
GcMethod* method = cast<GcMethod>(t, mtable->body()[i]);
|
||||||
if (((methodName == 0
|
if (((methodName == 0
|
||||||
or ::strcmp
|
or ::strcmp(
|
||||||
(reinterpret_cast<char*>
|
reinterpret_cast<char*>(method->name()->body().begin()),
|
||||||
(method->name()->body().begin()), methodName) == 0)
|
methodName) == 0)
|
||||||
and (methodSpec == 0
|
and (methodSpec == 0
|
||||||
or ::strcmp
|
or ::strcmp(reinterpret_cast<char*>(
|
||||||
(reinterpret_cast<char*>
|
method->spec()->body().begin()),
|
||||||
(method->spec()->body().begin()), methodSpec)
|
methodSpec) == 0))) {
|
||||||
== 0)))
|
if (method->code() or (method->flags() & ACC_NATIVE)) {
|
||||||
{
|
|
||||||
if (method->code()
|
|
||||||
or (method->flags() & ACC_NATIVE))
|
|
||||||
{
|
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
t->m->processor->compileMethod
|
t->m->processor->compileMethod(
|
||||||
(t, zone, reinterpret_cast<GcTriple**>(&constants), reinterpret_cast<GcTriple**>(&calls), &addresses, method, &resolver);
|
t,
|
||||||
|
zone,
|
||||||
|
reinterpret_cast<GcTriple**>(&constants),
|
||||||
|
reinterpret_cast<GcTriple**>(&calls),
|
||||||
|
&addresses,
|
||||||
|
method,
|
||||||
|
&resolver);
|
||||||
|
|
||||||
if (method->code()) {
|
if (method->code()) {
|
||||||
methods = makePair(t, reinterpret_cast<object>(method), reinterpret_cast<object>(methods));
|
methods = makePair(t,
|
||||||
|
reinterpret_cast<object>(method),
|
||||||
|
reinterpret_cast<object>(methods));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GcMethodAddendum* addendum = method->addendum();
|
GcMethodAddendum* addendum = method->addendum();
|
||||||
if (addendum and addendum->exceptionTable()) {
|
if (addendum and addendum->exceptionTable()) {
|
||||||
PROTECT(t, addendum);
|
PROTECT(t, addendum);
|
||||||
GcShortArray* exceptionTable = cast<GcShortArray>(t, addendum->exceptionTable());
|
GcShortArray* exceptionTable
|
||||||
|
= cast<GcShortArray>(t, addendum->exceptionTable());
|
||||||
PROTECT(t, exceptionTable);
|
PROTECT(t, exceptionTable);
|
||||||
|
|
||||||
// resolve exception types now to avoid trying to update
|
// resolve exception types now to avoid trying to update
|
||||||
// immutable references at runtime
|
// immutable references at runtime
|
||||||
for (unsigned i = 0; i < exceptionTable->length(); ++i)
|
for (unsigned i = 0; i < exceptionTable->length(); ++i) {
|
||||||
{
|
|
||||||
uint16_t index = exceptionTable->body()[i] - 1;
|
uint16_t index = exceptionTable->body()[i] - 1;
|
||||||
|
|
||||||
object o = singletonObject(t, addendum->pool(), index);
|
object o = singletonObject(t, addendum->pool(), index);
|
||||||
|
|
||||||
if (objectClass(t, o) == type(t, GcReference::Type)) {
|
if (objectClass(t, o) == type(t, GcReference::Type)) {
|
||||||
o = reinterpret_cast<object>(resolveClass
|
o = reinterpret_cast<object>(
|
||||||
(t, roots(t)->bootLoader(), cast<GcReference>(t, o)->name()));
|
resolveClass(t,
|
||||||
|
roots(t)->bootLoader(),
|
||||||
|
cast<GcReference>(t, o)->name()));
|
||||||
|
|
||||||
addendum->pool()->setBodyElement(t, index, reinterpret_cast<uintptr_t>(o));
|
addendum->pool()->setBodyElement(
|
||||||
|
t, index, reinterpret_cast<uintptr_t>(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -679,7 +738,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static_cast<ListenPromise*>(cast<GcPointer>(t, calls->second())->value())
|
static_cast<ListenPromise*>(cast<GcPointer>(t, calls->second())->value())
|
||||||
->listener->resolve(address, 0);
|
->listener->resolve(address, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; addresses; addresses = addresses->next) {
|
for (; addresses; addresses = addresses->next) {
|
||||||
@ -692,7 +751,7 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
|
|
||||||
for (; methods; methods = cast<GcPair>(t, methods->second())) {
|
for (; methods; methods = cast<GcPair>(t, methods->second())) {
|
||||||
cast<GcMethod>(t, methods->first())->code()->compiled()
|
cast<GcMethod>(t, methods->first())->code()->compiled()
|
||||||
-= reinterpret_cast<uintptr_t>(code);
|
-= reinterpret_cast<uintptr_t>(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
t->m->processor->normalizeVirtualThunks(t);
|
t->m->processor->normalizeVirtualThunks(t);
|
||||||
@ -700,19 +759,19 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
|
|||||||
return constants;
|
return constants;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void visitRoots(Thread* t, BootImage* image, HeapWalker* w, GcTriple* constants)
|
||||||
visitRoots(Thread* t, BootImage* image, HeapWalker* w, GcTriple* constants)
|
|
||||||
{
|
{
|
||||||
Machine* m = t->m;
|
Machine* m = t->m;
|
||||||
|
|
||||||
for (HashMapIterator it(t, cast<GcHashMap>(t, roots(t)->bootLoader()->map()));
|
for (HashMapIterator it(t, cast<GcHashMap>(t, roots(t)->bootLoader()->map()));
|
||||||
it.hasMore();)
|
it.hasMore();) {
|
||||||
{
|
|
||||||
w->visitRoot(it.next()->second());
|
w->visitRoot(it.next()->second());
|
||||||
}
|
}
|
||||||
|
|
||||||
image->bootLoader = w->visitRoot(reinterpret_cast<object>(roots(t)->bootLoader()));
|
image->bootLoader
|
||||||
image->appLoader = w->visitRoot(reinterpret_cast<object>(roots(t)->appLoader()));
|
= w->visitRoot(reinterpret_cast<object>(roots(t)->bootLoader()));
|
||||||
|
image->appLoader
|
||||||
|
= w->visitRoot(reinterpret_cast<object>(roots(t)->appLoader()));
|
||||||
image->types = w->visitRoot(reinterpret_cast<object>(m->types));
|
image->types = w->visitRoot(reinterpret_cast<object>(m->types));
|
||||||
|
|
||||||
m->processor->visitRoots(t, w);
|
m->processor->visitRoots(t, w);
|
||||||
@ -722,8 +781,7 @@ visitRoots(Thread* t, BootImage* image, HeapWalker* w, GcTriple* constants)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned targetOffset(Thread* t, GcHashMap* typeMaps, object p, unsigned offset)
|
||||||
targetOffset(Thread* t, GcHashMap* typeMaps, object p, unsigned offset)
|
|
||||||
{
|
{
|
||||||
TypeMap* map = typeMap(t, typeMaps, p);
|
TypeMap* map = typeMap(t, typeMaps, p);
|
||||||
|
|
||||||
@ -739,8 +797,7 @@ targetOffset(Thread* t, GcHashMap* typeMaps, object p, unsigned offset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned targetSize(Thread* t, GcHashMap* typeMaps, object p)
|
||||||
targetSize(Thread* t, GcHashMap* typeMaps, object p)
|
|
||||||
{
|
{
|
||||||
TypeMap* map = typeMap(t, typeMaps, p);
|
TypeMap* map = typeMap(t, typeMaps, p);
|
||||||
|
|
||||||
@ -784,14 +841,14 @@ objectMaskCount(TypeMap* map)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned targetSize(Thread* t,
|
||||||
targetSize(Thread* t, GcHashMap* typeMaps, object referer, unsigned refererOffset,
|
GcHashMap* typeMaps,
|
||||||
object p)
|
object referer,
|
||||||
|
unsigned refererOffset,
|
||||||
|
object p)
|
||||||
{
|
{
|
||||||
if (referer
|
if (referer and objectClass(t, referer) == type(t, GcClass::Type)
|
||||||
and objectClass(t, referer) == type(t, GcClass::Type)
|
and (refererOffset * BytesPerWord) == ClassObjectMask) {
|
||||||
and (refererOffset * BytesPerWord) == ClassObjectMask)
|
|
||||||
{
|
|
||||||
return (TargetBytesPerWord * 2)
|
return (TargetBytesPerWord * 2)
|
||||||
+ pad
|
+ pad
|
||||||
(ceilingDivide
|
(ceilingDivide
|
||||||
@ -911,8 +968,7 @@ nonObjectsEqual(TypeMap* map, uint8_t* src, uint8_t* dst)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void copy(Thread* t, GcHashMap* typeMaps, object p, uint8_t* dst)
|
||||||
copy(Thread* t, GcHashMap* typeMaps, object p, uint8_t* dst)
|
|
||||||
{
|
{
|
||||||
TypeMap* map = typeMap(t, typeMaps, p);
|
TypeMap* map = typeMap(t, typeMaps, p);
|
||||||
|
|
||||||
@ -937,23 +993,22 @@ copy(Thread* t, GcHashMap* typeMaps, object p, uint8_t* dst)
|
|||||||
if (objectClass(t, p) == type(t, GcClass::Type)) {
|
if (objectClass(t, p) == type(t, GcClass::Type)) {
|
||||||
uint16_t fixedSize;
|
uint16_t fixedSize;
|
||||||
uint8_t arrayElementSize;
|
uint8_t arrayElementSize;
|
||||||
GcByteArray* array = cast<GcByteArray>(t, hashMapFind(t, typeMaps, p, objectHash, objectEqual));
|
GcByteArray* array = cast<GcByteArray>(
|
||||||
|
t, hashMapFind(t, typeMaps, p, objectHash, objectEqual));
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
GcClass* c = cast<GcClass>(t, p);
|
GcClass* c = cast<GcClass>(t, p);
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
if (array) {
|
if (array) {
|
||||||
TypeMap* classMap = reinterpret_cast<TypeMap*>
|
TypeMap* classMap = reinterpret_cast<TypeMap*>(array->body().begin());
|
||||||
(array->body().begin());
|
|
||||||
|
|
||||||
fixedSize = targetV2
|
fixedSize = targetV2
|
||||||
(classMap->targetFixedSizeInWords * TargetBytesPerWord);
|
(classMap->targetFixedSizeInWords * TargetBytesPerWord);
|
||||||
|
|
||||||
arrayElementSize = classMap->targetArrayElementSizeInBytes;
|
arrayElementSize = classMap->targetArrayElementSizeInBytes;
|
||||||
} else if (c->fixedSize() == BytesPerWord * 2
|
} else if (c->fixedSize() == BytesPerWord * 2
|
||||||
and c->arrayElementSize() == BytesPerWord)
|
and c->arrayElementSize() == BytesPerWord) {
|
||||||
{
|
|
||||||
fixedSize = targetV2(TargetBytesPerWord * 2);
|
fixedSize = targetV2(TargetBytesPerWord * 2);
|
||||||
|
|
||||||
arrayElementSize = TargetBytesPerWord;
|
arrayElementSize = TargetBytesPerWord;
|
||||||
@ -975,7 +1030,8 @@ copy(Thread* t, GcHashMap* typeMaps, object p, uint8_t* dst)
|
|||||||
switch (map->kind) {
|
switch (map->kind) {
|
||||||
case TypeMap::NormalKind:
|
case TypeMap::NormalKind:
|
||||||
if (objectClass(t, p) == type(t, GcField::Type)) {
|
if (objectClass(t, p) == type(t, GcField::Type)) {
|
||||||
uint16_t offset = targetV2(targetFieldOffset(t, typeMaps, cast<GcField>(t, p)));
|
uint16_t offset
|
||||||
|
= targetV2(targetFieldOffset(t, typeMaps, cast<GcField>(t, p)));
|
||||||
memcpy(dst + TargetFieldOffset, &offset, 2);
|
memcpy(dst + TargetFieldOffset, &offset, 2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1068,14 +1124,15 @@ copy(Thread* t, GcHashMap* typeMaps, object p, uint8_t* dst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void copy(Thread* t,
|
||||||
copy(Thread* t, GcHashMap* typeMaps, object referer, unsigned refererOffset,
|
GcHashMap* typeMaps,
|
||||||
object p, uint8_t* dst)
|
object referer,
|
||||||
|
unsigned refererOffset,
|
||||||
|
object p,
|
||||||
|
uint8_t* dst)
|
||||||
{
|
{
|
||||||
if (referer
|
if (referer and objectClass(t, referer) == type(t, GcClass::Type)
|
||||||
and objectClass(t, referer) == type(t, GcClass::Type)
|
and (refererOffset * BytesPerWord) == ClassObjectMask) {
|
||||||
and (refererOffset * BytesPerWord) == ClassObjectMask)
|
|
||||||
{
|
|
||||||
TypeMap* map = classTypeMap(t, typeMaps, referer);
|
TypeMap* map = classTypeMap(t, typeMaps, referer);
|
||||||
|
|
||||||
memset(dst, 0, TargetBytesPerWord);
|
memset(dst, 0, TargetBytesPerWord);
|
||||||
@ -1115,17 +1172,30 @@ copy(Thread* t, GcHashMap* typeMaps, object referer, unsigned refererOffset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWalker*
|
HeapWalker* makeHeapImage(Thread* t,
|
||||||
makeHeapImage(Thread* t, BootImage* image, target_uintptr_t* heap,
|
BootImage* image,
|
||||||
target_uintptr_t* map, unsigned capacity, GcTriple* constants,
|
target_uintptr_t* heap,
|
||||||
GcHashMap* typeMaps)
|
target_uintptr_t* map,
|
||||||
|
unsigned capacity,
|
||||||
|
GcTriple* constants,
|
||||||
|
GcHashMap* typeMaps)
|
||||||
{
|
{
|
||||||
class Visitor: public HeapVisitor {
|
class Visitor: public HeapVisitor {
|
||||||
public:
|
public:
|
||||||
Visitor(Thread* t, GcHashMap* typeMaps, target_uintptr_t* heap,
|
Visitor(Thread* t,
|
||||||
target_uintptr_t* map, unsigned capacity):
|
GcHashMap* typeMaps,
|
||||||
t(t), typeMaps(typeMaps), currentObject(0), currentNumber(0),
|
target_uintptr_t* heap,
|
||||||
currentOffset(0), heap(heap), map(map), position(0), capacity(capacity)
|
target_uintptr_t* map,
|
||||||
|
unsigned capacity)
|
||||||
|
: t(t),
|
||||||
|
typeMaps(typeMaps),
|
||||||
|
currentObject(0),
|
||||||
|
currentNumber(0),
|
||||||
|
currentOffset(0),
|
||||||
|
heap(heap),
|
||||||
|
map(map),
|
||||||
|
position(0),
|
||||||
|
capacity(capacity)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void visit(unsigned number) {
|
void visit(unsigned number) {
|
||||||
@ -1164,8 +1234,7 @@ makeHeapImage(Thread* t, BootImage* image, target_uintptr_t* heap,
|
|||||||
if ((currentObject
|
if ((currentObject
|
||||||
and objectClass(t, currentObject) == type(t, GcClass::Type)
|
and objectClass(t, currentObject) == type(t, GcClass::Type)
|
||||||
and (currentOffset * BytesPerWord) == ClassStaticTable)
|
and (currentOffset * BytesPerWord) == ClassStaticTable)
|
||||||
or instanceOf(t, type(t, GcSystemClassLoader::Type), p))
|
or instanceOf(t, type(t, GcSystemClassLoader::Type), p)) {
|
||||||
{
|
|
||||||
// Static tables and system classloaders must be allocated
|
// Static tables and system classloaders must be allocated
|
||||||
// as fixed objects in the heap image so that they can be
|
// as fixed objects in the heap image so that they can be
|
||||||
// marked as dirty and visited during GC. Otherwise,
|
// marked as dirty and visited during GC. Otherwise,
|
||||||
@ -1256,17 +1325,17 @@ makeHeapImage(Thread* t, BootImage* image, target_uintptr_t* heap,
|
|||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void updateConstants(Thread* t, GcTriple* constants, HeapMap* heapTable)
|
||||||
updateConstants(Thread* t, GcTriple* constants, HeapMap* heapTable)
|
|
||||||
{
|
{
|
||||||
for (; constants; constants = cast<GcTriple>(t, constants->third())) {
|
for (; constants; constants = cast<GcTriple>(t, constants->third())) {
|
||||||
unsigned target = heapTable->find(constants->first());
|
unsigned target = heapTable->find(constants->first());
|
||||||
expect(t, target > 0);
|
expect(t, target > 0);
|
||||||
|
|
||||||
for (Promise::Listener* pl = static_cast<ListenPromise*>
|
for (Promise::Listener* pl
|
||||||
(cast<GcPointer>(t, constants->second())->value())->listener;
|
= static_cast<ListenPromise*>(
|
||||||
pl; pl = pl->next)
|
cast<GcPointer>(t, constants->second())->value())->listener;
|
||||||
{
|
pl;
|
||||||
|
pl = pl->next) {
|
||||||
pl->resolve((target - 1) * TargetBytesPerWord, 0);
|
pl->resolve((target - 1) * TargetBytesPerWord, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1287,7 +1356,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
const char* codeimageStart, const char* codeimageEnd,
|
const char* codeimageStart, const char* codeimageEnd,
|
||||||
bool useLZMA)
|
bool useLZMA)
|
||||||
{
|
{
|
||||||
GcThrowable* throwable = cast<GcThrowable>(t, make(t, type(t, GcOutOfMemoryError::Type)));
|
GcThrowable* throwable
|
||||||
|
= cast<GcThrowable>(t, make(t, type(t, GcOutOfMemoryError::Type)));
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
roots(t)->setOutOfMemoryError(t, throwable);
|
roots(t)->setOutOfMemoryError(t, throwable);
|
||||||
|
|
||||||
@ -1460,15 +1530,19 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
targetArrayElementSize = 0;
|
targetArrayElementSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcByteArray* array = makeByteArray
|
GcByteArray* array = makeByteArray(
|
||||||
(t, TypeMap::sizeInBytes
|
t,
|
||||||
(ceilingDivide(buildOffset, BytesPerWord), fixedFieldCount));
|
TypeMap::sizeInBytes(ceilingDivide(buildOffset, BytesPerWord),
|
||||||
|
fixedFieldCount));
|
||||||
|
|
||||||
TypeMap* map = new (array->body().begin()) TypeMap
|
TypeMap* map = new (array->body().begin())
|
||||||
(ceilingDivide(buildOffset, BytesPerWord),
|
TypeMap(ceilingDivide(buildOffset, BytesPerWord),
|
||||||
ceilingDivide(targetOffset, TargetBytesPerWord),
|
ceilingDivide(targetOffset, TargetBytesPerWord),
|
||||||
fixedFieldCount, TypeMap::NormalKind, buildArrayElementSize,
|
fixedFieldCount,
|
||||||
targetArrayElementSize, arrayElementType);
|
TypeMap::NormalKind,
|
||||||
|
buildArrayElementSize,
|
||||||
|
targetArrayElementSize,
|
||||||
|
arrayElementType);
|
||||||
|
|
||||||
for (unsigned j = 0; j < fixedFieldCount; ++j) {
|
for (unsigned j = 0; j < fixedFieldCount; ++j) {
|
||||||
Field* f = RUNTIME_ARRAY_BODY(fields) + j;
|
Field* f = RUNTIME_ARRAY_BODY(fields) + j;
|
||||||
@ -1481,9 +1555,12 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
map->fixedFields()[j] = *f;
|
map->fixedFields()[j] = *f;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashMapInsert
|
hashMapInsert(
|
||||||
(t, typeMaps, reinterpret_cast<object>(vm::type(t, static_cast<Gc::Type>(i))), reinterpret_cast<object>(array),
|
t,
|
||||||
objectHash);
|
typeMaps,
|
||||||
|
reinterpret_cast<object>(vm::type(t, static_cast<Gc::Type>(i))),
|
||||||
|
reinterpret_cast<object>(array),
|
||||||
|
objectHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
constants = makeCodeImage
|
constants = makeCodeImage
|
||||||
@ -1501,46 +1578,48 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
|
|
||||||
// name all primitive classes so we don't try to update immutable
|
// name all primitive classes so we don't try to update immutable
|
||||||
// references at runtime:
|
// references at runtime:
|
||||||
{ GcByteArray* name = makeByteArray(t, "void");
|
{
|
||||||
// sequence point, for gc (don't recombine statements)
|
GcByteArray* name = makeByteArray(t, "void");
|
||||||
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJvoid::Type)->setName(t, name);
|
type(t, GcJvoid::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "boolean");
|
name = makeByteArray(t, "boolean");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJboolean::Type)->setName(t, name);
|
type(t, GcJboolean::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "byte");
|
name = makeByteArray(t, "byte");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJbyte::Type)->setName(t, name);
|
type(t, GcJbyte::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "short");
|
name = makeByteArray(t, "short");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJshort::Type)->setName(t, name);
|
type(t, GcJshort::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "char");
|
name = makeByteArray(t, "char");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJchar::Type)->setName(t, name);
|
type(t, GcJchar::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "int");
|
name = makeByteArray(t, "int");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJint::Type)->setName(t, name);
|
type(t, GcJint::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "float");
|
name = makeByteArray(t, "float");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJfloat::Type)->setName(t, name);
|
type(t, GcJfloat::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "long");
|
name = makeByteArray(t, "long");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJlong::Type)->setName(t, name);
|
type(t, GcJlong::Type)->setName(t, name);
|
||||||
|
|
||||||
name = makeByteArray(t, "double");
|
name = makeByteArray(t, "double");
|
||||||
// sequence point, for gc (don't recombine statements)
|
// sequence point, for gc (don't recombine statements)
|
||||||
type(t, GcJdouble::Type)->setName(t, name);
|
type(t, GcJdouble::Type)->setName(t, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve primitive array classes in case they are needed at
|
// resolve primitive array classes in case they are needed at
|
||||||
// runtime:
|
// runtime:
|
||||||
{ GcByteArray* name = makeByteArray(t, "[B");
|
{
|
||||||
|
GcByteArray* name = makeByteArray(t, "[B");
|
||||||
resolveSystemClass(t, roots(t)->bootLoader(), name, true);
|
resolveSystemClass(t, roots(t)->bootLoader(), name, true);
|
||||||
|
|
||||||
name = makeByteArray(t, "[Z");
|
name = makeByteArray(t, "[Z");
|
||||||
@ -1578,35 +1657,33 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
|
|
||||||
updateConstants(t, constants, heapWalker->map());
|
updateConstants(t, constants, heapWalker->map());
|
||||||
|
|
||||||
image->bootClassCount = cast<GcHashMap>
|
image->bootClassCount
|
||||||
(t, roots(t)->bootLoader()->map())->size();
|
= cast<GcHashMap>(t, roots(t)->bootLoader()->map())->size();
|
||||||
|
|
||||||
unsigned* bootClassTable = static_cast<unsigned*>
|
unsigned* bootClassTable = static_cast<unsigned*>
|
||||||
(t->m->heap->allocate(image->bootClassCount * sizeof(unsigned)));
|
(t->m->heap->allocate(image->bootClassCount * sizeof(unsigned)));
|
||||||
|
|
||||||
{ unsigned i = 0;
|
{ unsigned i = 0;
|
||||||
for (HashMapIterator it
|
for (HashMapIterator it(t,
|
||||||
(t, cast<GcHashMap>(t, roots(t)->bootLoader()->map()));
|
cast<GcHashMap>(t, roots(t)->bootLoader()->map()));
|
||||||
it.hasMore();)
|
it.hasMore();) {
|
||||||
{
|
bootClassTable[i++]
|
||||||
bootClassTable[i++] = targetVW
|
= targetVW(heapWalker->map()->find(it.next()->second()));
|
||||||
(heapWalker->map()->find(it.next()->second()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image->appClassCount = cast<GcHashMap>
|
image->appClassCount
|
||||||
(t, roots(t)->appLoader()->map())->size();
|
= cast<GcHashMap>(t, roots(t)->appLoader()->map())->size();
|
||||||
|
|
||||||
unsigned* appClassTable = static_cast<unsigned*>
|
unsigned* appClassTable = static_cast<unsigned*>
|
||||||
(t->m->heap->allocate(image->appClassCount * sizeof(unsigned)));
|
(t->m->heap->allocate(image->appClassCount * sizeof(unsigned)));
|
||||||
|
|
||||||
{ unsigned i = 0;
|
{ unsigned i = 0;
|
||||||
for (HashMapIterator it
|
for (
|
||||||
(t, cast<GcHashMap>(t, roots(t)->appLoader()->map()));
|
HashMapIterator it(t, cast<GcHashMap>(t, roots(t)->appLoader()->map()));
|
||||||
it.hasMore();)
|
it.hasMore();) {
|
||||||
{
|
appClassTable[i++]
|
||||||
appClassTable[i++] = targetVW
|
= targetVW(heapWalker->map()->find(it.next()->second()));
|
||||||
(heapWalker->map()->find(it.next()->second()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1616,9 +1693,9 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp
|
|||||||
|
|
||||||
{ unsigned i = 0;
|
{ unsigned i = 0;
|
||||||
for (HashMapIterator it(t, roots(t)->stringMap()); it.hasMore();) {
|
for (HashMapIterator it(t, roots(t)->stringMap()); it.hasMore();) {
|
||||||
stringTable[i++] = targetVW
|
stringTable[i++]
|
||||||
(heapWalker->map()->find
|
= targetVW(heapWalker->map()->find(reinterpret_cast<object>(
|
||||||
(reinterpret_cast<object>(cast<GcJreference>(t, it.next()->first())->target())));
|
cast<GcJreference>(t, it.next()->first())->target())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,8 @@ class FileOutput : public Output {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void write(const std::string& s) {
|
virtual void write(const std::string& s)
|
||||||
|
{
|
||||||
fputs(s.c_str(), stream);
|
fputs(s.c_str(), stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,16 +77,18 @@ class Field {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dump() const {
|
std::string dump() const
|
||||||
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << "field " << name << ":" << typeName << ":" << javaSpec << ", size=" << elementSize << ", offset=" << offset;
|
ss << "field " << name << ":" << typeName << ":" << javaSpec
|
||||||
if(noassert) {
|
<< ", size=" << elementSize << ", offset=" << offset;
|
||||||
|
if (noassert) {
|
||||||
ss << " noassert";
|
ss << " noassert";
|
||||||
}
|
}
|
||||||
if(nogc) {
|
if (nogc) {
|
||||||
ss << " nogc";
|
ss << " nogc";
|
||||||
}
|
}
|
||||||
if(polyfill) {
|
if (polyfill) {
|
||||||
ss << " polyfill";
|
ss << " polyfill";
|
||||||
}
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
@ -103,14 +105,18 @@ class Method {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const Method& o) const {
|
bool operator==(const Method& o) const
|
||||||
|
{
|
||||||
return javaName == o.javaName && javaSpec == o.javaSpec;
|
return javaName == o.javaName && javaSpec == o.javaSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator < (const Method& o) const {
|
bool operator<(const Method& o) const
|
||||||
return javaName < o.javaName || (javaName == o.javaName && javaSpec < o.javaSpec);
|
{
|
||||||
|
return javaName < o.javaName
|
||||||
|
|| (javaName == o.javaName && javaSpec < o.javaSpec);
|
||||||
}
|
}
|
||||||
std::string dump() const {
|
std::string dump() const
|
||||||
|
{
|
||||||
return "method " + javaName + javaSpec;
|
return "method " + javaName + javaSpec;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -134,33 +140,44 @@ class Class {
|
|||||||
|
|
||||||
int fixedSize;
|
int fixedSize;
|
||||||
|
|
||||||
Class(const std::string& name) : name(name), super(0), arrayField(0), overridesMethods(false), fixedSize(-1)
|
Class(const std::string& name)
|
||||||
|
: name(name),
|
||||||
|
super(0),
|
||||||
|
arrayField(0),
|
||||||
|
overridesMethods(false),
|
||||||
|
fixedSize(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dump() const {
|
std::string dump() const
|
||||||
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << "class " << name;
|
ss << "class " << name;
|
||||||
if(javaName.size() > 0) {
|
if (javaName.size() > 0) {
|
||||||
ss << "(" << javaName << ")";
|
ss << "(" << javaName << ")";
|
||||||
}
|
}
|
||||||
if(super) {
|
if (super) {
|
||||||
ss << " : " << super->name << "(" << super->javaName << ")";
|
ss << " : " << super->name << "(" << super->javaName << ")";
|
||||||
}
|
}
|
||||||
ss << " {\n";
|
ss << " {\n";
|
||||||
|
|
||||||
for(std::vector<Field*>::const_iterator it = fields.begin(); it != fields.end(); it++) {
|
for (std::vector<Field*>::const_iterator it = fields.begin();
|
||||||
|
it != fields.end();
|
||||||
|
it++) {
|
||||||
ss << " " << (*it)->dump() << "\n";
|
ss << " " << (*it)->dump() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::set<Method>::const_iterator it = methods.begin(); it != methods.end(); ++it) {
|
for (std::set<Method>::const_iterator it = methods.begin();
|
||||||
|
it != methods.end();
|
||||||
|
++it) {
|
||||||
ss << " " << it->dump() << "\n";
|
ss << " " << it->dump() << "\n";
|
||||||
}
|
}
|
||||||
ss << "}";
|
ss << "}";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpToStdout() const AVIAN_EXPORT {
|
void dumpToStdout() const AVIAN_EXPORT
|
||||||
|
{
|
||||||
printf("%s\n", dump().c_str());
|
printf("%s\n", dump().c_str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -172,10 +189,11 @@ class Module {
|
|||||||
|
|
||||||
std::map<std::string, Class*> classes;
|
std::map<std::string, Class*> classes;
|
||||||
|
|
||||||
void add(Class* cl) {
|
void add(Class* cl)
|
||||||
|
{
|
||||||
assert(classes.find(cl->name) == classes.end());
|
assert(classes.find(cl->name) == classes.end());
|
||||||
classes[cl->name] = cl;
|
classes[cl->name] = cl;
|
||||||
if(cl->javaName != "") {
|
if (cl->javaName != "") {
|
||||||
assert(javaClasses.find(cl->javaName) == javaClasses.end());
|
assert(javaClasses.find(cl->javaName) == javaClasses.end());
|
||||||
javaClasses[cl->javaName] = cl;
|
javaClasses[cl->javaName] = cl;
|
||||||
}
|
}
|
||||||
@ -191,19 +209,17 @@ namespace {
|
|||||||
namespace local {
|
namespace local {
|
||||||
|
|
||||||
#ifndef POINTER_SIZE
|
#ifndef POINTER_SIZE
|
||||||
# define POINTER_SIZE sizeof(void*)
|
#define POINTER_SIZE sizeof(void*)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const unsigned BytesPerWord = POINTER_SIZE;
|
const unsigned BytesPerWord = POINTER_SIZE;
|
||||||
|
|
||||||
inline bool
|
inline bool equal(const char* a, const char* b)
|
||||||
equal(const char* a, const char* b)
|
|
||||||
{
|
{
|
||||||
return strcmp(a, b) == 0;
|
return strcmp(a, b) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool endsWith(const std::string& b, const std::string& a)
|
||||||
endsWith(const std::string& b, const std::string& a)
|
|
||||||
{
|
{
|
||||||
if (b.size() > a.size()) {
|
if (b.size() > a.size()) {
|
||||||
return false;
|
return false;
|
||||||
@ -211,18 +227,20 @@ endsWith(const std::string& b, const std::string& a)
|
|||||||
return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
|
return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string enumName(Module& module, Field& f) {
|
std::string enumName(Module& module, Field& f)
|
||||||
|
{
|
||||||
std::string& type = f.typeName;
|
std::string& type = f.typeName;
|
||||||
if (type == "void*") {
|
if (type == "void*") {
|
||||||
return "word";
|
return "word";
|
||||||
} else if(type == "maybe_object") {
|
} else if (type == "maybe_object") {
|
||||||
return "uintptr_t";
|
return "uintptr_t";
|
||||||
} else if(f.javaSpec.size() != 0 && (f.javaSpec[0] == 'L' || f.javaSpec[0] == '[')) {
|
} else if (f.javaSpec.size() != 0
|
||||||
|
&& (f.javaSpec[0] == 'L' || f.javaSpec[0] == '[')) {
|
||||||
return "object";
|
return "object";
|
||||||
}
|
}
|
||||||
std::map<std::string, Class*>::iterator it = module.classes.find(f.typeName);
|
std::map<std::string, Class*>::iterator it = module.classes.find(f.typeName);
|
||||||
assert(f.typeName.size() > 0);
|
assert(f.typeName.size() > 0);
|
||||||
if(it != module.classes.end()) {
|
if (it != module.classes.end()) {
|
||||||
return "object";
|
return "object";
|
||||||
} else {
|
} else {
|
||||||
return f.typeName;
|
return f.typeName;
|
||||||
@ -288,10 +306,9 @@ class Singleton : public Object {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string
|
std::string capitalize(const std::string& s)
|
||||||
capitalize(const std::string& s)
|
|
||||||
{
|
{
|
||||||
if(s[0] >= 'a' && s[0] <= 'z') {
|
if (s[0] >= 'a' && s[0] <= 'z') {
|
||||||
return (char)(s[0] + 'A' - 'a') + s.substr(1, s.size() - 1);
|
return (char)(s[0] + 'A' - 'a') + s.substr(1, s.size() - 1);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@ -358,20 +375,15 @@ read(Input* in, Object* eos, int level)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool namesPointer(const std::string& s)
|
||||||
namesPointer(const std::string& s)
|
|
||||||
{
|
{
|
||||||
return s == "Collector"
|
return s == "Collector" or s == "Disposer" or endsWith("*", s);
|
||||||
or s == "Disposer"
|
|
||||||
or endsWith("*", s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned sizeOf(Module& module, const std::string& type)
|
||||||
sizeOf(Module& module, const std::string& type)
|
|
||||||
{
|
{
|
||||||
if (type == "object"
|
if (type == "object" or type == "intptr_t" or type == "uintptr_t"
|
||||||
or type == "intptr_t" or type == "uintptr_t" or type == "maybe_object")
|
or type == "maybe_object") {
|
||||||
{
|
|
||||||
return BytesPerWord;
|
return BytesPerWord;
|
||||||
} else if (type == "unsigned" or type == "int") {
|
} else if (type == "unsigned" or type == "int") {
|
||||||
return sizeof(int);
|
return sizeof(int);
|
||||||
@ -393,7 +405,7 @@ sizeOf(Module& module, const std::string& type)
|
|||||||
return BytesPerWord;
|
return BytesPerWord;
|
||||||
} else {
|
} else {
|
||||||
std::map<std::string, Class*>::iterator it = module.classes.find(type);
|
std::map<std::string, Class*>::iterator it = module.classes.find(type);
|
||||||
if(it != module.classes.end()) {
|
if (it != module.classes.end()) {
|
||||||
return BytesPerWord;
|
return BytesPerWord;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "unexpected type: %s\n", type.c_str());
|
fprintf(stderr, "unexpected type: %s\n", type.c_str());
|
||||||
@ -408,9 +420,14 @@ struct FieldSpec {
|
|||||||
bool require;
|
bool require;
|
||||||
Field* field;
|
Field* field;
|
||||||
|
|
||||||
FieldSpec(){}
|
FieldSpec()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
FieldSpec(bool isArray, Field* field) :isArray(isArray), require(false), field(field) {}
|
FieldSpec(bool isArray, Field* field)
|
||||||
|
: isArray(isArray), require(false), field(field)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClassParser {
|
class ClassParser {
|
||||||
@ -422,9 +439,10 @@ class ClassParser {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(FieldSpec f) {
|
void add(FieldSpec f)
|
||||||
if(f.field->polyfill) {
|
{
|
||||||
if(fields.find(f.field->name) == fields.end()) {
|
if (f.field->polyfill) {
|
||||||
|
if (fields.find(f.field->name) == fields.end()) {
|
||||||
fields[f.field->name] = f.field;
|
fields[f.field->name] = f.field;
|
||||||
cl->fields.push_back(f.field);
|
cl->fields.push_back(f.field);
|
||||||
} else {
|
} else {
|
||||||
@ -432,11 +450,13 @@ class ClassParser {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(f.aliasName.size() > 0) {
|
if (f.aliasName.size() > 0) {
|
||||||
if(fields.find(f.aliasName) == fields.end()) {
|
if (fields.find(f.aliasName) == fields.end()) {
|
||||||
if(fields.find(f.field->name) != fields.end()) {
|
if (fields.find(f.field->name) != fields.end()) {
|
||||||
// printf("alias %s.%s -> %s.%s\n", cl->name.c_str(), f.field->name.c_str(), cl->name.c_str(), f.aliasName.c_str());
|
// printf("alias %s.%s -> %s.%s\n", cl->name.c_str(),
|
||||||
std::map<std::string, Field*>::iterator it = fields.find(f.field->name);
|
// f.field->name.c_str(), cl->name.c_str(), f.aliasName.c_str());
|
||||||
|
std::map<std::string, Field*>::iterator it
|
||||||
|
= fields.find(f.field->name);
|
||||||
assert(it != fields.end());
|
assert(it != fields.end());
|
||||||
Field* renamed = it->second;
|
Field* renamed = it->second;
|
||||||
fields.erase(it);
|
fields.erase(it);
|
||||||
@ -444,20 +464,24 @@ class ClassParser {
|
|||||||
|
|
||||||
renamed->name = f.aliasName;
|
renamed->name = f.aliasName;
|
||||||
|
|
||||||
// TODO: this currently works around how avian uses an object (either a char[] or byte[]) for String.data
|
// TODO: this currently works around how avian uses an object (either
|
||||||
|
// a char[] or byte[]) for String.data
|
||||||
renamed->typeName = f.field->typeName;
|
renamed->typeName = f.field->typeName;
|
||||||
renamed->javaSpec = f.field->javaSpec;
|
renamed->javaSpec = f.field->javaSpec;
|
||||||
} else {
|
} else {
|
||||||
// printf("ignoring absent alias %s.%s -> %s.%s\n", cl->name.c_str(), f.field->name.c_str(), cl->name.c_str(), f. aliasName.c_str());
|
// printf("ignoring absent alias %s.%s -> %s.%s\n", cl->name.c_str(),
|
||||||
|
// f.field->name.c_str(), cl->name.c_str(), f. aliasName.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// printf("ignoring already defined alias %s.%s -> %s.%s\n", cl->name.c_str(), f.field->name.c_str(), cl->name.c_str(), f. aliasName.c_str());
|
// printf("ignoring already defined alias %s.%s -> %s.%s\n",
|
||||||
|
// cl->name.c_str(), f.field->name.c_str(), cl->name.c_str(), f.
|
||||||
|
// aliasName.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(fields.find(f.field->name) == fields.end()) {
|
if (fields.find(f.field->name) == fields.end()) {
|
||||||
// printf("add %s.%s\n", cl->name.c_str(), f.field->name.c_str());
|
// printf("add %s.%s\n", cl->name.c_str(), f.field->name.c_str());
|
||||||
fields[f.field->name] = f.field;
|
fields[f.field->name] = f.field;
|
||||||
if(f.isArray) {
|
if (f.isArray) {
|
||||||
add(FieldSpec(false, new Field(cl, "uintptr_t", "", "length")));
|
add(FieldSpec(false, new Field(cl, "uintptr_t", "", "length")));
|
||||||
assert(!cl->arrayField);
|
assert(!cl->arrayField);
|
||||||
cl->arrayField = f.field;
|
cl->arrayField = f.field;
|
||||||
@ -465,7 +489,8 @@ class ClassParser {
|
|||||||
cl->fields.push_back(f.field);
|
cl->fields.push_back(f.field);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// printf("required check %s.%s\n", cl->name.c_str(), f.field->name.c_str());
|
// printf("required check %s.%s\n", cl->name.c_str(),
|
||||||
|
// f.field->name.c_str());
|
||||||
assert(f.aliasName.size() > 0 || f.require);
|
assert(f.aliasName.size() > 0 || f.require);
|
||||||
fields[f.field->name]->nogc |= f.field->nogc;
|
fields[f.field->name]->nogc |= f.field->nogc;
|
||||||
fields[f.field->name]->noassert |= f.field->noassert;
|
fields[f.field->name]->noassert |= f.field->noassert;
|
||||||
@ -473,12 +498,15 @@ class ClassParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSuper(Class* super) {
|
void setSuper(Class* super)
|
||||||
|
{
|
||||||
assert(!cl->super);
|
assert(!cl->super);
|
||||||
cl->super = super;
|
cl->super = super;
|
||||||
assert(!super->arrayField);
|
assert(!super->arrayField);
|
||||||
assert(fields.size() == 0);
|
assert(fields.size() == 0);
|
||||||
for(std::vector<Field*>::iterator it = super->fields.begin(); it != super->fields.end(); it++) {
|
for (std::vector<Field*>::iterator it = super->fields.begin();
|
||||||
|
it != super->fields.end();
|
||||||
|
it++) {
|
||||||
add(FieldSpec(false, *it));
|
add(FieldSpec(false, *it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -495,12 +523,11 @@ FieldSpec parseArray(Module&, ClassParser& clparser, Object* p)
|
|||||||
return FieldSpec(true, new Field(clparser.cl, typeName, "", name));
|
return FieldSpec(true, new Field(clparser.cl, typeName, "", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldSpec parseVerbatimField(Module&, ClassParser& clparser, Object* p) {
|
FieldSpec parseVerbatimField(Module&, ClassParser& clparser, Object* p)
|
||||||
|
{
|
||||||
const char* spec = string(car(p));
|
const char* spec = string(car(p));
|
||||||
const char* name = string(car(cdr(p)));
|
const char* name = string(car(cdr(p)));
|
||||||
return FieldSpec(
|
return FieldSpec(false, new Field(clparser.cl, spec, "", name));
|
||||||
false,
|
|
||||||
new Field(clparser.cl, spec, "", name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldSpec parseField(Module& module, ClassParser& clparser, Object* p)
|
FieldSpec parseField(Module& module, ClassParser& clparser, Object* p)
|
||||||
@ -535,8 +562,7 @@ FieldSpec parseField(Module& module, ClassParser& clparser, Object* p)
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void parseSubdeclaration(Module& module, ClassParser& clparser, Object* p)
|
||||||
parseSubdeclaration(Module& module, ClassParser& clparser, Object* p)
|
|
||||||
{
|
{
|
||||||
const char* front = string(car(p));
|
const char* front = string(car(p));
|
||||||
if (equal(front, "extends")) {
|
if (equal(front, "extends")) {
|
||||||
@ -592,8 +618,7 @@ fieldType(const char* spec)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void parseJavaClass(Module& module, ClassParser& clparser, Stream* s)
|
||||||
parseJavaClass(Module& module, ClassParser& clparser, Stream* s)
|
|
||||||
{
|
{
|
||||||
uint32_t magic = s->read4();
|
uint32_t magic = s->read4();
|
||||||
assert(magic == 0xCAFEBABE);
|
assert(magic == 0xCAFEBABE);
|
||||||
@ -659,8 +684,8 @@ parseJavaClass(Module& module, ClassParser& clparser, Stream* s)
|
|||||||
s->skip(interfaceCount * 2);
|
s->skip(interfaceCount * 2);
|
||||||
// for (unsigned i = 0; i < interfaceCount; ++i) {
|
// for (unsigned i = 0; i < interfaceCount; ++i) {
|
||||||
// const char* name = reinterpret_cast<const char*>
|
// const char* name = reinterpret_cast<const char*>
|
||||||
// (pool[pool[s->read2() - 1] - 1]);
|
// (pool[pool[s->read2() - 1] - 1]);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
unsigned fieldCount = s->read2();
|
unsigned fieldCount = s->read2();
|
||||||
for (unsigned i = 0; i < fieldCount; ++i) {
|
for (unsigned i = 0; i < fieldCount; ++i) {
|
||||||
@ -684,12 +709,14 @@ parseJavaClass(Module& module, ClassParser& clparser, Stream* s)
|
|||||||
const char* spec = reinterpret_cast<const char*>(pool[specIndex - 1]);
|
const char* spec = reinterpret_cast<const char*>(pool[specIndex - 1]);
|
||||||
const char* memberType = fieldType(spec);
|
const char* memberType = fieldType(spec);
|
||||||
|
|
||||||
clparser.add(FieldSpec(false, new Field(clparser.cl, memberType, spec, name)));
|
clparser.add(
|
||||||
|
FieldSpec(false, new Field(clparser.cl, memberType, spec, name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clparser.cl->super) {
|
if (clparser.cl->super) {
|
||||||
clparser.cl->methods.insert(clparser.cl->super->methods.begin(), clparser.cl->super->methods.end());
|
clparser.cl->methods.insert(clparser.cl->super->methods.begin(),
|
||||||
|
clparser.cl->super->methods.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned methodCount = s->read2();
|
unsigned methodCount = s->read2();
|
||||||
@ -782,8 +809,9 @@ void parse(Finder* finder, Input* in, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void layoutClass(Module& module, Class* cl) {
|
void layoutClass(Module& module, Class* cl)
|
||||||
if(cl->fixedSize >= 0) {
|
{
|
||||||
|
if (cl->fixedSize >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,12 +822,14 @@ void layoutClass(Module& module, Class* cl) {
|
|||||||
|
|
||||||
alignment = BytesPerWord;
|
alignment = BytesPerWord;
|
||||||
|
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); it++) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
it++) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
|
|
||||||
f.elementSize = sizeOf(module, f.typeName);
|
f.elementSize = sizeOf(module, f.typeName);
|
||||||
|
|
||||||
if(!f.polyfill) { // polyfills contribute no size
|
if (!f.polyfill) { // polyfills contribute no size
|
||||||
alignment = f.elementSize;
|
alignment = f.elementSize;
|
||||||
offset = (offset + alignment - 1) & ~(alignment - 1);
|
offset = (offset + alignment - 1) & ~(alignment - 1);
|
||||||
f.offset = offset;
|
f.offset = offset;
|
||||||
@ -809,7 +839,7 @@ void layoutClass(Module& module, Class* cl) {
|
|||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(cl->arrayField) {
|
if (cl->arrayField) {
|
||||||
Field& f = *cl->arrayField;
|
Field& f = *cl->arrayField;
|
||||||
|
|
||||||
f.elementSize = sizeOf(module, f.typeName);
|
f.elementSize = sizeOf(module, f.typeName);
|
||||||
@ -824,65 +854,68 @@ void layoutClass(Module& module, Class* cl) {
|
|||||||
|
|
||||||
void layoutClasses(Module& module)
|
void layoutClasses(Module& module)
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
layoutClass(module, cl);
|
layoutClass(module, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeOffset(Output* out, size_t offset)
|
||||||
writeOffset(Output* out, size_t offset)
|
|
||||||
{
|
{
|
||||||
out->write(offset);
|
out->write(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeOffset(Output* out, Class* cl)
|
||||||
writeOffset(Output* out, Class* cl)
|
|
||||||
{
|
{
|
||||||
out->write(cl->fixedSize);
|
out->write(cl->fixedSize);
|
||||||
if(cl->arrayField) {
|
if (cl->arrayField) {
|
||||||
out->write(" + pad(length * ");
|
out->write(" + pad(length * ");
|
||||||
out->write(cl->arrayField->elementSize);
|
out->write(cl->arrayField->elementSize);
|
||||||
out->write(")");
|
out->write(")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cppClassName(Class* cl) {
|
std::string cppClassName(Class* cl)
|
||||||
if(cl->name == "jobject") {
|
{
|
||||||
|
if (cl->name == "jobject") {
|
||||||
return "object";
|
return "object";
|
||||||
} else {
|
} else {
|
||||||
return "Gc" + capitalize(cl->name) + "*";
|
return "Gc" + capitalize(cl->name) + "*";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cppFieldType(Module& module, Field& f) {
|
std::string cppFieldType(Module& module, Field& f)
|
||||||
if(f.javaSpec.size() != 0) {
|
{
|
||||||
if(f.javaSpec[0] == 'L') {
|
if (f.javaSpec.size() != 0) {
|
||||||
|
if (f.javaSpec[0] == 'L') {
|
||||||
std::string className = f.javaSpec.substr(1, f.javaSpec.size() - 2);
|
std::string className = f.javaSpec.substr(1, f.javaSpec.size() - 2);
|
||||||
std::map<std::string, Class*>::iterator it = module.javaClasses.find(className);
|
std::map<std::string, Class*>::iterator it
|
||||||
if(it != module.javaClasses.end()) {
|
= module.javaClasses.find(className);
|
||||||
|
if (it != module.javaClasses.end()) {
|
||||||
return cppClassName(it->second);
|
return cppClassName(it->second);
|
||||||
}
|
}
|
||||||
} else if(f.javaSpec[0] == '[') {
|
} else if (f.javaSpec[0] == '[') {
|
||||||
std::map<std::string, Class*>::iterator it = module.javaClasses.find(f.javaSpec);
|
std::map<std::string, Class*>::iterator it
|
||||||
if(it != module.javaClasses.end()) {
|
= module.javaClasses.find(f.javaSpec);
|
||||||
|
if (it != module.javaClasses.end()) {
|
||||||
return cppClassName(it->second);
|
return cppClassName(it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::map<std::string, Class*>::iterator it = module.classes.find(f.typeName);
|
std::map<std::string, Class*>::iterator it = module.classes.find(f.typeName);
|
||||||
assert(f.typeName.size() > 0);
|
assert(f.typeName.size() > 0);
|
||||||
if(it != module.classes.end()) {
|
if (it != module.classes.end()) {
|
||||||
return cppClassName(it->second);
|
return cppClassName(it->second);
|
||||||
} else if(f.typeName == "maybe_object") {
|
} else if (f.typeName == "maybe_object") {
|
||||||
return "uintptr_t";
|
return "uintptr_t";
|
||||||
} else {
|
} else {
|
||||||
return f.typeName;
|
return f.typeName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeAccessor(Output* out, Class* cl, Field& field)
|
||||||
writeAccessor(Output* out, Class* cl, Field& field)
|
|
||||||
{
|
{
|
||||||
std::string typeName = field.typeName;
|
std::string typeName = field.typeName;
|
||||||
|
|
||||||
@ -899,28 +932,32 @@ writeAccessor(Output* out, Class* cl, Field& field)
|
|||||||
out->write(" 1\n\n");
|
out->write(" 1\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeAccessors(Output* out, Module& module)
|
||||||
writeAccessors(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); ++it) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
++it) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
|
|
||||||
if(!f.polyfill) {
|
if (!f.polyfill) {
|
||||||
writeAccessor(out, cl, f);
|
writeAccessor(out, cl, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(cl->arrayField) {
|
if (cl->arrayField) {
|
||||||
writeAccessor(out, cl, *cl->arrayField);
|
writeAccessor(out, cl, *cl->arrayField);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeSizes(Output* out, Module& module)
|
||||||
writeSizes(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
|
|
||||||
out->write("const unsigned FixedSizeOf");
|
out->write("const unsigned FixedSizeOf");
|
||||||
@ -939,8 +976,7 @@ writeSizes(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string obfuscate(const std::string& s)
|
||||||
obfuscate(const std::string& s)
|
|
||||||
{
|
{
|
||||||
if (s == "default" || s == "template" || s == "class" || s == "register"
|
if (s == "default" || s == "template" || s == "class" || s == "register"
|
||||||
|| s == "this") {
|
|| s == "this") {
|
||||||
@ -950,12 +986,13 @@ obfuscate(const std::string& s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeConstructorParameters(Output* out, Module& module, Class* cl)
|
||||||
writeConstructorParameters(Output* out, Module& module, Class* cl)
|
|
||||||
{
|
{
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); ++it) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
++it) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
if(!f.polyfill) {
|
if (!f.polyfill) {
|
||||||
out->write(", ");
|
out->write(", ");
|
||||||
out->write(cppFieldType(module, f));
|
out->write(cppFieldType(module, f));
|
||||||
out->write(" ");
|
out->write(" ");
|
||||||
@ -964,24 +1001,26 @@ writeConstructorParameters(Output* out, Module& module, Class* cl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeConstructorArguments(Output* out, Class* cl)
|
||||||
writeConstructorArguments(Output* out, Class* cl)
|
|
||||||
{
|
{
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); ++it) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
++it) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
if(!f.polyfill) {
|
if (!f.polyfill) {
|
||||||
out->write(", ");
|
out->write(", ");
|
||||||
out->write(obfuscate(f.name));
|
out->write(obfuscate(f.name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeConstructorInitializations(Output* out, Class* cl)
|
||||||
writeConstructorInitializations(Output* out, Class* cl)
|
|
||||||
{
|
{
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); ++it) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
++it) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
if(!f.polyfill) {
|
if (!f.polyfill) {
|
||||||
out->write(" o->set");
|
out->write(" o->set");
|
||||||
out->write(capitalize(f.name));
|
out->write(capitalize(f.name));
|
||||||
out->write("(t, ");
|
out->write("(t, ");
|
||||||
@ -991,10 +1030,11 @@ writeConstructorInitializations(Output* out, Class* cl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void writeClassDeclarations(Output* out, Module& module)
|
void writeClassDeclarations(Output* out, Module& module)
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); it++) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
it++) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
|
|
||||||
out->write("class Gc");
|
out->write("class Gc");
|
||||||
@ -1004,26 +1044,31 @@ void writeClassDeclarations(Output* out, Module& module)
|
|||||||
out->write("\n");
|
out->write("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFieldGcVisible(Module& module, Field& f) {
|
bool isFieldGcVisible(Module& module, Field& f)
|
||||||
|
{
|
||||||
return enumName(module, f) == "object" && !f.nogc;
|
return enumName(module, f) == "object" && !f.nogc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFieldGcMarkable(Module& module, Field& f) {
|
bool isFieldGcMarkable(Module& module, Field& f)
|
||||||
return (f.typeName == "maybe_object" || enumName(module, f) == "object") && !f.nogc;
|
{
|
||||||
|
return (f.typeName == "maybe_object" || enumName(module, f) == "object")
|
||||||
|
&& !f.nogc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeClassAccessors(Output* out, Module& module, Class* cl)
|
void writeClassAccessors(Output* out, Module& module, Class* cl)
|
||||||
{
|
{
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); ++it) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
++it) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
|
|
||||||
if(!f.polyfill) {
|
if (!f.polyfill) {
|
||||||
out->write(" void set");
|
out->write(" void set");
|
||||||
out->write(capitalize(f.name));
|
out->write(capitalize(f.name));
|
||||||
out->write("(Thread* t UNUSED, ");
|
out->write("(Thread* t UNUSED, ");
|
||||||
out->write(cppFieldType(module, f));
|
out->write(cppFieldType(module, f));
|
||||||
out->write(" value) { ");
|
out->write(" value) { ");
|
||||||
if(isFieldGcMarkable(module, f)) {
|
if (isFieldGcMarkable(module, f)) {
|
||||||
out->write("setField(t, this , ");
|
out->write("setField(t, this , ");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
out->write(capitalize(f.name));
|
out->write(capitalize(f.name));
|
||||||
@ -1052,17 +1097,17 @@ void writeClassAccessors(Output* out, Module& module, Class* cl)
|
|||||||
|
|
||||||
out->write(" ");
|
out->write(" ");
|
||||||
out->write(cppFieldType(module, f));
|
out->write(cppFieldType(module, f));
|
||||||
if(!f.polyfill && !isFieldGcMarkable(module, f)) {
|
if (!f.polyfill && !isFieldGcMarkable(module, f)) {
|
||||||
out->write("&");
|
out->write("&");
|
||||||
}
|
}
|
||||||
out->write(" ");
|
out->write(" ");
|
||||||
out->write(obfuscate(f.name));
|
out->write(obfuscate(f.name));
|
||||||
if(f.threadParam || f.polyfill) {
|
if (f.threadParam || f.polyfill) {
|
||||||
out->write("(Thread*");
|
out->write("(Thread*");
|
||||||
} else {
|
} else {
|
||||||
out->write("(");
|
out->write("(");
|
||||||
}
|
}
|
||||||
if(f.polyfill) {
|
if (f.polyfill) {
|
||||||
out->write("); // polyfill, assumed to be implemented elsewhere\n");
|
out->write("); // polyfill, assumed to be implemented elsewhere\n");
|
||||||
} else {
|
} else {
|
||||||
out->write(") { return field_at<");
|
out->write(") { return field_at<");
|
||||||
@ -1073,22 +1118,22 @@ void writeClassAccessors(Output* out, Module& module, Class* cl)
|
|||||||
out->write("); }\n");
|
out->write("); }\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(cl->arrayField) {
|
if (cl->arrayField) {
|
||||||
Field& f = *cl->arrayField;
|
Field& f = *cl->arrayField;
|
||||||
out->write(" avian::util::Slice<");
|
out->write(" avian::util::Slice<");
|
||||||
if(isFieldGcVisible(module, f)) {
|
if (isFieldGcVisible(module, f)) {
|
||||||
out->write("const ");
|
out->write("const ");
|
||||||
}
|
}
|
||||||
out->write(cppFieldType(module, f));
|
out->write(cppFieldType(module, f));
|
||||||
out->write("> ");
|
out->write("> ");
|
||||||
out->write(obfuscate(f.name));
|
out->write(obfuscate(f.name));
|
||||||
out->write("() { return avian::util::Slice<");
|
out->write("() { return avian::util::Slice<");
|
||||||
if(isFieldGcVisible(module, f)) {
|
if (isFieldGcVisible(module, f)) {
|
||||||
out->write("const ");
|
out->write("const ");
|
||||||
}
|
}
|
||||||
out->write(cppFieldType(module, f));
|
out->write(cppFieldType(module, f));
|
||||||
out->write("> (&field_at<");
|
out->write("> (&field_at<");
|
||||||
if(isFieldGcVisible(module, f)) {
|
if (isFieldGcVisible(module, f)) {
|
||||||
out->write("const ");
|
out->write("const ");
|
||||||
}
|
}
|
||||||
out->write(cppFieldType(module, f));
|
out->write(cppFieldType(module, f));
|
||||||
@ -1104,7 +1149,7 @@ void writeClassAccessors(Output* out, Module& module, Class* cl)
|
|||||||
out->write("Element(Thread* t UNUSED, size_t index, ");
|
out->write("Element(Thread* t UNUSED, size_t index, ");
|
||||||
out->write(cppFieldType(module, f));
|
out->write(cppFieldType(module, f));
|
||||||
out->write(" value) { ");
|
out->write(" value) { ");
|
||||||
if(isFieldGcMarkable(module, f)) {
|
if (isFieldGcMarkable(module, f)) {
|
||||||
out->write("setField(t, this , ");
|
out->write("setField(t, this , ");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
out->write(capitalize(f.name));
|
out->write(capitalize(f.name));
|
||||||
@ -1127,7 +1172,9 @@ void writeClassAccessors(Output* out, Module& module, Class* cl)
|
|||||||
|
|
||||||
void writeClasses(Output* out, Module& module)
|
void writeClasses(Output* out, Module& module)
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); it++) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
it++) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
|
|
||||||
out->write("class Gc");
|
out->write("class Gc");
|
||||||
@ -1147,10 +1194,11 @@ void writeClasses(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeInitializerDeclarations(Output* out, Module& module)
|
||||||
writeInitializerDeclarations(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
out->write("void init");
|
out->write("void init");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
@ -1164,10 +1212,11 @@ writeInitializerDeclarations(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeConstructorDeclarations(Output* out, Module& module)
|
||||||
writeConstructorDeclarations(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
out->write("Gc");
|
out->write("Gc");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
@ -1181,10 +1230,11 @@ writeConstructorDeclarations(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeInitializers(Output* out, Module& module)
|
||||||
writeInitializers(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
out->write("void init");
|
out->write("void init");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
@ -1197,7 +1247,9 @@ writeInitializers(Output* out, Module& module)
|
|||||||
out->write(")\n{\n");
|
out->write(")\n{\n");
|
||||||
|
|
||||||
out->write(" setObjectClass(t, reinterpret_cast<object>(o), ");
|
out->write(" setObjectClass(t, reinterpret_cast<object>(o), ");
|
||||||
out->write("reinterpret_cast<GcClass*>(reinterpret_cast<GcArray*>(t->m->types)->body()[Gc::");
|
out->write(
|
||||||
|
"reinterpret_cast<GcClass*>(reinterpret_cast<GcArray*>(t->m->types)->"
|
||||||
|
"body()[Gc::");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
out->write("Type]));\n");
|
out->write("Type]));\n");
|
||||||
|
|
||||||
@ -1207,10 +1259,11 @@ writeInitializers(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeConstructors(Output* out, Module& module)
|
||||||
writeConstructors(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
out->write("Gc");
|
out->write("Gc");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
@ -1223,11 +1276,11 @@ writeConstructors(Output* out, Module& module)
|
|||||||
out->write(")\n{\n");
|
out->write(")\n{\n");
|
||||||
|
|
||||||
bool hasObjectMask = cl->name == "singleton";
|
bool hasObjectMask = cl->name == "singleton";
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); it++) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
it++) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
if (enumName(module, f) == "object"
|
if (enumName(module, f) == "object" and not f.nogc) {
|
||||||
and not f.nogc)
|
|
||||||
{
|
|
||||||
out->write(" PROTECT(t, ");
|
out->write(" PROTECT(t, ");
|
||||||
out->write(obfuscate(f.name));
|
out->write(obfuscate(f.name));
|
||||||
out->write(");\n");
|
out->write(");\n");
|
||||||
@ -1235,7 +1288,7 @@ writeConstructors(Output* out, Module& module)
|
|||||||
hasObjectMask = true;
|
hasObjectMask = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(cl->arrayField) {
|
if (cl->arrayField) {
|
||||||
Field& f = *cl->arrayField;
|
Field& f = *cl->arrayField;
|
||||||
if (f.typeName == "object" and not f.nogc) {
|
if (f.typeName == "object" and not f.nogc) {
|
||||||
hasObjectMask = true;
|
hasObjectMask = true;
|
||||||
@ -1265,11 +1318,12 @@ writeConstructors(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeEnums(Output* out, Module& module)
|
||||||
writeEnums(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
bool wrote = false;
|
bool wrote = false;
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
if (wrote) {
|
if (wrote) {
|
||||||
out->write(",\n");
|
out->write(",\n");
|
||||||
@ -1295,26 +1349,27 @@ set(uint32_t* mask, unsigned index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t typeObjectMask(Module& module, Class* cl)
|
||||||
typeObjectMask(Module& module, Class* cl)
|
|
||||||
{
|
{
|
||||||
assert(cl->fixedSize + (cl->arrayField ? cl->arrayField->elementSize : 0)
|
assert(cl->fixedSize + (cl->arrayField ? cl->arrayField->elementSize : 0)
|
||||||
< 32 * BytesPerWord);
|
< 32 * BytesPerWord);
|
||||||
|
|
||||||
uint32_t mask = 1;
|
uint32_t mask = 1;
|
||||||
|
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); it++) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
it++) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
unsigned offset = f.offset / BytesPerWord;
|
unsigned offset = f.offset / BytesPerWord;
|
||||||
if(isFieldGcVisible(module, f)) {
|
if (isFieldGcVisible(module, f)) {
|
||||||
set(&mask, offset);
|
set(&mask, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cl->arrayField) {
|
if (cl->arrayField) {
|
||||||
Field& f = *cl->arrayField;
|
Field& f = *cl->arrayField;
|
||||||
unsigned offset = f.offset / BytesPerWord;
|
unsigned offset = f.offset / BytesPerWord;
|
||||||
if(isFieldGcVisible(module, f)) {
|
if (isFieldGcVisible(module, f)) {
|
||||||
set(&mask, offset);
|
set(&mask, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1322,14 +1377,16 @@ typeObjectMask(Module& module, Class* cl)
|
|||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeInitialization(Output* out,
|
||||||
writeInitialization(Output* out, Module& module, std::set<Class*>& alreadyInited, Class* cl)
|
Module& module,
|
||||||
|
std::set<Class*>& alreadyInited,
|
||||||
|
Class* cl)
|
||||||
{
|
{
|
||||||
if(alreadyInited.find(cl) != alreadyInited.end()) {
|
if (alreadyInited.find(cl) != alreadyInited.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
alreadyInited.insert(cl);
|
alreadyInited.insert(cl);
|
||||||
if(cl->super && cl->name != "intArray" && cl->name != "class") {
|
if (cl->super && cl->name != "intArray" && cl->name != "class") {
|
||||||
writeInitialization(out, module, alreadyInited, cl->super);
|
writeInitialization(out, module, alreadyInited, cl->super);
|
||||||
}
|
}
|
||||||
out->write("bootClass(t, Gc::");
|
out->write("bootClass(t, Gc::");
|
||||||
@ -1362,24 +1419,24 @@ writeInitialization(Output* out, Module& module, std::set<Class*>& alreadyInited
|
|||||||
out->write(");\n");
|
out->write(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeInitializations(Output* out, Module& module)
|
||||||
writeInitializations(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
std::set<Class*> alreadyInited;
|
std::set<Class*> alreadyInited;
|
||||||
|
|
||||||
writeInitialization(out, module, alreadyInited, module.classes["intArray"]);
|
writeInitialization(out, module, alreadyInited, module.classes["intArray"]);
|
||||||
writeInitialization(out, module, alreadyInited, module.classes["class"]);
|
writeInitialization(out, module, alreadyInited, module.classes["class"]);
|
||||||
|
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
if(cl->name != "intArray" && cl->name != "class") {
|
if (cl->name != "intArray" && cl->name != "class") {
|
||||||
writeInitialization(out, module, alreadyInited, cl);
|
writeInitialization(out, module, alreadyInited, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeJavaInitialization(Output* out, Class* cl)
|
||||||
writeJavaInitialization(Output* out, Class* cl)
|
|
||||||
{
|
{
|
||||||
out->write("bootJavaClass(t, Gc::");
|
out->write("bootJavaClass(t, Gc::");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
@ -1405,10 +1462,11 @@ writeJavaInitialization(Output* out, Class* cl)
|
|||||||
out->write(", bootMethod);\n");
|
out->write(", bootMethod);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeJavaInitializations(Output* out, Module& module)
|
||||||
writeJavaInitializations(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
if (cl->javaName.size()) {
|
if (cl->javaName.size()) {
|
||||||
writeJavaInitialization(out, cl);
|
writeJavaInitialization(out, cl);
|
||||||
@ -1416,22 +1474,14 @@ writeJavaInitializations(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeNameInitialization(Output* out, Class* cl)
|
||||||
writeNameInitialization(Output* out, Class* cl)
|
|
||||||
{
|
{
|
||||||
out->write("nameClass(t, Gc::");
|
out->write("nameClass(t, Gc::");
|
||||||
out->write(capitalize(cl->name));
|
out->write(capitalize(cl->name));
|
||||||
out->write("Type, \"");
|
out->write("Type, \"");
|
||||||
if (cl->name == "jbyte"
|
if (cl->name == "jbyte" or cl->name == "jboolean" or cl->name == "jshort"
|
||||||
or cl->name == "jboolean"
|
or cl->name == "jchar" or cl->name == "jint" or cl->name == "jlong"
|
||||||
or cl->name == "jshort"
|
or cl->name == "jfloat" or cl->name == "jdouble" or cl->name == "jvoid") {
|
||||||
or cl->name == "jchar"
|
|
||||||
or cl->name == "jint"
|
|
||||||
or cl->name == "jlong"
|
|
||||||
or cl->name == "jfloat"
|
|
||||||
or cl->name == "jdouble"
|
|
||||||
or cl->name == "jvoid")
|
|
||||||
{
|
|
||||||
out->write(cl->name.substr(1, cl->name.size() - 1));
|
out->write(cl->name.substr(1, cl->name.size() - 1));
|
||||||
} else {
|
} else {
|
||||||
out->write("vm::");
|
out->write("vm::");
|
||||||
@ -1440,10 +1490,11 @@ writeNameInitialization(Output* out, Class* cl)
|
|||||||
out->write("\");\n");
|
out->write("\");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeNameInitializations(Output* out, Module& module)
|
||||||
writeNameInitializations(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
if (!cl->javaName.size()) {
|
if (!cl->javaName.size()) {
|
||||||
writeNameInitialization(out, cl);
|
writeNameInitialization(out, cl);
|
||||||
@ -1451,15 +1502,16 @@ writeNameInitializations(Output* out, Module& module)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeMap(Output* out, Module& module, Class* cl)
|
||||||
writeMap(Output* out, Module& module, Class* cl)
|
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
uintptr_t ownerId = 0;
|
uintptr_t ownerId = 0;
|
||||||
for(std::vector<Field*>::iterator it = cl->fields.begin(); it != cl->fields.end(); it++) {
|
for (std::vector<Field*>::iterator it = cl->fields.begin();
|
||||||
|
it != cl->fields.end();
|
||||||
|
it++) {
|
||||||
Field& f = **it;
|
Field& f = **it;
|
||||||
|
|
||||||
if(ownerId && ownerId != f.ownerId) {
|
if (ownerId && ownerId != f.ownerId) {
|
||||||
ss << "Type_pad, ";
|
ss << "Type_pad, ";
|
||||||
}
|
}
|
||||||
ownerId = f.ownerId;
|
ownerId = f.ownerId;
|
||||||
@ -1473,9 +1525,9 @@ writeMap(Output* out, Module& module, Class* cl)
|
|||||||
ss << ", ";
|
ss << ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cl->arrayField) {
|
if (cl->arrayField) {
|
||||||
Field& f = *cl->arrayField;
|
Field& f = *cl->arrayField;
|
||||||
if(ownerId && ownerId != f.ownerId) {
|
if (ownerId && ownerId != f.ownerId) {
|
||||||
ss << "Type_pad, ";
|
ss << "Type_pad, ";
|
||||||
}
|
}
|
||||||
ss << "Type_array, ";
|
ss << "Type_array, ";
|
||||||
@ -1489,14 +1541,15 @@ writeMap(Output* out, Module& module, Class* cl)
|
|||||||
out->write(ss.str());
|
out->write(ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void writeMaps(Output* out, Module& module)
|
||||||
writeMaps(Output* out, Module& module)
|
|
||||||
{
|
{
|
||||||
out->write("Type types[][");
|
out->write("Type types[][");
|
||||||
out->write(module.classes.size());
|
out->write(module.classes.size());
|
||||||
out->write("] = {\n");
|
out->write("] = {\n");
|
||||||
bool wrote = false;
|
bool wrote = false;
|
||||||
for(std::map<std::string, Class*>::iterator it = module.classes.begin(); it != module.classes.end(); ++it) {
|
for (std::map<std::string, Class*>::iterator it = module.classes.begin();
|
||||||
|
it != module.classes.end();
|
||||||
|
++it) {
|
||||||
Class* cl = it->second;
|
Class* cl = it->second;
|
||||||
if (wrote) {
|
if (wrote) {
|
||||||
out->write(",\n");
|
out->write(",\n");
|
||||||
|
187
src/util.cpp
187
src/util.cpp
@ -49,21 +49,20 @@ class TreeContext {
|
|||||||
bool fresh;
|
bool fresh;
|
||||||
};
|
};
|
||||||
|
|
||||||
List<GcTreeNode*>*
|
List<GcTreeNode*>* path(TreeContext* c,
|
||||||
path(TreeContext* c, GcTreeNode* node, List<GcTreeNode*>* next)
|
GcTreeNode* node,
|
||||||
|
List<GcTreeNode*>* next)
|
||||||
{
|
{
|
||||||
return new(c->zone) List<GcTreeNode*>(node, next);
|
return new (c->zone) List<GcTreeNode*>(node, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object getTreeNodeValue(Thread*, GcTreeNode* n)
|
||||||
getTreeNodeValue(Thread*, GcTreeNode* n)
|
|
||||||
{
|
{
|
||||||
return reinterpret_cast<object>
|
return reinterpret_cast<object>
|
||||||
(alias(n, TreeNodeValue) & PointerMask);
|
(alias(n, TreeNodeValue) & PointerMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void setTreeNodeValue(Thread* t, GcTreeNode* n, object value)
|
||||||
setTreeNodeValue(Thread* t, GcTreeNode* n, object value)
|
|
||||||
{
|
{
|
||||||
intptr_t red = alias(n, TreeNodeValue) & (~PointerMask);
|
intptr_t red = alias(n, TreeNodeValue) & (~PointerMask);
|
||||||
|
|
||||||
@ -72,14 +71,12 @@ setTreeNodeValue(Thread* t, GcTreeNode* n, object value)
|
|||||||
alias(n, TreeNodeValue) |= red;
|
alias(n, TreeNodeValue) |= red;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool treeNodeRed(Thread*, GcTreeNode* n)
|
||||||
treeNodeRed(Thread*, GcTreeNode* n)
|
|
||||||
{
|
{
|
||||||
return (alias(n, TreeNodeValue) & (~PointerMask)) == 1;
|
return (alias(n, TreeNodeValue) & (~PointerMask)) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void setTreeNodeRed(Thread*, GcTreeNode* n, bool red)
|
||||||
setTreeNodeRed(Thread*, GcTreeNode* n, bool red)
|
|
||||||
{
|
{
|
||||||
if (red) {
|
if (red) {
|
||||||
alias(n, TreeNodeValue) |= 1;
|
alias(n, TreeNodeValue) |= 1;
|
||||||
@ -88,20 +85,21 @@ setTreeNodeRed(Thread*, GcTreeNode* n, bool red)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GcTreeNode*
|
inline GcTreeNode* cloneTreeNode(Thread* t, GcTreeNode* n)
|
||||||
cloneTreeNode(Thread* t, GcTreeNode* n)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, n);
|
PROTECT(t, n);
|
||||||
|
|
||||||
GcTreeNode* newNode = makeTreeNode
|
GcTreeNode* newNode
|
||||||
(t, getTreeNodeValue(t, n), n->left(), n->right());
|
= makeTreeNode(t, getTreeNodeValue(t, n), n->left(), n->right());
|
||||||
setTreeNodeRed(t, newNode, treeNodeRed(t, n));
|
setTreeNodeRed(t, newNode, treeNodeRed(t, n));
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTreeNode*
|
GcTreeNode* treeFind(Thread* t,
|
||||||
treeFind(Thread* t, GcTreeNode* tree, intptr_t key, GcTreeNode* sentinal,
|
GcTreeNode* tree,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
intptr_t key,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
||||||
{
|
{
|
||||||
GcTreeNode* node = tree;
|
GcTreeNode* node = tree;
|
||||||
while (node != sentinal) {
|
while (node != sentinal) {
|
||||||
@ -118,10 +116,13 @@ treeFind(Thread* t, GcTreeNode* tree, intptr_t key, GcTreeNode* sentinal,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void treeFind(Thread* t,
|
||||||
treeFind(Thread* t, TreeContext* c, GcTreeNode* old, intptr_t key, GcTreeNode* node,
|
TreeContext* c,
|
||||||
GcTreeNode* sentinal,
|
GcTreeNode* old,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
intptr_t key,
|
||||||
|
GcTreeNode* node,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
||||||
{
|
{
|
||||||
PROTECT(t, old);
|
PROTECT(t, old);
|
||||||
PROTECT(t, node);
|
PROTECT(t, node);
|
||||||
@ -173,8 +174,7 @@ treeFind(Thread* t, TreeContext* c, GcTreeNode* old, intptr_t key, GcTreeNode* n
|
|||||||
c->ancestors = c->ancestors;
|
c->ancestors = c->ancestors;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTreeNode*
|
GcTreeNode* leftRotate(Thread* t, GcTreeNode* n)
|
||||||
leftRotate(Thread* t, GcTreeNode* n)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, n);
|
PROTECT(t, n);
|
||||||
|
|
||||||
@ -184,8 +184,7 @@ leftRotate(Thread* t, GcTreeNode* n)
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTreeNode*
|
GcTreeNode* rightRotate(Thread* t, GcTreeNode* n)
|
||||||
rightRotate(Thread* t, GcTreeNode* n)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, n);
|
PROTECT(t, n);
|
||||||
|
|
||||||
@ -195,8 +194,7 @@ rightRotate(Thread* t, GcTreeNode* n)
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTreeNode*
|
GcTreeNode* treeAdd(Thread* t, TreeContext* c)
|
||||||
treeAdd(Thread* t, TreeContext* c)
|
|
||||||
{
|
{
|
||||||
GcTreeNode* new_ = c->node;
|
GcTreeNode* new_ = c->node;
|
||||||
PROTECT(t, new_);
|
PROTECT(t, new_);
|
||||||
@ -207,16 +205,11 @@ treeAdd(Thread* t, TreeContext* c)
|
|||||||
// rebalance
|
// rebalance
|
||||||
setTreeNodeRed(t, new_, true);
|
setTreeNodeRed(t, new_, true);
|
||||||
while (c->ancestors != 0 and treeNodeRed(t, c->ancestors->item)) {
|
while (c->ancestors != 0 and treeNodeRed(t, c->ancestors->item)) {
|
||||||
if (c->ancestors->item
|
if (c->ancestors->item == c->ancestors->next->item->left()) {
|
||||||
== c->ancestors->next->item->left())
|
if (treeNodeRed(t, c->ancestors->next->item->right())) {
|
||||||
{
|
|
||||||
if (treeNodeRed
|
|
||||||
(t, c->ancestors->next->item->right()))
|
|
||||||
{
|
|
||||||
setTreeNodeRed(t, c->ancestors->item, false);
|
setTreeNodeRed(t, c->ancestors->item, false);
|
||||||
|
|
||||||
GcTreeNode* n = cloneTreeNode
|
GcTreeNode* n = cloneTreeNode(t, c->ancestors->next->item->right());
|
||||||
(t, c->ancestors->next->item->right());
|
|
||||||
|
|
||||||
c->ancestors->next->item->setRight(t, n);
|
c->ancestors->next->item->setRight(t, n);
|
||||||
|
|
||||||
@ -247,8 +240,7 @@ treeAdd(Thread* t, TreeContext* c)
|
|||||||
if (c->ancestors->next->next == 0) {
|
if (c->ancestors->next->next == 0) {
|
||||||
newRoot = n;
|
newRoot = n;
|
||||||
} else if (c->ancestors->next->next->item->right()
|
} else if (c->ancestors->next->next->item->right()
|
||||||
== c->ancestors->next->item)
|
== c->ancestors->next->item) {
|
||||||
{
|
|
||||||
c->ancestors->next->next->item->setRight(t, n);
|
c->ancestors->next->next->item->setRight(t, n);
|
||||||
} else {
|
} else {
|
||||||
c->ancestors->next->next->item->setLeft(t, n);
|
c->ancestors->next->next->item->setLeft(t, n);
|
||||||
@ -257,13 +249,10 @@ treeAdd(Thread* t, TreeContext* c)
|
|||||||
}
|
}
|
||||||
} else { // this is just the reverse of the code above (right and
|
} else { // this is just the reverse of the code above (right and
|
||||||
// left swapped):
|
// left swapped):
|
||||||
if (treeNodeRed
|
if (treeNodeRed(t, c->ancestors->next->item->left())) {
|
||||||
(t, c->ancestors->next->item->left()))
|
|
||||||
{
|
|
||||||
setTreeNodeRed(t, c->ancestors->item, false);
|
setTreeNodeRed(t, c->ancestors->item, false);
|
||||||
|
|
||||||
GcTreeNode* n = cloneTreeNode
|
GcTreeNode* n = cloneTreeNode(t, c->ancestors->next->item->left());
|
||||||
(t, c->ancestors->next->item->left());
|
|
||||||
|
|
||||||
c->ancestors->next->item->setLeft(t, n);
|
c->ancestors->next->item->setLeft(t, n);
|
||||||
|
|
||||||
@ -294,8 +283,7 @@ treeAdd(Thread* t, TreeContext* c)
|
|||||||
if (c->ancestors->next->next == 0) {
|
if (c->ancestors->next->next == 0) {
|
||||||
newRoot = n;
|
newRoot = n;
|
||||||
} else if (c->ancestors->next->next->item->left()
|
} else if (c->ancestors->next->next->item->left()
|
||||||
== c->ancestors->next->item)
|
== c->ancestors->next->item) {
|
||||||
{
|
|
||||||
c->ancestors->next->next->item->setLeft(t, n);
|
c->ancestors->next->next->item->setLeft(t, n);
|
||||||
} else {
|
} else {
|
||||||
c->ancestors->next->next->item->setRight(t, n);
|
c->ancestors->next->next->item->setRight(t, n);
|
||||||
@ -314,17 +302,19 @@ treeAdd(Thread* t, TreeContext* c)
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
GcTriple*
|
GcTriple* hashMapFindNode(Thread* t,
|
||||||
hashMapFindNode(Thread* t, GcHashMap* map, object key,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object),
|
object key,
|
||||||
bool (*equal)(Thread*, object, object))
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object))
|
||||||
{
|
{
|
||||||
bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type);
|
bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type);
|
||||||
|
|
||||||
GcArray* array = map->array();
|
GcArray* array = map->array();
|
||||||
if (array) {
|
if (array) {
|
||||||
unsigned index = hash(t, key) & (array->length() - 1);
|
unsigned index = hash(t, key) & (array->length() - 1);
|
||||||
for (GcTriple* n = cast<GcTriple>(t, array->body()[index]); n; n = cast<GcTriple>(t, n->third())) {
|
for (GcTriple* n = cast<GcTriple>(t, array->body()[index]); n;
|
||||||
|
n = cast<GcTriple>(t, n->third())) {
|
||||||
object k = n->first();
|
object k = n->first();
|
||||||
if (weak) {
|
if (weak) {
|
||||||
k = cast<GcJreference>(t, k)->target();
|
k = cast<GcJreference>(t, k)->target();
|
||||||
@ -341,9 +331,10 @@ hashMapFindNode(Thread* t, GcHashMap* map, object key,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void hashMapResize(Thread* t,
|
||||||
hashMapResize(Thread* t, GcHashMap* map, uint32_t (*hash)(Thread*, object),
|
GcHashMap* map,
|
||||||
unsigned size)
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
unsigned size)
|
||||||
{
|
{
|
||||||
PROTECT(t, map);
|
PROTECT(t, map);
|
||||||
|
|
||||||
@ -370,7 +361,8 @@ hashMapResize(Thread* t, GcHashMap* map, uint32_t (*hash)(Thread*, object),
|
|||||||
bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type);
|
bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type);
|
||||||
for (unsigned i = 0; i < oldArray->length(); ++i) {
|
for (unsigned i = 0; i < oldArray->length(); ++i) {
|
||||||
GcTriple* next;
|
GcTriple* next;
|
||||||
for (GcTriple* p = cast<GcTriple>(t, oldArray->body()[i]); p; p = next) {
|
for (GcTriple* p = cast<GcTriple>(t, oldArray->body()[i]); p;
|
||||||
|
p = next) {
|
||||||
next = cast<GcTriple>(t, p->third());
|
next = cast<GcTriple>(t, p->third());
|
||||||
|
|
||||||
object k = p->first();
|
object k = p->first();
|
||||||
@ -393,9 +385,11 @@ hashMapResize(Thread* t, GcHashMap* map, uint32_t (*hash)(Thread*, object),
|
|||||||
map->setArray(t, newArray);
|
map->setArray(t, newArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void hashMapInsert(Thread* t,
|
||||||
hashMapInsert(Thread* t, GcHashMap* map, object key, object value,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object))
|
object key,
|
||||||
|
object value,
|
||||||
|
uint32_t (*hash)(Thread*, object))
|
||||||
{
|
{
|
||||||
// note that we reinitialize the array variable whenever an
|
// note that we reinitialize the array variable whenever an
|
||||||
// allocation (and thus possibly a collection) occurs, in case the
|
// allocation (and thus possibly a collection) occurs, in case the
|
||||||
@ -409,7 +403,7 @@ hashMapInsert(Thread* t, GcHashMap* map, object key, object value,
|
|||||||
|
|
||||||
GcArray* array = map->array();
|
GcArray* array = map->array();
|
||||||
|
|
||||||
++ map->size();
|
++map->size();
|
||||||
|
|
||||||
if (array == 0 or map->size() >= array->length() * 2) {
|
if (array == 0 or map->size() >= array->length() * 2) {
|
||||||
PROTECT(t, key);
|
PROTECT(t, key);
|
||||||
@ -452,22 +446,26 @@ hashMapInsert(Thread* t, GcHashMap* map, object key, object value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTriple*
|
GcTriple* hashMapRemoveNode(Thread* t,
|
||||||
hashMapRemoveNode(Thread* t, GcHashMap* map, unsigned index, GcTriple* p, GcTriple* n)
|
GcHashMap* map,
|
||||||
|
unsigned index,
|
||||||
|
GcTriple* p,
|
||||||
|
GcTriple* n)
|
||||||
{
|
{
|
||||||
if (p) {
|
if (p) {
|
||||||
p->setThird(t, n->third());
|
p->setThird(t, n->third());
|
||||||
} else {
|
} else {
|
||||||
map->array()->setBodyElement(t, index, n->third());
|
map->array()->setBodyElement(t, index, n->third());
|
||||||
}
|
}
|
||||||
-- map->size();
|
--map->size();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object hashMapRemove(Thread* t,
|
||||||
hashMapRemove(Thread* t, GcHashMap* map, object key,
|
GcHashMap* map,
|
||||||
uint32_t (*hash)(Thread*, object),
|
object key,
|
||||||
bool (*equal)(Thread*, object, object))
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object))
|
||||||
{
|
{
|
||||||
bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type);
|
bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type);
|
||||||
|
|
||||||
@ -481,7 +479,8 @@ hashMapRemove(Thread* t, GcHashMap* map, object key,
|
|||||||
if (weak) {
|
if (weak) {
|
||||||
k = cast<GcJreference>(t, k)->target();
|
k = cast<GcJreference>(t, k)->target();
|
||||||
if (k == 0) {
|
if (k == 0) {
|
||||||
n = cast<GcTriple>(t, hashMapRemoveNode(t, map, index, p, n)->third());
|
n = cast<GcTriple>(t,
|
||||||
|
hashMapRemoveNode(t, map, index, p, n)->third());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -495,9 +494,7 @@ hashMapRemove(Thread* t, GcHashMap* map, object key,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((not t->m->collecting)
|
if ((not t->m->collecting) and map->size() <= array->length() / 3) {
|
||||||
and map->size() <= array->length() / 3)
|
|
||||||
{
|
|
||||||
PROTECT(t, o);
|
PROTECT(t, o);
|
||||||
hashMapResize(t, map, hash, array->length() / 2);
|
hashMapResize(t, map, hash, array->length() / 2);
|
||||||
}
|
}
|
||||||
@ -506,12 +503,11 @@ hashMapRemove(Thread* t, GcHashMap* map, object key,
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void listAppend(Thread* t, GcList* list, object value)
|
||||||
listAppend(Thread* t, GcList* list, object value)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, list);
|
PROTECT(t, list);
|
||||||
|
|
||||||
++ list->size();
|
++list->size();
|
||||||
|
|
||||||
object p = makePair(t, value, 0);
|
object p = makePair(t, value, 0);
|
||||||
if (list->front()) {
|
if (list->front()) {
|
||||||
@ -522,18 +518,17 @@ listAppend(Thread* t, GcList* list, object value)
|
|||||||
list->setRear(t, p);
|
list->setRear(t, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcVector*
|
GcVector* vectorAppend(Thread* t, GcVector* vector, object value)
|
||||||
vectorAppend(Thread* t, GcVector* vector, object value)
|
|
||||||
{
|
{
|
||||||
if (vector->length() == vector->size()) {
|
if (vector->length() == vector->size()) {
|
||||||
PROTECT(t, vector);
|
PROTECT(t, vector);
|
||||||
PROTECT(t, value);
|
PROTECT(t, value);
|
||||||
|
|
||||||
GcVector* newVector = makeVector
|
GcVector* newVector
|
||||||
(t, vector->size(), max(16, vector->size() * 2));
|
= makeVector(t, vector->size(), max(16, vector->size() * 2));
|
||||||
|
|
||||||
if (vector->size()) {
|
if (vector->size()) {
|
||||||
for(size_t i = 0; i < vector->size(); i++) {
|
for (size_t i = 0; i < vector->size(); i++) {
|
||||||
newVector->setBodyElement(t, i, vector->body()[i]);
|
newVector->setBodyElement(t, i, vector->body()[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,20 +537,18 @@ vectorAppend(Thread* t, GcVector* vector, object value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector->setBodyElement(t, vector->size(), value);
|
vector->setBodyElement(t, vector->size(), value);
|
||||||
++ vector->size();
|
++vector->size();
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
GcArray*
|
GcArray* growArray(Thread* t, GcArray* array)
|
||||||
growArray(Thread* t, GcArray* array)
|
|
||||||
{
|
{
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
GcArray* newArray = makeArray
|
GcArray* newArray = makeArray(t, array == 0 ? 16 : (array->length() * 2));
|
||||||
(t, array == 0 ? 16 : (array->length() * 2));
|
|
||||||
|
|
||||||
if (array) {
|
if (array) {
|
||||||
for(size_t i = 0; i < array->length(); i++) {
|
for (size_t i = 0; i < array->length(); i++) {
|
||||||
newArray->setBodyElement(t, i, array->body()[i]);
|
newArray->setBodyElement(t, i, array->body()[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -563,18 +556,23 @@ growArray(Thread* t, GcArray* array)
|
|||||||
return newArray;
|
return newArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object treeQuery(Thread* t,
|
||||||
treeQuery(Thread* t, GcTreeNode* tree, intptr_t key, GcTreeNode* sentinal,
|
GcTreeNode* tree,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
intptr_t key,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
||||||
{
|
{
|
||||||
GcTreeNode* node = treeFind(t, tree, key, sentinal, compare);
|
GcTreeNode* node = treeFind(t, tree, key, sentinal, compare);
|
||||||
return (node ? getTreeNodeValue(t, node) : 0);
|
return (node ? getTreeNodeValue(t, node) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GcTreeNode*
|
GcTreeNode* treeInsert(Thread* t,
|
||||||
treeInsert(Thread* t, Zone* zone, GcTreeNode* tree, intptr_t key, object value,
|
Zone* zone,
|
||||||
GcTreeNode* sentinal,
|
GcTreeNode* tree,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
intptr_t key,
|
||||||
|
object value,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
||||||
{
|
{
|
||||||
PROTECT(t, tree);
|
PROTECT(t, tree);
|
||||||
PROTECT(t, sentinal);
|
PROTECT(t, sentinal);
|
||||||
@ -588,9 +586,12 @@ treeInsert(Thread* t, Zone* zone, GcTreeNode* tree, intptr_t key, object value,
|
|||||||
return treeAdd(t, &c);
|
return treeAdd(t, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void treeUpdate(Thread* t,
|
||||||
treeUpdate(Thread* t, GcTreeNode* tree, intptr_t key, object value, GcTreeNode* sentinal,
|
GcTreeNode* tree,
|
||||||
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
intptr_t key,
|
||||||
|
object value,
|
||||||
|
GcTreeNode* sentinal,
|
||||||
|
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
||||||
{
|
{
|
||||||
setTreeNodeValue(t, treeFind(t, tree, key, sentinal, compare), value);
|
setTreeNodeValue(t, treeFind(t, tree, key, sentinal, compare), value);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user