Refactor runtime support.
Change-Id: Id7470a4105838150d5ceb73ab2c8c83e739660df
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 35f88b5..909fb41 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -1,180 +1,195 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+// Copyright 2012 Google Inc. All Rights Reserved.
#ifndef ART_SRC_RUNTIME_SUPPORT_H_
#define ART_SRC_RUNTIME_SUPPORT_H_
#include "class_linker.h"
+#include "dex_file.h"
+#include "dex_verifier.h"
#include "object.h"
-#include "thread_list.h"
-#include "utils.h"
+#include "object_utils.h"
+#include "thread.h"
+
+extern "C" void art_proxy_invoke_handler();
+extern "C" void art_work_around_app_jni_bugs();
namespace art {
-extern void CheckSuspendFromCode(Thread* thread);
+class Array;
+class Class;
+class Field;
+class Method;
+class Object;
+
+// Helpers to give consistent descriptive exception messages
+void ThrowNewIllegalAccessErrorClass(Thread* self, Class* referrer, Class* accessed);
+void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self, Class* referrer,
+ Class* accessed,
+ const Method* caller,
+ const Method* called,
+ InvokeType type);
+void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
+ const Method* referrer,
+ const Method* interface_method,
+ Object* this_object);
+void ThrowNewIllegalAccessErrorField(Thread* self, Class* referrer, Field* accessed);
+void ThrowNewIllegalAccessErrorFinalField(Thread* self, const Method* referrer, Field* accessed);
+
+void ThrowNewIllegalAccessErrorMethod(Thread* self, Class* referrer, Method* accessed);
+void ThrowNullPointerExceptionForFieldAccess(Thread* self, Field* field, bool is_read);
+void ThrowNullPointerExceptionForMethodAccess(Thread* self, Method* caller, uint32_t method_idx,
+ InvokeType type);
+
+std::string FieldNameFromIndex(const Method* method, uint32_t ref,
+ verifier::VerifyErrorRefType ref_type, bool access);
+std::string MethodNameFromIndex(const Method* method, uint32_t ref,
+ verifier::VerifyErrorRefType ref_type, bool access);
+
+// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
+// cannot be resolved, throw an error. If it can, use it to create an instance.
+// When verification/compiler hasn't been able to verify access, optionally perform an access
+// check.
+static inline Object* AllocObjectFromCode(uint32_t type_idx, Method* method, Thread* self,
+ bool access_check) {
+ Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+ Runtime* runtime = Runtime::Current();
+ if (UNLIKELY(klass == NULL)) {
+ klass = runtime->GetClassLinker()->ResolveType(type_idx, method);
+ if (klass == NULL) {
+ DCHECK(self->IsExceptionPending());
+ return NULL; // Failure
+ }
+ }
+ if (access_check) {
+ if (UNLIKELY(!klass->IsInstantiable())) {
+ self->ThrowNewException("Ljava/lang/InstantiationError;",
+ PrettyDescriptor(klass).c_str());
+ return NULL; // Failure
+ }
+ Class* referrer = method->GetDeclaringClass();
+ if (UNLIKELY(!referrer->CanAccess(klass))) {
+ ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+ return NULL; // Failure
+ }
+ }
+ if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) {
+ DCHECK(self->IsExceptionPending());
+ return NULL; // Failure
+ }
+ return klass->AllocObject();
+}
+
+// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If
+// it cannot be resolved, throw an error. If it can, use it to create an array.
+// When verification/compiler hasn't been able to verify access, optionally perform an access
+// check.
+static inline Array* AllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+ Thread* self, bool access_check) {
+ if (UNLIKELY(component_count < 0)) {
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
+ component_count);
+ return NULL; // Failure
+ }
+ Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+ if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
+ klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+ if (klass == NULL) { // Error
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return NULL; // Failure
+ }
+ CHECK(klass->IsArrayClass()) << PrettyClass(klass);
+ }
+ if (access_check) {
+ Class* referrer = method->GetDeclaringClass();
+ if (UNLIKELY(!referrer->CanAccess(klass))) {
+ ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+ return NULL; // Failure
+ }
+ }
+ return Array::Alloc(klass, component_count);
+}
+
extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
Thread* self, bool access_check);
-extern void DebugMe(Method* method, uint32_t info);
-extern void UpdateDebuggerFromCode(Method* method, Thread* thread , int32_t dex_pc, Method** sp);
-extern Object* DecodeJObjectInThread(Thread* thread, jobject obj);
+
extern Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
- bool is_static, bool is_primitive, bool is_set, size_t expected_size);
-extern void* FindNativeMethod(Thread* thread);
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
-const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
- Runtime::TrampolineType);
+ bool is_static, bool is_primitive, bool is_set,
+ size_t expected_size);
+
+// Fast path field resolution that can't throw exceptions
+static inline Field* FindFieldFast(uint32_t field_idx, const Method* referrer, bool is_primitive,
+ size_t expected_size, bool is_set) {
+ Field* resolved_field = referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
+ if (UNLIKELY(resolved_field == NULL)) {
+ return NULL;
+ }
+ Class* fields_class = resolved_field->GetDeclaringClass();
+ // Check class is initiliazed or initializing
+ if (UNLIKELY(!fields_class->IsInitializing())) {
+ return NULL;
+ }
+ Class* referring_class = referrer->GetDeclaringClass();
+ if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
+ !referring_class->CanAccessMember(fields_class,
+ resolved_field->GetAccessFlags()) ||
+ (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) {
+ // illegal access
+ return NULL;
+ }
+ FieldHelper fh(resolved_field);
+ if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
+ fh.FieldSize() != expected_size)) {
+ return NULL;
+ }
+ return resolved_field;
+}
+
+// Fast path method resolution that can't throw exceptions
+static inline Method* FindMethodFast(uint32_t method_idx, Object* this_object, const Method* referrer,
+ bool access_check, InvokeType type) {
+ bool is_direct = type == kStatic || type == kDirect;
+ if (UNLIKELY(this_object == NULL && !is_direct)) {
+ return NULL;
+ }
+ Method* resolved_method =
+ referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx);
+ if (UNLIKELY(resolved_method == NULL)) {
+ return NULL;
+ }
+ if (access_check) {
+ Class* methods_class = resolved_method->GetDeclaringClass();
+ Class* referring_class = referrer->GetDeclaringClass();
+ if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
+ !referring_class->CanAccessMember(methods_class,
+ resolved_method->GetAccessFlags()))) {
+ // potential illegal access
+ return NULL;
+ }
+ }
+ if (type == kInterface) { // Most common form of slow path dispatch.
+ return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+ } else if (is_direct) {
+ return resolved_method;
+ } else if (type == kSuper) {
+ return referrer->GetDeclaringClass()->GetSuperClass()->GetVTable()->
+ Get(resolved_method->GetMethodIndex());
+ } else {
+ DCHECK(type == kVirtual);
+ return this_object->GetClass()->GetVTable()->Get(resolved_method->GetMethodIndex());
+ }
+}
+
+extern Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
+ Thread* self, bool access_check, InvokeType type);
+
extern Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
bool can_run_clinit, bool verify_access);
-extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
-uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
-void ObjectInitFromCode(Object* o);
-extern void LockObjectFromCode(Thread* thread, Object* obj);
-uint32_t TraceMethodUnwindFromCode(Thread* self);
-extern int32_t CmpgDouble(double a, double b);
-extern int32_t CmplDouble(double a, double b);
-extern int32_t CmpgFloat(float a, float b);
-extern int32_t CmplFloat(float a, float b);
-extern int64_t D2L(double d);
-extern int64_t F2L(float f);
+
+static inline String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ return class_linker->ResolveString(string_idx, referrer);
+}
} // namespace art
-// Helpers for both compiled code and libart.
-extern "C" void art_deliver_exception_from_code(void*);
-extern "C" void art_proxy_invoke_handler();
-extern "C" void art_update_debugger(void*, void*, int32_t, void*);
-
-#if defined(__arm__)
- /* Compiler helpers */
- extern "C" int32_t __memcmp16(void*, void*, int32_t);
- extern "C" int32_t art_indexof(void*, uint32_t, uint32_t, uint32_t);
- extern "C" int32_t art_string_compareto(void*, void*);
- extern "C" int32_t art_get32_static_from_code(uint32_t);
- extern "C" int64_t art_get64_static_from_code(uint32_t);
- extern "C" void* art_get_obj_static_from_code(uint32_t);
- extern "C" int32_t art_get32_instance_from_code(uint32_t, void*);
- extern "C" int64_t art_get64_instance_from_code(uint32_t, void*);
- extern "C" void* art_get_obj_instance_from_code(uint32_t, void*);
- extern "C" int art_set32_static_from_code(uint32_t, int32_t);
- extern "C" int art_set64_static_from_code(uint32_t, int64_t);
- extern "C" int art_set_obj_static_from_code(uint32_t, void*);
- extern "C" int art_set32_instance_from_code(uint32_t, void*, int32_t);
- extern "C" int art_set64_instance_from_code(uint32_t, void*, int64_t);
- extern "C" int art_set_obj_instance_from_code(uint32_t, void*, void*);
- extern "C" void art_can_put_array_element_from_code(void*, void*);
- extern "C" void art_check_cast_from_code(void*, void*);
- extern "C" void art_do_long_jump(uint32_t*, uint32_t*);
- extern "C" void art_handle_fill_data_from_code(void*, void*);
- extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
- extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
- extern "C" void art_invoke_interface_trampoline_with_access_check(uint32_t, void*);
- extern "C" void art_invoke_static_trampoline_with_access_check(uint32_t, void*);
- extern "C" void art_invoke_super_trampoline_with_access_check(uint32_t, void*);
- extern "C" void art_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
- extern "C" void art_lock_object_from_code(void*);
- extern "C" void art_test_suspend();
- extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
- extern "C" void art_throw_div_zero_from_code();
- extern "C" void art_throw_neg_array_size_from_code(int32_t size);
- extern "C" void art_throw_no_such_method_from_code(int32_t method_idx);
- extern "C" void art_throw_null_pointer_exception_from_code();
- extern "C" void art_throw_stack_overflow_from_code(void*);
- extern "C" void art_throw_verification_error_from_code(int32_t src1, int32_t ref);
- extern "C" void art_unlock_object_from_code(void*);
- extern "C" void* art_alloc_array_from_code(uint32_t, void*, int32_t);
- extern "C" void* art_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
- extern "C" void* art_alloc_object_from_code(uint32_t type_idx, void* method);
- extern "C" void* art_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
- extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
- extern "C" void* art_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
- extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
- extern "C" void* art_initialize_type_from_code(uint32_t, void*);
- extern "C" void* art_initialize_type_and_verify_access_from_code(uint32_t, void*);
- extern "C" void art_trace_entry_from_code(void*);
- extern "C" void art_trace_exit_from_code();
- extern "C" void* art_resolve_string_from_code(void*, uint32_t);
- extern "C" void art_work_around_app_jni_bugs();
-
- /* Conversions */
- extern "C" float __aeabi_i2f(int32_t op1); // INT_TO_FLOAT
- extern "C" int32_t __aeabi_f2iz(float op1); // FLOAT_TO_INT
- extern "C" float __aeabi_d2f(double op1); // DOUBLE_TO_FLOAT
- extern "C" double __aeabi_f2d(float op1); // FLOAT_TO_DOUBLE
- extern "C" double __aeabi_i2d(int32_t op1); // INT_TO_DOUBLE
- extern "C" int32_t __aeabi_d2iz(double op1); // DOUBLE_TO_INT
- extern "C" float __aeabi_l2f(int64_t op1); // LONG_TO_FLOAT
- extern "C" double __aeabi_l2d(int64_t op1); // LONG_TO_DOUBLE
-
- /* Single-precision FP arithmetics */
- extern "C" float __aeabi_fadd(float a, float b); // ADD_FLOAT[_2ADDR]
- extern "C" float __aeabi_fsub(float a, float b); // SUB_FLOAT[_2ADDR]
- extern "C" float __aeabi_fdiv(float a, float b); // DIV_FLOAT[_2ADDR]
- extern "C" float __aeabi_fmul(float a, float b); // MUL_FLOAT[_2ADDR]
- extern "C" float fmodf(float a, float b); // REM_FLOAT[_2ADDR]
-
- /* Double-precision FP arithmetics */
- extern "C" double __aeabi_dadd(double a, double b); // ADD_DOUBLE[_2ADDR]
- extern "C" double __aeabi_dsub(double a, double b); // SUB_DOUBLE[_2ADDR]
- extern "C" double __aeabi_ddiv(double a, double b); // DIV_DOUBLE[_2ADDR]
- extern "C" double __aeabi_dmul(double a, double b); // MUL_DOUBLE[_2ADDR]
- extern "C" double fmod(double a, double b); // REM_DOUBLE[_2ADDR]
-
- /* Integer arithmetics */
- extern "C" int __aeabi_idivmod(int32_t op1, int32_t op2); // REM_INT[_2ADDR|_LIT8|_LIT16]
- extern "C" int __aeabi_idiv(int32_t op1, int32_t op2); // DIV_INT[_2ADDR|_LIT8|_LIT16]
-
- /* Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR] */
- extern "C" long long __aeabi_ldivmod(long long op1, long long op2);
- extern "C" long long __aeabi_lmul(long long op1, long long op2);
- extern "C" uint64_t art_shl_long(uint64_t, uint32_t);
- extern "C" uint64_t art_shr_long(uint64_t, uint32_t);
- extern "C" uint64_t art_ushr_long(uint64_t, uint32_t);
-
-#endif
-
-#if defined(__mips__)
- /* Conversions */
- extern "C" float __floatsisf(int op1); // INT_TO_FLOAT
- extern "C" int32_t __fixsfsi(float op1); // FLOAT_TO_INT
- extern "C" float __truncdfsf2(double op1); // DOUBLE_TO_FLOAT
- extern "C" double __extendsfdf2(float op1); // FLOAT_TO_DOUBLE
- extern "C" double __floatsidf(int op1); // INT_TO_DOUBLE
- extern "C" int32_t __fixdfsi(double op1); // DOUBLE_TO_INT
- extern "C" float __floatdisf(int64_t op1); // LONG_TO_FLOAT
- extern "C" double __floatdidf(int64_t op1); // LONG_TO_DOUBLE
- extern "C" int64_t __fixsfdi(float op1); // FLOAT_TO_LONG
- extern "C" int64_t __fixdfdi(double op1); // DOUBLE_TO_LONG
-
- /* Single-precision FP arithmetics */
- extern "C" float __addsf3(float a, float b); // ADD_FLOAT[_2ADDR]
- extern "C" float __subsf3(float a, float b); // SUB_FLOAT[_2ADDR]
- extern "C" float __divsf3(float a, float b); // DIV_FLOAT[_2ADDR]
- extern "C" float __mulsf3(float a, float b); // MUL_FLOAT[_2ADDR]
- extern "C" float fmodf(float a, float b); // REM_FLOAT[_2ADDR]
-
- /* Double-precision FP arithmetics */
- extern "C" double __adddf3(double a, double b); // ADD_DOUBLE[_2ADDR]
- extern "C" double __subdf3(double a, double b); // SUB_DOUBLE[_2ADDR]
- extern "C" double __divdf3(double a, double b); // DIV_DOUBLE[_2ADDR]
- extern "C" double __muldf3(double a, double b); // MUL_DOUBLE[_2ADDR]
- extern "C" double fmod(double a, double b); // REM_DOUBLE[_2ADDR]
-
- /* Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR] */
- extern "C" long long __divdi3(int64_t op1, int64_t op2);
- extern "C" long long __moddi3(int64_t op1, int64_t op2);
-#endif
-
#endif // ART_SRC_RUNTIME_SUPPORT_H_