2014-04-21 02:14:48 +00:00
|
|
|
/* Copyright (c) 2008-2014, Avian Contributors
|
2008-02-19 18:06:52 +00:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
|
|
for any purpose with or without fee is hereby granted, provided
|
|
|
|
that the above copyright notice and this permission notice appear
|
|
|
|
in all copies.
|
|
|
|
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
|
|
details. */
|
|
|
|
|
2013-02-27 20:25:50 +00:00
|
|
|
#include "avian/common.h"
|
2014-02-07 21:24:56 +00:00
|
|
|
#include <avian/system/system.h>
|
2014-02-22 00:06:17 +00:00
|
|
|
#include <avian/system/signal.h>
|
2013-02-27 20:25:50 +00:00
|
|
|
#include "avian/constants.h"
|
|
|
|
#include "avian/machine.h"
|
|
|
|
#include "avian/processor.h"
|
|
|
|
#include "avian/process.h"
|
|
|
|
#include "avian/arch.h"
|
2007-07-02 01:42:35 +00:00
|
|
|
|
2013-02-20 05:56:05 +00:00
|
|
|
#include <avian/util/runtime-array.h>
|
2013-12-11 04:36:55 +00:00
|
|
|
#include <avian/util/list.h>
|
2014-02-25 22:46:35 +00:00
|
|
|
#include <avian/util/slice.h>
|
2013-02-16 03:28:39 +00:00
|
|
|
|
2007-06-18 19:23:44 +00:00
|
|
|
using namespace vm;
|
2014-02-22 00:06:17 +00:00
|
|
|
using namespace avian::system;
|
2007-06-18 19:23:44 +00:00
|
|
|
|
2013-01-28 15:20:52 +00:00
|
|
|
namespace local {
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
const unsigned FrameBaseOffset = 0;
|
|
|
|
const unsigned FrameNextOffset = 1;
|
|
|
|
const unsigned FrameMethodOffset = 2;
|
|
|
|
const unsigned FrameIpOffset = 3;
|
|
|
|
const unsigned FrameFootprint = 4;
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
class Thread: public vm::Thread {
|
|
|
|
public:
|
2012-08-11 12:56:19 +00:00
|
|
|
|
2014-06-28 19:16:26 +00:00
|
|
|
Thread(Machine* m, GcThread* javaThread, vm::Thread* parent):
|
2014-06-28 23:24:24 +00:00
|
|
|
vm::Thread(m, javaThread, parent),
|
2007-09-24 01:39:03 +00:00
|
|
|
ip(0),
|
|
|
|
sp(0),
|
|
|
|
frame(-1),
|
2012-08-11 12:56:19 +00:00
|
|
|
code(0),
|
2013-12-11 04:36:55 +00:00
|
|
|
stackPointers(0)
|
2007-09-24 01:39:03 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
unsigned ip;
|
|
|
|
unsigned sp;
|
|
|
|
int frame;
|
2014-06-29 05:40:16 +00:00
|
|
|
GcCode* code;
|
2013-12-11 04:36:55 +00:00
|
|
|
List<unsigned>* stackPointers;
|
2012-03-14 18:36:42 +00:00
|
|
|
uintptr_t stack[0];
|
2007-09-24 01:39:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pushObject(Thread* t, object o)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "push object %p at %d\n", o, t->sp);
|
|
|
|
}
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->sp + 1 < stackSizeInWords(t) / 2);
|
2007-09-24 01:39:03 +00:00
|
|
|
t->stack[(t->sp * 2) ] = ObjectTag;
|
|
|
|
t->stack[(t->sp * 2) + 1] = reinterpret_cast<uintptr_t>(o);
|
|
|
|
++ t->sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pushInt(Thread* t, uint32_t v)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "push int %d at %d\n", v, t->sp);
|
|
|
|
}
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->sp + 1 < stackSizeInWords(t) / 2);
|
2007-09-24 01:39:03 +00:00
|
|
|
t->stack[(t->sp * 2) ] = IntTag;
|
|
|
|
t->stack[(t->sp * 2) + 1] = v;
|
|
|
|
++ t->sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pushFloat(Thread* t, float v)
|
|
|
|
{
|
2007-10-15 19:12:38 +00:00
|
|
|
pushInt(t, floatToBits(v));
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pushLong(Thread* t, uint64_t v)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
2012-11-30 10:14:35 +00:00
|
|
|
fprintf(stderr, "push long %" LLD " at %d\n", v, t->sp);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pushInt(t, v >> 32);
|
|
|
|
pushInt(t, v & 0xFFFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pushDouble(Thread* t, double v)
|
|
|
|
{
|
2009-08-06 17:52:36 +00:00
|
|
|
uint64_t w = doubleToBits(v);
|
|
|
|
pushLong(t, w);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
popObject(Thread* t)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "pop object %p at %d\n",
|
|
|
|
reinterpret_cast<object>(t->stack[((t->sp - 1) * 2) + 1]),
|
|
|
|
t->sp - 1);
|
|
|
|
}
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->stack[(t->sp - 1) * 2] == ObjectTag);
|
2007-09-24 01:39:03 +00:00
|
|
|
return reinterpret_cast<object>(t->stack[((-- t->sp) * 2) + 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint32_t
|
|
|
|
popInt(Thread* t)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
2012-11-30 10:14:35 +00:00
|
|
|
fprintf(stderr, "pop int %" ULD " at %d\n",
|
2007-09-24 01:39:03 +00:00
|
|
|
t->stack[((t->sp - 1) * 2) + 1],
|
|
|
|
t->sp - 1);
|
|
|
|
}
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->stack[(t->sp - 1) * 2] == IntTag);
|
2007-09-24 01:39:03 +00:00
|
|
|
return t->stack[((-- t->sp) * 2) + 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline float
|
|
|
|
popFloat(Thread* t)
|
|
|
|
{
|
2007-10-15 19:12:38 +00:00
|
|
|
return bitsToFloat(popInt(t));
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline uint64_t
|
|
|
|
popLong(Thread* t)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
2012-11-30 10:14:35 +00:00
|
|
|
fprintf(stderr, "pop long %" LLD " at %d\n",
|
2007-09-24 01:39:03 +00:00
|
|
|
(static_cast<uint64_t>(t->stack[((t->sp - 2) * 2) + 1]) << 32)
|
|
|
|
| static_cast<uint64_t>(t->stack[((t->sp - 1) * 2) + 1]),
|
|
|
|
t->sp - 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t a = popInt(t);
|
|
|
|
uint64_t b = popInt(t);
|
|
|
|
return (b << 32) | a;
|
|
|
|
}
|
|
|
|
|
2009-08-06 17:52:36 +00:00
|
|
|
inline double
|
2007-09-24 01:39:03 +00:00
|
|
|
popDouble(Thread* t)
|
|
|
|
{
|
2009-08-06 17:52:36 +00:00
|
|
|
uint64_t v = popLong(t);
|
|
|
|
return bitsToDouble(v);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
peekObject(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "peek object %p at %d\n",
|
|
|
|
reinterpret_cast<object>(t->stack[(index * 2) + 1]),
|
|
|
|
index);
|
|
|
|
}
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, index < stackSizeInWords(t) / 2);
|
|
|
|
assertT(t, t->stack[index * 2] == ObjectTag);
|
2012-06-14 01:10:28 +00:00
|
|
|
return reinterpret_cast<object>(t->stack[(index * 2) + 1]);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline uint32_t
|
|
|
|
peekInt(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
2012-11-30 10:14:35 +00:00
|
|
|
fprintf(stderr, "peek int %" ULD " at %d\n",
|
2007-09-24 01:39:03 +00:00
|
|
|
t->stack[(index * 2) + 1],
|
|
|
|
index);
|
|
|
|
}
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, index < stackSizeInWords(t) / 2);
|
|
|
|
assertT(t, t->stack[index * 2] == IntTag);
|
2007-09-24 01:39:03 +00:00
|
|
|
return t->stack[(index * 2) + 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint64_t
|
|
|
|
peekLong(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
2012-11-30 10:14:35 +00:00
|
|
|
fprintf(stderr, "peek long %" LLD " at %d\n",
|
2007-09-24 01:39:03 +00:00
|
|
|
(static_cast<uint64_t>(t->stack[(index * 2) + 1]) << 32)
|
|
|
|
| static_cast<uint64_t>(t->stack[((index + 1) * 2) + 1]),
|
|
|
|
index);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (static_cast<uint64_t>(peekInt(t, index)) << 32)
|
|
|
|
| static_cast<uint64_t>(peekInt(t, index + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pokeObject(Thread* t, unsigned index, object value)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "poke object %p at %d\n", value, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
t->stack[index * 2] = ObjectTag;
|
|
|
|
t->stack[(index * 2) + 1] = reinterpret_cast<uintptr_t>(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pokeInt(Thread* t, unsigned index, uint32_t value)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "poke int %d at %d\n", value, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
t->stack[index * 2] = IntTag;
|
|
|
|
t->stack[(index * 2) + 1] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
pokeLong(Thread* t, unsigned index, uint64_t value)
|
|
|
|
{
|
|
|
|
if (DebugStack) {
|
2012-11-30 10:14:35 +00:00
|
|
|
fprintf(stderr, "poke long %" LLD " at %d\n", value, index);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pokeInt(t, index, value >> 32);
|
|
|
|
pokeInt(t, index + 1, value & 0xFFFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object*
|
|
|
|
pushReference(Thread* t, object o)
|
|
|
|
{
|
|
|
|
if (o) {
|
2012-03-14 18:36:42 +00:00
|
|
|
expect(t, t->sp + 1 < stackSizeInWords(t) / 2);
|
2007-09-24 01:39:03 +00:00
|
|
|
pushObject(t, o);
|
|
|
|
return reinterpret_cast<object*>(t->stack + ((t->sp - 1) * 2) + 1);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int
|
|
|
|
frameNext(Thread* t, int frame)
|
|
|
|
{
|
|
|
|
return peekInt(t, frame + FrameNextOffset);
|
|
|
|
}
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
inline GcMethod*
|
2007-09-24 01:39:03 +00:00
|
|
|
frameMethod(Thread* t, int frame)
|
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
return cast<GcMethod>(t, peekObject(t, frame + FrameMethodOffset));
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline unsigned
|
|
|
|
frameIp(Thread* t, int frame)
|
|
|
|
{
|
|
|
|
return peekInt(t, frame + FrameIpOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline unsigned
|
|
|
|
frameBase(Thread* t, int frame)
|
|
|
|
{
|
|
|
|
return peekInt(t, frame + FrameBaseOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
localObject(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
return peekObject(t, frameBase(t, t->frame) + index);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint32_t
|
|
|
|
localInt(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
return peekInt(t, frameBase(t, t->frame) + index);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint64_t
|
|
|
|
localLong(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
return peekLong(t, frameBase(t, t->frame) + index);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
setLocalObject(Thread* t, unsigned index, object value)
|
|
|
|
{
|
|
|
|
pokeObject(t, frameBase(t, t->frame) + index, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
setLocalInt(Thread* t, unsigned index, uint32_t value)
|
|
|
|
{
|
|
|
|
pokeInt(t, frameBase(t, t->frame) + index, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
setLocalLong(Thread* t, unsigned index, uint64_t value)
|
|
|
|
{
|
|
|
|
pokeLong(t, frameBase(t, t->frame) + index, value);
|
|
|
|
}
|
|
|
|
|
2007-07-06 15:24:06 +00:00
|
|
|
void
|
2014-05-29 04:17:25 +00:00
|
|
|
pushFrame(Thread* t, GcMethod* method)
|
2007-07-04 02:56:02 +00:00
|
|
|
{
|
2011-03-26 00:37:02 +00:00
|
|
|
PROTECT(t, method);
|
2007-07-04 17:58:27 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
unsigned parameterFootprint = method->parameterFootprint();
|
2007-07-06 15:24:06 +00:00
|
|
|
unsigned base = t->sp - parameterFootprint;
|
|
|
|
unsigned locals = parameterFootprint;
|
2007-07-06 01:06:06 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (method->flags() & ACC_SYNCHRONIZED) {
|
2011-03-26 00:37:02 +00:00
|
|
|
// Try to acquire the monitor before doing anything else.
|
|
|
|
// Otherwise, if we were to push the frame first, we risk trying
|
|
|
|
// to release a monitor we never successfully acquired when we try
|
|
|
|
// to pop the frame back off.
|
2014-05-29 04:17:25 +00:00
|
|
|
if (method->flags() & ACC_STATIC) {
|
2014-06-21 04:16:33 +00:00
|
|
|
acquire(t, reinterpret_cast<object>(method->class_()));
|
2011-03-26 00:37:02 +00:00
|
|
|
} else {
|
|
|
|
acquire(t, peekObject(t, base));
|
2014-05-29 04:17:25 +00:00
|
|
|
}
|
2011-03-26 00:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (t->frame >= 0) {
|
|
|
|
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
|
|
|
}
|
|
|
|
t->ip = 0;
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if ((method->flags() & ACC_NATIVE) == 0) {
|
2014-06-29 05:40:16 +00:00
|
|
|
t->code = method->code();
|
2007-07-06 01:06:06 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
locals = t->code->maxLocals();
|
2007-07-06 01:06:06 +00:00
|
|
|
|
|
|
|
memset(t->stack + ((base + parameterFootprint) * 2), 0,
|
|
|
|
(locals - parameterFootprint) * BytesPerWord * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned frame = base + locals;
|
|
|
|
pokeInt(t, frame + FrameNextOffset, t->frame);
|
|
|
|
t->frame = frame;
|
|
|
|
|
|
|
|
t->sp = frame + FrameFootprint;
|
|
|
|
|
|
|
|
pokeInt(t, frame + FrameBaseOffset, base);
|
2014-05-29 04:17:25 +00:00
|
|
|
pokeObject(t, frame + FrameMethodOffset, reinterpret_cast<object>(method));
|
2007-07-07 23:47:35 +00:00
|
|
|
pokeInt(t, t->frame + FrameIpOffset, 0);
|
2007-07-06 01:06:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
popFrame(Thread* t)
|
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
GcMethod* method = frameMethod(t, t->frame);
|
2007-07-07 23:47:35 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (method->flags() & ACC_SYNCHRONIZED) {
|
|
|
|
if (method->flags() & ACC_STATIC) {
|
2014-06-21 04:16:33 +00:00
|
|
|
release(t, reinterpret_cast<object>(method->class_()));
|
2007-07-07 23:47:35 +00:00
|
|
|
} else {
|
|
|
|
release(t, peekObject(t, frameBase(t, t->frame)));
|
2014-05-29 04:17:25 +00:00
|
|
|
}
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
t->sp = frameBase(t, t->frame);
|
|
|
|
t->frame = frameNext(t, t->frame);
|
|
|
|
if (t->frame >= 0) {
|
2014-06-29 05:40:16 +00:00
|
|
|
t->code = frameMethod(t, t->frame)->code();
|
2007-07-06 01:06:06 +00:00
|
|
|
t->ip = frameIp(t, t->frame);
|
|
|
|
} else {
|
|
|
|
t->code = 0;
|
|
|
|
t->ip = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-25 23:00:55 +00:00
|
|
|
class MyStackWalker: public Processor::StackWalker {
|
|
|
|
public:
|
|
|
|
MyStackWalker(Thread* t, int frame): t(t), frame(frame) { }
|
|
|
|
|
|
|
|
virtual void walk(Processor::StackVisitor* v) {
|
|
|
|
for (int frame = this->frame; frame >= 0; frame = frameNext(t, frame)) {
|
|
|
|
MyStackWalker walker(t, frame);
|
|
|
|
if (not v->visit(&walker)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
virtual GcMethod* method() {
|
2007-11-25 23:00:55 +00:00
|
|
|
return frameMethod(t, frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual int ip() {
|
|
|
|
return frameIp(t, frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual unsigned count() {
|
|
|
|
unsigned count = 0;
|
|
|
|
for (int frame = this->frame; frame >= 0; frame = frameNext(t, frame)) {
|
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread* t;
|
|
|
|
int frame;
|
|
|
|
};
|
|
|
|
|
2007-07-04 17:58:27 +00:00
|
|
|
inline void
|
2014-05-29 04:17:25 +00:00
|
|
|
checkStack(Thread* t, GcMethod* method)
|
2007-07-07 18:09:16 +00:00
|
|
|
{
|
2007-07-26 00:52:10 +00:00
|
|
|
if (UNLIKELY(t->sp
|
2014-05-29 04:17:25 +00:00
|
|
|
+ method->parameterFootprint()
|
2014-06-28 04:00:05 +00:00
|
|
|
+ method->code()->maxLocals()
|
2007-07-07 18:09:16 +00:00
|
|
|
+ FrameFootprint
|
2014-06-28 04:00:05 +00:00
|
|
|
+ method->code()->maxStack()
|
2012-03-14 18:36:42 +00:00
|
|
|
> stackSizeInWords(t) / 2))
|
2007-07-07 18:09:16 +00:00
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
throwNew(t, GcStackOverflowError::Type);
|
2007-07-07 18:09:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
void
|
2009-05-26 03:05:49 +00:00
|
|
|
pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect)
|
2007-06-24 21:49:04 +00:00
|
|
|
{
|
2009-05-03 20:57:11 +00:00
|
|
|
switch (returnCode) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: %d\n", static_cast<int8_t>(result));
|
|
|
|
}
|
|
|
|
pushInt(t, static_cast<int8_t>(result));
|
|
|
|
break;
|
2007-07-19 23:45:44 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
case CharField:
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: %d\n", static_cast<uint16_t>(result));
|
|
|
|
}
|
|
|
|
pushInt(t, static_cast<uint16_t>(result));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ShortField:
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: %d\n", static_cast<int16_t>(result));
|
|
|
|
}
|
|
|
|
pushInt(t, static_cast<int16_t>(result));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: %d\n", static_cast<int32_t>(result));
|
|
|
|
}
|
|
|
|
pushInt(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DoubleField:
|
2009-08-06 17:52:36 +00:00
|
|
|
case LongField:
|
2009-05-03 20:57:11 +00:00
|
|
|
if (DebugRun) {
|
2012-11-30 10:14:35 +00:00
|
|
|
fprintf(stderr, "result: %" LLD "\n", result);
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
pushLong(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjectField:
|
2009-05-26 03:05:49 +00:00
|
|
|
if (indirect) {
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: %p at %p\n",
|
|
|
|
static_cast<uintptr_t>(result) == 0 ? 0 :
|
|
|
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)),
|
|
|
|
reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
|
|
}
|
|
|
|
pushObject(t, static_cast<uintptr_t>(result) == 0 ? 0 :
|
|
|
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
|
|
} else {
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: %p\n", reinterpret_cast<object>(result));
|
|
|
|
}
|
|
|
|
pushObject(t, reinterpret_cast<object>(result));
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VoidField:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
2007-06-24 21:49:04 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
|
2009-05-26 03:20:29 +00:00
|
|
|
void
|
2010-09-14 16:49:41 +00:00
|
|
|
marshalArguments(Thread* t, uintptr_t* args, uint8_t* types, unsigned sp,
|
2014-05-29 04:17:25 +00:00
|
|
|
GcMethod* method, bool fastCallingConvention)
|
2009-05-03 20:57:11 +00:00
|
|
|
{
|
2010-09-14 16:49:41 +00:00
|
|
|
MethodSpecIterator it
|
|
|
|
(t, reinterpret_cast<const char*>
|
2014-06-21 04:16:33 +00:00
|
|
|
(method->spec()->body().begin()));
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
unsigned argOffset = 0;
|
|
|
|
unsigned typeOffset = 0;
|
|
|
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
unsigned type = fieldType(t, fieldCode(t, *it.next()));
|
|
|
|
if (types) {
|
|
|
|
types[typeOffset++] = type;
|
|
|
|
}
|
2007-06-24 21:49:04 +00:00
|
|
|
|
2007-06-29 02:58:48 +00:00
|
|
|
switch (type) {
|
|
|
|
case INT8_TYPE:
|
|
|
|
case INT16_TYPE:
|
|
|
|
case INT32_TYPE:
|
|
|
|
case FLOAT_TYPE:
|
2010-09-14 16:49:41 +00:00
|
|
|
args[argOffset++] = peekInt(t, sp++);
|
2007-06-29 02:58:48 +00:00
|
|
|
break;
|
|
|
|
|
2009-08-06 17:52:36 +00:00
|
|
|
case DOUBLE_TYPE:
|
|
|
|
case INT64_TYPE: {
|
2007-07-04 17:58:27 +00:00
|
|
|
uint64_t v = peekLong(t, sp);
|
2010-09-14 16:49:41 +00:00
|
|
|
memcpy(args + argOffset, &v, 8);
|
2010-09-27 23:12:08 +00:00
|
|
|
argOffset += fastCallingConvention ? 2 : (8 / BytesPerWord);
|
2007-07-04 17:58:27 +00:00
|
|
|
sp += 2;
|
2007-06-29 02:58:48 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-13 00:21:37 +00:00
|
|
|
case POINTER_TYPE: {
|
2010-09-27 23:12:08 +00:00
|
|
|
if (fastCallingConvention) {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(peekObject(t, sp++));
|
|
|
|
} else {
|
2009-05-26 03:20:29 +00:00
|
|
|
object* v = reinterpret_cast<object*>(t->stack + ((sp++) * 2) + 1);
|
|
|
|
if (*v == 0) {
|
|
|
|
v = 0;
|
|
|
|
}
|
2010-09-14 16:49:41 +00:00
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(v);
|
2007-09-13 00:21:37 +00:00
|
|
|
}
|
|
|
|
} break;
|
2007-06-29 02:58:48 +00:00
|
|
|
|
|
|
|
default: abort(t);
|
2007-06-24 01:39:49 +00:00
|
|
|
}
|
2007-06-24 21:49:04 +00:00
|
|
|
}
|
2009-05-26 03:20:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
2014-05-29 04:17:25 +00:00
|
|
|
invokeNativeSlow(Thread* t, GcMethod* method, void* function)
|
2009-05-26 03:20:29 +00:00
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
pushFrame(t, method);
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
unsigned footprint = method->parameterFootprint() + 1;
|
|
|
|
if (method->flags() & ACC_STATIC) {
|
2010-09-14 16:49:41 +00:00
|
|
|
++ footprint;
|
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
unsigned count = method->parameterCount() + 2;
|
2010-09-14 16:49:41 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint);
|
2010-09-14 16:49:41 +00:00
|
|
|
unsigned argOffset = 0;
|
2010-12-27 22:55:23 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, uint8_t, types, count);
|
2010-09-14 16:49:41 +00:00
|
|
|
unsigned typeOffset = 0;
|
2009-05-26 03:20:29 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast<uintptr_t>(t);
|
|
|
|
RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE;
|
2009-05-26 03:20:29 +00:00
|
|
|
|
2014-06-28 00:32:20 +00:00
|
|
|
GcJclass* jclass = 0;
|
2010-09-14 16:49:41 +00:00
|
|
|
PROTECT(t, jclass);
|
2009-05-26 03:20:29 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
unsigned sp;
|
2014-05-29 04:17:25 +00:00
|
|
|
if (method->flags() & ACC_STATIC) {
|
2010-09-14 16:49:41 +00:00
|
|
|
sp = frameBase(t, t->frame);
|
2014-06-21 04:16:33 +00:00
|
|
|
jclass = getJClass(t, method->class_());
|
2010-09-14 16:49:41 +00:00
|
|
|
RUNTIME_ARRAY_BODY(args)[argOffset++]
|
|
|
|
= reinterpret_cast<uintptr_t>(&jclass);
|
|
|
|
} else {
|
|
|
|
sp = frameBase(t, t->frame);
|
|
|
|
object* v = reinterpret_cast<object*>(t->stack + ((sp++) * 2) + 1);
|
|
|
|
if (*v == 0) {
|
|
|
|
v = 0;
|
|
|
|
}
|
|
|
|
RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast<uintptr_t>(v);
|
2009-05-26 03:20:29 +00:00
|
|
|
}
|
2010-09-14 16:49:41 +00:00
|
|
|
RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE;
|
2009-05-26 03:20:29 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
marshalArguments
|
|
|
|
(t, RUNTIME_ARRAY_BODY(args) + argOffset,
|
2010-09-27 23:12:08 +00:00
|
|
|
RUNTIME_ARRAY_BODY(types) + typeOffset, sp, method, false);
|
2007-06-24 21:49:04 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
unsigned returnCode = method->returnCode();
|
2007-06-29 02:58:48 +00:00
|
|
|
unsigned returnType = fieldType(t, returnCode);
|
2007-10-02 00:08:17 +00:00
|
|
|
uint64_t result;
|
2007-06-24 21:49:04 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "invoke native method %s.%s\n",
|
2014-06-21 04:16:33 +00:00
|
|
|
method->class_()->name()->body().begin(),
|
|
|
|
method->name()->body().begin());
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-09-18 23:30:09 +00:00
|
|
|
{ ENTER(t, Thread::IdleState);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
bool noThrow = t->checkpoint->noThrow;
|
|
|
|
t->checkpoint->noThrow = true;
|
|
|
|
THREAD_RESOURCE(t, bool, noThrow, t->checkpoint->noThrow = noThrow);
|
|
|
|
|
2014-02-23 04:40:57 +00:00
|
|
|
result = vm::dynamicCall(function,
|
|
|
|
RUNTIME_ARRAY_BODY(args),
|
|
|
|
RUNTIME_ARRAY_BODY(types),
|
|
|
|
count,
|
|
|
|
footprint * BytesPerWord,
|
|
|
|
returnType);
|
2007-09-18 23:30:09 +00:00
|
|
|
}
|
2007-06-24 21:49:04 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "return from native method %s.%s\n",
|
2014-06-21 04:16:33 +00:00
|
|
|
frameMethod(t, t->frame)->class_()->name()->body().begin(),
|
|
|
|
frameMethod(t, t->frame)->name()->body().begin());
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
popFrame(t);
|
|
|
|
|
2007-07-04 17:58:27 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
2014-06-28 23:24:24 +00:00
|
|
|
GcThrowable* exception = t->exception;
|
2010-12-27 22:55:23 +00:00
|
|
|
t->exception = 0;
|
|
|
|
throw_(t, exception);
|
2007-07-04 17:58:27 +00:00
|
|
|
}
|
|
|
|
|
2009-05-26 03:05:49 +00:00
|
|
|
pushResult(t, returnCode, result, true);
|
2007-10-24 23:06:12 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
return returnCode;
|
|
|
|
}
|
2007-10-24 23:06:12 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
unsigned
|
2014-05-29 04:17:25 +00:00
|
|
|
invokeNative(Thread* t, GcMethod* method)
|
2009-05-03 20:57:11 +00:00
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
2007-10-24 23:06:12 +00:00
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
resolveNative(t, method);
|
2007-07-04 17:58:27 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcNative* native = getMethodRuntimeData(t, method)->native();
|
|
|
|
if (native->fast()) {
|
2009-05-03 20:57:11 +00:00
|
|
|
pushFrame(t, method);
|
|
|
|
|
2011-02-02 02:23:25 +00:00
|
|
|
uint64_t result;
|
|
|
|
{ THREAD_RESOURCE0(t, popFrame(static_cast<Thread*>(t)));
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
unsigned footprint = method->parameterFootprint();
|
2013-02-05 17:13:59 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint);
|
2011-02-02 02:23:25 +00:00
|
|
|
unsigned sp = frameBase(t, t->frame);
|
|
|
|
unsigned argOffset = 0;
|
2014-05-29 04:17:25 +00:00
|
|
|
if ((method->flags() & ACC_STATIC) == 0) {
|
2011-02-02 02:23:25 +00:00
|
|
|
RUNTIME_ARRAY_BODY(args)[argOffset++]
|
|
|
|
= reinterpret_cast<uintptr_t>(peekObject(t, sp++));
|
|
|
|
}
|
2010-09-14 16:49:41 +00:00
|
|
|
|
2011-02-02 02:23:25 +00:00
|
|
|
marshalArguments
|
|
|
|
(t, RUNTIME_ARRAY_BODY(args) + argOffset, 0, sp, method, true);
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2011-02-02 02:23:25 +00:00
|
|
|
result = reinterpret_cast<FastNativeFunction>
|
2014-06-29 05:40:16 +00:00
|
|
|
(native->function())(t, method, RUNTIME_ARRAY_BODY(args));
|
2011-02-02 02:23:25 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
pushResult(t, method->returnCode(), result, false);
|
2007-07-04 17:58:27 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
return method->returnCode();
|
2009-05-03 20:57:11 +00:00
|
|
|
} else {
|
2014-06-29 05:40:16 +00:00
|
|
|
return invokeNativeSlow(t, method, native->function());
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
|
|
|
|
2007-09-13 00:21:37 +00:00
|
|
|
inline void
|
|
|
|
store(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
memcpy(t->stack + ((frameBase(t, t->frame) + index) * 2),
|
|
|
|
t->stack + ((-- t->sp) * 2),
|
|
|
|
BytesPerWord * 2);
|
|
|
|
}
|
|
|
|
|
2013-04-03 22:08:40 +00:00
|
|
|
bool
|
|
|
|
isNaN(double v)
|
|
|
|
{
|
|
|
|
return fpclassify(v) == FP_NAN;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
isNaN(float v)
|
|
|
|
{
|
|
|
|
return fpclassify(v) == FP_NAN;
|
|
|
|
}
|
|
|
|
|
2011-08-30 01:00:17 +00:00
|
|
|
uint64_t
|
2014-05-29 04:17:25 +00:00
|
|
|
findExceptionHandler(Thread* t, GcMethod* method, unsigned ip)
|
2008-04-11 19:03:40 +00:00
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcExceptionHandlerTable* eht = cast<GcExceptionHandlerTable>(t, method->code()->exceptionHandlerTable());
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2008-04-11 19:03:40 +00:00
|
|
|
if (eht) {
|
2014-06-29 05:40:16 +00:00
|
|
|
for (unsigned i = 0; i < eht->length(); ++i) {
|
|
|
|
uint64_t eh = eht->body()[i];
|
2008-04-11 19:03:40 +00:00
|
|
|
|
|
|
|
if (ip - 1 >= exceptionHandlerStart(eh)
|
|
|
|
and ip - 1 < exceptionHandlerEnd(eh))
|
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
GcClass* catchType = 0;
|
2008-04-11 19:03:40 +00:00
|
|
|
if (exceptionHandlerCatchType(eh)) {
|
2014-06-28 23:24:24 +00:00
|
|
|
GcThrowable* e = t->exception;
|
2008-04-11 19:03:40 +00:00
|
|
|
t->exception = 0;
|
|
|
|
PROTECT(t, e);
|
|
|
|
|
|
|
|
PROTECT(t, eht);
|
|
|
|
catchType = resolveClassInPool
|
2009-08-18 20:41:21 +00:00
|
|
|
(t, method, exceptionHandlerCatchType(eh) - 1);
|
2008-04-11 19:03:40 +00:00
|
|
|
|
|
|
|
if (catchType) {
|
2014-06-29 05:40:16 +00:00
|
|
|
eh = eht->body()[i];
|
2008-04-11 19:03:40 +00:00
|
|
|
t->exception = e;
|
|
|
|
} else {
|
|
|
|
// can't find what we're supposed to catch - move on.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
support multiple sequential VM instances with bootimage build
Until now, the bootimage build hasn't supported using the Java
invocation API to create a VM, destroy it, and create another in the
same process. Ideally, we would be able to create multiple VMs
simultaneously without any interference between them. In fact, Avian
is designed to support this for the most part, but there are a few
places we use global, mutable state which prevent this from working.
Most notably, the bootimage is modified in-place at runtime, so the
best we can do without extensive changes is to clean up the bootimage
when the VM is destroyed so it's ready for later instances. Hence
this commit.
Ultimately, we can move towards a fully reentrant VM by making the
bootimage immutable, but this will require some care to avoid
performance regressions. Another challenge is our Posix signal
handlers, which currently rely on a global handle to the VM, since you
can't, to my knowledge, pass a context pointer when registering a
signal handler. Thread local variables won't necessarily help, since
a thread might attatch to more than one VM at a time.
2011-11-10 20:10:53 +00:00
|
|
|
if (exceptionMatch(t, catchType, t->exception)) {
|
2008-04-11 19:03:40 +00:00
|
|
|
return eh;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-30 01:00:17 +00:00
|
|
|
uint64_t
|
2007-10-04 23:17:57 +00:00
|
|
|
findExceptionHandler(Thread* t, int frame)
|
2007-10-03 00:22:48 +00:00
|
|
|
{
|
2007-11-26 23:15:53 +00:00
|
|
|
return findExceptionHandler(t, frameMethod(t, frame), frameIp(t, frame));
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-11-02 21:08:14 +00:00
|
|
|
void
|
2014-06-29 05:40:16 +00:00
|
|
|
pushField(Thread* t, object target, GcField* field)
|
2007-11-02 21:08:14 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
switch (field->code()) {
|
2007-11-02 21:08:14 +00:00
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, fieldAtOffset<int8_t>(target, field->offset()));
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, fieldAtOffset<int16_t>(target, field->offset()));
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, fieldAtOffset<int32_t>(target, field->offset()));
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
2014-06-29 05:40:16 +00:00
|
|
|
pushLong(t, fieldAtOffset<int64_t>(target, field->offset()));
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjectField:
|
2014-06-29 05:40:16 +00:00
|
|
|
pushObject(t, fieldAtOffset<object>(target, field->offset()));
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-13 18:48:26 +00:00
|
|
|
void safePoint(Thread* t) {
|
2014-06-05 13:49:49 +00:00
|
|
|
if (UNLIKELY(t->m->exclusive)) {
|
|
|
|
ENTER(t, Thread::IdleState);
|
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
}
|
|
|
|
|
2007-05-21 15:47:44 +00:00
|
|
|
object
|
2010-12-27 22:55:23 +00:00
|
|
|
interpret3(Thread* t, const int base)
|
2007-05-21 15:47:44 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
unsigned instruction = nop;
|
2007-06-08 14:23:04 +00:00
|
|
|
unsigned& ip = t->ip;
|
|
|
|
unsigned& sp = t->sp;
|
2007-07-06 01:06:06 +00:00
|
|
|
int& frame = t->frame;
|
2014-06-29 05:40:16 +00:00
|
|
|
GcCode*& code = t->code;
|
|
|
|
GcMethod* method = 0;
|
|
|
|
PROTECT(t, method);
|
2014-06-28 23:24:24 +00:00
|
|
|
GcThrowable*& exception = t->exception;
|
2007-07-04 02:56:02 +00:00
|
|
|
uintptr_t* stack = t->stack;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
code = frameMethod(t, frame)->code();
|
2012-03-06 20:03:42 +00:00
|
|
|
|
2007-08-01 23:48:36 +00:00
|
|
|
if (UNLIKELY(exception)) {
|
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
|
2007-05-21 15:47:44 +00:00
|
|
|
loop:
|
2014-06-29 05:40:16 +00:00
|
|
|
instruction = code->body()[ip++];
|
2007-07-04 17:58:27 +00:00
|
|
|
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "ip: %d; instruction: 0x%x in %s.%s ",
|
|
|
|
ip - 1,
|
|
|
|
instruction,
|
2014-06-21 04:16:33 +00:00
|
|
|
frameMethod(t, frame)->class_()->name()->body().begin(),
|
|
|
|
frameMethod(t, frame)->name()->body().begin());
|
2007-07-04 17:58:27 +00:00
|
|
|
|
2007-11-26 23:15:53 +00:00
|
|
|
int line = findLineNumber(t, frameMethod(t, frame), ip);
|
2007-07-04 17:58:27 +00:00
|
|
|
switch (line) {
|
|
|
|
case NativeLine:
|
|
|
|
fprintf(stderr, "(native)\n");
|
|
|
|
break;
|
|
|
|
case UnknownLine:
|
|
|
|
fprintf(stderr, "(unknown line)\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "(line %d)\n", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
switch (instruction) {
|
2007-05-21 15:47:44 +00:00
|
|
|
case aaload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < objectArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, objectArrayBody(t, array, index));
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2010-12-27 22:55:23 +00:00
|
|
|
index, objectArrayLength(t, array));
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case aastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object value = popObject(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < objectArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-10-22 17:22:30 +00:00
|
|
|
set(t, array, ArrayBody + (index * BytesPerWord), value);
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2010-12-27 22:55:23 +00:00
|
|
|
index, objectArrayLength(t, array));
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case aconst_null: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload: {
|
2014-06-29 05:40:16 +00:00
|
|
|
pushObject(t, localObject(t, code->body()[ip++]));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 0));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 1));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 2));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 3));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case anewarray: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t count = popInt(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(count >= 0)) {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
|
|
|
GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
pushObject(t, reinterpret_cast<object>(makeObjectArray(t, class_, count)));
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcNegativeArraySizeException::Type, "%d", count);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
case areturn: {
|
|
|
|
object result = popObject(t);
|
2007-07-24 01:44:20 +00:00
|
|
|
if (frame > base) {
|
|
|
|
popFrame(t);
|
2007-07-07 23:47:35 +00:00
|
|
|
pushObject(t, result);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto loop;
|
|
|
|
} else {
|
2007-07-07 23:47:35 +00:00
|
|
|
return result;
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case arraylength: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object array = popObject(t);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2013-02-11 00:38:51 +00:00
|
|
|
pushInt(t, fieldAtOffset<uintptr_t>(array, BytesPerWord));
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-07-07 23:47:35 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore: {
|
2014-06-29 05:40:16 +00:00
|
|
|
store(t, code->body()[ip++]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_0: {
|
2007-09-13 00:21:37 +00:00
|
|
|
store(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_1: {
|
2007-09-13 00:21:37 +00:00
|
|
|
store(t, 1);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_2: {
|
2007-09-13 00:21:37 +00:00
|
|
|
store(t, 2);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_3: {
|
2007-09-13 00:21:37 +00:00
|
|
|
store(t, 3);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case athrow: {
|
2014-06-28 23:24:24 +00:00
|
|
|
exception = cast<GcThrowable>(t, popObject(t));
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception == 0)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case baload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
if (objectClass(t, array) == type(t, GcBooleanArray::Type)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcBooleanArray* a = cast<GcBooleanArray>(t, array);
|
2007-09-14 20:35:37 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
|
|
|
static_cast<uintptr_t>(index)
|
2014-06-29 05:40:16 +00:00
|
|
|
< a->length()))
|
2007-09-14 20:35:37 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, a->body()[index]);
|
2007-09-14 20:35:37 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type,
|
2014-06-29 05:40:16 +00:00
|
|
|
"%d not in [0,%d)", index, a->length());
|
2007-09-14 20:35:37 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcByteArray* a = cast<GcByteArray>(t, array);
|
2007-09-14 20:35:37 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
|
|
|
static_cast<uintptr_t>(index)
|
2014-06-29 05:40:16 +00:00
|
|
|
< a->length()))
|
2007-09-14 20:35:37 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, a->body()[index]);
|
2007-09-14 20:35:37 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type,
|
2014-06-29 05:40:16 +00:00
|
|
|
"%d not in [0,%d)", index, a->length());
|
2007-09-14 20:35:37 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case bastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int8_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
if (objectClass(t, array) == type(t, GcBooleanArray::Type)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcBooleanArray* a = cast<GcBooleanArray>(t, array);
|
2007-09-14 20:35:37 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
|
|
|
static_cast<uintptr_t>(index)
|
2014-06-29 05:40:16 +00:00
|
|
|
< a->length()))
|
2007-09-14 20:35:37 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
a->body()[index] = value;
|
2007-09-14 20:35:37 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type,
|
2014-06-29 05:40:16 +00:00
|
|
|
"%d not in [0,%d)", index, a->length());
|
2007-09-14 20:35:37 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcByteArray* a = cast<GcByteArray>(t, array);
|
2007-09-14 20:35:37 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-09-14 20:35:37 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
a->body()[index] = value;
|
2007-09-14 20:35:37 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type,
|
2014-06-29 05:40:16 +00:00
|
|
|
"%d not in [0,%d)", index, a->length());
|
2007-09-14 20:35:37 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case bipush: {
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, static_cast<int8_t>(code->body()[ip++]));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case caload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcCharArray* a = cast<GcCharArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, a->body()[index]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case castore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
uint16_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcCharArray* a = cast<GcCharArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
a->body()[index] = value;
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case checkcast: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (peekObject(t, sp - 1)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (not instanceOf(t, class_, peekObject(t, sp - 1))) {
|
2010-12-27 22:55:23 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcClassCastException::Type, "%s as %s",
|
2014-06-21 04:16:33 +00:00
|
|
|
objectClass(t, peekObject(t, sp - 1))->name()->body().begin(),
|
|
|
|
class_->name()->body().begin());
|
2007-11-05 16:08:08 +00:00
|
|
|
goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case d2f: {
|
|
|
|
pushFloat(t, static_cast<float>(popDouble(t)));
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case d2i: {
|
2012-08-12 20:31:58 +00:00
|
|
|
double f = popDouble(t);
|
|
|
|
switch (fpclassify(f)) {
|
|
|
|
case FP_NAN: pushInt(t, 0); break;
|
2012-08-12 20:52:48 +00:00
|
|
|
case FP_INFINITE: pushInt(t, signbit(f) ? INT32_MIN : INT32_MAX); break;
|
2012-08-12 20:31:58 +00:00
|
|
|
default: pushInt
|
|
|
|
(t, f >= INT32_MAX ? INT32_MAX
|
|
|
|
: (f <= INT32_MIN ? INT32_MIN : static_cast<int32_t>(f)));
|
|
|
|
break;
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case d2l: {
|
2012-08-12 20:31:58 +00:00
|
|
|
double f = popDouble(t);
|
|
|
|
switch (fpclassify(f)) {
|
|
|
|
case FP_NAN: pushLong(t, 0); break;
|
2012-08-12 20:52:48 +00:00
|
|
|
case FP_INFINITE: pushLong(t, signbit(f) ? INT64_MIN : INT64_MAX); break;
|
2012-08-12 20:31:58 +00:00
|
|
|
default: pushLong
|
|
|
|
(t, f >= INT64_MAX ? INT64_MAX
|
|
|
|
: (f <= INT64_MIN ? INT64_MIN : static_cast<int64_t>(f)));
|
|
|
|
break;
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dadd: {
|
|
|
|
double b = popDouble(t);
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushDouble(t, a + b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case daload: {
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
|
|
|
|
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcDoubleArray* a = cast<GcDoubleArray>(t, array);
|
2007-08-13 14:06:31 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-08-13 14:06:31 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushLong(t, a->body()[index]);
|
2007-08-13 14:06:31 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dastore: {
|
|
|
|
double value = popDouble(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
|
|
|
|
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcDoubleArray* a = cast<GcDoubleArray>(t, array);
|
2007-08-13 14:06:31 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-08-13 14:06:31 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
memcpy(&a->body()[index], &value, sizeof(uint64_t));
|
2007-08-13 14:06:31 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dcmpg: {
|
|
|
|
double b = popDouble(t);
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2013-04-03 22:08:40 +00:00
|
|
|
if (isNaN(a) or isNaN(b)) {
|
|
|
|
pushInt(t, 1);
|
|
|
|
} if (a < b) {
|
2007-10-15 19:12:38 +00:00
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
} else if (a > b) {
|
|
|
|
pushInt(t, 1);
|
|
|
|
} else if (a == b) {
|
|
|
|
pushInt(t, 0);
|
|
|
|
} else {
|
|
|
|
pushInt(t, 1);
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dcmpl: {
|
|
|
|
double b = popDouble(t);
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2013-04-03 22:08:40 +00:00
|
|
|
if (isNaN(a) or isNaN(b)) {
|
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
} if (a < b) {
|
2007-10-15 19:12:38 +00:00
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
} else if (a > b) {
|
|
|
|
pushInt(t, 1);
|
|
|
|
} else if (a == b) {
|
|
|
|
pushInt(t, 0);
|
|
|
|
} else {
|
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dconst_0: {
|
|
|
|
pushDouble(t, 0);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dconst_1: {
|
|
|
|
pushDouble(t, 1);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ddiv: {
|
|
|
|
double b = popDouble(t);
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushDouble(t, a / b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dmul: {
|
|
|
|
double b = popDouble(t);
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushDouble(t, a * b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dneg: {
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushDouble(t, - a);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case vm::drem: {
|
|
|
|
double b = popDouble(t);
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushDouble(t, fmod(a, b));
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dsub: {
|
|
|
|
double b = popDouble(t);
|
|
|
|
double a = popDouble(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushDouble(t, a - b);
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-22 00:05:29 +00:00
|
|
|
case dup: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
++ sp;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup_x1: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup_x1\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), stack + ((sp ) * 2), BytesPerWord * 2);
|
|
|
|
++ sp;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup_x2: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup_x2\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 3) * 2), stack + ((sp ) * 2), BytesPerWord * 2);
|
|
|
|
++ sp;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup2\n");
|
|
|
|
}
|
|
|
|
|
2007-09-14 20:35:37 +00:00
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 2) * 2), BytesPerWord * 4);
|
2007-07-04 02:56:02 +00:00
|
|
|
sp += 2;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2_x1: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup2_x1\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp + 1) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 3) * 2), stack + ((sp ) * 2), BytesPerWord * 4);
|
|
|
|
sp += 2;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2_x2: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup2_x2\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp + 1) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), stack + ((sp - 4) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 4) * 2), stack + ((sp ) * 2), BytesPerWord * 4);
|
|
|
|
sp += 2;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case f2d: {
|
|
|
|
pushDouble(t, popFloat(t));
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case f2i: {
|
2012-08-12 20:31:58 +00:00
|
|
|
float f = popFloat(t);
|
|
|
|
switch (fpclassify(f)) {
|
|
|
|
case FP_NAN: pushInt(t, 0); break;
|
2012-08-12 20:52:48 +00:00
|
|
|
case FP_INFINITE: pushInt(t, signbit(f) ? INT32_MIN : INT32_MAX); break;
|
2012-08-12 20:31:58 +00:00
|
|
|
default: pushInt(t, f >= INT32_MAX ? INT32_MAX
|
|
|
|
: (f <= INT32_MIN ? INT32_MIN : static_cast<int32_t>(f)));
|
|
|
|
break;
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case f2l: {
|
2012-08-12 20:31:58 +00:00
|
|
|
float f = popFloat(t);
|
|
|
|
switch (fpclassify(f)) {
|
|
|
|
case FP_NAN: pushLong(t, 0); break;
|
2012-08-12 20:52:48 +00:00
|
|
|
case FP_INFINITE: pushLong(t, signbit(f) ? INT64_MIN : INT64_MAX);
|
2012-08-12 20:31:58 +00:00
|
|
|
break;
|
|
|
|
default: pushLong(t, static_cast<int64_t>(f)); break;
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fadd: {
|
|
|
|
float b = popFloat(t);
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushFloat(t, a + b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case faload: {
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
|
|
|
|
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcFloatArray* a = cast<GcFloatArray>(t, array);
|
2007-08-13 14:06:31 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-08-13 14:06:31 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, a->body()[index]);
|
2007-08-13 14:06:31 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fastore: {
|
|
|
|
float value = popFloat(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
|
|
|
|
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcFloatArray* a = cast<GcFloatArray>(t, array);
|
2007-08-13 14:06:31 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-08-13 14:06:31 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
memcpy(&a->body()[index], &value, sizeof(uint32_t));
|
2007-08-13 14:06:31 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-08-13 14:06:31 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fcmpg: {
|
|
|
|
float b = popFloat(t);
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2013-04-03 22:08:40 +00:00
|
|
|
if (isNaN(a) or isNaN(b)) {
|
|
|
|
pushInt(t, 1);
|
|
|
|
} if (a < b) {
|
2007-10-04 16:21:14 +00:00
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
} else if (a > b) {
|
|
|
|
pushInt(t, 1);
|
|
|
|
} else if (a == b) {
|
|
|
|
pushInt(t, 0);
|
|
|
|
} else {
|
|
|
|
pushInt(t, 1);
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fcmpl: {
|
|
|
|
float b = popFloat(t);
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2013-04-03 22:08:40 +00:00
|
|
|
if (isNaN(a) or isNaN(b)) {
|
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
} if (a < b) {
|
2007-10-04 16:21:14 +00:00
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
} else if (a > b) {
|
|
|
|
pushInt(t, 1);
|
|
|
|
} else if (a == b) {
|
|
|
|
pushInt(t, 0);
|
|
|
|
} else {
|
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
}
|
2007-08-13 14:06:31 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fconst_0: {
|
|
|
|
pushFloat(t, 0);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fconst_1: {
|
|
|
|
pushFloat(t, 1);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fconst_2: {
|
|
|
|
pushFloat(t, 2);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fdiv: {
|
|
|
|
float b = popFloat(t);
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushFloat(t, a / b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fmul: {
|
|
|
|
float b = popFloat(t);
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushFloat(t, a * b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fneg: {
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushFloat(t, - a);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case frem: {
|
|
|
|
float b = popFloat(t);
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushFloat(t, fmodf(a, b));
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case fsub: {
|
|
|
|
float b = popFloat(t);
|
|
|
|
float a = popFloat(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
pushFloat(t, a - b);
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-22 00:05:29 +00:00
|
|
|
case getfield: {
|
2007-07-17 01:55:49 +00:00
|
|
|
if (LIKELY(peekObject(t, sp - 1))) {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcField* field = resolveField(t, frameMethod(t, frame), index - 1);
|
2009-01-10 19:25:52 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
assertT(t, (field->flags() & ACC_STATIC) == 0);
|
2009-01-10 19:25:52 +00:00
|
|
|
|
2011-03-15 23:52:02 +00:00
|
|
|
PROTECT(t, field);
|
2009-03-04 01:02:11 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
2009-03-03 03:18:15 +00:00
|
|
|
|
2011-03-15 23:52:02 +00:00
|
|
|
pushField(t, popObject(t), field);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case getstatic: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-25 14:48:07 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcField* field = resolveField(t, frameMethod(t, frame), index - 1);
|
2008-12-18 23:32:18 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
assertT(t, field->flags() & ACC_STATIC);
|
2009-01-10 19:25:52 +00:00
|
|
|
|
2007-09-15 00:32:32 +00:00
|
|
|
PROTECT(t, field);
|
2007-05-25 14:48:07 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
initClass(t, field->class_());
|
2007-07-04 02:56:02 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
ACQUIRE_FIELD_FOR_READ(t, field);
|
2009-03-04 01:02:11 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
pushField(t, reinterpret_cast<object>(field->class_()->staticTable()), field);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case goto_: {
|
2007-09-26 23:23:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-08-13 02:52:12 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-05-22 00:05:29 +00:00
|
|
|
case goto_w: {
|
2007-09-26 23:23:03 +00:00
|
|
|
int32_t offset = codeReadInt32(t, code, ip);
|
2007-08-13 02:52:12 +00:00
|
|
|
ip = (ip - 5) + offset;
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case i2b: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, static_cast<int8_t>(popInt(t)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2c: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, static_cast<uint16_t>(popInt(t)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-09-14 01:42:12 +00:00
|
|
|
case i2d: {
|
2007-10-25 20:26:51 +00:00
|
|
|
pushDouble(t, static_cast<double>(static_cast<int32_t>(popInt(t))));
|
2007-09-14 01:42:12 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2f: {
|
2007-10-25 20:26:51 +00:00
|
|
|
pushFloat(t, static_cast<float>(static_cast<int32_t>(popInt(t))));
|
2007-09-14 01:42:12 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-05-22 00:05:29 +00:00
|
|
|
case i2l: {
|
2007-09-17 22:16:17 +00:00
|
|
|
pushLong(t, static_cast<int32_t>(popInt(t)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2s: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, static_cast<int16_t>(popInt(t)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iadd: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a + b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iaload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcIntArray* a = cast<GcIntArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, a->body()[index]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iand: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a & b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcIntArray* a = cast<GcIntArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
a->body()[index] = value;
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-08-14 00:37:00 +00:00
|
|
|
case iconst_m1: {
|
|
|
|
pushInt(t, static_cast<unsigned>(-1));
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-22 00:05:29 +00:00
|
|
|
case iconst_0: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_1: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 1);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_2: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 2);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_3: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 3);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_4: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 4);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_5: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 5);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case idiv: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2010-12-20 00:47:21 +00:00
|
|
|
|
|
|
|
if (UNLIKELY(b == 0)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcArithmeticException::Type);
|
2010-12-20 00:47:21 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a / b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_acmpeq: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-20 03:18:25 +00:00
|
|
|
object b = popObject(t);
|
|
|
|
object a = popObject(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-05-22 00:05:29 +00:00
|
|
|
if (a == b) {
|
2007-09-30 16:32:17 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case if_acmpne: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-20 03:18:25 +00:00
|
|
|
object b = popObject(t);
|
|
|
|
object a = popObject(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-05-22 00:05:29 +00:00
|
|
|
if (a != b) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case if_icmpeq: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a == b) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case if_icmpne: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a != b) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case if_icmpgt: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a > b) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case if_icmpge: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a >= b) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case if_icmplt: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a < b) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case if_icmple: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
if (a <= b) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case ifeq: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popInt(t) == 0) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case ifne: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popInt(t)) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case ifgt: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) > 0) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case ifge: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) >= 0) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case iflt: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) < 0) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case ifle: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) <= 0) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case ifnonnull: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popObject(t)) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case ifnull: {
|
2007-09-28 23:41:03 +00:00
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popObject(t) == 0) {
|
2007-09-28 23:41:03 +00:00
|
|
|
ip = (ip - 3) + offset;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2013-12-13 18:48:26 +00:00
|
|
|
} goto back_branch;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case iinc: {
|
2014-06-29 05:40:16 +00:00
|
|
|
uint8_t index = code->body()[ip++];
|
|
|
|
int8_t c = code->body()[ip++];
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, index, localInt(t, index) + c);
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case iload:
|
|
|
|
case fload: {
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, localInt(t, code->body()[ip++]));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case iload_0:
|
|
|
|
case fload_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 0));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case iload_1:
|
|
|
|
case fload_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 1));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case iload_2:
|
|
|
|
case fload_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 2));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case iload_3:
|
|
|
|
case fload_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 3));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case imul: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a * b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ineg: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, - popInt(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case instanceof: {
|
2007-09-29 21:08:29 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (peekObject(t, sp - 1)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-08-15 01:14:55 +00:00
|
|
|
if (instanceOf(t, class_, popObject(t))) {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 1);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2007-08-15 01:14:55 +00:00
|
|
|
popObject(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-25 14:48:07 +00:00
|
|
|
case invokeinterface: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
ip += 2;
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
unsigned parameterFootprint = m->parameterFootprint();
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
2014-06-29 05:40:16 +00:00
|
|
|
method = findInterfaceMethod
|
|
|
|
(t, m, objectClass(t, peekObject(t, sp - parameterFootprint)));
|
2007-05-30 00:08:10 +00:00
|
|
|
goto invoke;
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case invokespecial: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
unsigned parameterFootprint = m->parameterFootprint();
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
2014-06-21 04:16:33 +00:00
|
|
|
GcClass* class_ = frameMethod(t, frame)->class_();
|
2014-06-29 05:40:16 +00:00
|
|
|
if (isSpecialMethod(t, m, class_)) {
|
2014-06-21 04:16:33 +00:00
|
|
|
class_ = class_->super();
|
2014-06-29 05:40:16 +00:00
|
|
|
PROTECT(t, m);
|
2011-04-01 01:43:49 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
initClass(t, class_);
|
2007-07-08 01:06:32 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
method = findVirtualMethod(t, m, class_);
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
2014-06-29 05:40:16 +00:00
|
|
|
method = m;
|
2007-05-30 00:08:10 +00:00
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
goto invoke;
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case invokestatic: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1);
|
|
|
|
PROTECT(t, m);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
initClass(t, m->class_());
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
method = m;
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto invoke;
|
|
|
|
|
|
|
|
case invokevirtual: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
unsigned parameterFootprint = m->parameterFootprint();
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
2014-05-29 04:17:25 +00:00
|
|
|
GcClass* class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
|
2014-06-29 05:40:16 +00:00
|
|
|
PROTECT(t, m);
|
2011-04-01 01:43:49 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
method = findVirtualMethod(t, m, class_);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto invoke;
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ior: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a | b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case irem: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2010-12-20 00:47:21 +00:00
|
|
|
if (UNLIKELY(b == 0)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcArithmeticException::Type);
|
2010-12-20 00:47:21 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a % b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case ireturn:
|
|
|
|
case freturn: {
|
2007-07-07 23:47:35 +00:00
|
|
|
int32_t result = popInt(t);
|
2007-07-24 01:44:20 +00:00
|
|
|
if (frame > base) {
|
|
|
|
popFrame(t);
|
2007-07-07 23:47:35 +00:00
|
|
|
pushInt(t, result);
|
|
|
|
goto loop;
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
return reinterpret_cast<object>(makeInt(t, result));
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case ishl: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-08-11 19:09:03 +00:00
|
|
|
pushInt(t, a << (b & 0x1F));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ishr: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-08-11 19:09:03 +00:00
|
|
|
pushInt(t, a >> (b & 0x1F));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case istore:
|
|
|
|
case fstore: {
|
2014-06-29 05:40:16 +00:00
|
|
|
setLocalInt(t, code->body()[ip++], popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case istore_0:
|
|
|
|
case fstore_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 0, popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case istore_1:
|
|
|
|
case fstore_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 1, popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case istore_2:
|
|
|
|
case fstore_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 2, popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case istore_3:
|
|
|
|
case fstore_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 3, popInt(t));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case isub: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a - b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iushr: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
2007-09-14 20:35:37 +00:00
|
|
|
uint32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-08-11 19:09:03 +00:00
|
|
|
pushInt(t, a >> (b & 0x1F));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ixor: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a ^ b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case jsr: {
|
2007-10-04 22:41:19 +00:00
|
|
|
uint16_t offset = codeReadInt16(t, code, ip);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, ip);
|
2007-10-04 22:41:19 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(offset);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case jsr_w: {
|
2007-10-04 22:41:19 +00:00
|
|
|
uint32_t offset = codeReadInt32(t, code, ip);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, ip);
|
2007-11-27 22:22:05 +00:00
|
|
|
ip = (ip - 5) + static_cast<int32_t>(offset);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2008-03-21 19:52:09 +00:00
|
|
|
case l2d: {
|
|
|
|
pushDouble(t, static_cast<double>(static_cast<int64_t>(popLong(t))));
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case l2f: {
|
|
|
|
pushFloat(t, static_cast<float>(static_cast<int64_t>(popLong(t))));
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case l2i: {
|
2007-07-07 23:47:35 +00:00
|
|
|
pushInt(t, static_cast<int32_t>(popLong(t)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ladd: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a + b);
|
2007-05-25 14:48:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case laload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcLongArray* a = cast<GcLongArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushLong(t, a->body()[index]);
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case land: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a & b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t value = popLong(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcLongArray* a = cast<GcLongArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
a->body()[index] = value;
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lcmp: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a > b ? 1 : a == b ? 0 : -1);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lconst_0: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, 0);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lconst_1: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, 1);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case ldc:
|
|
|
|
case ldc_w: {
|
|
|
|
uint16_t index;
|
|
|
|
|
|
|
|
if (instruction == ldc) {
|
2014-06-29 05:40:16 +00:00
|
|
|
index = code->body()[ip++];
|
2007-07-04 02:56:02 +00:00
|
|
|
} else {
|
2007-10-04 22:41:19 +00:00
|
|
|
index = codeReadInt16(t, code, ip);
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcSingleton* pool = code->pool();
|
2007-08-15 02:08:43 +00:00
|
|
|
|
2007-11-05 21:40:17 +00:00
|
|
|
if (singletonIsObject(t, pool, index - 1)) {
|
|
|
|
object v = singletonObject(t, pool, index - 1);
|
2014-05-29 04:17:25 +00:00
|
|
|
if (objectClass(t, v) == type(t, GcReference::Type)) {
|
|
|
|
GcClass* class_ = resolveClassInPool
|
|
|
|
(t, frameMethod(t, frame), index - 1);
|
2007-11-05 21:40:17 +00:00
|
|
|
|
2014-06-28 00:32:20 +00:00
|
|
|
pushObject(t, reinterpret_cast<object>(getJClass(t, class_)));
|
2014-05-29 04:17:25 +00:00
|
|
|
} else if (objectClass(t, v) == type(t, GcClass::Type)) {
|
2014-06-28 00:32:20 +00:00
|
|
|
pushObject(t, reinterpret_cast<object>(getJClass(t, cast<GcClass>(t, v))));
|
2014-05-29 04:17:25 +00:00
|
|
|
} else {
|
2007-11-05 21:40:17 +00:00
|
|
|
pushObject(t, v);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pushInt(t, singletonValue(t, pool, index - 1));
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ldc2_w: {
|
2007-10-04 22:41:19 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcSingleton* pool = code->pool();
|
2007-07-04 02:56:02 +00:00
|
|
|
|
2007-11-05 21:40:17 +00:00
|
|
|
uint64_t v;
|
|
|
|
memcpy(&v, &singletonValue(t, pool, index - 1), 8);
|
|
|
|
pushLong(t, v);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-20 14:36:31 +00:00
|
|
|
case ldiv_: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2010-12-20 00:47:21 +00:00
|
|
|
if (UNLIKELY(b == 0)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcArithmeticException::Type);
|
2010-12-20 00:47:21 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a / b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case lload:
|
|
|
|
case dload: {
|
2014-06-29 05:40:16 +00:00
|
|
|
pushLong(t, localLong(t, code->body()[ip++]));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case lload_0:
|
|
|
|
case dload_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 0));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case lload_1:
|
|
|
|
case dload_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 1));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case lload_2:
|
|
|
|
case dload_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 2));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case lload_3:
|
|
|
|
case dload_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 3));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case lmul: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a * b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lneg: {
|
2007-08-19 20:24:26 +00:00
|
|
|
pushLong(t, - popLong(t));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 02:52:12 +00:00
|
|
|
case lookupswitch: {
|
|
|
|
int32_t base = ip - 1;
|
|
|
|
|
|
|
|
ip += 3;
|
|
|
|
ip -= (ip % 4);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
int32_t default_ = codeReadInt32(t, code, ip);
|
|
|
|
int32_t pairCount = codeReadInt32(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 02:52:12 +00:00
|
|
|
int32_t key = popInt(t);
|
|
|
|
|
|
|
|
int32_t bottom = 0;
|
|
|
|
int32_t top = pairCount;
|
|
|
|
for (int32_t span = top - bottom; span; span = top - bottom) {
|
|
|
|
int32_t middle = bottom + (span / 2);
|
|
|
|
unsigned index = ip + (middle * 8);
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
int32_t k = codeReadInt32(t, code, index);
|
2007-08-13 02:52:12 +00:00
|
|
|
|
|
|
|
if (key < k) {
|
|
|
|
top = middle;
|
|
|
|
} else if (key > k) {
|
|
|
|
bottom = middle + 1;
|
|
|
|
} else {
|
2007-09-26 23:23:03 +00:00
|
|
|
ip = base + codeReadInt32(t, code, index);
|
2007-08-13 02:52:12 +00:00
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ip = base + default_;
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case lor: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a | b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lrem: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2010-12-20 00:47:21 +00:00
|
|
|
if (UNLIKELY(b == 0)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcArithmeticException::Type);
|
2010-12-20 00:47:21 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a % b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case lreturn:
|
|
|
|
case dreturn: {
|
2007-07-07 23:47:35 +00:00
|
|
|
int64_t result = popLong(t);
|
2007-07-24 01:44:20 +00:00
|
|
|
if (frame > base) {
|
|
|
|
popFrame(t);
|
2007-07-07 23:47:35 +00:00
|
|
|
pushLong(t, result);
|
|
|
|
goto loop;
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
return reinterpret_cast<object>(makeLong(t, result));
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case lshl: {
|
2007-09-14 03:59:39 +00:00
|
|
|
int32_t b = popInt(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-08-11 19:09:03 +00:00
|
|
|
pushLong(t, a << (b & 0x3F));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lshr: {
|
2007-09-14 03:59:39 +00:00
|
|
|
int32_t b = popInt(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-08-11 19:09:03 +00:00
|
|
|
pushLong(t, a >> (b & 0x3F));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 14:06:31 +00:00
|
|
|
case lstore:
|
|
|
|
case dstore: {
|
2014-06-29 05:40:16 +00:00
|
|
|
setLocalLong(t, code->body()[ip++], popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
case lstore_0:
|
2007-08-13 14:06:31 +00:00
|
|
|
case dstore_0:{
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 0, popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
case lstore_1:
|
2007-08-13 14:06:31 +00:00
|
|
|
case dstore_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 1, popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
case lstore_2:
|
2007-08-13 14:06:31 +00:00
|
|
|
case dstore_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 2, popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
case lstore_3:
|
2007-08-13 14:06:31 +00:00
|
|
|
case dstore_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 3, popLong(t));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lsub: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a - b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lushr: {
|
2008-01-13 22:05:08 +00:00
|
|
|
int64_t b = popInt(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
uint64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-08-11 19:09:03 +00:00
|
|
|
pushLong(t, a >> (b & 0x3F));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lxor: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a ^ b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-02 01:42:35 +00:00
|
|
|
case monitorenter: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object o = popObject(t);
|
2007-07-02 01:42:35 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-07-07 23:47:35 +00:00
|
|
|
acquire(t, o);
|
2007-07-02 01:42:35 +00:00
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-07-02 01:42:35 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case monitorexit: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object o = popObject(t);
|
2007-07-02 01:42:35 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-07-07 23:47:35 +00:00
|
|
|
release(t, o);
|
2007-07-02 01:42:35 +00:00
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-07-02 01:42:35 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
2007-07-01 21:34:22 +00:00
|
|
|
|
2007-09-14 20:35:37 +00:00
|
|
|
case multianewarray: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2014-06-29 05:40:16 +00:00
|
|
|
uint8_t dimensions = code->body()[ip++];
|
2007-09-14 20:35:37 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
|
2007-09-14 23:05:06 +00:00
|
|
|
PROTECT(t, class_);
|
2007-09-14 20:35:37 +00:00
|
|
|
|
2013-02-05 17:13:59 +00:00
|
|
|
THREAD_RUNTIME_ARRAY(t, int32_t, counts, dimensions);
|
2007-09-14 20:35:37 +00:00
|
|
|
for (int i = dimensions - 1; i >= 0; --i) {
|
2013-02-21 00:20:17 +00:00
|
|
|
RUNTIME_ARRAY_BODY(counts)[i] = popInt(t);
|
|
|
|
if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcNegativeArraySizeException::Type, "%d",
|
2013-02-21 00:20:17 +00:00
|
|
|
RUNTIME_ARRAY_BODY(counts)[i]);
|
2007-09-14 20:35:37 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
object array = reinterpret_cast<object>(makeArray(t, RUNTIME_ARRAY_BODY(counts)[0]));
|
2007-09-14 20:35:37 +00:00
|
|
|
setObjectClass(t, array, class_);
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
2013-02-21 00:20:17 +00:00
|
|
|
populateMultiArray(t, array, RUNTIME_ARRAY_BODY(counts), 0, dimensions);
|
2007-09-14 20:35:37 +00:00
|
|
|
|
|
|
|
pushObject(t, array);
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case new_: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
|
|
|
GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1);
|
2007-09-15 00:32:32 +00:00
|
|
|
PROTECT(t, class_);
|
2007-06-11 23:40:24 +00:00
|
|
|
|
2011-04-01 01:43:49 +00:00
|
|
|
initClass(t, class_);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, make(t, class_));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case newarray: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t count = popInt(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(count >= 0)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
uint8_t type = code->body()[ip++];
|
2007-05-31 00:29:07 +00:00
|
|
|
|
|
|
|
object array;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case T_BOOLEAN:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeBooleanArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_CHAR:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeCharArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_FLOAT:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeFloatArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_DOUBLE:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeDoubleArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_BYTE:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeByteArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_SHORT:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeShortArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_INT:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeIntArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_LONG:
|
2014-05-29 04:17:25 +00:00
|
|
|
array = reinterpret_cast<object>(makeLongArray(t, count));
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
default: abort(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, array);
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcNegativeArraySizeException::Type, "%d", count);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case nop: goto loop;
|
|
|
|
|
2007-06-25 02:02:24 +00:00
|
|
|
case pop_: {
|
2007-06-08 14:23:04 +00:00
|
|
|
-- sp;
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case pop2: {
|
2007-07-04 02:56:02 +00:00
|
|
|
sp -= 2;
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case putfield: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcField* field = resolveField(t, frameMethod(t, frame), index - 1);
|
2009-03-03 03:18:15 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
assertT(t, (field->flags() & ACC_STATIC) == 0);
|
2009-10-11 00:23:14 +00:00
|
|
|
PROTECT(t, field);
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
{ ACQUIRE_FIELD_FOR_WRITE(t, field);
|
2007-11-02 21:08:14 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
switch (field->code()) {
|
2011-03-15 23:52:02 +00:00
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
|
|
|
int32_t value = popInt(t);
|
|
|
|
object o = popObject(t);
|
|
|
|
if (LIKELY(o)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
switch (field->code()) {
|
2011-03-15 23:52:02 +00:00
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int8_t>(o, field->offset()) = value;
|
2011-03-15 23:52:02 +00:00
|
|
|
break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2011-03-15 23:52:02 +00:00
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int16_t>(o, field->offset()) = value;
|
2011-03-15 23:52:02 +00:00
|
|
|
break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2011-03-15 23:52:02 +00:00
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int32_t>(o, field->offset()) = value;
|
2011-03-15 23:52:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
2011-03-15 23:52:02 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
|
|
|
int64_t value = popLong(t);
|
|
|
|
object o = popObject(t);
|
|
|
|
if (LIKELY(o)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int64_t>(o, field->offset()) = value;
|
2011-03-15 23:52:02 +00:00
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2011-03-15 23:52:02 +00:00
|
|
|
}
|
|
|
|
} break;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
2011-03-15 23:52:02 +00:00
|
|
|
case ObjectField: {
|
|
|
|
object value = popObject(t);
|
|
|
|
object o = popObject(t);
|
|
|
|
if (LIKELY(o)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
set(t, o, field->offset(), value);
|
2011-03-15 23:52:02 +00:00
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2011-03-15 23:52:02 +00:00
|
|
|
}
|
|
|
|
} break;
|
2009-03-03 03:18:15 +00:00
|
|
|
|
2011-03-15 23:52:02 +00:00
|
|
|
default: abort(t);
|
2009-03-04 01:02:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UNLIKELY(exception)) {
|
|
|
|
goto throw_;
|
2009-03-03 03:18:15 +00:00
|
|
|
}
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case putstatic: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcField* field = resolveField(t, frameMethod(t, frame), index - 1);
|
2009-03-03 03:18:15 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
assertT(t, field->flags() & ACC_STATIC);
|
2009-10-11 00:23:14 +00:00
|
|
|
|
|
|
|
PROTECT(t, field);
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
ACQUIRE_FIELD_FOR_WRITE(t, field);
|
2008-12-18 23:32:18 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
initClass(t, field->class_());
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
GcSingleton* table = field->class_()->staticTable();
|
2007-07-04 02:56:02 +00:00
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
switch (field->code()) {
|
2007-07-04 02:56:02 +00:00
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
2007-11-02 21:08:14 +00:00
|
|
|
int32_t value = popInt(t);
|
2014-06-29 05:40:16 +00:00
|
|
|
switch (field->code()) {
|
2007-11-02 21:08:14 +00:00
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int8_t>(table, field->offset()) = value;
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-11-02 21:08:14 +00:00
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int16_t>(table, field->offset()) = value;
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-11-02 21:08:14 +00:00
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int32_t>(table, field->offset()) = value;
|
2007-11-02 21:08:14 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-07-04 02:56:02 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
2014-06-29 05:40:16 +00:00
|
|
|
fieldAtOffset<int64_t>(table, field->offset()) = popLong(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
} break;
|
|
|
|
|
2007-11-02 21:08:14 +00:00
|
|
|
case ObjectField: {
|
2014-06-29 05:40:16 +00:00
|
|
|
set(t, reinterpret_cast<object>(table), field->offset(), popObject(t));
|
2007-11-02 21:08:14 +00:00
|
|
|
} break;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ret: {
|
2014-06-29 05:40:16 +00:00
|
|
|
ip = localInt(t, code->body()[ip]);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case return_: {
|
2014-05-29 04:17:25 +00:00
|
|
|
GcMethod* method = frameMethod(t, frame);
|
|
|
|
if ((method->flags() & ConstructorFlag)
|
2014-06-21 04:16:33 +00:00
|
|
|
and (method->class_()->vmFlags() & HasFinalMemberFlag))
|
2009-03-03 03:18:15 +00:00
|
|
|
{
|
|
|
|
storeStoreMemoryBarrier();
|
|
|
|
}
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
if (frame > base) {
|
|
|
|
popFrame(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto loop;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case saload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcShortArray* a = cast<GcShortArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
pushInt(t, a->body()[index]);
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case sastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int16_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2014-06-29 05:40:16 +00:00
|
|
|
GcShortArray* a = cast<GcShortArray>(t, array);
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2014-06-29 05:40:16 +00:00
|
|
|
static_cast<uintptr_t>(index) < a->length()))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2014-06-29 05:40:16 +00:00
|
|
|
a->body()[index] = value;
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
avoid inifinite recursion if java.lang.Object is missing; refactoring
When trying to create an array class, we try to resolve
java.lang.Object so we can use its vtable in the array class.
However, if Object is missing, we'll try to create and throw a
ClassNotFoundException, which requires creating an array to store the
stack trace, which requires creating an array class, which requires
resolving Object, etc.. This commit short-circuits this process by
telling resolveClass not to create and throw an exception if it can't
find Object.
While doing the above work, I noticed that the implementations of
Classpath::makeThrowable in classpath-avian.cpp and
classpath-openjdk.cpp were identical, so I made makeThrowable a
top-level function.
Finally, I discovered that Thread.setDaemon can only be called before
the target thread has been started, which allowed me to simplify the
code to track daemon threads in the VM.
2010-12-10 02:38:12 +00:00
|
|
|
exception = makeThrowable
|
2014-05-29 04:17:25 +00:00
|
|
|
(t, GcArrayIndexOutOfBoundsException::Type, "%d not in [0,%d)",
|
2014-06-29 05:40:16 +00:00
|
|
|
index, a->length());
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-29 04:17:25 +00:00
|
|
|
exception = makeThrowable(t, GcNullPointerException::Type);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case sipush: {
|
2007-09-30 02:48:27 +00:00
|
|
|
pushInt(t, static_cast<int16_t>(codeReadInt16(t, code, ip)));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case swap: {
|
2007-07-04 02:56:02 +00:00
|
|
|
uintptr_t tmp[2];
|
|
|
|
memcpy(tmp , stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), tmp , BytesPerWord * 2);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-08-13 02:52:12 +00:00
|
|
|
case tableswitch: {
|
|
|
|
int32_t base = ip - 1;
|
|
|
|
|
|
|
|
ip += 3;
|
|
|
|
ip -= (ip % 4);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
int32_t default_ = codeReadInt32(t, code, ip);
|
|
|
|
int32_t bottom = codeReadInt32(t, code, ip);
|
|
|
|
int32_t top = codeReadInt32(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 02:52:12 +00:00
|
|
|
int32_t key = popInt(t);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-08-13 02:52:12 +00:00
|
|
|
if (key >= bottom and key <= top) {
|
|
|
|
unsigned index = ip + ((key - bottom) * 4);
|
2007-09-26 23:23:03 +00:00
|
|
|
ip = base + codeReadInt32(t, code, index);
|
2007-08-13 02:52:12 +00:00
|
|
|
} else {
|
2007-11-05 14:28:46 +00:00
|
|
|
ip = base + default_;
|
2007-08-13 02:52:12 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case wide: goto wide;
|
|
|
|
|
2007-11-04 21:15:28 +00:00
|
|
|
case impdep1: {
|
|
|
|
// this means we're invoking a virtual method on an instance of a
|
2007-11-05 15:29:43 +00:00
|
|
|
// bootstrap class, so we need to load the real class to get the
|
|
|
|
// real method and call it.
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, frameNext(t, frame) >= base);
|
2007-11-05 15:29:43 +00:00
|
|
|
popFrame(t);
|
|
|
|
|
2014-06-29 05:40:16 +00:00
|
|
|
assertT(t, code->body()[ip - 3] == invokevirtual);
|
2007-11-05 15:29:43 +00:00
|
|
|
ip -= 2;
|
|
|
|
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
GcMethod* method = resolveMethod(t, frameMethod(t, frame), index - 1);
|
2007-11-05 15:29:43 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
unsigned parameterFootprint = method->parameterFootprint();
|
|
|
|
GcClass* class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, class_->vmFlags() & BootstrapFlag);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2014-06-28 21:11:31 +00:00
|
|
|
resolveClass(t, frameMethod(t, frame)->class_()->loader(),
|
2014-06-28 23:24:24 +00:00
|
|
|
class_->name());
|
2007-11-05 15:29:43 +00:00
|
|
|
|
|
|
|
ip -= 3;
|
|
|
|
} goto loop;
|
2007-11-04 21:15:28 +00:00
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
default: abort(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
wide:
|
2014-06-29 05:40:16 +00:00
|
|
|
switch (code->body()[ip++]) {
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload: {
|
2007-09-26 23:23:03 +00:00
|
|
|
pushObject(t, localObject(t, codeReadInt16(t, code, ip)));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore: {
|
2007-09-26 23:23:03 +00:00
|
|
|
setLocalObject(t, codeReadInt16(t, code, ip), popObject(t));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iinc: {
|
2007-09-26 23:23:03 +00:00
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2010-09-27 23:12:08 +00:00
|
|
|
int16_t count = codeReadInt16(t, code, ip);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, index, localInt(t, index) + count);
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iload: {
|
2007-09-26 23:23:03 +00:00
|
|
|
pushInt(t, localInt(t, codeReadInt16(t, code, ip)));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case istore: {
|
2007-09-26 23:23:03 +00:00
|
|
|
setLocalInt(t, codeReadInt16(t, code, ip), popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lload: {
|
2007-09-26 23:23:03 +00:00
|
|
|
pushLong(t, localLong(t, codeReadInt16(t, code, ip)));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lstore: {
|
2007-09-26 23:23:03 +00:00
|
|
|
setLocalLong(t, codeReadInt16(t, code, ip), popLong(t));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ret: {
|
2007-09-26 23:23:03 +00:00
|
|
|
ip = localInt(t, codeReadInt16(t, code, ip));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
default: abort(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
}
|
|
|
|
|
2013-12-13 18:48:26 +00:00
|
|
|
back_branch:
|
|
|
|
safePoint(t);
|
|
|
|
goto loop;
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
invoke: {
|
2014-06-29 05:40:16 +00:00
|
|
|
if (method->flags() & ACC_NATIVE) {
|
|
|
|
invokeNative(t, method);
|
2007-06-24 01:39:49 +00:00
|
|
|
} else {
|
2014-06-29 05:40:16 +00:00
|
|
|
checkStack(t, method);
|
|
|
|
pushFrame(t, method);
|
2007-06-24 19:57:00 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
throw_:
|
2007-07-12 00:06:57 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "throw\n");
|
|
|
|
}
|
|
|
|
|
2007-07-08 01:06:32 +00:00
|
|
|
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
2007-07-25 01:56:05 +00:00
|
|
|
for (; frame >= base; popFrame(t)) {
|
2011-08-30 01:00:17 +00:00
|
|
|
uint64_t eh = findExceptionHandler(t, frame);
|
2007-10-02 00:08:17 +00:00
|
|
|
if (eh) {
|
|
|
|
sp = frame + FrameFootprint;
|
|
|
|
ip = exceptionHandlerIp(eh);
|
2014-06-28 23:24:24 +00:00
|
|
|
pushObject(t, reinterpret_cast<object>(exception));
|
2007-10-02 00:08:17 +00:00
|
|
|
exception = 0;
|
|
|
|
goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-24 19:57:00 +00:00
|
|
|
return 0;
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
uint64_t
|
|
|
|
interpret2(vm::Thread* t, uintptr_t* arguments)
|
|
|
|
{
|
|
|
|
int base = arguments[0];
|
|
|
|
bool* success = reinterpret_cast<bool*>(arguments[1]);
|
|
|
|
|
|
|
|
object r = interpret3(static_cast<Thread*>(t), base);
|
|
|
|
*success = true;
|
|
|
|
return reinterpret_cast<uint64_t>(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
interpret(Thread* t)
|
|
|
|
{
|
|
|
|
const int base = t->frame;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
bool success = false;
|
2012-06-14 01:10:28 +00:00
|
|
|
uintptr_t arguments[] = { static_cast<uintptr_t>(base),
|
|
|
|
reinterpret_cast<uintptr_t>(&success) };
|
2010-12-27 22:55:23 +00:00
|
|
|
|
|
|
|
uint64_t r = run(t, interpret2, arguments);
|
|
|
|
if (success) {
|
|
|
|
if (t->exception) {
|
2014-06-28 23:24:24 +00:00
|
|
|
GcThrowable* exception = t->exception;
|
2010-12-27 22:55:23 +00:00
|
|
|
t->exception = 0;
|
|
|
|
throw_(t, exception);
|
|
|
|
} else {
|
|
|
|
return reinterpret_cast<object>(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
void
|
2007-09-07 23:20:21 +00:00
|
|
|
pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
|
|
|
va_list a)
|
2007-06-18 21:13:21 +00:00
|
|
|
{
|
2007-07-16 23:58:37 +00:00
|
|
|
if (this_) {
|
|
|
|
pushObject(t, this_);
|
|
|
|
}
|
|
|
|
|
2007-11-02 21:08:14 +00:00
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
2007-07-16 23:58:37 +00:00
|
|
|
case 'L':
|
|
|
|
case '[':
|
2007-09-13 03:15:16 +00:00
|
|
|
if (indirectObjects) {
|
|
|
|
object* v = va_arg(a, object*);
|
|
|
|
pushObject(t, v ? *v : 0);
|
|
|
|
} else {
|
|
|
|
pushObject(t, va_arg(a, object));
|
|
|
|
}
|
2007-07-16 23:58:37 +00:00
|
|
|
break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-16 23:58:37 +00:00
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
pushLong(t, va_arg(a, uint64_t));
|
|
|
|
break;
|
2007-10-02 15:50:08 +00:00
|
|
|
|
|
|
|
case 'F': {
|
2007-10-15 19:12:38 +00:00
|
|
|
pushFloat(t, va_arg(a, double));
|
2007-10-02 15:50:08 +00:00
|
|
|
} break;
|
2007-11-02 21:08:14 +00:00
|
|
|
|
2007-07-16 23:58:37 +00:00
|
|
|
default:
|
|
|
|
pushInt(t, va_arg(a, uint32_t));
|
2014-05-29 04:17:25 +00:00
|
|
|
break;
|
2007-07-16 23:58:37 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-24 01:44:20 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
void
|
|
|
|
pushArguments(Thread* t, object this_, const char* spec,
|
|
|
|
const jvalue* arguments)
|
|
|
|
{
|
|
|
|
if (this_) {
|
|
|
|
pushObject(t, this_);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned index = 0;
|
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
|
|
|
case 'L':
|
|
|
|
case '[': {
|
|
|
|
jobject v = arguments[index++].l;
|
|
|
|
pushObject(t, v ? *v : 0);
|
|
|
|
} break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
pushLong(t, arguments[index++].j);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'F': {
|
2012-10-05 16:56:07 +00:00
|
|
|
pushFloat(t, arguments[index++].f);
|
2012-06-15 23:41:40 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
pushInt(t, arguments[index++].i);
|
2014-05-29 04:17:25 +00:00
|
|
|
break;
|
2012-06-15 23:41:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
void
|
|
|
|
pushArguments(Thread* t, object this_, const char* spec, object a)
|
|
|
|
{
|
|
|
|
if (this_) {
|
|
|
|
pushObject(t, this_);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned index = 0;
|
2007-11-02 21:08:14 +00:00
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
2007-07-24 01:44:20 +00:00
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
pushObject(t, objectArrayBody(t, a, index++));
|
|
|
|
break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
case 'J':
|
|
|
|
case 'D':
|
2013-02-11 00:38:51 +00:00
|
|
|
pushLong(t, fieldAtOffset<int64_t>(objectArrayBody(t, a, index++), 8));
|
2007-07-24 01:44:20 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2013-02-11 00:38:51 +00:00
|
|
|
pushInt(t, fieldAtOffset<int32_t>(objectArrayBody(t, a, index++),
|
2007-11-02 21:08:14 +00:00
|
|
|
BytesPerWord));
|
2014-05-29 04:17:25 +00:00
|
|
|
break;
|
2007-07-24 01:44:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
2014-05-29 04:17:25 +00:00
|
|
|
invoke(Thread* t, GcMethod* method)
|
2007-07-24 01:44:20 +00:00
|
|
|
{
|
2007-08-23 03:30:37 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
GcClass* class_;
|
2007-08-23 03:30:37 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
2007-11-05 15:52:03 +00:00
|
|
|
if (methodVirtual(t, method)) {
|
2014-05-29 04:17:25 +00:00
|
|
|
unsigned parameterFootprint = method->parameterFootprint();
|
2007-08-23 03:30:37 +00:00
|
|
|
class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint));
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (class_->vmFlags() & BootstrapFlag) {
|
2014-06-28 23:24:24 +00:00
|
|
|
resolveClass(t, cast<GcClassLoader>(t, root(t, Machine::BootLoader)), class_->name());
|
2007-11-05 15:29:43 +00:00
|
|
|
}
|
|
|
|
|
2014-06-21 04:16:33 +00:00
|
|
|
if (method->class_()->flags() & ACC_INTERFACE) {
|
2007-08-23 03:30:37 +00:00
|
|
|
method = findInterfaceMethod(t, method, class_);
|
|
|
|
} else {
|
2009-08-18 20:41:21 +00:00
|
|
|
method = findVirtualMethod(t, method, class_);
|
2007-08-23 03:30:37 +00:00
|
|
|
}
|
2007-11-05 15:52:03 +00:00
|
|
|
} else {
|
2014-06-21 04:16:33 +00:00
|
|
|
class_ = method->class_();
|
2007-08-23 03:30:37 +00:00
|
|
|
}
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (method->flags() & ACC_STATIC) {
|
2013-05-01 04:48:43 +00:00
|
|
|
initClass(t, class_);
|
|
|
|
}
|
2007-08-23 03:30:37 +00:00
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
object result = 0;
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (method->flags() & ACC_NATIVE) {
|
2007-07-24 01:44:20 +00:00
|
|
|
unsigned returnCode = invokeNative(t, method);
|
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
switch (returnCode) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2014-05-29 04:17:25 +00:00
|
|
|
result = reinterpret_cast<object>(makeInt(t, popInt(t)));
|
2010-12-27 22:55:23 +00:00
|
|
|
break;
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
2014-05-29 04:17:25 +00:00
|
|
|
result = reinterpret_cast<object>(makeLong(t, popLong(t)));
|
2010-12-27 22:55:23 +00:00
|
|
|
break;
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
case ObjectField:
|
|
|
|
result = popObject(t);
|
|
|
|
break;
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
case VoidField:
|
|
|
|
result = 0;
|
|
|
|
break;
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2010-12-27 22:55:23 +00:00
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
};
|
2007-07-24 01:44:20 +00:00
|
|
|
} else {
|
|
|
|
checkStack(t, method);
|
2010-12-27 22:55:23 +00:00
|
|
|
pushFrame(t, method);
|
|
|
|
|
|
|
|
result = interpret(t);
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
if (LIKELY(t->exception == 0)) {
|
2010-12-27 22:55:23 +00:00
|
|
|
popFrame(t);
|
|
|
|
} else {
|
2014-06-28 23:24:24 +00:00
|
|
|
GcThrowable* exception = t->exception;
|
2010-12-27 22:55:23 +00:00
|
|
|
t->exception = 0;
|
|
|
|
throw_(t, exception);
|
2007-07-24 01:44:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-17 19:55:05 +00:00
|
|
|
return result;
|
2007-07-24 01:44:20 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
class MyProcessor: public Processor {
|
|
|
|
public:
|
2014-02-22 00:06:17 +00:00
|
|
|
MyProcessor(System* s, Allocator* allocator, const char* crashDumpDirectory)
|
|
|
|
: s(s), allocator(allocator)
|
|
|
|
{
|
|
|
|
signals.setCrashDumpDirectory(crashDumpDirectory);
|
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
virtual vm::Thread*
|
2014-06-28 19:16:26 +00:00
|
|
|
makeThread(Machine* m, GcThread* javaThread, vm::Thread* parent)
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
2012-03-14 18:36:42 +00:00
|
|
|
Thread* t = new (m->heap->allocate(sizeof(Thread) + m->stackSizeInBytes))
|
2007-10-25 22:06:05 +00:00
|
|
|
Thread(m, javaThread, parent);
|
|
|
|
t->init();
|
|
|
|
return t;
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
virtual GcMethod*
|
2007-11-05 21:40:17 +00:00
|
|
|
makeMethod(vm::Thread* t,
|
|
|
|
uint8_t vmFlags,
|
|
|
|
uint8_t returnCode,
|
|
|
|
uint8_t parameterCount,
|
|
|
|
uint8_t parameterFootprint,
|
|
|
|
uint16_t flags,
|
|
|
|
uint16_t offset,
|
2014-05-29 04:17:25 +00:00
|
|
|
GcByteArray* name,
|
|
|
|
GcByteArray* spec,
|
2014-06-28 19:16:26 +00:00
|
|
|
GcMethodAddendum* addendum,
|
2014-05-29 04:17:25 +00:00
|
|
|
GcClass* class_,
|
|
|
|
GcCode* code)
|
2007-10-01 15:19:15 +00:00
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
return vm::makeMethod(t,
|
|
|
|
vmFlags,
|
|
|
|
returnCode,
|
|
|
|
parameterCount,
|
|
|
|
parameterFootprint,
|
|
|
|
flags,
|
|
|
|
offset,
|
|
|
|
0,
|
|
|
|
0,
|
2014-06-21 04:16:33 +00:00
|
|
|
name,
|
|
|
|
spec,
|
2014-06-28 19:16:26 +00:00
|
|
|
addendum,
|
2014-06-21 04:16:33 +00:00
|
|
|
class_,
|
2014-06-28 04:00:05 +00:00
|
|
|
code);
|
2014-05-29 04:17:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual GcClass*
|
2007-11-05 21:40:17 +00:00
|
|
|
makeClass(vm::Thread* t,
|
|
|
|
uint16_t flags,
|
2009-08-18 20:26:28 +00:00
|
|
|
uint16_t vmFlags,
|
2007-11-05 21:40:17 +00:00
|
|
|
uint16_t fixedSize,
|
2009-08-18 20:26:28 +00:00
|
|
|
uint8_t arrayElementSize,
|
|
|
|
uint8_t arrayDimensions,
|
2014-06-28 00:32:20 +00:00
|
|
|
GcClass* arrayElementClass,
|
2014-06-28 19:16:26 +00:00
|
|
|
GcIntArray* objectMask,
|
|
|
|
GcByteArray* name,
|
|
|
|
GcByteArray* sourceFile,
|
|
|
|
GcClass* super,
|
2007-11-05 21:40:17 +00:00
|
|
|
object interfaceTable,
|
|
|
|
object virtualTable,
|
|
|
|
object fieldTable,
|
|
|
|
object methodTable,
|
2014-06-28 00:32:20 +00:00
|
|
|
GcClassAddendum* addendum,
|
2014-06-28 18:28:44 +00:00
|
|
|
GcSingleton* staticTable,
|
2014-06-28 19:16:26 +00:00
|
|
|
GcClassLoader* loader,
|
2007-11-05 21:40:17 +00:00
|
|
|
unsigned vtableLength UNUSED)
|
2007-09-26 14:43:40 +00:00
|
|
|
{
|
2014-06-21 04:16:33 +00:00
|
|
|
return vm::makeClass(t,
|
|
|
|
flags,
|
|
|
|
vmFlags,
|
|
|
|
fixedSize,
|
|
|
|
arrayElementSize,
|
|
|
|
arrayDimensions,
|
2014-06-28 00:32:20 +00:00
|
|
|
arrayElementClass,
|
2014-06-21 04:16:33 +00:00
|
|
|
0,
|
2014-06-28 19:16:26 +00:00
|
|
|
objectMask,
|
|
|
|
name,
|
|
|
|
sourceFile,
|
|
|
|
super,
|
2014-06-21 04:16:33 +00:00
|
|
|
interfaceTable,
|
|
|
|
virtualTable,
|
|
|
|
fieldTable,
|
|
|
|
methodTable,
|
2014-06-28 00:32:20 +00:00
|
|
|
addendum,
|
2014-06-21 04:16:33 +00:00
|
|
|
staticTable,
|
2014-06-28 19:16:26 +00:00
|
|
|
loader,
|
2014-06-21 04:16:33 +00:00
|
|
|
0,
|
|
|
|
0);
|
2007-09-26 14:43:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual void
|
2014-05-29 04:17:25 +00:00
|
|
|
initVtable(vm::Thread*, GcClass*)
|
2007-12-11 21:26:59 +00:00
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
}
|
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
virtual void
|
|
|
|
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-10-28 19:14:53 +00:00
|
|
|
v->visit(&(t->code));
|
2007-09-24 13:46:48 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < t->sp; ++i) {
|
|
|
|
if (t->stack[i * 2] == ObjectTag) {
|
2007-10-28 19:14:53 +00:00
|
|
|
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
2007-09-24 13:46:48 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
2007-11-25 23:00:55 +00:00
|
|
|
virtual void
|
|
|
|
walkStack(vm::Thread* vmt, StackVisitor* v)
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
if (t->frame >= 0) {
|
|
|
|
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2007-11-25 23:00:55 +00:00
|
|
|
MyStackWalker walker(t, t->frame);
|
|
|
|
walker.walk(v);
|
2007-09-24 13:46:48 +00:00
|
|
|
}
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
virtual int
|
2014-05-29 04:17:25 +00:00
|
|
|
lineNumber(vm::Thread* t, GcMethod* method, int ip)
|
2007-10-04 22:41:19 +00:00
|
|
|
{
|
2007-11-26 23:15:53 +00:00
|
|
|
return findLineNumber(static_cast<Thread*>(t), method, ip);
|
2007-10-04 22:41:19 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
virtual object*
|
|
|
|
makeLocalReference(vm::Thread* vmt, object o)
|
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
return pushReference(t, o);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
disposeLocalReference(vm::Thread*, object* r)
|
2007-07-24 01:44:20 +00:00
|
|
|
{
|
2007-09-24 13:46:48 +00:00
|
|
|
if (r) {
|
|
|
|
*r = 0;
|
|
|
|
}
|
2007-07-24 01:44:20 +00:00
|
|
|
}
|
|
|
|
|
2012-08-11 12:56:19 +00:00
|
|
|
virtual bool
|
|
|
|
pushLocalFrame(vm::Thread* vmt, unsigned capacity)
|
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
|
|
|
|
|
|
|
if (t->sp + capacity < stackSizeInWords(t) / 2) {
|
2013-12-11 04:36:55 +00:00
|
|
|
t->stackPointers = new(t->m->heap)
|
|
|
|
List<unsigned>(t->sp, t->stackPointers);
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2012-08-11 12:56:19 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
popLocalFrame(vm::Thread* vmt)
|
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
|
|
|
|
2013-12-11 04:36:55 +00:00
|
|
|
List<unsigned>* f = t->stackPointers;
|
|
|
|
t->stackPointers = f->next;
|
|
|
|
t->sp = f->item;
|
2012-08-11 12:56:19 +00:00
|
|
|
|
2013-12-11 04:36:55 +00:00
|
|
|
t->m->heap->free(f, sizeof(List<unsigned>));
|
2012-08-11 12:56:19 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
virtual object
|
2014-05-29 04:17:25 +00:00
|
|
|
invokeArray(vm::Thread* vmt, GcMethod* method, object this_, object arguments)
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->state == Thread::ActiveState
|
2007-09-24 13:46:48 +00:00
|
|
|
or t->state == Thread::ExclusiveState);
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
2007-09-24 13:46:48 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (UNLIKELY(t->sp + method->parameterFootprint() + 1
|
2012-03-14 18:36:42 +00:00
|
|
|
> stackSizeInWords(t) / 2))
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
throwNew(t, GcStackOverflowError::Type);
|
2007-09-24 13:46:48 +00:00
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
const char* spec = reinterpret_cast<char*>
|
2014-06-21 04:16:33 +00:00
|
|
|
(method->spec()->body().begin());
|
2007-09-24 13:46:48 +00:00
|
|
|
pushArguments(t, this_, spec, arguments);
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2013-01-28 15:20:52 +00:00
|
|
|
return local::invoke(t, method);
|
2007-07-24 01:44:20 +00:00
|
|
|
}
|
|
|
|
|
2012-06-15 23:41:40 +00:00
|
|
|
virtual object
|
2014-05-29 04:17:25 +00:00
|
|
|
invokeArray(vm::Thread* vmt, GcMethod* method, object this_,
|
2012-06-15 23:41:40 +00:00
|
|
|
const jvalue* arguments)
|
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->state == Thread::ActiveState
|
2012-06-15 23:41:40 +00:00
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
2012-06-15 23:41:40 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (UNLIKELY(t->sp + method->parameterFootprint() + 1
|
2012-06-15 23:41:40 +00:00
|
|
|
> stackSizeInWords(t) / 2))
|
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
throwNew(t, GcStackOverflowError::Type);
|
2012-06-15 23:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char* spec = reinterpret_cast<char*>
|
2014-06-21 04:16:33 +00:00
|
|
|
(method->spec()->body().begin());
|
2012-06-15 23:41:40 +00:00
|
|
|
pushArguments(t, this_, spec, arguments);
|
|
|
|
|
2013-01-28 15:20:52 +00:00
|
|
|
return local::invoke(t, method);
|
2012-06-15 23:41:40 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
virtual object
|
2014-05-29 04:17:25 +00:00
|
|
|
invokeList(vm::Thread* vmt, GcMethod* method, object this_,
|
2007-09-25 23:53:11 +00:00
|
|
|
bool indirectObjects, va_list arguments)
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->state == Thread::ActiveState
|
2007-09-24 13:46:48 +00:00
|
|
|
or t->state == Thread::ExclusiveState);
|
2007-07-16 23:58:37 +00:00
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
2007-07-07 18:09:16 +00:00
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
if (UNLIKELY(t->sp + method->parameterFootprint() + 1
|
2012-03-14 18:36:42 +00:00
|
|
|
> stackSizeInWords(t) / 2))
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
throwNew(t, GcStackOverflowError::Type);
|
2007-09-24 13:46:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char* spec = reinterpret_cast<char*>
|
2014-06-21 04:16:33 +00:00
|
|
|
(method->spec()->body().begin());
|
2007-09-24 13:46:48 +00:00
|
|
|
pushArguments(t, this_, spec, indirectObjects, arguments);
|
|
|
|
|
2013-01-28 15:20:52 +00:00
|
|
|
return local::invoke(t, method);
|
2007-06-18 21:13:21 +00:00
|
|
|
}
|
2007-09-24 13:46:48 +00:00
|
|
|
|
|
|
|
virtual object
|
2014-06-28 19:16:26 +00:00
|
|
|
invokeList(vm::Thread* vmt, GcClassLoader* loader, const char* className,
|
2009-08-18 20:41:21 +00:00
|
|
|
const char* methodName, const char* methodSpec, object this_,
|
|
|
|
va_list arguments)
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
|
|
|
Thread* t = static_cast<Thread*>(vmt);
|
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, t->state == Thread::ActiveState
|
2007-09-24 13:46:48 +00:00
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false)
|
2012-03-14 18:36:42 +00:00
|
|
|
> stackSizeInWords(t) / 2))
|
2007-09-24 13:46:48 +00:00
|
|
|
{
|
2014-05-29 04:17:25 +00:00
|
|
|
throwNew(t, GcStackOverflowError::Type);
|
2007-09-24 13:46:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pushArguments(t, this_, methodSpec, false, arguments);
|
|
|
|
|
2014-05-29 04:17:25 +00:00
|
|
|
GcMethod* method = resolveMethod
|
2014-06-28 21:11:31 +00:00
|
|
|
(t, loader, className, methodName, methodSpec);
|
2009-08-18 20:41:21 +00:00
|
|
|
|
2014-06-04 01:52:01 +00:00
|
|
|
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
|
2007-09-24 13:46:48 +00:00
|
|
|
|
2013-01-28 15:20:52 +00:00
|
|
|
return local::invoke(t, method);
|
2007-09-24 13:46:48 +00:00
|
|
|
}
|
|
|
|
|
2011-02-02 02:51:00 +00:00
|
|
|
virtual object getStackTrace(vm::Thread* t, vm::Thread*) {
|
2008-04-11 22:48:39 +00:00
|
|
|
// not implemented
|
2011-02-02 02:51:00 +00:00
|
|
|
return makeObjectArray(t, 0);
|
2008-04-11 22:48:39 +00:00
|
|
|
}
|
|
|
|
|
2014-02-25 22:46:35 +00:00
|
|
|
virtual void initialize(BootImage*, avian::util::Slice<uint8_t>)
|
|
|
|
{
|
2008-12-03 15:44:07 +00:00
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2012-06-12 22:32:53 +00:00
|
|
|
virtual void addCompilationHandler(CompilationHandler*) {
|
2012-05-02 15:49:31 +00:00
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2014-06-28 19:16:26 +00:00
|
|
|
virtual void compileMethod(vm::Thread*, Zone*, GcTriple**, GcTriple**,
|
2014-05-29 04:17:25 +00:00
|
|
|
avian::codegen::DelayedPromise**, GcMethod*, OffsetResolver*)
|
2008-12-03 15:44:07 +00:00
|
|
|
{
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2010-09-14 16:49:41 +00:00
|
|
|
virtual void visitRoots(vm::Thread*, HeapWalker*) {
|
2008-12-03 15:44:07 +00:00
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2011-09-01 03:18:00 +00:00
|
|
|
virtual void normalizeVirtualThunks(vm::Thread*) {
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2009-06-01 03:16:58 +00:00
|
|
|
virtual unsigned* makeCallTable(vm::Thread*, HeapWalker*) {
|
2008-12-03 15:44:07 +00:00
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2011-09-20 22:30:30 +00:00
|
|
|
virtual void boot(vm::Thread*, BootImage* image, uint8_t* code) {
|
|
|
|
expect(s, image == 0 and code == 0);
|
2008-12-03 15:44:07 +00:00
|
|
|
}
|
2009-05-26 03:05:49 +00:00
|
|
|
|
|
|
|
virtual void callWithCurrentContinuation(vm::Thread*, object) {
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dynamicWind(vm::Thread*, object, object, object) {
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2014-06-28 19:16:26 +00:00
|
|
|
virtual void feedResultToContinuation(vm::Thread*, GcContinuation*, object){
|
2009-05-26 03:05:49 +00:00
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2014-06-28 19:16:26 +00:00
|
|
|
virtual void feedExceptionToContinuation(vm::Thread*, GcContinuation*, GcThrowable*) {
|
2009-05-26 03:05:49 +00:00
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void walkContinuationBody(vm::Thread*, Heap::Walker*, object,
|
|
|
|
unsigned)
|
|
|
|
{
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
virtual void dispose(vm::Thread* t) {
|
2012-07-31 20:02:03 +00:00
|
|
|
t->m->heap->free(t, sizeof(Thread) + t->m->stackSizeInBytes);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
virtual void dispose() {
|
2014-02-22 00:06:17 +00:00
|
|
|
signals.setCrashDumpDirectory(0);
|
2014-05-20 22:11:28 +00:00
|
|
|
this->~MyProcessor();
|
|
|
|
allocator->free(this, sizeof(*this));
|
2007-09-24 13:46:48 +00:00
|
|
|
}
|
2014-05-29 04:17:25 +00:00
|
|
|
|
2007-09-24 13:46:48 +00:00
|
|
|
System* s;
|
2008-01-13 22:05:08 +00:00
|
|
|
Allocator* allocator;
|
2014-02-22 00:06:17 +00:00
|
|
|
SignalRegistrar signals;
|
2007-09-24 13:46:48 +00:00
|
|
|
};
|
2007-06-18 21:13:21 +00:00
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
} // namespace
|
2007-07-16 01:03:02 +00:00
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
namespace vm {
|
2007-07-16 01:03:02 +00:00
|
|
|
|
2014-02-22 00:06:17 +00:00
|
|
|
Processor* makeProcessor(System* system,
|
|
|
|
Allocator* allocator,
|
|
|
|
const char* crashDumpDirectory,
|
|
|
|
bool)
|
2007-09-24 01:39:03 +00:00
|
|
|
{
|
2013-01-28 15:20:52 +00:00
|
|
|
return new (allocator->allocate(sizeof(local::MyProcessor)))
|
2014-02-22 00:06:17 +00:00
|
|
|
local::MyProcessor(system, allocator, crashDumpDirectory);
|
2007-06-18 21:13:21 +00:00
|
|
|
}
|
|
|
|
|
2007-07-20 14:36:31 +00:00
|
|
|
} // namespace vm
|