mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
handle weak maps properly in hashMapResize, hashMapRemove, etc.; move Processor::parameterFootprint() into machine.h/machine.cpp
This commit is contained in:
parent
6fe0c4636f
commit
a017dab73a
289
src/compile2.cpp
289
src/compile2.cpp
@ -2476,4 +2476,293 @@ compile(MyThread* t, Compiler* compiler, object method)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MyProcessor: public Processor {
|
||||||
|
public:
|
||||||
|
MyProcessor(System* s):
|
||||||
|
s(s)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual Thread*
|
||||||
|
makeThread(Machine* m, object javaThread, Thread* parent)
|
||||||
|
{
|
||||||
|
MyThread* t = new (s->allocate(sizeof(Thread)))
|
||||||
|
MyThread(m, javaThread, parent);
|
||||||
|
t->init();
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
makeMethod(vm::Thread* t,
|
||||||
|
uint8_t vmFlags,
|
||||||
|
uint8_t returnCode,
|
||||||
|
uint8_t parameterCount,
|
||||||
|
uint8_t parameterFootprint,
|
||||||
|
uint16_t flags,
|
||||||
|
uint16_t offset,
|
||||||
|
object name,
|
||||||
|
object spec,
|
||||||
|
object class_,
|
||||||
|
object code)
|
||||||
|
{
|
||||||
|
object compiled
|
||||||
|
= ((flags & ACC_NATIVE) ? nativeCompiled : defaultCompiled);
|
||||||
|
|
||||||
|
return vm::makeMethod
|
||||||
|
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
|
||||||
|
offset, name, spec, class_, code, compiled);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
makeClass(vm::Thread* t,
|
||||||
|
uint16_t flags,
|
||||||
|
uint8_t vmFlags,
|
||||||
|
uint8_t arrayDimensions,
|
||||||
|
uint16_t fixedSize,
|
||||||
|
uint16_t arrayElementSize,
|
||||||
|
object objectMask,
|
||||||
|
object name,
|
||||||
|
object super,
|
||||||
|
object interfaceTable,
|
||||||
|
object virtualTable,
|
||||||
|
object fieldTable,
|
||||||
|
object methodTable,
|
||||||
|
object staticTable,
|
||||||
|
object loader,
|
||||||
|
unsigned vtableLength)
|
||||||
|
{
|
||||||
|
object c = vm::makeClass
|
||||||
|
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
|
||||||
|
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
|
||||||
|
methodTable, staticTable, loader, vtableLength, false);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < vtableLength; ++i) {
|
||||||
|
object compiled
|
||||||
|
= ((flags & ACC_NATIVE) ? nativeCompiled : defaultCompiled);
|
||||||
|
classVtable(t, c, i) = &singletonBody(t, compiled, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
initClass(Thread* t, object c)
|
||||||
|
{
|
||||||
|
PROTECT(t, c);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
if (classVmFlags(t, c) & NeedInitFlag
|
||||||
|
and (classVmFlags(t, c) & InitFlag) == 0)
|
||||||
|
{
|
||||||
|
classVmFlags(t, c) |= InitFlag;
|
||||||
|
invoke(t, classInitializer(t, c), 0);
|
||||||
|
if (t->exception) {
|
||||||
|
t->exception = makeExceptionInInitializerError(t, t->exception);
|
||||||
|
}
|
||||||
|
classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
visitObjects(Thread* vmt, Heap::Visitor* v)
|
||||||
|
{
|
||||||
|
MyThread* t = static_cast<MyThread*>(vmt);
|
||||||
|
|
||||||
|
if (t == t->m->rootThread) {
|
||||||
|
visit(&defaultCompiled);
|
||||||
|
visit(&nativeCompiled);
|
||||||
|
visit(&addressTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Reference* r = t->reference; r; r = r->next) {
|
||||||
|
v->visit(&(r->target));
|
||||||
|
}
|
||||||
|
|
||||||
|
visitStack(t, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uintptr_t
|
||||||
|
frameStart(Thread* vmt)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(::frameStart(static_cast<MyThread*>(vmt)));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uintptr_t
|
||||||
|
frameNext(Thread*, uintptr_t frame)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>
|
||||||
|
(::frameNext(reinterpret_cast<void*>(frame)));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
frameValid(Thread*, uintptr_t frame)
|
||||||
|
{
|
||||||
|
return ::frameValid(reinterpret_cast<void*>(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
frameMethod(Thread*, uintptr_t frame)
|
||||||
|
{
|
||||||
|
return ::frameMethod(reinterpret_cast<void*>(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual unsigned
|
||||||
|
frameIp(Thread* t, uintptr_t frame)
|
||||||
|
{
|
||||||
|
void* f = reinterpret_cast<void*>(frame);
|
||||||
|
return addressOffset(t, ::frameMethod(f), ::frameAddress(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int
|
||||||
|
lineNumber(Thread* t, object method, unsigned ip)
|
||||||
|
{
|
||||||
|
if (methodFlags(t, method) & ACC_NATIVE) {
|
||||||
|
return NativeLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
|
||||||
|
if (compiledLineNumberCount(t, code)) {
|
||||||
|
unsigned bottom = 0;
|
||||||
|
unsigned top = compiledLineNumberCount(t, code);
|
||||||
|
for (unsigned span = top - bottom; span; span = top - bottom) {
|
||||||
|
unsigned middle = bottom + (span / 2);
|
||||||
|
NativeLineNumber* ln = compiledLineNumber(t, code, middle);
|
||||||
|
|
||||||
|
if (ip >= nativeLineNumberIp(ln)
|
||||||
|
and (middle + 1 == compiledLineNumberCount(t, code)
|
||||||
|
or ip < nativeLineNumberIp
|
||||||
|
(compiledLineNumber(t, code, middle + 1))))
|
||||||
|
{
|
||||||
|
return nativeLineNumberLine(ln);
|
||||||
|
} else if (ip < nativeLineNumberIp(ln)) {
|
||||||
|
top = middle;
|
||||||
|
} else if (ip > nativeLineNumberIp(ln)) {
|
||||||
|
bottom = middle + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(t);
|
||||||
|
} else {
|
||||||
|
return UnknownLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object*
|
||||||
|
makeLocalReference(Thread* vmt, object o)
|
||||||
|
{
|
||||||
|
if (o) {
|
||||||
|
MyThread* t = static_cast<MyThread*>(vmt);
|
||||||
|
|
||||||
|
Reference* r = new (t->m->system->allocate(sizeof(Reference)))
|
||||||
|
Reference(o, &(t->reference));
|
||||||
|
|
||||||
|
return &(r->target);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
disposeLocalReference(Thread* t, object* r)
|
||||||
|
{
|
||||||
|
if (r) {
|
||||||
|
vm::dispose(t, reinterpret_cast<Reference*>(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
invokeArray(Thread* t, object method, object this_, object arguments)
|
||||||
|
{
|
||||||
|
assert(t, t->state == Thread::ActiveState
|
||||||
|
or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
|
const char* spec = reinterpret_cast<char*>
|
||||||
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
|
||||||
|
unsigned size = methodParameterFootprint(t, method) + FrameFootprint;
|
||||||
|
uintptr_t array[size];
|
||||||
|
bool objectMask[size];
|
||||||
|
ArgumentList list(t, array, objectMask, this_, spec, arguments);
|
||||||
|
|
||||||
|
return ::invoke(t, method, &list);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
invokeList(Thread* t, object method, object this_, bool indirectObjects,
|
||||||
|
va_list arguments)
|
||||||
|
{
|
||||||
|
assert(t, t->state == Thread::ActiveState
|
||||||
|
or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
|
const char* spec = reinterpret_cast<char*>
|
||||||
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
|
||||||
|
unsigned size = methodParameterFootprint(t, method) + FrameFootprint;
|
||||||
|
uintptr_t array[size];
|
||||||
|
bool objectMask[size];
|
||||||
|
ArgumentList list
|
||||||
|
(t, array, objectMask, this_, spec, indirectObjects, arguments);
|
||||||
|
|
||||||
|
return ::invoke(t, method, &list);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
invokeList(Thread* t, const char* className, const char* methodName,
|
||||||
|
const char* methodSpec, object this_, va_list arguments)
|
||||||
|
{
|
||||||
|
assert(t, t->state == Thread::ActiveState
|
||||||
|
or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
|
unsigned size = parameterFootprint(t, methodSpec, false) + FrameFootprint;
|
||||||
|
uintptr_t array[size];
|
||||||
|
bool objectMask[size];
|
||||||
|
ArgumentList list
|
||||||
|
(t, array, objectMask, this_, methodSpec, false, arguments);
|
||||||
|
|
||||||
|
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||||
|
if (LIKELY(t->exception == 0)) {
|
||||||
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
|
return ::invoke(t, method, &list);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dispose() {
|
||||||
|
if (methodStub_) {
|
||||||
|
s->free(methodStub_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nativeInvoker_) {
|
||||||
|
s->free(nativeInvoker_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caller_) {
|
||||||
|
s->free(caller_);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
System* s;
|
||||||
|
Compiled* methodStub_;
|
||||||
|
Compiled* nativeInvoker_;
|
||||||
|
Compiled* caller_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
|
||||||
|
Processor*
|
||||||
|
makeProcessor(System* system)
|
||||||
|
{
|
||||||
|
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vm
|
||||||
|
@ -2870,29 +2870,6 @@ class MyProcessor: public Processor {
|
|||||||
methodTable, staticTable, loader, 0, false);
|
methodTable, staticTable, loader, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned
|
|
||||||
parameterFootprint(vm::Thread* t, const char* s, bool static_)
|
|
||||||
{
|
|
||||||
unsigned footprint = 0;
|
|
||||||
for (MethodSpecIterator it(t, s); it.hasNext();) {
|
|
||||||
switch (*it.next()) {
|
|
||||||
case 'J':
|
|
||||||
case 'D':
|
|
||||||
footprint += 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
++ footprint;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not static_) {
|
|
||||||
++ footprint;
|
|
||||||
}
|
|
||||||
return footprint;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
initClass(vm::Thread* t, object c)
|
initClass(vm::Thread* t, object c)
|
||||||
{
|
{
|
||||||
|
@ -1212,15 +1212,12 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
unsigned returnCode;
|
unsigned returnCode;
|
||||||
scanMethodSpec(t, specString, ¶meterCount, &returnCode);
|
scanMethodSpec(t, specString, ¶meterCount, &returnCode);
|
||||||
|
|
||||||
unsigned parameterFootprint = t->m->processor->parameterFootprint
|
|
||||||
(t, specString, flags & ACC_STATIC);
|
|
||||||
|
|
||||||
object method = t->m->processor->makeMethod
|
object method = t->m->processor->makeMethod
|
||||||
(t,
|
(t,
|
||||||
0, // vm flags
|
0, // vm flags
|
||||||
returnCode,
|
returnCode,
|
||||||
parameterCount,
|
parameterCount,
|
||||||
parameterFootprint,
|
parameterFootprint(t, specString, flags & ACC_STATIC),
|
||||||
flags,
|
flags,
|
||||||
0, // offset
|
0, // offset
|
||||||
singletonObject(t, pool, name - 1),
|
singletonObject(t, pool, name - 1),
|
||||||
@ -2244,6 +2241,9 @@ hashMapFindNode(Thread* t, object map, object key,
|
|||||||
object k = tripleFirst(t, n);
|
object k = tripleFirst(t, n);
|
||||||
if (weak) {
|
if (weak) {
|
||||||
k = jreferenceTarget(t, k);
|
k = jreferenceTarget(t, k);
|
||||||
|
if (k == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (equal(t, key, k)) {
|
if (equal(t, key, k)) {
|
||||||
@ -2285,6 +2285,9 @@ hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
|
|||||||
object k = tripleFirst(t, p);
|
object k = tripleFirst(t, p);
|
||||||
if (weak) {
|
if (weak) {
|
||||||
k = jreferenceTarget(t, k);
|
k = jreferenceTarget(t, k);
|
||||||
|
if (k == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned index = hash(t, k) & (newLength - 1);
|
unsigned index = hash(t, k) & (newLength - 1);
|
||||||
@ -2337,6 +2340,19 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
|||||||
set(t, array, ArrayBody + (index * BytesPerWord), n);
|
set(t, array, ArrayBody + (index * BytesPerWord), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
hashMapRemoveNode(Thread* t, object map, unsigned index, object p, object n)
|
||||||
|
{
|
||||||
|
if (p) {
|
||||||
|
set(t, p, TripleThird, tripleThird(t, n));
|
||||||
|
} else {
|
||||||
|
set(t, hashMapArray(t, map), ArrayBody + (index * BytesPerWord),
|
||||||
|
tripleThird(t, n));
|
||||||
|
}
|
||||||
|
-- hashMapSize(t, map);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
hashMapRemove(Thread* t, object map, object key,
|
hashMapRemove(Thread* t, object map, object key,
|
||||||
uint32_t (*hash)(Thread*, object),
|
uint32_t (*hash)(Thread*, object),
|
||||||
@ -2354,17 +2370,14 @@ hashMapRemove(Thread* t, object map, object key,
|
|||||||
object k = tripleFirst(t, n);
|
object k = tripleFirst(t, n);
|
||||||
if (weak) {
|
if (weak) {
|
||||||
k = jreferenceTarget(t, k);
|
k = jreferenceTarget(t, k);
|
||||||
|
if (k == 0) {
|
||||||
|
n = tripleThird(t, hashMapRemoveNode(t, map, index, p, n));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (equal(t, key, k)) {
|
if (equal(t, key, k)) {
|
||||||
o = tripleSecond(t, n);
|
o = tripleSecond(t, hashMapRemoveNode(t, map, index, p, n));
|
||||||
if (p) {
|
|
||||||
set(t, p, TripleThird, tripleThird(t, n));
|
|
||||||
} else {
|
|
||||||
set(t, array, ArrayBody + (index * BytesPerWord),
|
|
||||||
tripleThird(t, n));
|
|
||||||
}
|
|
||||||
-- hashMapSize(t, map);
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
p = n;
|
p = n;
|
||||||
@ -2825,6 +2838,29 @@ findInHierarchy(Thread* t, object class_, object name, object spec,
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
parameterFootprint(Thread* t, const char* s, bool static_)
|
||||||
|
{
|
||||||
|
unsigned footprint = 0;
|
||||||
|
for (MethodSpecIterator it(t, s); it.hasNext();) {
|
||||||
|
switch (*it.next()) {
|
||||||
|
case 'J':
|
||||||
|
case 'D':
|
||||||
|
footprint += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++ footprint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not static_) {
|
||||||
|
++ footprint;
|
||||||
|
}
|
||||||
|
return footprint;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
|
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
|
||||||
{
|
{
|
||||||
|
@ -2062,6 +2062,9 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index)
|
|||||||
return cast<object>(array, (2 + index) * BytesPerWord);
|
return cast<object>(array, (2 + index) * BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
parameterFootprint(Thread* t, const char* s, bool static_);
|
||||||
|
|
||||||
void
|
void
|
||||||
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
||||||
|
|
||||||
|
@ -45,9 +45,6 @@ class Processor {
|
|||||||
object loader,
|
object loader,
|
||||||
unsigned vtableLength) = 0;
|
unsigned vtableLength) = 0;
|
||||||
|
|
||||||
virtual unsigned
|
|
||||||
parameterFootprint(Thread* t, const char* spec, bool static_) = 0;
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
initClass(Thread* t, object c) = 0;
|
initClass(Thread* t, object c) = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user