Move compiler-specific code out of runtime_support_common.
Helpers or utilities such as FindFieldFast are still in
runtime_support_common. But LLVM has different stacks, no callee-saves
and different exception mechanisms. Those won't belong to
runtime_support_common.
Change-Id: Ibc43d7d53316941481a6a21815ddefdc1e6bdde6
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 9854151..6531eb2 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -29,6 +29,57 @@
namespace art {
+extern "C" int art_cmpl_float(float a, float b) {
+ if (a == b) {
+ return 0;
+ } else if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ }
+ return -1;
+}
+
+extern "C" int art_cmpg_float(float a, float b) {
+ if (a == b) {
+ return 0;
+ } else if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ }
+ return 1;
+}
+
+extern "C" int art_cmpl_double(double a, double b) {
+ if (a == b) {
+ return 0;
+ } else if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ }
+ return -1;
+}
+
+extern "C" int art_cmpg_double(double a, double b) {
+ if (a == b) {
+ return 0;
+ } else if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ }
+ return 1;
+}
+
+// Place a special frame at the TOS that will save the callee saves for the given type
+static void FinishCalleeSaveFrameSetup(Thread* self, Method** sp, Runtime::CalleeSaveType type) {
+ // Be aware the store below may well stomp on an incoming argument
+ *sp = Runtime::Current()->GetCalleeSaveMethod(type);
+ self->SetTopOfStack(sp, 0);
+}
+
/*
* Report location to debugger. Note: dex_pc is the current offset within
* the method. However, because the offset alone cannot distinguish between
@@ -529,6 +580,216 @@
return code;
}
+
+extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer,
+ Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
+ if (LIKELY(field != NULL)) {
+ return field->Get32(NULL);
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int32_t));
+ if (LIKELY(field != NULL)) {
+ return field->Get32(NULL);
+ }
+ return 0; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer,
+ Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
+ if (LIKELY(field != NULL)) {
+ return field->Get64(NULL);
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int64_t));
+ if (LIKELY(field != NULL)) {
+ return field->Get64(NULL);
+ }
+ return 0; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
+ Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
+ if (LIKELY(field != NULL)) {
+ return field->GetObj(NULL);
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, true, false, false, sizeof(Object*));
+ if (LIKELY(field != NULL)) {
+ return field->GetObj(NULL);
+ }
+ return NULL; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, Object* obj,
+ const Method* referrer, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
+ if (LIKELY(field != NULL && obj != NULL)) {
+ return field->Get32(obj);
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int32_t));
+ if (LIKELY(field != NULL)) {
+ if (UNLIKELY(obj == NULL)) {
+ ThrowNullPointerExceptionForFieldAccess(self, field, true);
+ } else {
+ return field->Get32(obj);
+ }
+ }
+ return 0; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, Object* obj,
+ const Method* referrer, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
+ if (LIKELY(field != NULL && obj != NULL)) {
+ return field->Get64(obj);
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int64_t));
+ if (LIKELY(field != NULL)) {
+ if (UNLIKELY(obj == NULL)) {
+ ThrowNullPointerExceptionForFieldAccess(self, field, true);
+ } else {
+ return field->Get64(obj);
+ }
+ }
+ return 0; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" Object* artGetObjInstanceFromCode(uint32_t field_idx, Object* obj,
+ const Method* referrer, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
+ if (LIKELY(field != NULL && obj != NULL)) {
+ return field->GetObj(obj);
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, false, false, false, sizeof(Object*));
+ if (LIKELY(field != NULL)) {
+ if (UNLIKELY(obj == NULL)) {
+ ThrowNullPointerExceptionForFieldAccess(self, field, true);
+ } else {
+ return field->GetObj(obj);
+ }
+ }
+ return NULL; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
+ const Method* referrer, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
+ if (LIKELY(field != NULL)) {
+ field->Set32(NULL, new_value);
+ return 0; // success
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int32_t));
+ if (LIKELY(field != NULL)) {
+ field->Set32(NULL, new_value);
+ return 0; // success
+ }
+ return -1; // failure
+}
+
+extern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer,
+ uint64_t new_value, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
+ if (LIKELY(field != NULL)) {
+ field->Set64(NULL, new_value);
+ return 0; // success
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int64_t));
+ if (LIKELY(field != NULL)) {
+ field->Set64(NULL, new_value);
+ return 0; // success
+ }
+ return -1; // failure
+}
+
+extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value,
+ const Method* referrer, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
+ if (LIKELY(field != NULL)) {
+ if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
+ field->SetObj(NULL, new_value);
+ return 0; // success
+ }
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, true, false, true, sizeof(Object*));
+ if (LIKELY(field != NULL)) {
+ field->SetObj(NULL, new_value);
+ return 0; // success
+ }
+ return -1; // failure
+}
+
+extern "C" int artSet32InstanceFromCode(uint32_t field_idx, Object* obj, uint32_t new_value,
+ const Method* referrer, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
+ if (LIKELY(field != NULL && obj != NULL)) {
+ field->Set32(obj, new_value);
+ return 0; // success
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int32_t));
+ if (LIKELY(field != NULL)) {
+ if (UNLIKELY(obj == NULL)) {
+ ThrowNullPointerExceptionForFieldAccess(self, field, false);
+ } else {
+ field->Set32(obj, new_value);
+ return 0; // success
+ }
+ }
+ return -1; // failure
+}
+
+extern "C" int artSet64InstanceFromCode(uint32_t field_idx, Object* obj, uint64_t new_value,
+ Thread* self, Method** sp) {
+ Method* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly);
+ Method* referrer = sp[callee_save->GetFrameSizeInBytes() / sizeof(Method*)];
+ Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
+ if (LIKELY(field != NULL && obj != NULL)) {
+ field->Set64(obj, new_value);
+ return 0; // success
+ }
+ *sp = callee_save;
+ self->SetTopOfStack(sp, 0);
+ field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int64_t));
+ if (LIKELY(field != NULL)) {
+ if (UNLIKELY(obj == NULL)) {
+ ThrowNullPointerExceptionForFieldAccess(self, field, false);
+ } else {
+ field->Set64(obj, new_value);
+ return 0; // success
+ }
+ }
+ return -1; // failure
+}
+
+extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, Object* obj, Object* new_value,
+ const Method* referrer, Thread* self, Method** sp) {
+ Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
+ if (LIKELY(field != NULL && obj != NULL)) {
+ field->SetObj(obj, new_value);
+ return 0; // success
+ }
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ field = FindFieldFromCode(field_idx, referrer, self, false, false, true, sizeof(Object*));
+ if (LIKELY(field != NULL)) {
+ if (UNLIKELY(obj == NULL)) {
+ ThrowNullPointerExceptionForFieldAccess(self, field, false);
+ } else {
+ field->SetObj(obj, new_value);
+ return 0; // success
+ }
+ }
+ return -1; // failure
+}
+
extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method,
Thread* self, Method** sp) {
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
@@ -702,6 +963,30 @@
return 0; // Success
}
+static uint64_t artInvokeCommon(uint32_t method_idx, Object* this_object, Method* caller_method,
+ Thread* self, Method** sp, bool access_check, InvokeType type){
+ Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
+ if (UNLIKELY(method == NULL)) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
+ if (UNLIKELY(this_object == NULL && type != kDirect && type != kStatic)) {
+ ThrowNullPointerExceptionForMethodAccess(self, caller_method, method_idx, type);
+ return 0; // failure
+ }
+ method = FindMethodFromCode(method_idx, this_object, caller_method, self, access_check, type);
+ if (UNLIKELY(method == NULL)) {
+ CHECK(self->IsExceptionPending());
+ return 0; // failure
+ }
+ }
+ DCHECK(!self->IsExceptionPending());
+ const void* code = method->GetCode();
+
+ uint32_t method_uint = reinterpret_cast<uint32_t>(method);
+ uint64_t code_uint = reinterpret_cast<uint32_t>(code);
+ uint64_t result = ((code_uint << 32) | method_uint);
+ return result;
+}
+
// See comments in runtime_support_asm.S
extern "C" uint64_t artInvokeInterfaceTrampoline(uint32_t method_idx, Object* this_object,
Method* caller_method, Thread* self,