blob: 55305af88f9483d385b2b408c65b9653e53d2508 [file] [log] [blame]
//===----------- JavaObject.cpp - Java object definition ------------------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "mvm/Threads/Locks.h"
#include "JavaClass.h"
#include "JavaObject.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include <jni.h>
#include "debug.h"
using namespace j3;
static const int hashCodeIncrement = mvm::GCBitMask + 1;
uint16_t JavaObject::hashCodeGenerator = hashCodeIncrement;
static const uint64_t HashMask = ((1 << mvm::HashBits) - 1) << mvm::GCBits;
/// hashCode - Return the hash code of this object.
uint32_t JavaObject::hashCode(JavaObject* self) {
llvm_gcroot(self, 0);
if (!mvm::MovesObject) return (uint32_t)(long)self;
assert(HashMask != 0);
assert(mvm::HashBits != 0);
word_t header = self->header;
word_t GCBits = header & mvm::GCBitMask;
word_t val = header & HashMask;
if (val != 0) {
return val ^ (word_t)getClass(self);
}
val = hashCodeGenerator;
hashCodeGenerator += hashCodeIncrement;
val = val & HashMask;
if (val == 0) {
// It is possible that in the same time, a thread is in this method and
// gets the same hash code value than this thread. This is fine.
val = hashCodeIncrement;
hashCodeGenerator += hashCodeIncrement;
}
assert(val > mvm::GCBitMask);
assert(val <= HashMask);
do {
header = self->header;
if ((header & HashMask) != 0) break;
word_t newHeader = header | val;
assert((newHeader & ~HashMask) == header);
__sync_val_compare_and_swap(&(self->header), header, newHeader);
} while (true);
assert((self->header & HashMask) != 0);
assert(GCBits == (self->header & mvm::GCBitMask));
return (self->header & HashMask) ^ (word_t)getClass(self);
}
void JavaObject::waitIntern(
JavaObject* self, struct timeval* info, bool timed) {
llvm_gcroot(self, 0);
JavaThread* thread = JavaThread::get();
mvm::LockSystem& table = thread->getJVM()->lockSystem;
if (!owner(self)) {
thread->getJVM()->illegalMonitorStateException(self);
UNREACHABLE();
}
bool interrupted = thread->lockingThread.wait(self, table, info, timed);
if (interrupted) {
thread->getJVM()->interruptedException(self);
UNREACHABLE();
}
}
void JavaObject::wait(JavaObject* self) {
llvm_gcroot(self, 0);
waitIntern(self, NULL, false);
}
void JavaObject::timedWait(JavaObject* self, struct timeval& info) {
llvm_gcroot(self, 0);
waitIntern(self, &info, true);
}
void JavaObject::notify(JavaObject* self) {
llvm_gcroot(self, 0);
JavaThread* thread = JavaThread::get();
mvm::LockSystem& table = thread->getJVM()->lockSystem;
if (!owner(self)) {
thread->getJVM()->illegalMonitorStateException(self);
UNREACHABLE();
}
thread->lockingThread.notify(self, table);
}
void JavaObject::notifyAll(JavaObject* self) {
llvm_gcroot(self, 0);
JavaThread* thread = JavaThread::get();
mvm::LockSystem& table = thread->getJVM()->lockSystem;
if (!owner(self)) {
thread->getJVM()->illegalMonitorStateException(self);
UNREACHABLE();
}
thread->lockingThread.notifyAll(self, table);
}
void JavaObject::overflowThinLock(JavaObject* self) {
llvm_gcroot(self, 0);
mvm::ThinLock::overflowThinLock(self, JavaThread::get()->getJVM()->lockSystem);
}
void JavaObject::acquire(JavaObject* self) {
llvm_gcroot(self, 0);
mvm::ThinLock::acquire(self, JavaThread::get()->getJVM()->lockSystem);
}
void JavaObject::release(JavaObject* self) {
llvm_gcroot(self, 0);
mvm::ThinLock::release(self, JavaThread::get()->getJVM()->lockSystem);
}
bool JavaObject::owner(JavaObject* self) {
llvm_gcroot(self, 0);
return mvm::ThinLock::owner(self, JavaThread::get()->getJVM()->lockSystem);
}
void JavaObject::decapsulePrimitive(JavaObject* obj, Jnjvm *vm, jvalue* buf,
const Typedef* signature) {
llvm_gcroot(obj, 0);
if (!signature->isPrimitive()) {
if (obj && !(getClass(obj)->isOfTypeName(signature->getName()))) {
vm->illegalArgumentException("wrong type argument");
}
return;
} else if (obj == NULL) {
vm->illegalArgumentException("");
} else {
UserCommonClass* cl = getClass(obj);
UserClassPrimitive* value = cl->toPrimitive(vm);
const PrimitiveTypedef* prim = (const PrimitiveTypedef*)signature;
if (value == 0) {
vm->illegalArgumentException("");
}
if (prim->isShort()) {
if (value == vm->upcalls->OfShort) {
(*buf).s = vm->upcalls->shortValue->getInstanceInt16Field(obj);
return;
} else if (value == vm->upcalls->OfByte) {
(*buf).s = (sint16)vm->upcalls->byteValue->getInstanceInt8Field(obj);
return;
} else {
vm->illegalArgumentException("");
}
} else if (prim->isByte()) {
if (value == vm->upcalls->OfByte) {
(*buf).b = vm->upcalls->byteValue->getInstanceInt8Field(obj);
return;
} else {
vm->illegalArgumentException("");
}
} else if (prim->isBool()) {
if (value == vm->upcalls->OfBool) {
(*buf).z = vm->upcalls->boolValue->getInstanceInt8Field(obj);
return;
} else {
vm->illegalArgumentException("");
}
} else if (prim->isInt()) {
if (value == vm->upcalls->OfInt) {
(*buf).i = vm->upcalls->intValue->getInstanceInt32Field(obj);
} else if (value == vm->upcalls->OfByte) {
(*buf).i = (sint32)vm->upcalls->byteValue->getInstanceInt8Field(obj);
} else if (value == vm->upcalls->OfChar) {
(*buf).i = (uint32)vm->upcalls->charValue->getInstanceInt16Field(obj);
} else if (value == vm->upcalls->OfShort) {
(*buf).i = (sint32)vm->upcalls->shortValue->getInstanceInt16Field(obj);
} else {
vm->illegalArgumentException("");
}
return;
} else if (prim->isChar()) {
if (value == vm->upcalls->OfChar) {
(*buf).c = (uint16)vm->upcalls->charValue->getInstanceInt16Field(obj);
} else {
vm->illegalArgumentException("");
}
return;
} else if (prim->isFloat()) {
if (value == vm->upcalls->OfFloat) {
(*buf).f = (float)vm->upcalls->floatValue->getInstanceFloatField(obj);
} else if (value == vm->upcalls->OfByte) {
(*buf).f = (float)(sint32)vm->upcalls->byteValue->getInstanceInt8Field(obj);
} else if (value == vm->upcalls->OfChar) {
(*buf).f = (float)(uint32)vm->upcalls->charValue->getInstanceInt16Field(obj);
} else if (value == vm->upcalls->OfShort) {
(*buf).f = (float)(sint32)vm->upcalls->shortValue->getInstanceInt16Field(obj);
} else if (value == vm->upcalls->OfInt) {
(*buf).f = (float)(sint32)vm->upcalls->intValue->getInstanceInt32Field(obj);
} else if (value == vm->upcalls->OfLong) {
(*buf).f = (float)vm->upcalls->longValue->getInstanceLongField(obj);
} else {
vm->illegalArgumentException("");
}
return;
} else if (prim->isDouble()) {
if (value == vm->upcalls->OfDouble) {
(*buf).d = (double)vm->upcalls->doubleValue->getInstanceDoubleField(obj);
} else if (value == vm->upcalls->OfFloat) {
(*buf).d = (double)vm->upcalls->floatValue->getInstanceFloatField(obj);
} else if (value == vm->upcalls->OfByte) {
(*buf).d = (double)(sint64)vm->upcalls->byteValue->getInstanceInt8Field(obj);
} else if (value == vm->upcalls->OfChar) {
(*buf).d = (double)(uint64)vm->upcalls->charValue->getInstanceInt16Field(obj);
} else if (value == vm->upcalls->OfShort) {
(*buf).d = (double)(sint16)vm->upcalls->shortValue->getInstanceInt16Field(obj);
} else if (value == vm->upcalls->OfInt) {
(*buf).d = (double)(sint32)vm->upcalls->intValue->getInstanceInt32Field(obj);
} else if (value == vm->upcalls->OfLong) {
(*buf).d = (double)(sint64)vm->upcalls->longValue->getInstanceLongField(obj);
} else {
vm->illegalArgumentException("");
}
return;
} else if (prim->isLong()) {
if (value == vm->upcalls->OfByte) {
(*buf).j = (sint64)vm->upcalls->byteValue->getInstanceInt8Field(obj);
} else if (value == vm->upcalls->OfChar) {
(*buf).j = (sint64)(uint64)vm->upcalls->charValue->getInstanceInt16Field(obj);
} else if (value == vm->upcalls->OfShort) {
(*buf).j = (sint64)vm->upcalls->shortValue->getInstanceInt16Field(obj);
} else if (value == vm->upcalls->OfInt) {
(*buf).j = (sint64)vm->upcalls->intValue->getInstanceInt32Field(obj);
} else if (value == vm->upcalls->OfLong) {
(*buf).j = (sint64)vm->upcalls->intValue->getInstanceLongField(obj);
} else {
vm->illegalArgumentException("");
}
return;
}
}
// can not be here
return;
}
bool JavaObject::instanceOf(JavaObject* self, UserCommonClass* cl) {
llvm_gcroot(self, 0);
if (self == NULL) return false;
else return getClass(self)->isAssignableFrom(cl);
}