Merge "Store resolved Strings for AOT code in .bss."
diff --git a/benchmark/Android.bp b/benchmark/Android.bp
index dd19888..014a2b3 100644
--- a/benchmark/Android.bp
+++ b/benchmark/Android.bp
@@ -17,7 +17,7 @@
art_cc_library {
name: "libartbenchmark",
host_supported: true,
- defaults: ["art_defaults", "art_debug_defaults"],
+ defaults: ["art_defaults" ],
srcs: [
"jni_loader.cc",
"jobject-benchmark/jobject_benchmark.cc",
diff --git a/benchmark/jni-perf/perf_jni.cc b/benchmark/jni-perf/perf_jni.cc
index cd8d520..06dded8 100644
--- a/benchmark/jni-perf/perf_jni.cc
+++ b/benchmark/jni-perf/perf_jni.cc
@@ -17,7 +17,7 @@
#include <assert.h>
#include "jni.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
namespace art {
diff --git a/benchmark/jobject-benchmark/jobject_benchmark.cc b/benchmark/jobject-benchmark/jobject_benchmark.cc
index e7ca9eb..4b2c024 100644
--- a/benchmark/jobject-benchmark/jobject_benchmark.cc
+++ b/benchmark/jobject-benchmark/jobject_benchmark.cc
@@ -16,8 +16,9 @@
#include "jni.h"
+#include "java_vm_ext.h"
#include "mirror/class-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
namespace {
@@ -25,10 +26,10 @@
extern "C" JNIEXPORT void JNICALL Java_JObjectBenchmark_timeAddRemoveLocal(
JNIEnv* env, jobject jobj, jint reps) {
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
for (jint i = 0; i < reps; ++i) {
- jobject ref = soa.Env()->AddLocalReference<jobject>(obj);
+ jobject ref = soa.Env()->AddLocalReference<jobject>(obj.Decode());
soa.Env()->DeleteLocalRef(ref);
}
}
@@ -36,11 +37,11 @@
extern "C" JNIEXPORT void JNICALL Java_JObjectBenchmark_timeDecodeLocal(
JNIEnv* env, jobject jobj, jint reps) {
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
- jobject ref = soa.Env()->AddLocalReference<jobject>(obj);
+ jobject ref = soa.Env()->AddLocalReference<jobject>(obj.Decode());
for (jint i = 0; i < reps; ++i) {
- CHECK_EQ(soa.Decode<mirror::Object*>(ref), obj);
+ CHECK_EQ(soa.Decode<mirror::Object>(ref), obj);
}
soa.Env()->DeleteLocalRef(ref);
}
@@ -48,7 +49,7 @@
extern "C" JNIEXPORT void JNICALL Java_JObjectBenchmark_timeAddRemoveGlobal(
JNIEnv* env, jobject jobj, jint reps) {
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
for (jint i = 0; i < reps; ++i) {
jobject ref = soa.Vm()->AddGlobalRef(soa.Self(), obj);
@@ -59,11 +60,11 @@
extern "C" JNIEXPORT void JNICALL Java_JObjectBenchmark_timeDecodeGlobal(
JNIEnv* env, jobject jobj, jint reps) {
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
jobject ref = soa.Vm()->AddGlobalRef(soa.Self(), obj);
for (jint i = 0; i < reps; ++i) {
- CHECK_EQ(soa.Decode<mirror::Object*>(ref), obj);
+ CHECK_EQ(soa.Decode<mirror::Object>(ref), obj);
}
soa.Vm()->DeleteGlobalRef(soa.Self(), ref);
}
@@ -71,7 +72,7 @@
extern "C" JNIEXPORT void JNICALL Java_JObjectBenchmark_timeAddRemoveWeakGlobal(
JNIEnv* env, jobject jobj, jint reps) {
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
for (jint i = 0; i < reps; ++i) {
jobject ref = soa.Vm()->AddWeakGlobalRef(soa.Self(), obj);
@@ -82,11 +83,11 @@
extern "C" JNIEXPORT void JNICALL Java_JObjectBenchmark_timeDecodeWeakGlobal(
JNIEnv* env, jobject jobj, jint reps) {
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
jobject ref = soa.Vm()->AddWeakGlobalRef(soa.Self(), obj);
for (jint i = 0; i < reps; ++i) {
- CHECK_EQ(soa.Decode<mirror::Object*>(ref), obj);
+ CHECK_EQ(soa.Decode<mirror::Object>(ref), obj);
}
soa.Vm()->DeleteWeakGlobalRef(soa.Self(), ref);
}
@@ -95,7 +96,7 @@
JNIEnv* env, jobject jobj, jint reps) {
ScopedObjectAccess soa(env);
for (jint i = 0; i < reps; ++i) {
- soa.Decode<mirror::Object*>(jobj);
+ soa.Decode<mirror::Object>(jobj);
}
}
diff --git a/build/art.go b/build/art.go
index 0ae6c8f..b826538 100644
--- a/build/art.go
+++ b/build/art.go
@@ -91,7 +91,7 @@
var cflags []string
deviceFrameSizeLimit := 1736
if len(ctx.AConfig().SanitizeDevice()) > 0 {
- deviceFrameSizeLimit = 6400
+ deviceFrameSizeLimit = 7400
}
cflags = append(cflags,
fmt.Sprintf("-Wframe-larger-than=%d", deviceFrameSizeLimit),
diff --git a/compiler/Android.bp b/compiler/Android.bp
index f264d30..7fb009a 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -31,8 +31,6 @@
"dex/verified_method.cc",
"dex/verification_results.cc",
"dex/quick_compiler_callbacks.cc",
- "dex/quick/dex_file_method_inliner.cc",
- "dex/quick/dex_file_to_method_inliner_map.cc",
"driver/compiled_method_storage.cc",
"driver/compiler_driver.cc",
"driver/compiler_options.cc",
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 60740b6..bc8facd 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -23,7 +23,6 @@
#include "class_linker.h"
#include "compiled_method.h"
#include "dex/quick_compiler_callbacks.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
@@ -33,7 +32,7 @@
#include "mirror/dex_cache.h"
#include "mirror/object-inl.h"
#include "oat_quick_method_header.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"
@@ -109,7 +108,8 @@
FlushInstructionCache(reinterpret_cast<char*>(base), reinterpret_cast<char*>(base + len));
}
-void CommonCompilerTest::MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name) {
+void CommonCompilerTest::MakeExecutable(ObjPtr<mirror::ClassLoader> class_loader,
+ const char* class_name) {
std::string class_descriptor(DotToDescriptor(class_name));
Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
@@ -177,7 +177,6 @@
compiler_options_->boot_image_ = true;
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
- method_inliner_map_.get(),
kind,
isa,
instruction_set_features_.get(),
@@ -199,9 +198,7 @@
compiler_options_.reset(new CompilerOptions);
verification_results_.reset(new VerificationResults(compiler_options_.get()));
- method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get(),
CompilerCallbacks::CallbackMode::kCompileApp));
}
@@ -222,7 +219,6 @@
timer_.reset();
compiler_driver_.reset();
callbacks_.reset();
- method_inliner_map_.reset();
verification_results_.reset();
compiler_options_.reset();
image_reservation_.reset();
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 5239121..f4838c1 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -34,7 +34,6 @@
class CompilerDriver;
class CompilerOptions;
class CumulativeLogger;
-class DexFileToMethodInlinerMap;
class VerificationResults;
template<class T> class Handle;
@@ -51,7 +50,7 @@
static void MakeExecutable(const void* code_start, size_t code_length);
- void MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name)
+ void MakeExecutable(ObjPtr<mirror::ClassLoader> class_loader, const char* class_name)
REQUIRES_SHARED(Locks::mutator_lock_);
protected:
@@ -102,7 +101,6 @@
Compiler::Kind compiler_kind_ = Compiler::kOptimizing;
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<VerificationResults> verification_results_;
- std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<CumulativeLogger> timer_;
std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index e0abf19..236a3b2 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -280,7 +280,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(unit_.GetClassLoader())));
+ soa.Decode<mirror::ClassLoader>(unit_.GetClassLoader())));
ClassLinker* class_linker = unit_.GetClassLinker();
ArtMethod* resolved_method = class_linker->ResolveMethod<ClassLinker::kForceICCECheck>(
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
deleted file mode 100644
index 6750554..0000000
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "dex_file_method_inliner.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/mutex-inl.h"
-#include "driver/compiler_driver.h"
-#include "thread-inl.h"
-#include "dex_instruction-inl.h"
-#include "driver/dex_compilation_unit.h"
-#include "verifier/method_verifier-inl.h"
-
-namespace art {
-
-namespace { // anonymous namespace
-
-static constexpr bool kIntrinsicIsStatic[] = {
- true, // kIntrinsicDoubleCvt
- true, // kIntrinsicFloatCvt
- true, // kIntrinsicFloat2Int
- true, // kIntrinsicDouble2Long
- true, // kIntrinsicFloatIsInfinite
- true, // kIntrinsicDoubleIsInfinite
- true, // kIntrinsicFloatIsNaN
- true, // kIntrinsicDoubleIsNaN
- true, // kIntrinsicReverseBits
- true, // kIntrinsicReverseBytes
- true, // kIntrinsicBitCount
- true, // kIntrinsicCompare,
- true, // kIntrinsicHighestOneBit
- true, // kIntrinsicLowestOneBit
- true, // kIntrinsicNumberOfLeadingZeros
- true, // kIntrinsicNumberOfTrailingZeros
- true, // kIntrinsicRotateRight
- true, // kIntrinsicRotateLeft
- true, // kIntrinsicSignum
- true, // kIntrinsicAbsInt
- true, // kIntrinsicAbsLong
- true, // kIntrinsicAbsFloat
- true, // kIntrinsicAbsDouble
- true, // kIntrinsicMinMaxInt
- true, // kIntrinsicMinMaxLong
- true, // kIntrinsicMinMaxFloat
- true, // kIntrinsicMinMaxDouble
- true, // kIntrinsicCos
- true, // kIntrinsicSin
- true, // kIntrinsicAcos
- true, // kIntrinsicAsin
- true, // kIntrinsicAtan
- true, // kIntrinsicAtan2
- true, // kIntrinsicCbrt
- true, // kIntrinsicCosh
- true, // kIntrinsicExp
- true, // kIntrinsicExpm1
- true, // kIntrinsicHypot
- true, // kIntrinsicLog
- true, // kIntrinsicLog10
- true, // kIntrinsicNextAfter
- true, // kIntrinsicSinh
- true, // kIntrinsicTan
- true, // kIntrinsicTanh
- true, // kIntrinsicSqrt
- true, // kIntrinsicCeil
- true, // kIntrinsicFloor
- true, // kIntrinsicRint
- true, // kIntrinsicRoundFloat
- true, // kIntrinsicRoundDouble
- false, // kIntrinsicReferenceGetReferent
- false, // kIntrinsicCharAt
- false, // kIntrinsicCompareTo
- false, // kIntrinsicEquals
- false, // kIntrinsicGetCharsNoCheck
- false, // kIntrinsicIsEmptyOrLength
- false, // kIntrinsicIndexOf
- true, // kIntrinsicNewStringFromBytes
- true, // kIntrinsicNewStringFromChars
- true, // kIntrinsicNewStringFromString
- true, // kIntrinsicCurrentThread
- true, // kIntrinsicPeek
- true, // kIntrinsicPoke
- false, // kIntrinsicCas
- false, // kIntrinsicUnsafeGet
- false, // kIntrinsicUnsafePut
- false, // kIntrinsicUnsafeGetAndAddInt,
- false, // kIntrinsicUnsafeGetAndAddLong,
- false, // kIntrinsicUnsafeGetAndSetInt,
- false, // kIntrinsicUnsafeGetAndSetLong,
- false, // kIntrinsicUnsafeGetAndSetObject,
- false, // kIntrinsicUnsafeLoadFence,
- false, // kIntrinsicUnsafeStoreFence,
- false, // kIntrinsicUnsafeFullFence,
- true, // kIntrinsicSystemArrayCopyCharArray
- true, // kIntrinsicSystemArrayCopy
-};
-static_assert(arraysize(kIntrinsicIsStatic) == kInlineOpNop,
- "arraysize of kIntrinsicIsStatic unexpected");
-static_assert(kIntrinsicIsStatic[kIntrinsicDoubleCvt], "DoubleCvt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloatCvt], "FloatCvt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloat2Int], "Float2Int must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicDouble2Long], "Double2Long must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsInfinite], "FloatIsInfinite must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsInfinite], "DoubleIsInfinite must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsNaN], "FloatIsNaN must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsNaN], "DoubleIsNaN must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicReverseBits], "ReverseBits must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicReverseBytes], "ReverseBytes must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicBitCount], "BitCount must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCompare], "Compare must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicHighestOneBit], "HighestOneBit must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicLowestOneBit], "LowestOneBit must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfLeadingZeros],
- "NumberOfLeadingZeros must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfTrailingZeros],
- "NumberOfTrailingZeros must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRotateRight], "RotateRight must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRotateLeft], "RotateLeft must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSignum], "Signum must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsInt], "AbsInt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsLong], "AbsLong must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsFloat], "AbsFloat must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAbsDouble], "AbsDouble must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxInt], "MinMaxInt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxLong], "MinMaxLong must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], "MinMaxFloat must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], "MinMaxDouble must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCos], "Cos must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSin], "Sin must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAcos], "Acos must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAsin], "Asin must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAtan], "Atan must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicAtan2], "Atan2 must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCbrt], "Cbrt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCosh], "Cosh must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicExp], "Exp must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicExpm1], "Expm1 must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicHypot], "Hypot must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicLog], "Log must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicLog10], "Log10 must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNextAfter], "NextAfter must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSinh], "Sinh must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicTan], "Tan must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicTanh], "Tanh must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSqrt], "Sqrt must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCeil], "Ceil must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicFloor], "Floor must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRint], "Rint must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRoundFloat], "RoundFloat must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicRoundDouble], "RoundDouble must be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicReferenceGetReferent], "Get must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicCharAt], "CharAt must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicCompareTo], "CompareTo must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicEquals], "String equals must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicGetCharsNoCheck], "GetCharsNoCheck must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], "IsEmptyOrLength must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicIndexOf], "IndexOf must not be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromBytes],
- "NewStringFromBytes must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromChars],
- "NewStringFromChars must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromString],
- "NewStringFromString must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicCurrentThread], "CurrentThread must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicPeek], "Peek must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicPoke], "Poke must be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicCas], "Cas must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGet], "UnsafeGet must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafePut], "UnsafePut must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddInt], "UnsafeGetAndAddInt must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddLong], "UnsafeGetAndAddLong must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetInt], "UnsafeGetAndSetInt must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetLong], "UnsafeGetAndSetLong must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetObject], "UnsafeGetAndSetObject must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeLoadFence], "UnsafeLoadFence must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeStoreFence], "UnsafeStoreFence must not be static");
-static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeFullFence], "UnsafeFullFence must not be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopyCharArray],
- "SystemArrayCopyCharArray must be static");
-static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopy],
- "SystemArrayCopy must be static");
-
-} // anonymous namespace
-
-const uint32_t DexFileMethodInliner::kIndexUnresolved;
-const char* const DexFileMethodInliner::kClassCacheNames[] = {
- "Z", // kClassCacheBoolean
- "B", // kClassCacheByte
- "C", // kClassCacheChar
- "S", // kClassCacheShort
- "I", // kClassCacheInt
- "J", // kClassCacheLong
- "F", // kClassCacheFloat
- "D", // kClassCacheDouble
- "V", // kClassCacheVoid
- "[B", // kClassCacheJavaLangByteArray
- "[C", // kClassCacheJavaLangCharArray
- "[I", // kClassCacheJavaLangIntArray
- "Ljava/lang/Object;", // kClassCacheJavaLangObject
- "Ljava/lang/ref/Reference;", // kClassCacheJavaLangRefReference
- "Ljava/lang/String;", // kClassCacheJavaLangString
- "Ljava/lang/StringBuffer;", // kClassCacheJavaLangStringBuffer
- "Ljava/lang/StringBuilder;", // kClassCacheJavaLangStringBuilder
- "Ljava/lang/StringFactory;", // kClassCacheJavaLangStringFactory
- "Ljava/lang/Double;", // kClassCacheJavaLangDouble
- "Ljava/lang/Float;", // kClassCacheJavaLangFloat
- "Ljava/lang/Integer;", // kClassCacheJavaLangInteger
- "Ljava/lang/Long;", // kClassCacheJavaLangLong
- "Ljava/lang/Short;", // kClassCacheJavaLangShort
- "Ljava/lang/Math;", // kClassCacheJavaLangMath
- "Ljava/lang/StrictMath;", // kClassCacheJavaLangStrictMath
- "Ljava/lang/Thread;", // kClassCacheJavaLangThread
- "Ljava/nio/charset/Charset;", // kClassCacheJavaNioCharsetCharset
- "Llibcore/io/Memory;", // kClassCacheLibcoreIoMemory
- "Lsun/misc/Unsafe;", // kClassCacheSunMiscUnsafe
- "Ljava/lang/System;", // kClassCacheJavaLangSystem
-};
-
-const char* const DexFileMethodInliner::kNameCacheNames[] = {
- "reverse", // kNameCacheReverse
- "reverseBytes", // kNameCacheReverseBytes
- "doubleToRawLongBits", // kNameCacheDoubleToRawLongBits
- "longBitsToDouble", // kNameCacheLongBitsToDouble
- "floatToRawIntBits", // kNameCacheFloatToRawIntBits
- "intBitsToFloat", // kNameCacheIntBitsToFloat
- "abs", // kNameCacheAbs
- "max", // kNameCacheMax
- "min", // kNameCacheMin
- "cos", // kNameCacheCos
- "sin", // kNameCacheSin
- "acos", // kNameCacheAcos
- "asin", // kNameCacheAsin
- "atan", // kNameCacheAtan
- "atan2", // kNameCacheAtan2
- "cbrt", // kNameCacheCbrt
- "cosh", // kNameCacheCosh
- "exp", // kNameCacheExp
- "expm1", // kNameCacheExpm1
- "hypot", // kNameCacheHypot
- "log", // kNameCacheLog
- "log10", // kNameCacheLog10
- "nextAfter", // kNameCacheNextAfter
- "sinh", // kNameCacheSinh
- "tan", // kNameCacheTan
- "tanh", // kNameCacheTanh
- "sqrt", // kNameCacheSqrt
- "ceil", // kNameCacheCeil
- "floor", // kNameCacheFloor
- "rint", // kNameCacheRint
- "round", // kNameCacheRound
- "getReferent", // kNameCacheReferenceGet
- "charAt", // kNameCacheCharAt
- "compareTo", // kNameCacheCompareTo
- "equals", // kNameCacheEquals
- "getCharsNoCheck", // kNameCacheGetCharsNoCheck
- "isEmpty", // kNameCacheIsEmpty
- "floatToIntBits", // kNameCacheFloatToIntBits
- "doubleToLongBits", // kNameCacheDoubleToLongBits
- "isInfinite", // kNameCacheIsInfinite
- "isNaN", // kNameCacheIsNaN
- "indexOf", // kNameCacheIndexOf
- "length", // kNameCacheLength
- "<init>", // kNameCacheInit
- "newStringFromBytes", // kNameCacheNewStringFromBytes
- "newStringFromChars", // kNameCacheNewStringFromChars
- "newStringFromString", // kNameCacheNewStringFromString
- "currentThread", // kNameCacheCurrentThread
- "peekByte", // kNameCachePeekByte
- "peekIntNative", // kNameCachePeekIntNative
- "peekLongNative", // kNameCachePeekLongNative
- "peekShortNative", // kNameCachePeekShortNative
- "pokeByte", // kNameCachePokeByte
- "pokeIntNative", // kNameCachePokeIntNative
- "pokeLongNative", // kNameCachePokeLongNative
- "pokeShortNative", // kNameCachePokeShortNative
- "compareAndSwapInt", // kNameCacheCompareAndSwapInt
- "compareAndSwapLong", // kNameCacheCompareAndSwapLong
- "compareAndSwapObject", // kNameCacheCompareAndSwapObject
- "getInt", // kNameCacheGetInt
- "getIntVolatile", // kNameCacheGetIntVolatile
- "putInt", // kNameCachePutInt
- "putIntVolatile", // kNameCachePutIntVolatile
- "putOrderedInt", // kNameCachePutOrderedInt
- "getLong", // kNameCacheGetLong
- "getLongVolatile", // kNameCacheGetLongVolatile
- "putLong", // kNameCachePutLong
- "putLongVolatile", // kNameCachePutLongVolatile
- "putOrderedLong", // kNameCachePutOrderedLong
- "getObject", // kNameCacheGetObject
- "getObjectVolatile", // kNameCacheGetObjectVolatile
- "putObject", // kNameCachePutObject
- "putObjectVolatile", // kNameCachePutObjectVolatile
- "putOrderedObject", // kNameCachePutOrderedObject
- "getAndAddInt", // kNameCacheGetAndAddInt,
- "getAndAddLong", // kNameCacheGetAndAddLong,
- "getAndSetInt", // kNameCacheGetAndSetInt,
- "getAndSetLong", // kNameCacheGetAndSetLong,
- "getAndSetObject", // kNameCacheGetAndSetObject,
- "loadFence", // kNameCacheLoadFence,
- "storeFence", // kNameCacheStoreFence,
- "fullFence", // kNameCacheFullFence,
- "arraycopy", // kNameCacheArrayCopy
- "bitCount", // kNameCacheBitCount
- "compare", // kNameCacheCompare
- "highestOneBit", // kNameCacheHighestOneBit
- "lowestOneBit", // kNameCacheLowestOneBit
- "numberOfLeadingZeros", // kNameCacheNumberOfLeadingZeros
- "numberOfTrailingZeros", // kNameCacheNumberOfTrailingZeros
- "rotateRight", // kNameCacheRotateRight
- "rotateLeft", // kNameCacheRotateLeft
- "signum", // kNameCacheSignum
-};
-
-const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = {
- // kProtoCacheI_I
- { kClassCacheInt, 1, { kClassCacheInt } },
- // kProtoCacheJ_J
- { kClassCacheLong, 1, { kClassCacheLong } },
- // kProtoCacheS_S
- { kClassCacheShort, 1, { kClassCacheShort } },
- // kProtoCacheD_D
- { kClassCacheDouble, 1, { kClassCacheDouble } },
- // kProtoCacheDD_D
- { kClassCacheDouble, 2, { kClassCacheDouble, kClassCacheDouble } },
- // kProtoCacheF_F
- { kClassCacheFloat, 1, { kClassCacheFloat } },
- // kProtoCacheFF_F
- { kClassCacheFloat, 2, { kClassCacheFloat, kClassCacheFloat } },
- // kProtoCacheD_J
- { kClassCacheLong, 1, { kClassCacheDouble } },
- // kProtoCacheD_Z
- { kClassCacheBoolean, 1, { kClassCacheDouble } },
- // kProtoCacheJ_D
- { kClassCacheDouble, 1, { kClassCacheLong } },
- // kProtoCacheF_I
- { kClassCacheInt, 1, { kClassCacheFloat } },
- // kProtoCacheF_Z
- { kClassCacheBoolean, 1, { kClassCacheFloat } },
- // kProtoCacheI_F
- { kClassCacheFloat, 1, { kClassCacheInt } },
- // kProtoCacheII_I
- { kClassCacheInt, 2, { kClassCacheInt, kClassCacheInt } },
- // kProtoCacheI_C
- { kClassCacheChar, 1, { kClassCacheInt } },
- // kProtoCacheString_I
- { kClassCacheInt, 1, { kClassCacheJavaLangString } },
- // kProtoCache_Z
- { kClassCacheBoolean, 0, { } },
- // kProtoCache_I
- { kClassCacheInt, 0, { } },
- // kProtoCache_Object
- { kClassCacheJavaLangObject, 0, { } },
- // kProtoCache_Thread
- { kClassCacheJavaLangThread, 0, { } },
- // kProtoCacheJ_B
- { kClassCacheByte, 1, { kClassCacheLong } },
- // kProtoCacheJ_I
- { kClassCacheInt, 1, { kClassCacheLong } },
- // kProtoCacheJ_S
- { kClassCacheShort, 1, { kClassCacheLong } },
- // kProtoCacheJB_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheByte } },
- // kProtoCacheJI_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheInt } },
- // kProtoCacheJJ_J
- { kClassCacheLong, 2, { kClassCacheLong, kClassCacheLong } },
- // kProtoCacheJJ_I
- { kClassCacheInt, 2, { kClassCacheLong, kClassCacheLong } },
- // kProtoCacheJJ_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheLong } },
- // kProtoCacheJS_V
- { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheShort } },
- // kProtoCacheObject_Z
- { kClassCacheBoolean, 1, { kClassCacheJavaLangObject } },
- // kProtoCacheJI_J
- { kClassCacheLong, 2, { kClassCacheLong, kClassCacheInt } },
- // kProtoCacheObjectJII_Z
- { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheInt, kClassCacheInt } },
- // kProtoCacheObjectJJJ_Z
- { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheLong, kClassCacheLong } },
- // kProtoCacheObjectJObjectObject_Z
- { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheJavaLangObject, kClassCacheJavaLangObject } },
- // kProtoCacheObjectJ_I
- { kClassCacheInt, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
- // kProtoCacheObjectJI_I
- { kClassCacheInt, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheInt } },
- // kProtoCacheObjectJI_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheInt } },
- // kProtoCacheObjectJ_J
- { kClassCacheLong, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
- // kProtoCacheObjectJJ_J
- { kClassCacheLong, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheLong } },
- // kProtoCacheObjectJJ_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheLong } },
- // kProtoCacheObjectJ_Object
- { kClassCacheJavaLangObject, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
- // kProtoCacheObjectJObject_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheJavaLangObject } },
- // kProtoCacheObjectJObject_Object
- { kClassCacheJavaLangObject, 3, { kClassCacheJavaLangObject, kClassCacheLong,
- kClassCacheJavaLangObject } },
- // kProtoCacheCharArrayICharArrayII_V
- { kClassCacheVoid, 5, {kClassCacheJavaLangCharArray, kClassCacheInt,
- kClassCacheJavaLangCharArray, kClassCacheInt, kClassCacheInt} },
- // kProtoCacheObjectIObjectII_V
- { kClassCacheVoid, 5, {kClassCacheJavaLangObject, kClassCacheInt,
- kClassCacheJavaLangObject, kClassCacheInt, kClassCacheInt} },
- // kProtoCacheIICharArrayI_V
- { kClassCacheVoid, 4, { kClassCacheInt, kClassCacheInt, kClassCacheJavaLangCharArray,
- kClassCacheInt } },
- // kProtoCacheByteArrayIII_String
- { kClassCacheJavaLangString, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheInt } },
- // kProtoCacheIICharArray_String
- { kClassCacheJavaLangString, 3, { kClassCacheInt, kClassCacheInt,
- kClassCacheJavaLangCharArray } },
- // kProtoCacheString_String
- { kClassCacheJavaLangString, 1, { kClassCacheJavaLangString } },
- // kProtoCache_V
- { kClassCacheVoid, 0, { } },
- // kProtoCacheByteArray_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangByteArray } },
- // kProtoCacheByteArrayI_V
- { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheInt } },
- // kProtoCacheByteArrayII_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt } },
- // kProtoCacheByteArrayIII_V
- { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheInt } },
- // kProtoCacheByteArrayIIString_V
- { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheJavaLangString } },
- // kProtoCacheByteArrayString_V
- { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheJavaLangString } },
- // kProtoCacheByteArrayIICharset_V
- { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
- kClassCacheJavaNioCharsetCharset } },
- // kProtoCacheByteArrayCharset_V
- { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheJavaNioCharsetCharset } },
- // kProtoCacheCharArray_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangCharArray } },
- // kProtoCacheCharArrayII_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangCharArray, kClassCacheInt, kClassCacheInt } },
- // kProtoCacheIICharArray_V
- { kClassCacheVoid, 3, { kClassCacheInt, kClassCacheInt, kClassCacheJavaLangCharArray } },
- // kProtoCacheIntArrayII_V
- { kClassCacheVoid, 3, { kClassCacheJavaLangIntArray, kClassCacheInt, kClassCacheInt } },
- // kProtoCacheString_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangString } },
- // kProtoCacheStringBuffer_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangStringBuffer } },
- // kProtoCacheStringBuilder_V
- { kClassCacheVoid, 1, { kClassCacheJavaLangStringBuilder } },
-};
-
-const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods[] = {
-#define INTRINSIC(c, n, p, o, d) \
- { { kClassCache ## c, kNameCache ## n, kProtoCache ## p }, { o, kInlineIntrinsic, { d } } }
-
- INTRINSIC(JavaLangDouble, DoubleToRawLongBits, D_J, kIntrinsicDoubleCvt, 0),
- INTRINSIC(JavaLangDouble, LongBitsToDouble, J_D, kIntrinsicDoubleCvt, kIntrinsicFlagToFloatingPoint),
- INTRINSIC(JavaLangFloat, FloatToRawIntBits, F_I, kIntrinsicFloatCvt, 0),
- INTRINSIC(JavaLangFloat, IntBitsToFloat, I_F, kIntrinsicFloatCvt, kIntrinsicFlagToFloatingPoint),
-
- INTRINSIC(JavaLangFloat, FloatToIntBits, F_I, kIntrinsicFloat2Int, 0),
- INTRINSIC(JavaLangDouble, DoubleToLongBits, D_J, kIntrinsicDouble2Long, 0),
-
- INTRINSIC(JavaLangFloat, IsInfinite, F_Z, kIntrinsicFloatIsInfinite, 0),
- INTRINSIC(JavaLangDouble, IsInfinite, D_Z, kIntrinsicDoubleIsInfinite, 0),
- INTRINSIC(JavaLangFloat, IsNaN, F_Z, kIntrinsicFloatIsNaN, 0),
- INTRINSIC(JavaLangDouble, IsNaN, D_Z, kIntrinsicDoubleIsNaN, 0),
-
- INTRINSIC(JavaLangInteger, ReverseBytes, I_I, kIntrinsicReverseBytes, k32),
- INTRINSIC(JavaLangLong, ReverseBytes, J_J, kIntrinsicReverseBytes, k64),
- INTRINSIC(JavaLangShort, ReverseBytes, S_S, kIntrinsicReverseBytes, kSignedHalf),
- INTRINSIC(JavaLangInteger, Reverse, I_I, kIntrinsicReverseBits, k32),
- INTRINSIC(JavaLangLong, Reverse, J_J, kIntrinsicReverseBits, k64),
-
- INTRINSIC(JavaLangInteger, BitCount, I_I, kIntrinsicBitCount, k32),
- INTRINSIC(JavaLangLong, BitCount, J_I, kIntrinsicBitCount, k64),
- INTRINSIC(JavaLangInteger, Compare, II_I, kIntrinsicCompare, k32),
- INTRINSIC(JavaLangLong, Compare, JJ_I, kIntrinsicCompare, k64),
- INTRINSIC(JavaLangInteger, HighestOneBit, I_I, kIntrinsicHighestOneBit, k32),
- INTRINSIC(JavaLangLong, HighestOneBit, J_J, kIntrinsicHighestOneBit, k64),
- INTRINSIC(JavaLangInteger, LowestOneBit, I_I, kIntrinsicLowestOneBit, k32),
- INTRINSIC(JavaLangLong, LowestOneBit, J_J, kIntrinsicLowestOneBit, k64),
- INTRINSIC(JavaLangInteger, NumberOfLeadingZeros, I_I, kIntrinsicNumberOfLeadingZeros, k32),
- INTRINSIC(JavaLangLong, NumberOfLeadingZeros, J_I, kIntrinsicNumberOfLeadingZeros, k64),
- INTRINSIC(JavaLangInteger, NumberOfTrailingZeros, I_I, kIntrinsicNumberOfTrailingZeros, k32),
- INTRINSIC(JavaLangLong, NumberOfTrailingZeros, J_I, kIntrinsicNumberOfTrailingZeros, k64),
- INTRINSIC(JavaLangInteger, Signum, I_I, kIntrinsicSignum, k32),
- INTRINSIC(JavaLangLong, Signum, J_I, kIntrinsicSignum, k64),
-
- INTRINSIC(JavaLangMath, Abs, I_I, kIntrinsicAbsInt, 0),
- INTRINSIC(JavaLangStrictMath, Abs, I_I, kIntrinsicAbsInt, 0),
- INTRINSIC(JavaLangMath, Abs, J_J, kIntrinsicAbsLong, 0),
- INTRINSIC(JavaLangStrictMath, Abs, J_J, kIntrinsicAbsLong, 0),
- INTRINSIC(JavaLangMath, Abs, F_F, kIntrinsicAbsFloat, 0),
- INTRINSIC(JavaLangStrictMath, Abs, F_F, kIntrinsicAbsFloat, 0),
- INTRINSIC(JavaLangMath, Abs, D_D, kIntrinsicAbsDouble, 0),
- INTRINSIC(JavaLangStrictMath, Abs, D_D, kIntrinsicAbsDouble, 0),
- INTRINSIC(JavaLangMath, Min, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMax),
- INTRINSIC(JavaLangMath, Min, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMax),
- INTRINSIC(JavaLangMath, Min, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMax),
- INTRINSIC(JavaLangMath, Min, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMin),
- INTRINSIC(JavaLangStrictMath, Min, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMin),
- INTRINSIC(JavaLangMath, Max, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMax),
- INTRINSIC(JavaLangStrictMath, Max, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMax),
-
- INTRINSIC(JavaLangMath, Cos, D_D, kIntrinsicCos, 0),
- INTRINSIC(JavaLangMath, Sin, D_D, kIntrinsicSin, 0),
- INTRINSIC(JavaLangMath, Acos, D_D, kIntrinsicAcos, 0),
- INTRINSIC(JavaLangMath, Asin, D_D, kIntrinsicAsin, 0),
- INTRINSIC(JavaLangMath, Atan, D_D, kIntrinsicAtan, 0),
- INTRINSIC(JavaLangMath, Atan2, DD_D, kIntrinsicAtan2, 0),
- INTRINSIC(JavaLangMath, Cbrt, D_D, kIntrinsicCbrt, 0),
- INTRINSIC(JavaLangMath, Cosh, D_D, kIntrinsicCosh, 0),
- INTRINSIC(JavaLangMath, Exp, D_D, kIntrinsicExp, 0),
- INTRINSIC(JavaLangMath, Expm1, D_D, kIntrinsicExpm1, 0),
- INTRINSIC(JavaLangMath, Hypot, DD_D, kIntrinsicHypot, 0),
- INTRINSIC(JavaLangMath, Log, D_D, kIntrinsicLog, 0),
- INTRINSIC(JavaLangMath, Log10, D_D, kIntrinsicLog10, 0),
- INTRINSIC(JavaLangMath, NextAfter, DD_D, kIntrinsicNextAfter, 0),
- INTRINSIC(JavaLangMath, Sinh, D_D, kIntrinsicSinh, 0),
- INTRINSIC(JavaLangMath, Tan, D_D, kIntrinsicTan, 0),
- INTRINSIC(JavaLangMath, Tanh, D_D, kIntrinsicTanh, 0),
- INTRINSIC(JavaLangMath, Sqrt, D_D, kIntrinsicSqrt, 0),
- INTRINSIC(JavaLangStrictMath, Sqrt, D_D, kIntrinsicSqrt, 0),
-
- INTRINSIC(JavaLangMath, Ceil, D_D, kIntrinsicCeil, 0),
- INTRINSIC(JavaLangStrictMath, Ceil, D_D, kIntrinsicCeil, 0),
- INTRINSIC(JavaLangMath, Floor, D_D, kIntrinsicFloor, 0),
- INTRINSIC(JavaLangStrictMath, Floor, D_D, kIntrinsicFloor, 0),
- INTRINSIC(JavaLangMath, Rint, D_D, kIntrinsicRint, 0),
- INTRINSIC(JavaLangStrictMath, Rint, D_D, kIntrinsicRint, 0),
- INTRINSIC(JavaLangMath, Round, F_I, kIntrinsicRoundFloat, 0),
- INTRINSIC(JavaLangStrictMath, Round, F_I, kIntrinsicRoundFloat, 0),
- INTRINSIC(JavaLangMath, Round, D_J, kIntrinsicRoundDouble, 0),
- INTRINSIC(JavaLangStrictMath, Round, D_J, kIntrinsicRoundDouble, 0),
-
- INTRINSIC(JavaLangRefReference, ReferenceGetReferent, _Object, kIntrinsicReferenceGetReferent, 0),
-
- INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0),
- INTRINSIC(JavaLangString, CompareTo, String_I, kIntrinsicCompareTo, 0),
- INTRINSIC(JavaLangString, Equals, Object_Z, kIntrinsicEquals, 0),
- INTRINSIC(JavaLangString, GetCharsNoCheck, IICharArrayI_V, kIntrinsicGetCharsNoCheck, 0),
- INTRINSIC(JavaLangString, IsEmpty, _Z, kIntrinsicIsEmptyOrLength, kIntrinsicFlagIsEmpty),
- INTRINSIC(JavaLangString, IndexOf, II_I, kIntrinsicIndexOf, kIntrinsicFlagNone),
- INTRINSIC(JavaLangString, IndexOf, I_I, kIntrinsicIndexOf, kIntrinsicFlagBase0),
- INTRINSIC(JavaLangString, Length, _I, kIntrinsicIsEmptyOrLength, kIntrinsicFlagLength),
-
- INTRINSIC(JavaLangStringFactory, NewStringFromBytes, ByteArrayIII_String,
- kIntrinsicNewStringFromBytes, kIntrinsicFlagNone),
- INTRINSIC(JavaLangStringFactory, NewStringFromChars, IICharArray_String,
- kIntrinsicNewStringFromChars, kIntrinsicFlagNone),
- INTRINSIC(JavaLangStringFactory, NewStringFromString, String_String,
- kIntrinsicNewStringFromString, kIntrinsicFlagNone),
-
- INTRINSIC(JavaLangThread, CurrentThread, _Thread, kIntrinsicCurrentThread, 0),
-
- INTRINSIC(LibcoreIoMemory, PeekByte, J_B, kIntrinsicPeek, kSignedByte),
- INTRINSIC(LibcoreIoMemory, PeekIntNative, J_I, kIntrinsicPeek, k32),
- INTRINSIC(LibcoreIoMemory, PeekLongNative, J_J, kIntrinsicPeek, k64),
- INTRINSIC(LibcoreIoMemory, PeekShortNative, J_S, kIntrinsicPeek, kSignedHalf),
- INTRINSIC(LibcoreIoMemory, PokeByte, JB_V, kIntrinsicPoke, kSignedByte),
- INTRINSIC(LibcoreIoMemory, PokeIntNative, JI_V, kIntrinsicPoke, k32),
- INTRINSIC(LibcoreIoMemory, PokeLongNative, JJ_V, kIntrinsicPoke, k64),
- INTRINSIC(LibcoreIoMemory, PokeShortNative, JS_V, kIntrinsicPoke, kSignedHalf),
-
- INTRINSIC(SunMiscUnsafe, CompareAndSwapInt, ObjectJII_Z, kIntrinsicCas,
- kIntrinsicFlagNone),
- INTRINSIC(SunMiscUnsafe, CompareAndSwapLong, ObjectJJJ_Z, kIntrinsicCas,
- kIntrinsicFlagIsLong),
- INTRINSIC(SunMiscUnsafe, CompareAndSwapObject, ObjectJObjectObject_Z, kIntrinsicCas,
- kIntrinsicFlagIsObject),
-
-#define UNSAFE_GET_PUT(type, code, type_flags) \
- INTRINSIC(SunMiscUnsafe, Get ## type, ObjectJ_ ## code, kIntrinsicUnsafeGet, \
- type_flags), \
- INTRINSIC(SunMiscUnsafe, Get ## type ## Volatile, ObjectJ_ ## code, kIntrinsicUnsafeGet, \
- (type_flags) | kIntrinsicFlagIsVolatile), \
- INTRINSIC(SunMiscUnsafe, Put ## type, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
- type_flags), \
- INTRINSIC(SunMiscUnsafe, Put ## type ## Volatile, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
- (type_flags) | kIntrinsicFlagIsVolatile), \
- INTRINSIC(SunMiscUnsafe, PutOrdered ## type, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
- (type_flags) | kIntrinsicFlagIsOrdered)
-
- UNSAFE_GET_PUT(Int, I, kIntrinsicFlagNone),
- UNSAFE_GET_PUT(Long, J, kIntrinsicFlagIsLong),
- UNSAFE_GET_PUT(Object, Object, kIntrinsicFlagIsObject),
-#undef UNSAFE_GET_PUT
-
- // 1.8
- INTRINSIC(SunMiscUnsafe, GetAndAddInt, ObjectJI_I, kIntrinsicUnsafeGetAndAddInt, 0),
- INTRINSIC(SunMiscUnsafe, GetAndAddLong, ObjectJJ_J, kIntrinsicUnsafeGetAndAddLong, 0),
- INTRINSIC(SunMiscUnsafe, GetAndSetInt, ObjectJI_I, kIntrinsicUnsafeGetAndSetInt, 0),
- INTRINSIC(SunMiscUnsafe, GetAndSetLong, ObjectJJ_J, kIntrinsicUnsafeGetAndSetLong, 0),
- INTRINSIC(SunMiscUnsafe, GetAndSetObject, ObjectJObject_Object, kIntrinsicUnsafeGetAndSetObject, 0),
- INTRINSIC(SunMiscUnsafe, LoadFence, _V, kIntrinsicUnsafeLoadFence, 0),
- INTRINSIC(SunMiscUnsafe, StoreFence, _V, kIntrinsicUnsafeStoreFence, 0),
- INTRINSIC(SunMiscUnsafe, FullFence, _V, kIntrinsicUnsafeFullFence, 0),
-
- INTRINSIC(JavaLangSystem, ArrayCopy, CharArrayICharArrayII_V , kIntrinsicSystemArrayCopyCharArray,
- 0),
- INTRINSIC(JavaLangSystem, ArrayCopy, ObjectIObjectII_V , kIntrinsicSystemArrayCopy,
- 0),
-
- INTRINSIC(JavaLangInteger, RotateRight, II_I, kIntrinsicRotateRight, k32),
- INTRINSIC(JavaLangLong, RotateRight, JI_J, kIntrinsicRotateRight, k64),
- INTRINSIC(JavaLangInteger, RotateLeft, II_I, kIntrinsicRotateLeft, k32),
- INTRINSIC(JavaLangLong, RotateLeft, JI_J, kIntrinsicRotateLeft, k64),
-
-#undef INTRINSIC
-};
-
-DexFileMethodInliner::DexFileMethodInliner()
- : lock_("DexFileMethodInliner lock", kDexFileMethodInlinerLock),
- dex_file_(nullptr) {
- static_assert(kClassCacheFirst == 0, "kClassCacheFirst not 0");
- static_assert(arraysize(kClassCacheNames) == kClassCacheLast,
- "bad arraysize for kClassCacheNames");
- static_assert(kNameCacheFirst == 0, "kNameCacheFirst not 0");
- static_assert(arraysize(kNameCacheNames) == kNameCacheLast,
- "bad arraysize for kNameCacheNames");
- static_assert(kProtoCacheFirst == 0, "kProtoCacheFirst not 0");
- static_assert(arraysize(kProtoCacheDefs) == kProtoCacheLast,
- "bad arraysize kProtoCacheNames");
-}
-
-DexFileMethodInliner::~DexFileMethodInliner() {
-}
-
-bool DexFileMethodInliner::AnalyseMethodCode(verifier::MethodVerifier* verifier) {
- InlineMethod method;
- bool success = InlineMethodAnalyser::AnalyseMethodCode(verifier, &method);
- return success && AddInlineMethod(verifier->GetMethodReference().dex_method_index, method);
-}
-
-InlineMethodFlags DexFileMethodInliner::IsIntrinsicOrSpecial(uint32_t method_index) {
- ReaderMutexLock mu(Thread::Current(), lock_);
- auto it = inline_methods_.find(method_index);
- if (it != inline_methods_.end()) {
- DCHECK_NE(it->second.flags & (kInlineIntrinsic | kInlineSpecial), 0);
- return it->second.flags;
- } else {
- return kNoInlineMethodFlags;
- }
-}
-
-bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) {
- ReaderMutexLock mu(Thread::Current(), lock_);
- auto it = inline_methods_.find(method_index);
- bool res = (it != inline_methods_.end() && (it->second.flags & kInlineIntrinsic) != 0);
- if (res && intrinsic != nullptr) {
- *intrinsic = it->second;
- }
- return res;
-}
-
-bool DexFileMethodInliner::IsSpecial(uint32_t method_index) {
- ReaderMutexLock mu(Thread::Current(), lock_);
- auto it = inline_methods_.find(method_index);
- return it != inline_methods_.end() && (it->second.flags & kInlineSpecial) != 0;
-}
-
-uint32_t DexFileMethodInliner::FindClassIndex(const DexFile* dex_file, IndexCache* cache,
- ClassCacheIndex index) {
- uint32_t* class_index = &cache->class_indexes[index];
- if (*class_index != kIndexUnresolved) {
- return *class_index;
- }
-
- const DexFile::TypeId* type_id = dex_file->FindTypeId(kClassCacheNames[index]);
- if (type_id == nullptr) {
- *class_index = kIndexNotFound;
- return *class_index;
- }
- *class_index = dex_file->GetIndexForTypeId(*type_id);
- return *class_index;
-}
-
-uint32_t DexFileMethodInliner::FindNameIndex(const DexFile* dex_file, IndexCache* cache,
- NameCacheIndex index) {
- uint32_t* name_index = &cache->name_indexes[index];
- if (*name_index != kIndexUnresolved) {
- return *name_index;
- }
-
- const DexFile::StringId* string_id = dex_file->FindStringId(kNameCacheNames[index]);
- if (string_id == nullptr) {
- *name_index = kIndexNotFound;
- return *name_index;
- }
- *name_index = dex_file->GetIndexForStringId(*string_id);
- return *name_index;
-}
-
-uint32_t DexFileMethodInliner::FindProtoIndex(const DexFile* dex_file, IndexCache* cache,
- ProtoCacheIndex index) {
- uint32_t* proto_index = &cache->proto_indexes[index];
- if (*proto_index != kIndexUnresolved) {
- return *proto_index;
- }
-
- const ProtoDef& proto_def = kProtoCacheDefs[index];
- uint32_t return_index = FindClassIndex(dex_file, cache, proto_def.return_type);
- if (return_index == kIndexNotFound) {
- *proto_index = kIndexNotFound;
- return *proto_index;
- }
- uint16_t return_type = static_cast<uint16_t>(return_index);
- DCHECK_EQ(static_cast<uint32_t>(return_type), return_index);
-
- uint32_t signature_length = proto_def.param_count;
- uint16_t signature_type_idxs[kProtoMaxParams];
- for (uint32_t i = 0; i != signature_length; ++i) {
- uint32_t param_index = FindClassIndex(dex_file, cache, proto_def.params[i]);
- if (param_index == kIndexNotFound) {
- *proto_index = kIndexNotFound;
- return *proto_index;
- }
- signature_type_idxs[i] = static_cast<uint16_t>(param_index);
- DCHECK_EQ(static_cast<uint32_t>(signature_type_idxs[i]), param_index);
- }
-
- const DexFile::ProtoId* proto_id = dex_file->FindProtoId(return_type, signature_type_idxs,
- signature_length);
- if (proto_id == nullptr) {
- *proto_index = kIndexNotFound;
- return *proto_index;
- }
- *proto_index = dex_file->GetIndexForProtoId(*proto_id);
- return *proto_index;
-}
-
-uint32_t DexFileMethodInliner::FindMethodIndex(const DexFile* dex_file, IndexCache* cache,
- const MethodDef& method_def) {
- uint32_t declaring_class_index = FindClassIndex(dex_file, cache, method_def.declaring_class);
- if (declaring_class_index == kIndexNotFound) {
- return kIndexNotFound;
- }
- uint32_t name_index = FindNameIndex(dex_file, cache, method_def.name);
- if (name_index == kIndexNotFound) {
- return kIndexNotFound;
- }
- uint32_t proto_index = FindProtoIndex(dex_file, cache, method_def.proto);
- if (proto_index == kIndexNotFound) {
- return kIndexNotFound;
- }
- const DexFile::MethodId* method_id =
- dex_file->FindMethodId(dex_file->GetTypeId(declaring_class_index),
- dex_file->GetStringId(name_index),
- dex_file->GetProtoId(proto_index));
- if (method_id == nullptr) {
- return kIndexNotFound;
- }
- return dex_file->GetIndexForMethodId(*method_id);
-}
-
-DexFileMethodInliner::IndexCache::IndexCache() {
- std::fill_n(class_indexes, arraysize(class_indexes), kIndexUnresolved);
- std::fill_n(name_indexes, arraysize(name_indexes), kIndexUnresolved);
- std::fill_n(proto_indexes, arraysize(proto_indexes), kIndexUnresolved);
-}
-
-void DexFileMethodInliner::FindIntrinsics(const DexFile* dex_file) {
- DCHECK(dex_file != nullptr);
- DCHECK(dex_file_ == nullptr);
- IndexCache cache;
- for (const IntrinsicDef& def : kIntrinsicMethods) {
- uint32_t method_idx = FindMethodIndex(dex_file, &cache, def.method_def);
- if (method_idx != kIndexNotFound) {
- DCHECK(inline_methods_.find(method_idx) == inline_methods_.end());
- inline_methods_.Put(method_idx, def.intrinsic);
- }
- }
- dex_file_ = dex_file;
-}
-
-bool DexFileMethodInliner::AddInlineMethod(int32_t method_idx, const InlineMethod& method) {
- WriterMutexLock mu(Thread::Current(), lock_);
- if (LIKELY(inline_methods_.find(method_idx) == inline_methods_.end())) {
- inline_methods_.Put(method_idx, method);
- return true;
- } else {
- if (PrettyMethod(method_idx, *dex_file_) == "int java.lang.String.length()") {
- // TODO: String.length is both kIntrinsicIsEmptyOrLength and kInlineOpIGet.
- } else {
- LOG(WARNING) << "Inliner: " << PrettyMethod(method_idx, *dex_file_) << " already inline";
- }
- return false;
- }
-}
-
-} // namespace art
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
deleted file mode 100644
index f4ae5a5..0000000
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_
-#define ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_
-
-#include <stdint.h>
-
-#include "base/enums.h"
-#include "base/mutex.h"
-#include "base/macros.h"
-#include "safe_map.h"
-#include "dex_file.h"
-#include "quick/inline_method_analyser.h"
-
-namespace art {
-
-namespace verifier {
-class MethodVerifier;
-} // namespace verifier
-
-enum OpSize {
- k32,
- k64,
- kSignedHalf,
- kSignedByte,
-};
-
-/**
- * Handles inlining of methods from a particular DexFile.
- *
- * Intrinsics are a special case of inline methods. The DexFile indices for
- * all the supported intrinsic methods are looked up once by the FindIntrinsics
- * function and cached by this class for quick lookup by the method index.
- *
- * TODO: Detect short methods (at least getters, setters and empty functions)
- * from the verifier and mark them for inlining. Inline these methods early
- * during compilation to allow further optimizations. Similarly, provide
- * additional information about intrinsics to the early phases of compilation.
- */
-class DexFileMethodInliner {
- public:
- DexFileMethodInliner();
- ~DexFileMethodInliner();
-
- /**
- * Analyse method code to determine if the method is a candidate for inlining.
- * If it is, record its data for later.
- *
- * @param verifier the method verifier holding data about the method to analyse.
- * @return true if the method is a candidate for inlining, false otherwise.
- */
- bool AnalyseMethodCode(verifier::MethodVerifier* verifier)
- REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!lock_);
-
- /**
- * Check whether a particular method index corresponds to an intrinsic or special function.
- */
- InlineMethodFlags IsIntrinsicOrSpecial(uint32_t method_index) REQUIRES(!lock_);
-
- /**
- * Check whether a particular method index corresponds to an intrinsic function.
- */
- bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) REQUIRES(!lock_);
-
- /**
- * Check whether a particular method index corresponds to a special function.
- */
- bool IsSpecial(uint32_t method_index) REQUIRES(!lock_);
-
- /**
- * To avoid multiple lookups of a class by its descriptor, we cache its
- * type index in the IndexCache. These are the indexes into the IndexCache
- * class_indexes array.
- */
- enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
- kClassCacheFirst = 0,
- kClassCacheBoolean = kClassCacheFirst,
- kClassCacheByte,
- kClassCacheChar,
- kClassCacheShort,
- kClassCacheInt,
- kClassCacheLong,
- kClassCacheFloat,
- kClassCacheDouble,
- kClassCacheVoid,
- kClassCacheJavaLangByteArray,
- kClassCacheJavaLangCharArray,
- kClassCacheJavaLangIntArray,
- kClassCacheJavaLangObject,
- kClassCacheJavaLangRefReference,
- kClassCacheJavaLangString,
- kClassCacheJavaLangStringBuffer,
- kClassCacheJavaLangStringBuilder,
- kClassCacheJavaLangStringFactory,
- kClassCacheJavaLangDouble,
- kClassCacheJavaLangFloat,
- kClassCacheJavaLangInteger,
- kClassCacheJavaLangLong,
- kClassCacheJavaLangShort,
- kClassCacheJavaLangMath,
- kClassCacheJavaLangStrictMath,
- kClassCacheJavaLangThread,
- kClassCacheJavaNioCharsetCharset,
- kClassCacheLibcoreIoMemory,
- kClassCacheSunMiscUnsafe,
- kClassCacheJavaLangSystem,
- kClassCacheLast
- };
-
- /**
- * To avoid multiple lookups of a method name string, we cache its string
- * index in the IndexCache. These are the indexes into the IndexCache
- * name_indexes array.
- */
- enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
- kNameCacheFirst = 0,
- kNameCacheReverse = kNameCacheFirst,
- kNameCacheReverseBytes,
- kNameCacheDoubleToRawLongBits,
- kNameCacheLongBitsToDouble,
- kNameCacheFloatToRawIntBits,
- kNameCacheIntBitsToFloat,
- kNameCacheAbs,
- kNameCacheMax,
- kNameCacheMin,
- kNameCacheCos,
- kNameCacheSin,
- kNameCacheAcos,
- kNameCacheAsin,
- kNameCacheAtan,
- kNameCacheAtan2,
- kNameCacheCbrt,
- kNameCacheCosh,
- kNameCacheExp,
- kNameCacheExpm1,
- kNameCacheHypot,
- kNameCacheLog,
- kNameCacheLog10,
- kNameCacheNextAfter,
- kNameCacheSinh,
- kNameCacheTan,
- kNameCacheTanh,
- kNameCacheSqrt,
- kNameCacheCeil,
- kNameCacheFloor,
- kNameCacheRint,
- kNameCacheRound,
- kNameCacheReferenceGetReferent,
- kNameCacheCharAt,
- kNameCacheCompareTo,
- kNameCacheEquals,
- kNameCacheGetCharsNoCheck,
- kNameCacheIsEmpty,
- kNameCacheFloatToIntBits,
- kNameCacheDoubleToLongBits,
- kNameCacheIsInfinite,
- kNameCacheIsNaN,
- kNameCacheIndexOf,
- kNameCacheLength,
- kNameCacheInit,
- kNameCacheNewStringFromBytes,
- kNameCacheNewStringFromChars,
- kNameCacheNewStringFromString,
- kNameCacheCurrentThread,
- kNameCachePeekByte,
- kNameCachePeekIntNative,
- kNameCachePeekLongNative,
- kNameCachePeekShortNative,
- kNameCachePokeByte,
- kNameCachePokeIntNative,
- kNameCachePokeLongNative,
- kNameCachePokeShortNative,
- kNameCacheCompareAndSwapInt,
- kNameCacheCompareAndSwapLong,
- kNameCacheCompareAndSwapObject,
- kNameCacheGetInt,
- kNameCacheGetIntVolatile,
- kNameCachePutInt,
- kNameCachePutIntVolatile,
- kNameCachePutOrderedInt,
- kNameCacheGetLong,
- kNameCacheGetLongVolatile,
- kNameCachePutLong,
- kNameCachePutLongVolatile,
- kNameCachePutOrderedLong,
- kNameCacheGetObject,
- kNameCacheGetObjectVolatile,
- kNameCachePutObject,
- kNameCachePutObjectVolatile,
- kNameCachePutOrderedObject,
- kNameCacheGetAndAddInt,
- kNameCacheGetAndAddLong,
- kNameCacheGetAndSetInt,
- kNameCacheGetAndSetLong,
- kNameCacheGetAndSetObject,
- kNameCacheLoadFence,
- kNameCacheStoreFence,
- kNameCacheFullFence,
- kNameCacheArrayCopy,
- kNameCacheBitCount,
- kNameCacheCompare,
- kNameCacheHighestOneBit,
- kNameCacheLowestOneBit,
- kNameCacheNumberOfLeadingZeros,
- kNameCacheNumberOfTrailingZeros,
- kNameCacheRotateRight,
- kNameCacheRotateLeft,
- kNameCacheSignum,
- kNameCacheLast
- };
-
- /**
- * To avoid multiple lookups of a method signature, we cache its proto
- * index in the IndexCache. These are the indexes into the IndexCache
- * proto_indexes array.
- */
- enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
- kProtoCacheFirst = 0,
- kProtoCacheI_I = kProtoCacheFirst,
- kProtoCacheJ_J,
- kProtoCacheS_S,
- kProtoCacheD_D,
- kProtoCacheDD_D,
- kProtoCacheF_F,
- kProtoCacheFF_F,
- kProtoCacheD_J,
- kProtoCacheD_Z,
- kProtoCacheJ_D,
- kProtoCacheF_I,
- kProtoCacheF_Z,
- kProtoCacheI_F,
- kProtoCacheII_I,
- kProtoCacheI_C,
- kProtoCacheString_I,
- kProtoCache_Z,
- kProtoCache_I,
- kProtoCache_Object,
- kProtoCache_Thread,
- kProtoCacheJ_B,
- kProtoCacheJ_I,
- kProtoCacheJ_S,
- kProtoCacheJB_V,
- kProtoCacheJI_V,
- kProtoCacheJJ_J,
- kProtoCacheJJ_I,
- kProtoCacheJJ_V,
- kProtoCacheJS_V,
- kProtoCacheObject_Z,
- kProtoCacheJI_J,
- kProtoCacheObjectJII_Z,
- kProtoCacheObjectJJJ_Z,
- kProtoCacheObjectJObjectObject_Z,
- kProtoCacheObjectJ_I,
- kProtoCacheObjectJI_I,
- kProtoCacheObjectJI_V,
- kProtoCacheObjectJ_J,
- kProtoCacheObjectJJ_J,
- kProtoCacheObjectJJ_V,
- kProtoCacheObjectJ_Object,
- kProtoCacheObjectJObject_V,
- kProtoCacheObjectJObject_Object,
- kProtoCacheCharArrayICharArrayII_V,
- kProtoCacheObjectIObjectII_V,
- kProtoCacheIICharArrayI_V,
- kProtoCacheByteArrayIII_String,
- kProtoCacheIICharArray_String,
- kProtoCacheString_String,
- kProtoCache_V,
- kProtoCacheByteArray_V,
- kProtoCacheByteArrayI_V,
- kProtoCacheByteArrayII_V,
- kProtoCacheByteArrayIII_V,
- kProtoCacheByteArrayIIString_V,
- kProtoCacheByteArrayString_V,
- kProtoCacheByteArrayIICharset_V,
- kProtoCacheByteArrayCharset_V,
- kProtoCacheCharArray_V,
- kProtoCacheCharArrayII_V,
- kProtoCacheIICharArray_V,
- kProtoCacheIntArrayII_V,
- kProtoCacheString_V,
- kProtoCacheStringBuffer_V,
- kProtoCacheStringBuilder_V,
- kProtoCacheLast
- };
-
- private:
- /**
- * The maximum number of method parameters we support in the ProtoDef.
- */
- static constexpr uint32_t kProtoMaxParams = 6;
-
- /**
- * The method signature (proto) definition using cached class indexes.
- * The return_type and params are used with the IndexCache to look up
- * appropriate class indexes to be passed to DexFile::FindProtoId().
- */
- struct ProtoDef {
- ClassCacheIndex return_type;
- uint8_t param_count;
- ClassCacheIndex params[kProtoMaxParams];
- };
-
- /**
- * The method definition using cached class, name and proto indexes.
- * The class index, method name index and proto index are used with
- * IndexCache to look up appropriate parameters for DexFile::FindMethodId().
- */
- struct MethodDef {
- ClassCacheIndex declaring_class;
- NameCacheIndex name;
- ProtoCacheIndex proto;
- };
-
- /**
- * The definition of an intrinsic function binds the method definition
- * to an Intrinsic.
- */
- struct IntrinsicDef {
- MethodDef method_def;
- InlineMethod intrinsic;
- };
-
- /**
- * Cache for class, method name and method signature indexes used during
- * intrinsic function lookup to avoid multiple lookups of the same items.
- *
- * Many classes have multiple intrinsics and/or they are used in multiple
- * method signatures and we want to avoid repeated lookups since they are
- * not exactly cheap. The method names and method signatures are sometimes
- * reused and therefore cached as well.
- */
- struct IndexCache {
- IndexCache();
-
- uint32_t class_indexes[kClassCacheLast - kClassCacheFirst];
- uint32_t name_indexes[kNameCacheLast - kNameCacheFirst];
- uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst];
- };
-
- static const char* const kClassCacheNames[];
- static const char* const kNameCacheNames[];
- static const ProtoDef kProtoCacheDefs[];
- static const IntrinsicDef kIntrinsicMethods[];
-
- static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1);
- static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2);
-
- static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache,
- ClassCacheIndex index);
- static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache,
- NameCacheIndex index);
- static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache,
- ProtoCacheIndex index);
- static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache,
- const MethodDef& method_def);
-
- /**
- * Find all known intrinsic methods in the dex_file and cache their indices.
- *
- * Only DexFileToMethodInlinerMap may call this function to initialize the inliner.
- */
- void FindIntrinsics(const DexFile* dex_file) REQUIRES(lock_);
-
- friend class DexFileToMethodInlinerMap;
-
- bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) REQUIRES(!lock_);
-
- ReaderWriterMutex lock_;
- /*
- * Maps method indexes (for the particular DexFile) to Intrinsic defintions.
- */
- SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_);
- const DexFile* dex_file_;
-
- DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_
diff --git a/compiler/dex/quick/dex_file_to_method_inliner_map.cc b/compiler/dex/quick/dex_file_to_method_inliner_map.cc
deleted file mode 100644
index 2fec183..0000000
--- a/compiler/dex/quick/dex_file_to_method_inliner_map.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include <algorithm>
-#include <utility>
-#include "thread.h"
-#include "thread-inl.h"
-#include "base/mutex.h"
-#include "base/mutex-inl.h"
-#include "base/logging.h"
-#include "driver/compiler_driver.h"
-
-#include "dex_file_to_method_inliner_map.h"
-
-namespace art {
-
-DexFileToMethodInlinerMap::DexFileToMethodInlinerMap()
- : lock_("DexFileToMethodInlinerMap lock", kDexFileToMethodInlinerMapLock) {
-}
-
-DexFileToMethodInlinerMap::~DexFileToMethodInlinerMap() {
- for (auto& entry : inliners_) {
- delete entry.second;
- }
-}
-
-DexFileMethodInliner* DexFileToMethodInlinerMap::GetMethodInliner(const DexFile* dex_file) {
- Thread* self = Thread::Current();
- {
- ReaderMutexLock mu(self, lock_);
- auto it = inliners_.find(dex_file);
- if (it != inliners_.end()) {
- return it->second;
- }
- }
-
- // We need to acquire our lock_ to modify inliners_ but we want to release it
- // before we initialize the new inliner. However, we need to acquire the
- // new inliner's lock_ before we release our lock_ to prevent another thread
- // from using the uninitialized inliner. This requires explicit calls to
- // ExclusiveLock()/ExclusiveUnlock() on one of the locks, the other one
- // can use WriterMutexLock.
- DexFileMethodInliner* locked_inliner;
- {
- WriterMutexLock mu(self, lock_);
- DexFileMethodInliner** inliner = &inliners_[dex_file]; // inserts new entry if not found
- if (*inliner) {
- return *inliner;
- }
- *inliner = new DexFileMethodInliner;
- DCHECK(*inliner != nullptr);
- locked_inliner = *inliner;
- locked_inliner->lock_.ExclusiveLock(self); // Acquire inliner's lock_ before releasing lock_.
- }
- locked_inliner->FindIntrinsics(dex_file);
- locked_inliner->lock_.ExclusiveUnlock(self);
- return locked_inliner;
-}
-
-} // namespace art
diff --git a/compiler/dex/quick/dex_file_to_method_inliner_map.h b/compiler/dex/quick/dex_file_to_method_inliner_map.h
deleted file mode 100644
index 215dc12..0000000
--- a/compiler/dex/quick/dex_file_to_method_inliner_map.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ART_COMPILER_DEX_QUICK_DEX_FILE_TO_METHOD_INLINER_MAP_H_
-#define ART_COMPILER_DEX_QUICK_DEX_FILE_TO_METHOD_INLINER_MAP_H_
-
-#include <map>
-#include <vector>
-#include "base/macros.h"
-#include "base/mutex.h"
-
-#include "dex/quick/dex_file_method_inliner.h"
-
-namespace art {
-
-class CompilerDriver;
-class DexFile;
-
-/**
- * Map each DexFile to its DexFileMethodInliner.
- *
- * The method inliner is created and initialized the first time it's requested
- * for a particular DexFile.
- */
-class DexFileToMethodInlinerMap {
- public:
- DexFileToMethodInlinerMap();
- ~DexFileToMethodInlinerMap();
-
- DexFileMethodInliner* GetMethodInliner(const DexFile* dex_file) NO_THREAD_SAFETY_ANALYSIS;
- // TODO: There is an irregular non-scoped use of locks that defeats annotalysis with -O0.
- // Fix the NO_THREAD_SAFETY_ANALYSIS when this works and add the appropriate LOCKS_EXCLUDED.
-
- private:
- ReaderWriterMutex lock_;
- std::map<const DexFile*, DexFileMethodInliner*> inliners_ GUARDED_BY(lock_);
-
- DISALLOW_COPY_AND_ASSIGN(DexFileToMethodInlinerMap);
-};
-
-} // namespace art
-
-#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_TO_METHOD_INLINER_MAP_H_
diff --git a/compiler/dex/quick_compiler_callbacks.cc b/compiler/dex/quick_compiler_callbacks.cc
index 2532bda..932eb51 100644
--- a/compiler/dex/quick_compiler_callbacks.cc
+++ b/compiler/dex/quick_compiler_callbacks.cc
@@ -16,7 +16,6 @@
#include "quick_compiler_callbacks.h"
-#include "quick/dex_file_to_method_inliner_map.h"
#include "verifier/method_verifier-inl.h"
#include "verification_results.h"
@@ -24,8 +23,6 @@
void QuickCompilerCallbacks::MethodVerified(verifier::MethodVerifier* verifier) {
verification_results_->ProcessVerifiedMethod(verifier);
- MethodReference ref = verifier->GetMethodReference();
- method_inliner_map_->GetMethodInliner(ref.dex_file)->AnalyseMethodCode(verifier);
}
void QuickCompilerCallbacks::ClassRejected(ClassReference ref) {
diff --git a/compiler/dex/quick_compiler_callbacks.h b/compiler/dex/quick_compiler_callbacks.h
index 824194c..34fd88b 100644
--- a/compiler/dex/quick_compiler_callbacks.h
+++ b/compiler/dex/quick_compiler_callbacks.h
@@ -22,19 +22,15 @@
namespace art {
class VerificationResults;
-class DexFileToMethodInlinerMap;
class QuickCompilerCallbacks FINAL : public CompilerCallbacks {
public:
QuickCompilerCallbacks(VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map,
CompilerCallbacks::CallbackMode mode)
: CompilerCallbacks(mode),
verification_results_(verification_results),
- method_inliner_map_(method_inliner_map),
verifier_deps_(nullptr) {
CHECK(verification_results != nullptr);
- CHECK(method_inliner_map != nullptr);
}
~QuickCompilerCallbacks() { }
@@ -59,7 +55,6 @@
private:
VerificationResults* const verification_results_;
- DexFileToMethodInlinerMap* const method_inliner_map_;
verifier::VerifierDeps* verifier_deps_;
};
diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc
index 4481c3d..b72d0ac 100644
--- a/compiler/driver/compiled_method_storage_test.cc
+++ b/compiler/driver/compiled_method_storage_test.cc
@@ -21,17 +21,14 @@
#include "compiler_driver.h"
#include "compiler_options.h"
#include "dex/verification_results.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
namespace art {
TEST(CompiledMethodStorage, Deduplicate) {
CompilerOptions compiler_options;
VerificationResults verification_results(&compiler_options);
- DexFileToMethodInlinerMap method_inliner_map;
CompilerDriver driver(&compiler_options,
&verification_results,
- &method_inliner_map,
Compiler::kOptimizing,
/* instruction_set_ */ kNone,
/* instruction_set_features */ nullptr,
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index 4b913f4..2d0dd3c 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -26,7 +26,7 @@
#include "dex_compilation_unit.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "handle_scope-inl.h"
namespace art {
@@ -37,7 +37,7 @@
inline mirror::ClassLoader* CompilerDriver::GetClassLoader(const ScopedObjectAccess& soa,
const DexCompilationUnit* mUnit) {
- return soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader());
+ return soa.Decode<mirror::ClassLoader>(mUnit->GetClassLoader()).Decode();
}
inline mirror::Class* CompilerDriver::ResolveClass(
@@ -45,7 +45,7 @@
Handle<mirror::ClassLoader> class_loader, uint16_t cls_index,
const DexCompilationUnit* mUnit) {
DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile());
- DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()));
+ DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
mirror::Class* cls = mUnit->GetClassLinker()->ResolveType(
*mUnit->GetDexFile(), cls_index, dex_cache, class_loader);
DCHECK_EQ(cls == nullptr, soa.Self()->IsExceptionPending());
@@ -60,7 +60,7 @@
const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit) {
DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile());
- DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()));
+ DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
const DexFile::MethodId& referrer_method_id =
mUnit->GetDexFile()->GetMethodId(mUnit->GetDexMethodIndex());
return ResolveClass(soa, dex_cache, class_loader, referrer_method_id.class_idx_, mUnit);
@@ -95,7 +95,7 @@
const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
uint32_t field_idx, bool is_static) {
- DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()));
+ DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
return ResolveFieldWithDexFile(soa, dex_cache, class_loader, mUnit->GetDexFile(), field_idx,
is_static);
}
@@ -258,7 +258,7 @@
ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change) {
- DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()));
+ DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
ArtMethod* resolved_method =
check_incompatible_class_change
? mUnit->GetClassLinker()->ResolveMethod<ClassLinker::kForceICCECheck>(
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 1244bd7..895721f 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -44,9 +44,8 @@
#include "dex/dex_to_dex_compiler.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
-#include "dex/quick/dex_file_method_inliner.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_options.h"
+#include "intrinsics_enum.h"
#include "jni_internal.h"
#include "object_lock.h"
#include "runtime.h"
@@ -60,7 +59,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/throwable.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "handle_scope-inl.h"
#include "thread.h"
@@ -353,7 +352,6 @@
CompilerDriver::CompilerDriver(
const CompilerOptions* compiler_options,
VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map,
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
@@ -368,7 +366,6 @@
const ProfileCompilationInfo* profile_compilation_info)
: compiler_options_(compiler_options),
verification_results_(verification_results),
- method_inliner_map_(method_inliner_map),
compiler_(Compiler::Create(this, compiler_kind)),
compiler_kind_(compiler_kind),
instruction_set_(instruction_set == kArm ? kThumb2: instruction_set),
@@ -397,7 +394,6 @@
dex_to_dex_references_(),
current_dex_to_dex_methods_(nullptr) {
DCHECK(compiler_options_ != nullptr);
- DCHECK(method_inliner_map_ != nullptr);
compiler_->Init();
@@ -459,6 +455,29 @@
}
#undef CREATE_TRAMPOLINE
+static void SetupIntrinsic(Thread* self,
+ Intrinsics intrinsic,
+ InvokeType invoke_type,
+ const char* class_name,
+ const char* method_name,
+ const char* signature)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ PointerSize image_size = class_linker->GetImagePointerSize();
+ mirror::Class* cls = class_linker->FindSystemClass(self, class_name);
+ if (cls == nullptr) {
+ LOG(FATAL) << "Could not find class of intrinsic " << class_name;
+ }
+ ArtMethod* method = (invoke_type == kStatic || invoke_type == kDirect)
+ ? cls->FindDeclaredDirectMethod(method_name, signature, image_size)
+ : cls->FindDeclaredVirtualMethod(method_name, signature, image_size);
+ if (method == nullptr) {
+ LOG(FATAL) << "Could not find method of intrinsic " << class_name << method_name << signature;
+ }
+ DCHECK_EQ(method->GetInvokeType(), invoke_type);
+ method->SetIntrinsic(static_cast<uint32_t>(intrinsic));
+}
+
void CompilerDriver::CompileAll(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings) {
@@ -473,6 +492,17 @@
// 3) Attempt to verify all classes
// 4) Attempt to initialize image classes, and trivially initialized classes
PreCompile(class_loader, dex_files, timings);
+ if (IsBootImage()) {
+ // We don't need to setup the intrinsics for non boot image compilation, as
+ // those compilations will pick up a boot image that have the ArtMethod already
+ // set with the intrinsics flag.
+ ScopedObjectAccess soa(Thread::Current());
+#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnvironmentOrCache, SideEffects, Exceptions, ClassName, MethodName, Signature) \
+ SetupIntrinsic(soa.Self(), Intrinsics::k##Name, InvokeType, ClassName, MethodName, Signature);
+#include "intrinsics_list.h"
+INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+#undef INTRINSICS_LIST
+ }
// Compile:
// 1) Compile all classes and methods enabled for compilation. May fall back to dex-to-dex
// compilation.
@@ -531,7 +561,7 @@
ScopedObjectAccess soa(self);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
return GetDexToDexCompilationLevel(self, driver, class_loader, dex_file, class_def);
}
@@ -606,7 +636,7 @@
ScopedObjectAccess soa(self);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader_handle(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(class_loader)));
+ soa.Decode<mirror::ClassLoader>(class_loader)));
// TODO: Lookup annotation from DexFile directly without resolving method.
ArtMethod* method =
@@ -1622,7 +1652,7 @@
{
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader_handle(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(mUnit->GetClassLoader())));
resolved_field = ResolveField(soa, dex_cache, class_loader_handle, mUnit, field_idx, false);
referrer_class = resolved_field != nullptr
? ResolveCompilingMethodsClass(soa, dex_cache, class_loader_handle, mUnit) : nullptr;
@@ -1966,7 +1996,7 @@
ScopedObjectAccess soa(self);
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(
soa.Self(), dex_file, false)));
// Resolve the class.
@@ -2063,7 +2093,7 @@
const DexFile& dex_file = *manager_->GetDexFile();
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(manager_->GetClassLoader())));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(manager_->GetClassLoader())));
Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->RegisterDexFile(
dex_file,
class_loader.Get())));
@@ -2162,7 +2192,7 @@
jobject jclass_loader = manager_->GetClassLoader();
StackHandleScope<3> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> klass(
hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader)));
if (klass.Get() == nullptr) {
@@ -2250,7 +2280,7 @@
jobject jclass_loader = manager_->GetClassLoader();
StackHandleScope<3> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> klass(
hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader)));
// Class might have failed resolution. Then don't set it to verified.
@@ -2312,7 +2342,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<3> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> klass(
hs.NewHandle(manager_->GetClassLinker()->FindClass(soa.Self(), descriptor, class_loader)));
@@ -2548,7 +2578,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<3> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> klass(
hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader)));
Handle<mirror::DexCache> dex_cache;
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index fb17603..eb1222c 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -57,7 +57,6 @@
class CompiledMethod;
class CompilerOptions;
class DexCompilationUnit;
-class DexFileToMethodInlinerMap;
struct InlineIGetIPutData;
class InstructionSetFeatures;
class ParallelCompilationManager;
@@ -88,7 +87,6 @@
// classes.
CompilerDriver(const CompilerOptions* compiler_options,
VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map,
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
@@ -131,10 +129,6 @@
return verification_results_;
}
- DexFileToMethodInlinerMap* GetMethodInlinerMap() const {
- return method_inliner_map_;
- }
-
InstructionSet GetInstructionSet() const {
return instruction_set_;
}
@@ -596,7 +590,6 @@
const CompilerOptions* const compiler_options_;
VerificationResults* const verification_results_;
- DexFileToMethodInlinerMap* const method_inliner_map_;
std::unique_ptr<Compiler> compiler_;
Compiler::Kind compiler_kind_;
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index b9a5a78..96f17ac 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -32,7 +32,7 @@
#include "mirror/object-inl.h"
#include "handle_scope-inl.h"
#include "jit/offline_profiling_info.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -83,7 +83,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
mirror::Class* c = class_linker->FindClass(soa.Self(), descriptor, loader);
CHECK(c != nullptr);
const auto pointer_size = class_linker->GetImagePointerSize();
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index ca0869a..0c06090 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -26,7 +26,7 @@
#include "invoke_type.h"
#include "mirror/object-inl.h"
#include "oat.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index 86f91c5..f9e5cb9 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -31,7 +31,7 @@
#include "oat_quick_method_header.h"
#include "optimizing/stack_map_stream.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "handle_scope-inl.h"
#include "thread.h"
@@ -45,7 +45,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("ExceptionHandle"))));
my_klass_ = class_linker_->FindClass(soa.Self(), "LExceptionHandle;", class_loader);
ASSERT_TRUE(my_klass_ != nullptr);
Handle<mirror::Class> klass(hs.NewHandle(my_klass_));
@@ -219,7 +219,7 @@
ASSERT_TRUE(internal != nullptr);
jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(soa, internal);
ASSERT_TRUE(ste_array != nullptr);
- auto* trace_array = soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
+ auto trace_array = soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>>(ste_array);
ASSERT_TRUE(trace_array != nullptr);
ASSERT_TRUE(trace_array->Get(0) != nullptr);
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 90fddce..9e94b9d 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -33,7 +33,7 @@
#include "lock_word.h"
#include "mirror/object-inl.h"
#include "oat_writer.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "signal_catcher.h"
#include "utils.h"
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 6b5758b..41bda60 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -63,7 +63,7 @@
#include "oat_file.h"
#include "oat_file_manager.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "handle_scope-inl.h"
#include "utils/dex_cache_arrays_layout-inl.h"
diff --git a/compiler/intrinsics_enum.h b/compiler/intrinsics_enum.h
new file mode 100644
index 0000000..5528181
--- /dev/null
+++ b/compiler/intrinsics_enum.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_COMPILER_INTRINSICS_ENUM_H_
+#define ART_COMPILER_INTRINSICS_ENUM_H_
+
+namespace art {
+
+enum class Intrinsics {
+#define OPTIMIZING_INTRINSICS(Name, ...) \
+ k ## Name,
+#include "intrinsics_list.h"
+ kNone,
+ INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+#undef INTRINSICS_LIST
+#undef OPTIMIZING_INTRINSICS
+};
+std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
+
+} // namespace art
+
+#endif // ART_COMPILER_INTRINSICS_ENUM_H_
diff --git a/compiler/intrinsics_list.h b/compiler/intrinsics_list.h
new file mode 100644
index 0000000..5877f57
--- /dev/null
+++ b/compiler/intrinsics_list.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C, "", "", "") 2015 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.
+ */
+
+#ifndef ART_COMPILER_INTRINSICS_LIST_H_
+#define ART_COMPILER_INTRINSICS_LIST_H_
+
+// All intrinsics supported by ART. Format is name, then whether it is expected
+// to be a HInvokeStaticOrDirect node (compared to HInvokeVirtual), then whether it requires an
+// environment, may have side effects, or may throw exceptions.
+
+// Note: adding a new intrinsic requires an art image version change,
+// as the modifiers flag for some ArtMethods will need to be changed.
+
+#define INTRINSICS_LIST(V) \
+ V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \
+ V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToLongBits", "(D)J") \
+ V(DoubleIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isInfinite", "(D)Z") \
+ V(DoubleIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isNaN", "(D)Z") \
+ V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \
+ V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \
+ V(FloatFloatToIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToIntBits", "(F)I") \
+ V(FloatIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isInfinite", "(F)Z") \
+ V(FloatIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isNaN", "(F)Z") \
+ V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \
+ V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverse", "(I)I") \
+ V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverseBytes", "(I)I") \
+ V(IntegerBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "bitCount", "(I)I") \
+ V(IntegerCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "compare", "(II)I") \
+ V(IntegerHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "highestOneBit", "(I)I") \
+ V(IntegerLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "lowestOneBit", "(I)I") \
+ V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfLeadingZeros", "(I)I") \
+ V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfTrailingZeros", "(I)I") \
+ V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateRight", "(II)I") \
+ V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateLeft", "(II)I") \
+ V(IntegerSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "signum", "(I)I") \
+ V(LongReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverse", "(J)J") \
+ V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverseBytes", "(J)J") \
+ V(LongBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "bitCount", "(J)I") \
+ V(LongCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "compare", "(JJ)I") \
+ V(LongHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "highestOneBit", "(J)J") \
+ V(LongLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "lowestOneBit", "(J)J") \
+ V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfLeadingZeros", "(J)I") \
+ V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfTrailingZeros", "(J)I") \
+ V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateRight", "(JI)J") \
+ V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateLeft", "(JI)J") \
+ V(LongSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "signum", "(J)I") \
+ V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \
+ V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(D)D") \
+ V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(F)F") \
+ V(MathAbsLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(J)J") \
+ V(MathAbsInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(I)I") \
+ V(MathMinDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(DD)D") \
+ V(MathMinFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(FF)F") \
+ V(MathMinLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(JJ)J") \
+ V(MathMinIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(II)I") \
+ V(MathMaxDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(DD)D") \
+ V(MathMaxFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(FF)F") \
+ V(MathMaxLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(JJ)J") \
+ V(MathMaxIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(II)I") \
+ V(MathCos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cos", "(D)D") \
+ V(MathSin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sin", "(D)D") \
+ V(MathAcos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "acos", "(D)D") \
+ V(MathAsin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "asin", "(D)D") \
+ V(MathAtan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan", "(D)D") \
+ V(MathAtan2, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "atan2", "(DD)D") \
+ V(MathCbrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cbrt", "(D)D") \
+ V(MathCosh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cosh", "(D)D") \
+ V(MathExp, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "exp", "(D)D") \
+ V(MathExpm1, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "expm1", "(D)D") \
+ V(MathHypot, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "hypot", "(DD)D") \
+ V(MathLog, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log", "(D)D") \
+ V(MathLog10, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "log10", "(D)D") \
+ V(MathNextAfter, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "nextAfter", "(DD)D") \
+ V(MathSinh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sinh", "(D)D") \
+ V(MathTan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tan", "(D)D") \
+ V(MathTanh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "tanh", "(D)D") \
+ V(MathSqrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sqrt", "(D)D") \
+ V(MathCeil, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "ceil", "(D)D") \
+ V(MathFloor, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "floor", "(D)D") \
+ V(MathRint, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "rint", "(D)D") \
+ V(MathRoundDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(D)J") \
+ V(MathRoundFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(F)I") \
+ V(SystemArrayCopyChar, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "([CI[CII)V") \
+ V(SystemArrayCopy, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V") \
+ V(ThreadCurrentThread, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow, "Ljava/lang/Thread;", "currentThread", "()Ljava/lang/Thread;") \
+ V(MemoryPeekByte, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekByte", "(J)B") \
+ V(MemoryPeekIntNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekIntNative", "(J)I") \
+ V(MemoryPeekLongNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekLongNative", "(J)J") \
+ V(MemoryPeekShortNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Llibcore/io/Memory;", "peekShortNative", "(J)S") \
+ V(MemoryPokeByte, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeByte", "(JB)V") \
+ V(MemoryPokeIntNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeIntNative", "(JI)V") \
+ V(MemoryPokeLongNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeLongNative", "(JJ)V") \
+ V(MemoryPokeShortNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow, "Llibcore/io/Memory;", "pokeShortNative", "(JS)V") \
+ V(StringCharAt, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \
+ V(StringCompareTo, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I") \
+ V(StringEquals, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z") \
+ V(StringGetCharsNoCheck, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "getCharsNoCheck", "(II[CI)V") \
+ V(StringIndexOf, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(I)I") \
+ V(StringIndexOfAfter, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(II)I") \
+ V(StringIsEmpty, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \
+ V(StringLength, kVirtual, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \
+ V(StringNewStringFromBytes, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromBytes", "([BIII)Ljava/lang/String;") \
+ V(StringNewStringFromChars, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromChars", "(II[C)Ljava/lang/String;") \
+ V(StringNewStringFromString, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromString", "(Ljava/lang/String;)Ljava/lang/String;") \
+ V(UnsafeCASInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \
+ V(UnsafeCASLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \
+ V(UnsafeCASObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
+ V(UnsafeGet, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getInt", "(Ljava/lang/Object;J)I") \
+ V(UnsafeGetVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getIntVolatile", "(Ljava/lang/Object;J)I") \
+ V(UnsafeGetObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
+ V(UnsafeGetObjectVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;") \
+ V(UnsafeGetLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLong", "(Ljava/lang/Object;J)J") \
+ V(UnsafeGetLongVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLongVolatile", "(Ljava/lang/Object;J)J") \
+ V(UnsafePut, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putInt", "(Ljava/lang/Object;JI)V") \
+ V(UnsafePutOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedInt", "(Ljava/lang/Object;JI)V") \
+ V(UnsafePutVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putIntVolatile", "(Ljava/lang/Object;JI)V") \
+ V(UnsafePutObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+ V(UnsafePutObjectOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+ V(UnsafePutObjectVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V") \
+ V(UnsafePutLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLong", "(Ljava/lang/Object;JJ)V") \
+ V(UnsafePutLongOrdered, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedLong", "(Ljava/lang/Object;JJ)V") \
+ V(UnsafePutLongVolatile, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLongVolatile", "(Ljava/lang/Object;JJ)V") \
+ V(UnsafeGetAndAddInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddInt", "(Ljava/lang/Object;JI)I") \
+ V(UnsafeGetAndAddLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddLong", "(Ljava/lang/Object;JJ)J") \
+ V(UnsafeGetAndSetInt, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \
+ V(UnsafeGetAndSetLong, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \
+ V(UnsafeGetAndSetObject, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetObject", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \
+ V(UnsafeLoadFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \
+ V(UnsafeStoreFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \
+ V(UnsafeFullFence, kVirtual, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \
+ V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;")
+
+#endif // ART_COMPILER_INTRINSICS_LIST_H_
+#undef ART_COMPILER_INTRINSICS_LIST_H_ // #define is only for lint.
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 16a19eb..4ef2db8 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -150,11 +150,9 @@
instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines());
}
cumulative_logger_.reset(new CumulativeLogger("jit times"));
- method_inliner_map_.reset(new DexFileToMethodInlinerMap);
compiler_driver_.reset(new CompilerDriver(
compiler_options_.get(),
/* verification_results */ nullptr,
- method_inliner_map_.get(),
Compiler::kOptimizing,
instruction_set,
instruction_set_features_.get(),
diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h
index 18e3155..ea2747c 100644
--- a/compiler/jit/jit_compiler.h
+++ b/compiler/jit/jit_compiler.h
@@ -19,7 +19,6 @@
#include "base/mutex.h"
#include "compiled_method.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
@@ -49,7 +48,6 @@
private:
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<CumulativeLogger> cumulative_logger_;
- std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
std::unique_ptr<File> perf_file_;
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index b692c6d..19d55a3 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -36,7 +36,7 @@
#include "nativeloader/native_loader.h"
#include "runtime.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_bar(JNIEnv*, jobject, jint count) {
@@ -238,7 +238,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
// Compile the native method before starting the runtime
mirror::Class* c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader);
const auto pointer_size = class_linker_->GetImagePointerSize();
@@ -431,6 +431,7 @@
TEST_F(JniCompilerTest, TestName ## CriticalGeneric) { \
SCOPED_TRACE("@CriticalNative JNI with generic"); \
gCurrentJni = static_cast<uint32_t>(JniKind::kCritical); \
+ SetCheckGenericJni(true); \
TestName ## Impl(); \
}
@@ -1139,8 +1140,8 @@
// Build stack trace
jobject internal = Thread::Current()->CreateInternalStackTrace<false>(soa);
jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(soa, internal);
- mirror::ObjectArray<mirror::StackTraceElement>* trace_array =
- soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
+ ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> trace_array =
+ soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>>(ste_array);
EXPECT_TRUE(trace_array != nullptr);
EXPECT_EQ(11, trace_array->GetLength());
@@ -1204,7 +1205,7 @@
// Add 10 local references
ScopedObjectAccess soa(env);
for (int i = 0; i < 10; i++) {
- soa.AddLocalReference<jobject>(soa.Decode<mirror::Object*>(thisObj));
+ soa.AddLocalReference<jobject>(soa.Decode<mirror::Object>(thisObj));
}
return x+1;
}
@@ -1282,7 +1283,7 @@
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
- EXPECT_TRUE(self->HoldsLock(soa.Decode<mirror::Object*>(thisObj)));
+ EXPECT_TRUE(self->HoldsLock(soa.Decode<mirror::Object>(thisObj).Decode()));
return nullptr;
}
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index 01278b0..0151789 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -22,7 +22,6 @@
#include "base/array_ref.h"
#include "base/macros.h"
#include "compiled_method.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
@@ -43,10 +42,8 @@
RelativePatcherTest(InstructionSet instruction_set, const std::string& variant)
: compiler_options_(),
verification_results_(&compiler_options_),
- inliner_map_(),
driver_(&compiler_options_,
&verification_results_,
- &inliner_map_,
Compiler::kQuick,
instruction_set,
/* instruction_set_features*/ nullptr,
@@ -267,7 +264,6 @@
CompilerOptions compiler_options_;
VerificationResults verification_results_;
- DexFileToMethodInlinerMap inliner_map_;
CompilerDriver driver_; // Needed for constructing CompiledMethod.
std::string error_msg_;
InstructionSet instruction_set_;
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index ea31672..3fddbde 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -23,7 +23,6 @@
#include "compiled_method.h"
#include "compiler.h"
#include "debug/method_debug_info.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
@@ -38,7 +37,7 @@
#include "mirror/object_array-inl.h"
#include "oat_file-inl.h"
#include "oat_writer.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "utils/test_dex_file_builder.h"
namespace art {
@@ -100,15 +99,12 @@
compiler_options_->ParseCompilerOption(option, Usage);
}
verification_results_.reset(new VerificationResults(compiler_options_.get()));
- method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
- method_inliner_map_.get(),
CompilerCallbacks::CallbackMode::kCompileApp));
Runtime::Current()->SetCompilerCallbacks(callbacks_.get());
timer_.reset(new CumulativeLogger("Compilation times"));
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
- method_inliner_map_.get(),
compiler_kind,
insn_set,
insn_features_.get(),
@@ -502,7 +498,8 @@
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
for (const DexFile* dex_file : dex_files) {
ScopedObjectAccess soa(Thread::Current());
- class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader*>(class_loader));
+ class_linker->RegisterDexFile(*dex_file,
+ soa.Decode<mirror::ClassLoader>(class_loader).Decode());
}
compiler_driver_->SetDexFilesForOatFile(dex_files);
compiler_driver_->CompileAll(class_loader, dex_files, &timings);
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 02eacbc..44c26ed 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -50,7 +50,7 @@
#include "oat_quick_method_header.h"
#include "os.h"
#include "safe_map.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "type_lookup_table.h"
#include "utils/dex_cache_arrays_layout-inl.h"
#include "vdex_file.h"
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index f21dc0e..af2fe9c 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -41,7 +41,7 @@
#include "sharpening.h"
#include "ssa_builder.h"
#include "ssa_phi_elimination.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
namespace art {
@@ -1321,7 +1321,7 @@
HConstantFolding fold(callee_graph);
HSharpening sharpening(callee_graph, codegen_, dex_compilation_unit, compiler_driver_);
InstructionSimplifier simplify(callee_graph, stats_);
- IntrinsicsRecognizer intrinsics(callee_graph, compiler_driver_, stats_);
+ IntrinsicsRecognizer intrinsics(callee_graph, stats_);
HOptimization* optimizations[] = {
&intrinsics,
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 3b08d9f..f7d67db 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -22,7 +22,7 @@
#include "dex_instruction-inl.h"
#include "driver/compiler_options.h"
#include "imtable-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -675,7 +675,7 @@
ClassLinker* class_linker = dex_compilation_unit_->GetClassLinker();
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
+ soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader())));
Handle<mirror::Class> compiling_class(hs.NewHandle(GetCompilingClass()));
// We fetch the referenced class eagerly (that is, the class pointed by in the MethodId
// at method_idx), as `CanAccessResolvedMethod` expects it be be in the dex cache.
@@ -1284,7 +1284,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(compilation_unit.GetClassLoader())));
+ soa.Decode<mirror::ClassLoader>(compilation_unit.GetClassLoader())));
Handle<mirror::DexCache> dex_cache = compilation_unit.GetDexCache();
return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit);
@@ -1303,7 +1303,7 @@
StackHandleScope<3> hs(soa.Self());
Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache();
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
+ soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader())));
Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
@@ -1344,7 +1344,7 @@
StackHandleScope<3> hs(soa.Self());
Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache();
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
+ soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader())));
ArtField* resolved_field = compiler_driver_->ResolveField(
soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true);
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index ff829af..3bb1c1d 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -18,7 +18,7 @@
#include "intrinsics.h"
#include "mirror/class-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 4d4bbcf..412ccfc 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -18,14 +18,11 @@
#include "art_method.h"
#include "class_linker.h"
-#include "dex/quick/dex_file_method_inliner.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "invoke_type.h"
#include "mirror/dex_cache-inl.h"
#include "nodes.h"
-#include "quick/inline_method_analyser.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"
@@ -36,7 +33,7 @@
switch (i) {
case Intrinsics::kNone:
return kInterface; // Non-sensical for intrinsic.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
return IsStatic;
#include "intrinsics_list.h"
@@ -52,7 +49,7 @@
switch (i) {
case Intrinsics::kNone:
return kNeedsEnvironmentOrCache; // Non-sensical for intrinsic.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
return NeedsEnvironmentOrCache;
#include "intrinsics_list.h"
@@ -68,7 +65,7 @@
switch (i) {
case Intrinsics::kNone:
return kAllSideEffects;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
return SideEffects;
#include "intrinsics_list.h"
@@ -84,7 +81,7 @@
switch (i) {
case Intrinsics::kNone:
return kCanThrow;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
return Exceptions;
#include "intrinsics_list.h"
@@ -95,430 +92,7 @@
return kCanThrow;
}
-static Primitive::Type GetType(uint64_t data, bool is_op_size) {
- if (is_op_size) {
- switch (static_cast<OpSize>(data)) {
- case kSignedByte:
- return Primitive::kPrimByte;
- case kSignedHalf:
- return Primitive::kPrimShort;
- case k32:
- return Primitive::kPrimInt;
- case k64:
- return Primitive::kPrimLong;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << data;
- UNREACHABLE();
- }
- } else {
- if ((data & kIntrinsicFlagIsLong) != 0) {
- return Primitive::kPrimLong;
- }
- if ((data & kIntrinsicFlagIsObject) != 0) {
- return Primitive::kPrimNot;
- }
- return Primitive::kPrimInt;
- }
-}
-
-static Intrinsics GetIntrinsic(InlineMethod method) {
- switch (method.opcode) {
- // Floating-point conversions.
- case kIntrinsicDoubleCvt:
- return ((method.d.data & kIntrinsicFlagToFloatingPoint) == 0) ?
- Intrinsics::kDoubleDoubleToRawLongBits : Intrinsics::kDoubleLongBitsToDouble;
- case kIntrinsicFloatCvt:
- return ((method.d.data & kIntrinsicFlagToFloatingPoint) == 0) ?
- Intrinsics::kFloatFloatToRawIntBits : Intrinsics::kFloatIntBitsToFloat;
- case kIntrinsicFloat2Int:
- return Intrinsics::kFloatFloatToIntBits;
- case kIntrinsicDouble2Long:
- return Intrinsics::kDoubleDoubleToLongBits;
-
- // Floating-point tests.
- case kIntrinsicFloatIsInfinite:
- return Intrinsics::kFloatIsInfinite;
- case kIntrinsicDoubleIsInfinite:
- return Intrinsics::kDoubleIsInfinite;
- case kIntrinsicFloatIsNaN:
- return Intrinsics::kFloatIsNaN;
- case kIntrinsicDoubleIsNaN:
- return Intrinsics::kDoubleIsNaN;
-
- // Bit manipulations.
- case kIntrinsicReverseBits:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerReverse;
- case Primitive::kPrimLong:
- return Intrinsics::kLongReverse;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicReverseBytes:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimShort:
- return Intrinsics::kShortReverseBytes;
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerReverseBytes;
- case Primitive::kPrimLong:
- return Intrinsics::kLongReverseBytes;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicRotateRight:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerRotateRight;
- case Primitive::kPrimLong:
- return Intrinsics::kLongRotateRight;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicRotateLeft:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerRotateLeft;
- case Primitive::kPrimLong:
- return Intrinsics::kLongRotateLeft;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
-
- // Misc data processing.
- case kIntrinsicBitCount:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerBitCount;
- case Primitive::kPrimLong:
- return Intrinsics::kLongBitCount;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicCompare:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerCompare;
- case Primitive::kPrimLong:
- return Intrinsics::kLongCompare;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicHighestOneBit:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerHighestOneBit;
- case Primitive::kPrimLong:
- return Intrinsics::kLongHighestOneBit;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicLowestOneBit:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerLowestOneBit;
- case Primitive::kPrimLong:
- return Intrinsics::kLongLowestOneBit;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicNumberOfLeadingZeros:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerNumberOfLeadingZeros;
- case Primitive::kPrimLong:
- return Intrinsics::kLongNumberOfLeadingZeros;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicNumberOfTrailingZeros:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerNumberOfTrailingZeros;
- case Primitive::kPrimLong:
- return Intrinsics::kLongNumberOfTrailingZeros;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicSignum:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimInt:
- return Intrinsics::kIntegerSignum;
- case Primitive::kPrimLong:
- return Intrinsics::kLongSignum;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
-
- // Abs.
- case kIntrinsicAbsDouble:
- return Intrinsics::kMathAbsDouble;
- case kIntrinsicAbsFloat:
- return Intrinsics::kMathAbsFloat;
- case kIntrinsicAbsInt:
- return Intrinsics::kMathAbsInt;
- case kIntrinsicAbsLong:
- return Intrinsics::kMathAbsLong;
-
- // Min/max.
- case kIntrinsicMinMaxDouble:
- return ((method.d.data & kIntrinsicFlagMin) == 0) ?
- Intrinsics::kMathMaxDoubleDouble : Intrinsics::kMathMinDoubleDouble;
- case kIntrinsicMinMaxFloat:
- return ((method.d.data & kIntrinsicFlagMin) == 0) ?
- Intrinsics::kMathMaxFloatFloat : Intrinsics::kMathMinFloatFloat;
- case kIntrinsicMinMaxInt:
- return ((method.d.data & kIntrinsicFlagMin) == 0) ?
- Intrinsics::kMathMaxIntInt : Intrinsics::kMathMinIntInt;
- case kIntrinsicMinMaxLong:
- return ((method.d.data & kIntrinsicFlagMin) == 0) ?
- Intrinsics::kMathMaxLongLong : Intrinsics::kMathMinLongLong;
-
- // More math builtins.
- case kIntrinsicCos:
- return Intrinsics::kMathCos;
- case kIntrinsicSin:
- return Intrinsics::kMathSin;
- case kIntrinsicAcos:
- return Intrinsics::kMathAcos;
- case kIntrinsicAsin:
- return Intrinsics::kMathAsin;
- case kIntrinsicAtan:
- return Intrinsics::kMathAtan;
- case kIntrinsicAtan2:
- return Intrinsics::kMathAtan2;
- case kIntrinsicCbrt:
- return Intrinsics::kMathCbrt;
- case kIntrinsicCosh:
- return Intrinsics::kMathCosh;
- case kIntrinsicExp:
- return Intrinsics::kMathExp;
- case kIntrinsicExpm1:
- return Intrinsics::kMathExpm1;
- case kIntrinsicHypot:
- return Intrinsics::kMathHypot;
- case kIntrinsicLog:
- return Intrinsics::kMathLog;
- case kIntrinsicLog10:
- return Intrinsics::kMathLog10;
- case kIntrinsicNextAfter:
- return Intrinsics::kMathNextAfter;
- case kIntrinsicSinh:
- return Intrinsics::kMathSinh;
- case kIntrinsicTan:
- return Intrinsics::kMathTan;
- case kIntrinsicTanh:
- return Intrinsics::kMathTanh;
-
- // Misc math.
- case kIntrinsicSqrt:
- return Intrinsics::kMathSqrt;
- case kIntrinsicCeil:
- return Intrinsics::kMathCeil;
- case kIntrinsicFloor:
- return Intrinsics::kMathFloor;
- case kIntrinsicRint:
- return Intrinsics::kMathRint;
- case kIntrinsicRoundDouble:
- return Intrinsics::kMathRoundDouble;
- case kIntrinsicRoundFloat:
- return Intrinsics::kMathRoundFloat;
-
- // System.arraycopy.
- case kIntrinsicSystemArrayCopyCharArray:
- return Intrinsics::kSystemArrayCopyChar;
-
- case kIntrinsicSystemArrayCopy:
- return Intrinsics::kSystemArrayCopy;
-
- // Thread.currentThread.
- case kIntrinsicCurrentThread:
- return Intrinsics::kThreadCurrentThread;
-
- // Memory.peek.
- case kIntrinsicPeek:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimByte:
- return Intrinsics::kMemoryPeekByte;
- case Primitive::kPrimShort:
- return Intrinsics::kMemoryPeekShortNative;
- case Primitive::kPrimInt:
- return Intrinsics::kMemoryPeekIntNative;
- case Primitive::kPrimLong:
- return Intrinsics::kMemoryPeekLongNative;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
-
- // Memory.poke.
- case kIntrinsicPoke:
- switch (GetType(method.d.data, true)) {
- case Primitive::kPrimByte:
- return Intrinsics::kMemoryPokeByte;
- case Primitive::kPrimShort:
- return Intrinsics::kMemoryPokeShortNative;
- case Primitive::kPrimInt:
- return Intrinsics::kMemoryPokeIntNative;
- case Primitive::kPrimLong:
- return Intrinsics::kMemoryPokeLongNative;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
-
- // String.
- case kIntrinsicCharAt:
- return Intrinsics::kStringCharAt;
- case kIntrinsicCompareTo:
- return Intrinsics::kStringCompareTo;
- case kIntrinsicEquals:
- return Intrinsics::kStringEquals;
- case kIntrinsicGetCharsNoCheck:
- return Intrinsics::kStringGetCharsNoCheck;
- case kIntrinsicIsEmptyOrLength:
- return ((method.d.data & kIntrinsicFlagIsEmpty) == 0) ?
- Intrinsics::kStringLength : Intrinsics::kStringIsEmpty;
- case kIntrinsicIndexOf:
- return ((method.d.data & kIntrinsicFlagBase0) == 0) ?
- Intrinsics::kStringIndexOfAfter : Intrinsics::kStringIndexOf;
- case kIntrinsicNewStringFromBytes:
- return Intrinsics::kStringNewStringFromBytes;
- case kIntrinsicNewStringFromChars:
- return Intrinsics::kStringNewStringFromChars;
- case kIntrinsicNewStringFromString:
- return Intrinsics::kStringNewStringFromString;
-
- case kIntrinsicCas:
- switch (GetType(method.d.data, false)) {
- case Primitive::kPrimNot:
- return Intrinsics::kUnsafeCASObject;
- case Primitive::kPrimInt:
- return Intrinsics::kUnsafeCASInt;
- case Primitive::kPrimLong:
- return Intrinsics::kUnsafeCASLong;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- case kIntrinsicUnsafeGet: {
- const bool is_volatile = (method.d.data & kIntrinsicFlagIsVolatile);
- switch (GetType(method.d.data, false)) {
- case Primitive::kPrimInt:
- return is_volatile ? Intrinsics::kUnsafeGetVolatile : Intrinsics::kUnsafeGet;
- case Primitive::kPrimLong:
- return is_volatile ? Intrinsics::kUnsafeGetLongVolatile : Intrinsics::kUnsafeGetLong;
- case Primitive::kPrimNot:
- return is_volatile ? Intrinsics::kUnsafeGetObjectVolatile : Intrinsics::kUnsafeGetObject;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- }
- case kIntrinsicUnsafePut: {
- enum Sync { kNoSync, kVolatile, kOrdered };
- const Sync sync =
- ((method.d.data & kIntrinsicFlagIsVolatile) != 0) ? kVolatile :
- ((method.d.data & kIntrinsicFlagIsOrdered) != 0) ? kOrdered :
- kNoSync;
- switch (GetType(method.d.data, false)) {
- case Primitive::kPrimInt:
- switch (sync) {
- case kNoSync:
- return Intrinsics::kUnsafePut;
- case kVolatile:
- return Intrinsics::kUnsafePutVolatile;
- case kOrdered:
- return Intrinsics::kUnsafePutOrdered;
- }
- break;
- case Primitive::kPrimLong:
- switch (sync) {
- case kNoSync:
- return Intrinsics::kUnsafePutLong;
- case kVolatile:
- return Intrinsics::kUnsafePutLongVolatile;
- case kOrdered:
- return Intrinsics::kUnsafePutLongOrdered;
- }
- break;
- case Primitive::kPrimNot:
- switch (sync) {
- case kNoSync:
- return Intrinsics::kUnsafePutObject;
- case kVolatile:
- return Intrinsics::kUnsafePutObjectVolatile;
- case kOrdered:
- return Intrinsics::kUnsafePutObjectOrdered;
- }
- break;
- default:
- LOG(FATAL) << "Unknown/unsupported op size " << method.d.data;
- UNREACHABLE();
- }
- break;
- }
-
- // 1.8.
- case kIntrinsicUnsafeGetAndAddInt:
- return Intrinsics::kUnsafeGetAndAddInt;
- case kIntrinsicUnsafeGetAndAddLong:
- return Intrinsics::kUnsafeGetAndAddLong;
- case kIntrinsicUnsafeGetAndSetInt:
- return Intrinsics::kUnsafeGetAndSetInt;
- case kIntrinsicUnsafeGetAndSetLong:
- return Intrinsics::kUnsafeGetAndSetLong;
- case kIntrinsicUnsafeGetAndSetObject:
- return Intrinsics::kUnsafeGetAndSetObject;
- case kIntrinsicUnsafeLoadFence:
- return Intrinsics::kUnsafeLoadFence;
- case kIntrinsicUnsafeStoreFence:
- return Intrinsics::kUnsafeStoreFence;
- case kIntrinsicUnsafeFullFence:
- return Intrinsics::kUnsafeFullFence;
-
- // Virtual cases.
-
- case kIntrinsicReferenceGetReferent:
- return Intrinsics::kReferenceGetReferent;
-
- // Quick inliner cases. Remove after refactoring. They are here so that we can use the
- // compiler to warn on missing cases.
-
- case kInlineOpNop:
- case kInlineOpReturnArg:
- case kInlineOpNonWideConst:
- case kInlineOpIGet:
- case kInlineOpIPut:
- case kInlineOpConstructor:
- return Intrinsics::kNone;
-
- // String init cases, not intrinsics.
-
- case kInlineStringInit:
- return Intrinsics::kNone;
-
- // No default case to make the compiler warn on missing cases.
- }
- return Intrinsics::kNone;
-}
-
-static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke, const DexFile& dex_file) {
- // The DexFileMethodInliner should have checked whether the methods are agreeing with
- // what we expect, i.e., static methods are called as such. Add another check here for
- // our expectations:
- //
+static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke) {
// Whenever the intrinsic is marked as static, report an error if we find an InvokeVirtual.
//
// Whenever the intrinsic is marked as direct and we find an InvokeVirtual, a devirtualization
@@ -542,13 +116,9 @@
return true;
}
if (invoke_type == kVirtual) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ArtMethod* art_method = invoke->GetResolvedMethod();
ScopedObjectAccess soa(Thread::Current());
- ArtMethod* art_method =
- class_linker->FindDexCache(soa.Self(), dex_file)->GetResolvedMethod(
- invoke->GetDexMethodIndex(), class_linker->GetImagePointerSize());
- return art_method != nullptr &&
- (art_method->IsFinal() || art_method->GetDeclaringClass()->IsFinal());
+ return (art_method->IsFinal() || art_method->GetDeclaringClass()->IsFinal());
}
return false;
@@ -561,8 +131,8 @@
}
}
-// TODO: Refactor DexFileMethodInliner and have something nicer than InlineMethod.
void IntrinsicsRecognizer::Run() {
+ ScopedObjectAccess soa(Thread::Current());
for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
HBasicBlock* block = it.Current();
for (HInstructionIterator inst_it(block->GetInstructions()); !inst_it.Done();
@@ -570,26 +140,20 @@
HInstruction* inst = inst_it.Current();
if (inst->IsInvoke()) {
HInvoke* invoke = inst->AsInvoke();
- InlineMethod method;
- const DexFile& dex_file = invoke->GetDexFile();
- DexFileMethodInliner* inliner = driver_->GetMethodInlinerMap()->GetMethodInliner(&dex_file);
- DCHECK(inliner != nullptr);
- if (inliner->IsIntrinsic(invoke->GetDexMethodIndex(), &method)) {
- Intrinsics intrinsic = GetIntrinsic(method);
-
- if (intrinsic != Intrinsics::kNone) {
- if (!CheckInvokeType(intrinsic, invoke, dex_file)) {
- LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
- << intrinsic << " for "
- << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile())
- << invoke->DebugName();
- } else {
- invoke->SetIntrinsic(intrinsic,
- NeedsEnvironmentOrCache(intrinsic),
- GetSideEffects(intrinsic),
- GetExceptions(intrinsic));
- MaybeRecordStat(MethodCompilationStat::kIntrinsicRecognized);
- }
+ ArtMethod* art_method = invoke->GetResolvedMethod();
+ if (art_method != nullptr && art_method->IsIntrinsic()) {
+ Intrinsics intrinsic = static_cast<Intrinsics>(art_method->GetIntrinsic());
+ if (!CheckInvokeType(intrinsic, invoke)) {
+ LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
+ << intrinsic << " for "
+ << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile())
+ << invoke->DebugName();
+ } else {
+ invoke->SetIntrinsic(intrinsic,
+ NeedsEnvironmentOrCache(intrinsic),
+ GetSideEffects(intrinsic),
+ GetExceptions(intrinsic));
+ MaybeRecordStat(MethodCompilationStat::kIntrinsicRecognized);
}
}
}
@@ -602,7 +166,7 @@
case Intrinsics::kNone:
os << "None";
break;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
os << # Name; \
break;
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index 62f731d..1e73cf6 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -34,17 +34,14 @@
// Recognize intrinsics from HInvoke nodes.
class IntrinsicsRecognizer : public HOptimization {
public:
- IntrinsicsRecognizer(HGraph* graph, CompilerDriver* driver, OptimizingCompilerStats* stats)
- : HOptimization(graph, kIntrinsicsRecognizerPassName, stats),
- driver_(driver) {}
+ IntrinsicsRecognizer(HGraph* graph, OptimizingCompilerStats* stats)
+ : HOptimization(graph, kIntrinsicsRecognizerPassName, stats) {}
void Run() OVERRIDE;
static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition";
private:
- CompilerDriver* driver_;
-
DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer);
};
@@ -58,7 +55,7 @@
switch (invoke->GetIntrinsic()) {
case Intrinsics::kNone:
return;
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, ...) \
case Intrinsics::k ## Name: \
Visit ## Name(invoke); \
return;
@@ -73,7 +70,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, ...) \
virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
}
#include "intrinsics_list.h"
diff --git a/compiler/optimizing/intrinsics_arm.h b/compiler/optimizing/intrinsics_arm.h
index c671700..7f20ea4 100644
--- a/compiler/optimizing/intrinsics_arm.h
+++ b/compiler/optimizing/intrinsics_arm.h
@@ -37,7 +37,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -64,7 +64,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_arm64.h b/compiler/optimizing/intrinsics_arm64.h
index 5251536..28e41cb 100644
--- a/compiler/optimizing/intrinsics_arm64.h
+++ b/compiler/optimizing/intrinsics_arm64.h
@@ -42,7 +42,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -66,7 +66,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_list.h b/compiler/optimizing/intrinsics_list.h
deleted file mode 100644
index db60238..0000000
--- a/compiler/optimizing/intrinsics_list.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_
-#define ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_
-
-// All intrinsics supported by the optimizing compiler. Format is name, then whether it is expected
-// to be a HInvokeStaticOrDirect node (compared to HInvokeVirtual), then whether it requires an
-// environment, may have side effects, or may throw exceptions.
-
-#define INTRINSICS_LIST(V) \
- V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatFloatToIntBits, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatIsInfinite, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatIsNaN, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(FloatIntBitsToFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(IntegerSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongReverse, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongBitCount, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongCompare, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongHighestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongLowestOneBit, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongRotateRight, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongRotateLeft, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(LongSignum, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(ShortReverseBytes, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAbsInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMinIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxDoubleDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxFloatFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxLongLong, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathMaxIntInt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathSin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAcos, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAsin, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAtan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathAtan2, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCbrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCosh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathExp, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathExpm1, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathHypot, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathLog, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathLog10, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathNextAfter, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathSinh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathTan, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathTanh, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathSqrt, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathCeil, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathFloor, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathRint, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathRoundDouble, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MathRoundFloat, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(SystemArrayCopyChar, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(SystemArrayCopy, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(ThreadCurrentThread, kStatic, kNeedsEnvironmentOrCache, kNoSideEffects, kNoThrow) \
- V(MemoryPeekByte, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPeekIntNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPeekLongNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPeekShortNative, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(MemoryPokeByte, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(MemoryPokeIntNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(MemoryPokeLongNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(MemoryPokeShortNative, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kCanThrow) \
- V(StringCharAt, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringCompareTo, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringEquals, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringGetCharsNoCheck, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringIndexOf, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringIndexOfAfter, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kCanThrow) \
- V(StringIsEmpty, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow) \
- V(StringLength, kDirect, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow) \
- V(StringNewStringFromBytes, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(StringNewStringFromChars, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(StringNewStringFromString, kStatic, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeCASInt, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeCASLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeCASObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGet, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetObjectVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetLongVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePut, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutObjectOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutObjectVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutLongOrdered, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafePutLongVolatile, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndAddInt, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndAddLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndSetInt, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndSetLong, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeGetAndSetObject, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeLoadFence, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeStoreFence, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(UnsafeFullFence, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow) \
- V(ReferenceGetReferent, kDirect, kNeedsEnvironmentOrCache, kAllSideEffects, kCanThrow)
-
-#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_
-#undef ART_COMPILER_OPTIMIZING_INTRINSICS_LIST_H_ // #define is only for lint.
diff --git a/compiler/optimizing/intrinsics_mips.h b/compiler/optimizing/intrinsics_mips.h
index 575a7d0..e134cb8 100644
--- a/compiler/optimizing/intrinsics_mips.h
+++ b/compiler/optimizing/intrinsics_mips.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -60,7 +60,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_mips64.h b/compiler/optimizing/intrinsics_mips64.h
index 4137fbd..5b95c26 100644
--- a/compiler/optimizing/intrinsics_mips64.h
+++ b/compiler/optimizing/intrinsics_mips64.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -60,7 +60,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_x86.h b/compiler/optimizing/intrinsics_x86.h
index 08bd197..3743cb1 100644
--- a/compiler/optimizing/intrinsics_x86.h
+++ b/compiler/optimizing/intrinsics_x86.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -61,7 +61,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/intrinsics_x86_64.h b/compiler/optimizing/intrinsics_x86_64.h
index 155ff65..97404aa 100644
--- a/compiler/optimizing/intrinsics_x86_64.h
+++ b/compiler/optimizing/intrinsics_x86_64.h
@@ -36,7 +36,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
@@ -61,7 +61,7 @@
// Define visitor methods.
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
+#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
void Visit ## Name(HInvoke* invoke) OVERRIDE;
#include "intrinsics_list.h"
INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 106b348..cea29bc 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -25,7 +25,7 @@
#include "base/stl_util.h"
#include "intrinsics.h"
#include "mirror/class-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 9c82e17..077e867 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -32,6 +32,7 @@
#include "handle.h"
#include "handle_scope.h"
#include "invoke_type.h"
+#include "intrinsics_enum.h"
#include "locations.h"
#include "method_reference.h"
#include "mirror/class.h"
@@ -3690,17 +3691,6 @@
DISALLOW_COPY_AND_ASSIGN(HNewInstance);
};
-enum class Intrinsics {
-#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions) \
- k ## Name,
-#include "intrinsics_list.h"
- kNone,
- INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
-#undef INTRINSICS_LIST
-#undef OPTIMIZING_INTRINSICS
-};
-std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
-
enum IntrinsicNeedsEnvironmentOrCache {
kNoEnvironmentOrCache, // Intrinsic does not require an environment or dex cache.
kNeedsEnvironmentOrCache // Intrinsic requires an environment or requires a dex cache.
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index c5d7611..d3a55dd 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -56,7 +56,6 @@
#include "dead_code_elimination.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
#include "driver/compiler_driver-inl.h"
@@ -479,7 +478,7 @@
} else if (opt_name == InstructionSimplifier::kInstructionSimplifierPassName) {
return new (arena) InstructionSimplifier(graph, stats, pass_name.c_str());
} else if (opt_name == IntrinsicsRecognizer::kIntrinsicsRecognizerPassName) {
- return new (arena) IntrinsicsRecognizer(graph, driver, stats);
+ return new (arena) IntrinsicsRecognizer(graph, stats);
} else if (opt_name == LICM::kLoopInvariantCodeMotionPassName) {
CHECK(most_recent_side_effects != nullptr);
return new (arena) LICM(graph, *most_recent_side_effects, stats);
@@ -743,7 +742,7 @@
graph, stats, "instruction_simplifier$after_bce");
InstructionSimplifier* simplify3 = new (arena) InstructionSimplifier(
graph, stats, "instruction_simplifier$before_codegen");
- IntrinsicsRecognizer* intrinsics = new (arena) IntrinsicsRecognizer(graph, driver, stats);
+ IntrinsicsRecognizer* intrinsics = new (arena) IntrinsicsRecognizer(graph, stats);
HOptimization* optimizations1[] = {
intrinsics,
@@ -899,7 +898,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(class_loader)));
+ soa.Decode<mirror::ClassLoader>(class_loader)));
method = compiler_driver->ResolveMethod(
soa, dex_cache, loader, &dex_compilation_unit, method_idx, invoke_type);
}
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index dd5cb1c..2a23c92 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -22,7 +22,7 @@
#include "common_compiler_test.h"
#include "dex_file.h"
#include "dex_instruction.h"
-#include "handle_scope-inl.h"
+#include "handle_scope.h"
#include "scoped_thread_state_change.h"
#include "ssa_builder.h"
#include "ssa_liveness_analysis.h"
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 4289cf7..5a47df1 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -20,7 +20,7 @@
#include "class_linker-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index b1e242a..c1cfe8d 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -31,7 +31,7 @@
#include "mirror/string.h"
#include "nodes.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index aa0c249..9cdd24b 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -49,7 +49,6 @@
#include "compiler_callbacks.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "dex_file-inl.h"
@@ -77,7 +76,7 @@
#include "runtime.h"
#include "runtime_options.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "utils.h"
#include "verifier/verifier_deps.h"
#include "well_known_classes.h"
@@ -509,7 +508,6 @@
image_patch_delta_(0),
key_value_store_(nullptr),
verification_results_(nullptr),
- method_inliner_map_(),
runtime_(nullptr),
thread_count_(sysconf(_SC_NPROCESSORS_CONF)),
start_ns_(NanoTime()),
@@ -1370,7 +1368,6 @@
verification_results_.reset(new VerificationResults(compiler_options_.get()));
callbacks_.reset(new QuickCompilerCallbacks(
verification_results_.get(),
- &method_inliner_map_,
IsBootImage() ?
CompilerCallbacks::CallbackMode::kCompileBootImage :
CompilerCallbacks::CallbackMode::kCompileApp));
@@ -1565,7 +1562,7 @@
ScopedObjectAccess soa(self);
dex_caches_.push_back(soa.AddLocalReference<jobject>(
class_linker->RegisterDexFile(*dex_file,
- soa.Decode<mirror::ClassLoader*>(class_loader_))));
+ soa.Decode<mirror::ClassLoader>(class_loader_).Decode())));
}
return true;
@@ -1630,7 +1627,6 @@
driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
- &method_inliner_map_,
compiler_kind_,
instruction_set_,
instruction_set_features_.get(),
@@ -2539,7 +2535,6 @@
std::unique_ptr<VerificationResults> verification_results_;
- DexFileToMethodInlinerMap method_inliner_map_;
std::unique_ptr<QuickCompilerCallbacks> callbacks_;
std::unique_ptr<Runtime> runtime_;
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index 925047f..30b708c 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -116,8 +116,7 @@
public:
CustomDisassembler(std::ostream& os, const DisassemblerOptions* options)
- // vixl::aarch32::Disassembler::~Disassembler() will delete the stream.
- : PrintDisassembler(new CustomDisassemblerStream(os, this, options)) {}
+ : PrintDisassembler(&disassembler_stream_), disassembler_stream_(os, this, options) {}
void PrintPc(uint32_t prog_ctr) OVERRIDE {
os() << "0x" << std::hex << std::setw(8) << std::setfill('0') << prog_ctr << ": ";
@@ -133,6 +132,7 @@
private:
bool is_t32_;
+ CustomDisassemblerStream disassembler_stream_;
};
void DisassemblerArm::CustomDisassembler::CustomDisassemblerStream::PrintLiteral(LocationType type,
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index 106cf2f..ace21aa 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -34,7 +34,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "image.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "os.h"
#include "cmdline.h"
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 7cfd776..f2062c3 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -23,6 +23,7 @@
#include <set>
#include <string>
#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "arch/instruction_set_features.h"
@@ -42,6 +43,7 @@
#include "gc/space/large_object_space.h"
#include "gc/space/space-inl.h"
#include "image-inl.h"
+#include "imtable-inl.h"
#include "indenter.h"
#include "linker/buffered_output_stream.h"
#include "linker/file_output_stream.h"
@@ -55,7 +57,7 @@
#include "oat_file_manager.h"
#include "os.h"
#include "safe_map.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "stack_map.h"
#include "string_reference.h"
@@ -2475,7 +2477,7 @@
// Use the class loader while dumping.
StackHandleScope<1> scope(self);
Handle<mirror::ClassLoader> loader_handle = scope.NewHandle(
- soa.Decode<mirror::ClassLoader*>(class_loader));
+ soa.Decode<mirror::ClassLoader>(class_loader));
options->class_loader_ = &loader_handle;
OatDumper oat_dumper(*oat_file, *options);
@@ -2550,6 +2552,392 @@
return EXIT_SUCCESS;
}
+class IMTDumper {
+ public:
+ static bool DumpImt(Runtime* runtime, const std::string& imt_file) {
+ std::vector<std::string> lines = ReadCommentedInputFromFile(imt_file);
+ std::unordered_set<std::string> prepared;
+
+ for (const std::string& line : lines) {
+ // A line should be either a class descriptor, in which case we will dump the complete IMT,
+ // or a class descriptor and an interface method, in which case we will lookup the method,
+ // determine its IMT slot, and check the class' IMT.
+ size_t first_space = line.find(' ');
+ if (first_space == std::string::npos) {
+ DumpIMTForClass(runtime, line, &prepared);
+ } else {
+ DumpIMTForMethod(runtime,
+ line.substr(0, first_space),
+ line.substr(first_space + 1, std::string::npos),
+ &prepared);
+ }
+ std::cerr << std::endl;
+ }
+
+ return true;
+ }
+
+ static bool DumpImtStats(Runtime* runtime, const std::vector<const DexFile*>& dex_files) {
+ size_t wo_imt = 0;
+ size_t w_imt = 0;
+ std::map<size_t, size_t> histogram;
+
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ const PointerSize pointer_size = class_linker->GetImagePointerSize();
+ std::unordered_set<std::string> prepared;
+
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ StackHandleScope<1> scope(self);
+ MutableHandle<mirror::Class> h_klass(scope.NewHandle<mirror::Class>(nullptr));
+
+ for (const DexFile* dex_file : dex_files) {
+ for (uint32_t class_def_index = 0;
+ class_def_index != dex_file->NumClassDefs();
+ ++class_def_index) {
+ const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+ const char* descriptor = dex_file->GetClassDescriptor(class_def);
+ h_klass.Assign(class_linker->FindClass(self,
+ descriptor,
+ ScopedNullHandle<mirror::ClassLoader>()));
+ if (h_klass.Get() == nullptr) {
+ std::cerr << "Warning: could not load " << descriptor << std::endl;
+ continue;
+ }
+
+ if (HasNoIMT(runtime, h_klass, pointer_size, &prepared)) {
+ wo_imt++;
+ continue;
+ }
+
+ ImTable* im_table = PrepareAndGetImTable(runtime, h_klass, pointer_size, &prepared);
+ if (im_table == nullptr) {
+ // Should not happen, but accept.
+ wo_imt++;
+ continue;
+ }
+
+ w_imt++;
+ for (size_t imt_index = 0; imt_index != ImTable::kSize; ++imt_index) {
+ ArtMethod* ptr = im_table->Get(imt_index, pointer_size);
+ if (ptr->IsRuntimeMethod()) {
+ if (ptr->IsImtUnimplementedMethod()) {
+ histogram[0]++;
+ } else {
+ ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
+ histogram[current_table->NumEntries(pointer_size)]++;
+ }
+ } else {
+ histogram[1]++;
+ }
+ }
+ }
+ }
+
+ std::cerr << "IMT stats:"
+ << std::endl << std::endl;
+
+ std::cerr << " " << w_imt << " classes with IMT."
+ << std::endl << std::endl;
+ std::cerr << " " << wo_imt << " classes without IMT (or copy from Object)."
+ << std::endl << std::endl;
+
+ double sum_one = 0;
+ size_t count_one = 0;
+
+ std::cerr << " " << "IMT histogram" << std::endl;
+ for (auto& bucket : histogram) {
+ std::cerr << " " << bucket.first << " " << bucket.second << std::endl;
+ if (bucket.first > 0) {
+ sum_one += bucket.second * bucket.first;
+ count_one += bucket.second;
+ }
+ }
+
+ double count_zero = count_one + histogram[0];
+ std::cerr << " Stats:" << std::endl;
+ std::cerr << " Average depth (including empty): " << (sum_one / count_zero) << std::endl;
+ std::cerr << " Average depth (excluding empty): " << (sum_one / count_one) << std::endl;
+
+ return true;
+ }
+
+ private:
+ // Check whether the given class has no IMT (or the one shared with java.lang.Object).
+ static bool HasNoIMT(Runtime* runtime,
+ Handle<mirror::Class> klass,
+ const PointerSize pointer_size,
+ std::unordered_set<std::string>* prepared)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (klass->IsObjectClass() || !klass->ShouldHaveImt()) {
+ return true;
+ }
+
+ if (klass->GetImt(pointer_size) == nullptr) {
+ PrepareClass(runtime, klass, prepared);
+ }
+
+ mirror::Class* object_class = mirror::Class::GetJavaLangClass()->GetSuperClass();
+ DCHECK(object_class->IsObjectClass());
+
+ bool result = klass->GetImt(pointer_size) == object_class->GetImt(pointer_size);
+
+ if (klass->GetIfTable() == nullptr) {
+ DCHECK(result);
+ }
+
+ return result;
+ }
+
+ static void PrintTable(ImtConflictTable* table, PointerSize pointer_size)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (table == nullptr) {
+ std::cerr << " <No IMT?>" << std::endl;
+ return;
+ }
+ size_t table_index = 0;
+ for (;;) {
+ ArtMethod* ptr = table->GetInterfaceMethod(table_index, pointer_size);
+ if (ptr == nullptr) {
+ return;
+ }
+ table_index++;
+ std::cerr << " " << PrettyMethod(ptr, true) << std::endl;
+ }
+ }
+
+ static ImTable* PrepareAndGetImTable(Runtime* runtime,
+ Thread* self,
+ const std::string& class_name,
+ const PointerSize pointer_size,
+ mirror::Class** klass_out,
+ std::unordered_set<std::string>* prepared)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (class_name.empty()) {
+ return nullptr;
+ }
+
+ std::string descriptor;
+ if (class_name[0] == 'L') {
+ descriptor = class_name;
+ } else {
+ descriptor = DotToDescriptor(class_name.c_str());
+ }
+
+ ScopedNullHandle<mirror::ClassLoader> null_handle;
+
+ mirror::Class* klass =
+ runtime->GetClassLinker()->FindClass(self, descriptor.c_str(), null_handle);
+
+ if (klass == nullptr) {
+ self->ClearException();
+ std::cerr << "Did not find " << class_name << std::endl;
+ *klass_out = nullptr;
+ return nullptr;
+ }
+
+ StackHandleScope<1> scope(Thread::Current());
+ Handle<mirror::Class> h_klass = scope.NewHandle<mirror::Class>(klass);
+
+ ImTable* ret = PrepareAndGetImTable(runtime, h_klass, pointer_size, prepared);
+ *klass_out = h_klass.Get();
+ return ret;
+ }
+
+ static ImTable* PrepareAndGetImTable(Runtime* runtime,
+ Handle<mirror::Class> h_klass,
+ const PointerSize pointer_size,
+ std::unordered_set<std::string>* prepared)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ PrepareClass(runtime, h_klass, prepared);
+ return h_klass->GetImt(pointer_size);
+ }
+
+ static void DumpIMTForClass(Runtime* runtime,
+ const std::string& class_name,
+ std::unordered_set<std::string>* prepared) {
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+
+ const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+ mirror::Class* klass;
+ ImTable* imt = PrepareAndGetImTable(runtime, self, class_name, pointer_size, &klass, prepared);
+ if (imt == nullptr) {
+ return;
+ }
+
+ std::cerr << class_name << std::endl << " IMT:" << std::endl;
+ for (size_t index = 0; index < ImTable::kSize; ++index) {
+ std::cerr << " " << index << ":" << std::endl;
+ ArtMethod* ptr = imt->Get(index, pointer_size);
+ if (ptr->IsRuntimeMethod()) {
+ if (ptr->IsImtUnimplementedMethod()) {
+ std::cerr << " <empty>" << std::endl;
+ } else {
+ ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
+ PrintTable(current_table, pointer_size);
+ }
+ } else {
+ std::cerr << " " << PrettyMethod(ptr, true) << std::endl;
+ }
+ }
+
+ std::cerr << " Interfaces:" << std::endl;
+ // Run through iftable, find methods that slot here, see if they fit.
+ mirror::IfTable* if_table = klass->GetIfTable();
+ if (if_table != nullptr) {
+ for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
+ mirror::Class* iface = if_table->GetInterface(i);
+ std::string iface_name;
+ std::cerr << " " << iface->GetDescriptor(&iface_name) << std::endl;
+
+ for (ArtMethod& iface_method : iface->GetVirtualMethods(pointer_size)) {
+ uint32_t base_hash = ImTable::GetBaseImtHash(&iface_method);
+ uint32_t imt_slot = ImTable::GetImtIndex(&iface_method);
+ std::cerr << " " << PrettyMethod(&iface_method, true) << " slot=" << std::dec
+ << imt_slot << " base_hash=0x" << std::hex << base_hash << std::endl;
+ }
+ }
+ }
+ }
+
+ static void DumpIMTForMethod(Runtime* runtime,
+ const std::string& class_name,
+ const std::string& method,
+ std::unordered_set<std::string>* prepared) {
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+
+ const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+ mirror::Class* klass;
+ ImTable* imt = PrepareAndGetImTable(runtime,
+ self,
+ class_name,
+ pointer_size,
+ &klass,
+ prepared);
+ if (imt == nullptr) {
+ return;
+ }
+
+ std::cerr << class_name << " <" << method << ">" << std::endl;
+ for (size_t index = 0; index < ImTable::kSize; ++index) {
+ ArtMethod* ptr = imt->Get(index, pointer_size);
+ if (ptr->IsRuntimeMethod()) {
+ if (ptr->IsImtUnimplementedMethod()) {
+ continue;
+ }
+
+ ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
+ if (current_table == nullptr) {
+ continue;
+ }
+
+ size_t table_index = 0;
+ for (;;) {
+ ArtMethod* ptr2 = current_table->GetInterfaceMethod(table_index, pointer_size);
+ if (ptr2 == nullptr) {
+ break;
+ }
+ table_index++;
+
+ std::string p_name = PrettyMethod(ptr2, true);
+ if (StartsWith(p_name, method.c_str())) {
+ std::cerr << " Slot "
+ << index
+ << " ("
+ << current_table->NumEntries(pointer_size)
+ << ")"
+ << std::endl;
+ PrintTable(current_table, pointer_size);
+ return;
+ }
+ }
+ } else {
+ std::string p_name = PrettyMethod(ptr, true);
+ if (StartsWith(p_name, method.c_str())) {
+ std::cerr << " Slot " << index << " (1)" << std::endl;
+ std::cerr << " " << p_name << std::endl;
+ } else {
+ // Run through iftable, find methods that slot here, see if they fit.
+ mirror::IfTable* if_table = klass->GetIfTable();
+ if (if_table != nullptr) {
+ for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
+ mirror::Class* iface = if_table->GetInterface(i);
+ size_t num_methods = iface->NumDeclaredVirtualMethods();
+ if (num_methods > 0) {
+ for (ArtMethod& iface_method : iface->GetMethods(pointer_size)) {
+ if (ImTable::GetImtIndex(&iface_method) == index) {
+ std::string i_name = PrettyMethod(&iface_method, true);
+ if (StartsWith(i_name, method.c_str())) {
+ std::cerr << " Slot " << index << " (1)" << std::endl;
+ std::cerr << " " << p_name << " (" << i_name << ")" << std::endl;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Read lines from the given stream, dropping comments and empty lines
+ static std::vector<std::string> ReadCommentedInputStream(std::istream& in_stream) {
+ std::vector<std::string> output;
+ while (in_stream.good()) {
+ std::string dot;
+ std::getline(in_stream, dot);
+ if (StartsWith(dot, "#") || dot.empty()) {
+ continue;
+ }
+ output.push_back(dot);
+ }
+ return output;
+ }
+
+ // Read lines from the given file, dropping comments and empty lines.
+ static std::vector<std::string> ReadCommentedInputFromFile(const std::string& input_filename) {
+ std::unique_ptr<std::ifstream> input_file(new std::ifstream(input_filename, std::ifstream::in));
+ if (input_file.get() == nullptr) {
+ LOG(ERROR) << "Failed to open input file " << input_filename;
+ return std::vector<std::string>();
+ }
+ std::vector<std::string> result = ReadCommentedInputStream(*input_file);
+ input_file->close();
+ return result;
+ }
+
+ // Prepare a class, i.e., ensure it has a filled IMT. Will do so recursively for superclasses,
+ // and note in the given set that the work was done.
+ static void PrepareClass(Runtime* runtime,
+ Handle<mirror::Class> h_klass,
+ std::unordered_set<std::string>* done)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (!h_klass->ShouldHaveImt()) {
+ return;
+ }
+
+ std::string name;
+ name = h_klass->GetDescriptor(&name);
+
+ if (done->find(name) != done->end()) {
+ return;
+ }
+ done->insert(name);
+
+ if (h_klass->HasSuperClass()) {
+ StackHandleScope<1> h(Thread::Current());
+ PrepareClass(runtime, h.NewHandle<mirror::Class>(h_klass->GetSuperClass()), done);
+ }
+
+ if (!h_klass->IsTemp()) {
+ runtime->GetClassLinker()->FillIMTAndConflictTables(h_klass.Get());
+ }
+ }
+};
+
struct OatdumpArgs : public CmdlineArgs {
protected:
using Base = CmdlineArgs;
@@ -2599,6 +2987,10 @@
app_image_ = option.substr(strlen("--app-image=")).data();
} else if (option.starts_with("--app-oat=")) {
app_oat_ = option.substr(strlen("--app-oat=")).data();
+ } else if (option.starts_with("--dump-imt=")) {
+ imt_dump_ = option.substr(strlen("--dump-imt=")).data();
+ } else if (option == "--dump-imt-stats") {
+ imt_stat_dump_ = true;
} else {
return kParseUnknownArgument;
}
@@ -2695,6 +3087,16 @@
" --addr2instr=<address>: output matching method disassembled code from relative\n"
" address (e.g. PC from crash dump)\n"
" Example: --addr2instr=0x00001a3b\n"
+ "\n"
+ " --dump-imt=<file.txt>: output IMT collisions (if any) for the given receiver\n"
+ " types and interface methods in the given file. The file\n"
+ " is read line-wise, and each line should either be a class\n"
+ " name or descriptor, or a class name/descriptor and a prefix\n"
+ " of a complete method name.\n"
+ " Example: --dump-imt=imt.txt\n"
+ "\n"
+ " --dump-imt-stats: output IMT statistics for the given boot image\n"
+ " Example: --dump-imt-stats"
"\n";
return usage;
@@ -2706,6 +3108,7 @@
const char* method_filter_ = "";
const char* image_location_ = nullptr;
std::string elf_filename_prefix_;
+ std::string imt_dump_;
bool dump_vmap_ = true;
bool dump_code_info_stack_maps_ = false;
bool disassemble_code_ = true;
@@ -2714,6 +3117,7 @@
bool list_classes_ = false;
bool list_methods_ = false;
bool dump_header_only_ = false;
+ bool imt_stat_dump_ = false;
uint32_t addr2instr_ = 0;
const char* export_dex_location_ = nullptr;
const char* app_image_ = nullptr;
@@ -2742,7 +3146,9 @@
args_->app_oat_,
args_->addr2instr_));
- return (args_->boot_image_location_ != nullptr || args_->image_location_ != nullptr) &&
+ return (args_->boot_image_location_ != nullptr ||
+ args_->image_location_ != nullptr ||
+ !args_->imt_dump_.empty()) &&
!args_->symbolize_;
}
@@ -2770,6 +3176,14 @@
virtual bool ExecuteWithRuntime(Runtime* runtime) {
CHECK(args_ != nullptr);
+ if (!args_->imt_dump_.empty()) {
+ return IMTDumper::DumpImt(runtime, args_->imt_dump_);
+ }
+
+ if (args_->imt_stat_dump_) {
+ return IMTDumper::DumpImtStats(runtime, runtime->GetClassLinker()->GetBootClassPath());
+ }
+
if (args_->oat_filename_ != nullptr) {
return DumpOat(runtime,
args_->oat_filename_,
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 1af3660..d58f38c 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -46,7 +46,7 @@
#include "offsets.h"
#include "os.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "utils.h"
diff --git a/runtime/Android.bp b/runtime/Android.bp
index fd9b5b9..31f2490 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -126,6 +126,8 @@
"mirror/executable.cc",
"mirror/field.cc",
"mirror/method.cc",
+ "mirror/method_handle_impl.cc",
+ "mirror/method_type.cc",
"mirror/object.cc",
"mirror/reference.cc",
"mirror/stack_trace_element.cc",
@@ -546,6 +548,7 @@
"mem_map_test.cc",
"memory_region_test.cc",
"mirror/dex_cache_test.cc",
+ "mirror/method_type_test.cc",
"mirror/object_test.cc",
"monitor_pool_test.cc",
"monitor_test.cc",
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 3424e3c..5e39f42 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -26,7 +26,7 @@
#include "linear_alloc.h"
#include "mirror/class-inl.h"
#include "mirror/string-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -1796,7 +1796,7 @@
ScopedObjectAccess soa(self);
StackHandleScope<3> hs(self);
- Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object*>(o)));
+ Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object>(o)));
Handle<mirror::Class> c(hs.NewHandle(obj->GetClass()));
// Need a method as a referrer
ArtMethod* m = c->GetDirectMethod(0, kRuntimePointerSize);
@@ -1995,11 +1995,11 @@
jobject jarray_list = env->NewObject(arraylist_jclass, arraylist_constructor);
ASSERT_NE(nullptr, jarray_list);
- Handle<mirror::Object> array_list(hs.NewHandle(soa.Decode<mirror::Object*>(jarray_list)));
+ Handle<mirror::Object> array_list(hs.NewHandle(soa.Decode<mirror::Object>(jarray_list)));
jobject jobj = env->NewObject(obj_jclass, obj_constructor);
ASSERT_NE(nullptr, jobj);
- Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object*>(jobj)));
+ Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object>(jobj)));
// Invocation tests.
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index ef75f94..ca96169 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -28,7 +28,7 @@
#include "mirror/object-inl.h"
#include "primitive.h"
#include "thread-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index ea5078e..3b4db0b 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -24,7 +24,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "utils.h"
#include "well_known_classes.h"
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 73cce5e..73c6cf1 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -36,7 +36,7 @@
#include "quick/quick_method_frame_info.h"
#include "read_barrier-inl.h"
#include "runtime-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 193bea1..c97c328 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -40,7 +40,7 @@
#include "mirror/object-inl.h"
#include "mirror/string.h"
#include "oat_file-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "well_known_classes.h"
namespace art {
@@ -52,7 +52,7 @@
ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
jobject jlr_method) {
- auto* executable = soa.Decode<mirror::Executable*>(jlr_method);
+ ObjPtr<mirror::Executable> executable = soa.Decode<mirror::Executable>(jlr_method);
DCHECK(executable != nullptr);
return executable->GetArtMethod();
}
@@ -350,7 +350,7 @@
ScopedObjectAccess soa(self);
StackHandleScope<1> shs(self);
- mirror::Class* annotation = soa.Decode<mirror::Class*>(klass);
+ ObjPtr<mirror::Class> annotation = soa.Decode<mirror::Class>(klass);
DCHECK(annotation->IsAnnotation());
Handle<mirror::Class> annotation_handle(shs.NewHandle(annotation));
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 3d2db69..7a8f479 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -137,7 +137,52 @@
return (GetAccessFlags() & kAccFinal) != 0;
}
+ bool IsIntrinsic() {
+ return (GetAccessFlags() & kAccIntrinsic) != 0;
+ }
+
+ void SetIntrinsic(uint32_t intrinsic) {
+ DCHECK(IsUint<8>(intrinsic));
+ uint32_t new_value = (GetAccessFlags() & kAccFlagsNotUsedByIntrinsic) |
+ kAccIntrinsic |
+ (intrinsic << POPCOUNT(kAccFlagsNotUsedByIntrinsic));
+ if (kIsDebugBuild) {
+ uint32_t java_flags = (GetAccessFlags() & kAccJavaFlagsMask);
+ bool is_constructor = IsConstructor();
+ bool is_synchronized = IsSynchronized();
+ bool skip_access_checks = SkipAccessChecks();
+ bool is_fast_native = IsFastNative();
+ bool is_copied = IsCopied();
+ bool is_miranda = IsMiranda();
+ bool is_default = IsDefault();
+ bool is_default_conflict = IsDefaultConflicting();
+ bool is_compilable = IsCompilable();
+ bool must_count_locks = MustCountLocks();
+ SetAccessFlags(new_value);
+ DCHECK_EQ(java_flags, (GetAccessFlags() & kAccJavaFlagsMask));
+ DCHECK_EQ(is_constructor, IsConstructor());
+ DCHECK_EQ(is_synchronized, IsSynchronized());
+ DCHECK_EQ(skip_access_checks, SkipAccessChecks());
+ DCHECK_EQ(is_fast_native, IsFastNative());
+ DCHECK_EQ(is_copied, IsCopied());
+ DCHECK_EQ(is_miranda, IsMiranda());
+ DCHECK_EQ(is_default, IsDefault());
+ DCHECK_EQ(is_default_conflict, IsDefaultConflicting());
+ DCHECK_EQ(is_compilable, IsCompilable());
+ DCHECK_EQ(must_count_locks, MustCountLocks());
+ } else {
+ SetAccessFlags(new_value);
+ }
+ }
+
+ uint32_t GetIntrinsic() {
+ DCHECK(IsIntrinsic());
+ return (GetAccessFlags() >> POPCOUNT(kAccFlagsNotUsedByIntrinsic)) & kAccMaxIntrinsic;
+ }
+
bool IsCopied() {
+ static_assert((kAccCopied & kAccFlagsNotUsedByIntrinsic) == kAccCopied,
+ "kAccCopied conflicts with intrinsic modifier");
const bool copied = (GetAccessFlags() & kAccCopied) != 0;
// (IsMiranda() || IsDefaultConflicting()) implies copied
DCHECK(!(IsMiranda() || IsDefaultConflicting()) || copied)
@@ -146,6 +191,8 @@
}
bool IsMiranda() {
+ static_assert((kAccMiranda & kAccFlagsNotUsedByIntrinsic) == kAccMiranda,
+ "kAccMiranda conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccMiranda) != 0;
}
@@ -156,6 +203,9 @@
}
bool IsCompilable() {
+ if (IsIntrinsic()) {
+ return true;
+ }
return (GetAccessFlags() & kAccCompileDontBother) == 0;
}
@@ -163,11 +213,16 @@
// multiple default methods. It cannot be invoked, throwing an IncompatibleClassChangeError if one
// attempts to do so.
bool IsDefaultConflicting() {
+ if (IsIntrinsic()) {
+ return false;
+ }
return (GetAccessFlags() & kAccDefaultConflict) != 0u;
}
// This is set by the class linker.
bool IsDefault() {
+ static_assert((kAccDefault & kAccFlagsNotUsedByIntrinsic) == kAccDefault,
+ "kAccDefault conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccDefault) != 0;
}
@@ -204,6 +259,9 @@
// Should this method be run in the interpreter and count locks (e.g., failed structured-
// locking verification)?
bool MustCountLocks() {
+ if (IsIntrinsic()) {
+ return false;
+ }
return (GetAccessFlags() & kAccMustCountLocks) != 0;
}
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 9d56954..1183dea 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -26,7 +26,7 @@
#include "base/value_object.h"
#include "mutex-inl.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 8af9fa5..91e31d8 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -78,7 +78,6 @@
kAllocSpaceLock,
kBumpPointerSpaceBlockLock,
kArenaPoolLock,
- kDexFileMethodInlinerLock,
kDexFileToMethodInlinerMapLock,
kInternTableLock,
kOatFileSecondaryLookupLock,
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index a980535..9f07702 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -36,7 +36,7 @@
#include "mirror/string-inl.h"
#include "mirror/throwable.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "well_known_classes.h"
@@ -269,12 +269,12 @@
*/
bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
if (o == nullptr) {
AbortF("field operation on NULL object: %p", java_object);
return false;
}
- if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
+ if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Decode())) {
Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
AbortF("field operation on invalid %s: %p",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
@@ -333,15 +333,15 @@
return false;
}
if (invoke != kVirtual) {
- mirror::Class* c = soa.Decode<mirror::Class*>(jc);
- if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
+ if (!m->GetDeclaringClass()->IsAssignableFrom(c.Decode())) {
AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
PrettyMethod(m).c_str(), PrettyClass(c).c_str());
return false;
}
}
if (invoke != kStatic) {
- mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
if (o == nullptr) {
AbortF("can't call %s on null object", PrettyMethod(m).c_str());
return false;
@@ -360,12 +360,12 @@
*/
bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
ArtField* f = CheckFieldID(soa, fid);
if (f == nullptr) {
return false;
}
- if (f->GetDeclaringClass() != c) {
+ if (c != f->GetDeclaringClass()) {
AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
return false;
}
@@ -387,8 +387,8 @@
if (m == nullptr) {
return false;
}
- mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
- if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
+ if (!m->GetDeclaringClass()->IsAssignableFrom(c.Decode())) {
AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
return false;
}
@@ -408,7 +408,7 @@
if (m == nullptr) {
return false;
}
- mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
if (o == nullptr) {
AbortF("can't call %s on null object", PrettyMethod(m).c_str());
return false;
@@ -557,14 +557,14 @@
bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
+ ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
if (method == nullptr) {
AbortF("expected non-null method");
return false;
}
mirror::Class* c = method->GetClass();
- if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
+ if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
AbortF("expected java.lang.reflect.Method or "
"java.lang.reflect.Constructor but got object of type %s: %p",
PrettyTypeOf(method).c_str(), jmethod);
@@ -589,13 +589,13 @@
bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
+ ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
if (field == nullptr) {
AbortF("expected non-null java.lang.reflect.Field");
return false;
}
mirror::Class* c = field->GetClass();
- if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
+ if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
PrettyTypeOf(field).c_str(), jfield);
return false;
@@ -605,10 +605,10 @@
bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
if (!obj->GetClass()->IsThrowableClass()) {
AbortF("expected java.lang.Throwable but got object of type "
- "%s: %p", PrettyTypeOf(obj).c_str(), obj);
+ "%s: %p", PrettyTypeOf(obj).c_str(), obj.Decode());
return false;
}
return true;
@@ -616,10 +616,10 @@
bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Class* c = soa.Decode<mirror::Class*>(jc);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
if (!c->IsThrowableClass()) {
AbortF("expected java.lang.Throwable class but got object of "
- "type %s: %p", PrettyDescriptor(c).c_str(), c);
+ "type %s: %p", PrettyDescriptor(c).c_str(), c.Decode());
return false;
}
return true;
@@ -647,9 +647,9 @@
bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Class* c = soa.Decode<mirror::Class*>(jc);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
if (!c->IsInstantiableNonArray()) {
- AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
+ AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c.Decode());
return false;
}
return true;
@@ -660,7 +660,7 @@
if (!CheckArray(soa, array)) {
return false;
}
- mirror::Array* a = soa.Decode<mirror::Array*>(array);
+ ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
AbortF("incompatible array type %s expected %s[]: %p",
PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
@@ -692,20 +692,20 @@
return false;
}
if (is_static) {
- mirror::Object* o = soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
if (o == nullptr || !o->IsClass()) {
AbortF("attempt to access static field %s with a class argument of type %s: %p",
PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
return false;
}
- mirror::Class* c = o->AsClass();
- if (field->GetDeclaringClass() != c) {
+ ObjPtr<mirror::Class> c = o->AsClass();
+ if (c != field->GetDeclaringClass()) {
AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
return false;
}
} else {
- mirror::Object* o = soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
AbortF("attempt to access field %s from an object argument of type %s: %p",
PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
@@ -763,7 +763,7 @@
}
}
- mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
if (obj == nullptr) {
// Either java_object is invalid or is a cleared weak.
IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
@@ -772,12 +772,12 @@
okay = false;
} else {
obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
- okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
+ okay = Runtime::Current()->IsClearedJniWeakGlobal(obj.Decode());
}
if (!okay) {
AbortF("%s is an invalid %s: %p (%p)",
what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
- java_object, obj);
+ java_object, obj.Decode());
return false;
}
}
@@ -786,7 +786,7 @@
Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
AbortF("%s is an invalid %s: %p (%p)",
what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
- java_object, obj);
+ java_object, obj.Decode());
return false;
}
@@ -936,10 +936,10 @@
break;
case 'c': { // jclass
jclass jc = arg.c;
- mirror::Class* c = soa.Decode<mirror::Class*>(jc);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
if (c == nullptr) {
*msg += "NULL";
- } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
+ } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Decode())) {
StringAppendF(msg, "INVALID POINTER:%p", jc);
} else if (!c->IsClass()) {
*msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
@@ -1107,12 +1107,12 @@
return false;
}
- mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
- if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
+ ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
+ if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Decode()))) {
Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
AbortF("jarray is an invalid %s: %p (%p)",
ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
- java_array, a);
+ java_array, a.Decode());
return false;
} else if (!a->IsArrayInstance()) {
AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
@@ -1411,7 +1411,7 @@
void* original_ptr) {
ScopedObjectAccess soa(env);
- mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
+ ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
size_t component_size = a->GetClass()->GetComponentSize();
size_t byte_count = a->GetLength() * component_size;
void* result = Create(original_ptr, byte_count, true);
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 843d4c1..ab712f9 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -19,7 +19,7 @@
#include "art_method-inl.h"
#include "oat_quick_method_header.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack_map.h"
namespace art {
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index caabcde..51e5aae 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -67,9 +67,10 @@
// MethodVerifier refuses methods with string_idx out of bounds.
DCHECK_LT(string_idx, declaring_class->GetDexFile().NumStringIds());;
mirror::String* string =
- mirror::StringDexCachePair::LookupString(declaring_class->GetDexCacheStrings(),
- string_idx,
- mirror::DexCache::kDexCacheStringCacheSize).Read();
+ mirror::StringDexCachePair::Lookup(declaring_class->GetDexCacheStrings(),
+ string_idx,
+ mirror::DexCache::kDexCacheStringCacheSize).Read();
+ Thread::PoisonObjectPointersIfDebug();
if (UNLIKELY(string == nullptr)) {
StackHandleScope<1> hs(Thread::Current());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
@@ -84,6 +85,7 @@
inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtMethod* referrer) {
mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx, image_pointer_size_);
+ Thread::PoisonObjectPointersIfDebug();
if (UNLIKELY(resolved_type == nullptr)) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
StackHandleScope<2> hs(Thread::Current());
@@ -101,6 +103,7 @@
mirror::Class* declaring_class = referrer->GetDeclaringClass();
mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache();
mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx);
+ Thread::PoisonObjectPointersIfDebug();
if (UNLIKELY(resolved_type == nullptr)) {
StackHandleScope<2> hs(Thread::Current());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(dex_cache_ptr));
@@ -148,6 +151,7 @@
ArtMethod* referrer,
InvokeType type) {
ArtMethod* resolved_method = GetResolvedMethod(method_idx, referrer);
+ Thread::PoisonObjectPointersIfDebug();
if (UNLIKELY(resolved_method == nullptr)) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
StackHandleScope<2> hs(self);
@@ -179,6 +183,7 @@
bool is_static) {
mirror::Class* declaring_class = referrer->GetDeclaringClass();
ArtField* resolved_field = GetResolvedField(field_idx, declaring_class);
+ Thread::PoisonObjectPointersIfDebug();
if (UNLIKELY(resolved_field == nullptr)) {
StackHandleScope<2> hs(Thread::Current());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c51b99a..0a1f7a9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -73,6 +73,8 @@
#include "mirror/field.h"
#include "mirror/iftable-inl.h"
#include "mirror/method.h"
+#include "mirror/method_type.h"
+#include "mirror/method_handle_impl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/proxy.h"
@@ -89,7 +91,7 @@
#include "os.h"
#include "runtime.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "trace.h"
#include "utils.h"
@@ -636,6 +638,18 @@
SetClassRoot(kJavaLangReflectMethodArrayClass, class_root);
mirror::Method::SetArrayClass(class_root);
+ // Create java.lang.invoke.MethodType.class root
+ class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodType;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangInvokeMethodType, class_root);
+ mirror::MethodType::SetClass(class_root);
+
+ // Create java.lang.invoke.MethodHandleImpl.class root
+ class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandleImpl;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangInvokeMethodHandleImpl, class_root);
+ mirror::MethodHandleImpl::SetClass(class_root);
+
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
// finish initializing Reference class
mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
@@ -1032,6 +1046,8 @@
mirror::Constructor::SetArrayClass(GetClassRoot(kJavaLangReflectConstructorArrayClass));
mirror::Method::SetClass(GetClassRoot(kJavaLangReflectMethod));
mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass));
+ mirror::MethodType::SetClass(GetClassRoot(kJavaLangInvokeMethodType));
+ mirror::MethodHandleImpl::SetClass(GetClassRoot(kJavaLangInvokeMethodHandleImpl));
mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
@@ -1069,8 +1085,8 @@
bool ClassLinker::IsBootClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
mirror::ClassLoader* class_loader) {
return class_loader == nullptr ||
- class_loader->GetClass() ==
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader);
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader) ==
+ class_loader->GetClass();
}
static mirror::String* GetDexPathListElementName(ScopedObjectAccessUnchecked& soa,
@@ -1109,8 +1125,8 @@
CHECK(dex_path_list_field != nullptr);
CHECK(dex_elements_field != nullptr);
while (!ClassLinker::IsBootClassLoader(soa, class_loader)) {
- if (class_loader->GetClass() !=
- soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader)) {
+ if (soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader) !=
+ class_loader->GetClass()) {
*error_msg = StringPrintf("Unknown class loader type %s", PrettyTypeOf(class_loader).c_str());
// Unsupported class loader.
return false;
@@ -1292,8 +1308,8 @@
mirror::StringDexCacheType* const strings =
reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset());
for (size_t j = 0; j < num_strings; ++j) {
- DCHECK_EQ(strings[j].load(std::memory_order_relaxed).string_index, 0u);
- DCHECK(strings[j].load(std::memory_order_relaxed).string_pointer.IsNull());
+ DCHECK_EQ(strings[j].load(std::memory_order_relaxed).index, 0u);
+ DCHECK(strings[j].load(std::memory_order_relaxed).object.IsNull());
strings[j].store(image_resolved_strings[j].load(std::memory_order_relaxed),
std::memory_order_relaxed);
}
@@ -1687,7 +1703,7 @@
return false;
}
// Add the temporary dex path list elements at the end.
- auto* elements = soa.Decode<mirror::ObjectArray<mirror::Object>*>(dex_elements);
+ auto elements = soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements);
for (size_t i = 0, num_elems = elements->GetLength(); i < num_elems; ++i) {
mirror::Object* element = elements->GetWithoutChecks(i);
if (element != nullptr) {
@@ -2032,6 +2048,8 @@
mirror::IntArray::ResetArrayClass();
mirror::LongArray::ResetArrayClass();
mirror::ShortArray::ResetArrayClass();
+ mirror::MethodType::ResetClass();
+ mirror::MethodHandleImpl::ResetClass();
Thread* const self = Thread::Current();
for (const ClassLoaderData& data : class_loaders_) {
DeleteClassLoader(self, data);
@@ -2109,8 +2127,8 @@
if (kIsDebugBuild) {
// Sanity check to make sure all the dex cache arrays are empty. b/28992179
for (size_t i = 0; i < num_strings; ++i) {
- CHECK_EQ(strings[i].load(std::memory_order_relaxed).string_index, 0u);
- CHECK(strings[i].load(std::memory_order_relaxed).string_pointer.IsNull());
+ CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
+ CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
}
for (size_t i = 0; i < dex_file.NumTypeIds(); ++i) {
CHECK(types[i].Read<kWithoutReadBarrier>() == nullptr);
@@ -2169,6 +2187,7 @@
const char* descriptor,
mirror::Class* klass) {
DCHECK(klass != nullptr);
+ Thread::PoisonObjectPointersIfDebug();
// For temporary classes we must wait for them to be retired.
if (init_done_ && klass->IsTemp()) {
@@ -2285,8 +2304,8 @@
}
// Unsupported class-loader?
- if (class_loader->GetClass() !=
- soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader)) {
+ if (soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader) !=
+ class_loader->GetClass()) {
*result = nullptr;
return false;
}
@@ -2380,7 +2399,7 @@
DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
DCHECK(self != nullptr);
self->AssertNoPendingException();
- self->PoisonObjectPointers();
+ self->PoisonObjectPointers(); // For DefineClass, CreateArrayClass, etc...
if (descriptor[1] == '\0') {
// only the descriptors of primitive types should be 1 character long, also avoid class lookup
// for primitive classes that aren't backed by dex files.
@@ -2463,7 +2482,7 @@
return nullptr;
} else {
// success, return mirror::Class*
- return soa.Decode<mirror::Class*>(result.get());
+ return soa.Decode<mirror::Class>(result.get()).Decode();
}
}
UNREACHABLE();
@@ -4186,9 +4205,9 @@
// Set the class access flags incl. VerificationAttempted, so we do not try to set the flag on
// the methods.
klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal | kAccVerificationAttempted);
- klass->SetClassLoader(soa.Decode<mirror::ClassLoader*>(loader));
+ klass->SetClassLoader(soa.Decode<mirror::ClassLoader>(loader).Decode());
DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
- klass->SetName(soa.Decode<mirror::String*>(name));
+ klass->SetName(soa.Decode<mirror::String>(name).Decode());
klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache());
mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self);
std::string descriptor(GetDescriptorForProxy(klass.Get()));
@@ -4226,7 +4245,7 @@
const size_t num_direct_methods = 1;
// They have as many virtual methods as the array
- auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods));
+ auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>>(methods));
DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
<< PrettyClass(h_methods->GetClass());
const size_t num_virtual_methods = h_methods->GetLength();
@@ -4268,7 +4287,7 @@
// Link the fields and virtual methods, creating vtable and iftables.
// The new class will replace the old one in the class table.
Handle<mirror::ObjectArray<mirror::Class>> h_interfaces(
- hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces)));
+ hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces)));
if (!LinkClass(self, descriptor.c_str(), klass, h_interfaces, &new_class)) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
return nullptr;
@@ -4279,11 +4298,13 @@
klass.Assign(new_class.Get());
CHECK_EQ(interfaces_sfield.GetDeclaringClass(), klass.Get());
- interfaces_sfield.SetObject<false>(klass.Get(),
- soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
+ interfaces_sfield.SetObject<false>(
+ klass.Get(),
+ soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces).Decode());
CHECK_EQ(throws_sfield.GetDeclaringClass(), klass.Get());
throws_sfield.SetObject<false>(
- klass.Get(), soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(throws));
+ klass.Get(),
+ soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>>(throws).Decode());
{
// Lock on klass is released. Lock new class object.
@@ -4303,7 +4324,7 @@
}
StackHandleScope<1> hs2(self);
- Handle<mirror::String> decoded_name = hs2.NewHandle(soa.Decode<mirror::String*>(name));
+ Handle<mirror::String> decoded_name = hs2.NewHandle(soa.Decode<mirror::String>(name));
std::string interfaces_field_name(StringPrintf("java.lang.Class[] %s.interfaces",
decoded_name->ToModifiedUtf8().c_str()));
CHECK_EQ(PrettyField(klass->GetStaticField(0)), interfaces_field_name);
@@ -4313,9 +4334,9 @@
CHECK_EQ(PrettyField(klass->GetStaticField(1)), throws_field_name);
CHECK_EQ(klass.Get()->GetInterfaces(),
- soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
+ soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces).Decode());
CHECK_EQ(klass.Get()->GetThrows(),
- soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>*>(throws));
+ soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>>(throws).Decode());
}
return klass.Get();
}
@@ -7526,6 +7547,7 @@
Handle<mirror::DexCache> dex_cache) {
DCHECK(dex_cache.Get() != nullptr);
mirror::String* resolved = dex_cache->GetResolvedString(string_idx);
+ Thread::PoisonObjectPointersIfDebug();
if (resolved != nullptr) {
return resolved;
}
@@ -7568,6 +7590,7 @@
Handle<mirror::ClassLoader> class_loader) {
DCHECK(dex_cache.Get() != nullptr);
mirror::Class* resolved = dex_cache->GetResolvedType(type_idx);
+ Thread::PoisonObjectPointersIfDebug();
if (resolved == nullptr) {
Thread* self = Thread::Current();
const char* descriptor = dex_file.StringByTypeIdx(type_idx);
@@ -7606,6 +7629,7 @@
DCHECK(dex_cache.Get() != nullptr);
// Check for hit in the dex cache.
ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_);
+ Thread::PoisonObjectPointersIfDebug();
if (resolved != nullptr && !resolved->IsRuntimeMethod()) {
DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex();
if (kResolveMode == ClassLinker::kForceICCECheck) {
@@ -7809,6 +7833,7 @@
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_);
+ Thread::PoisonObjectPointersIfDebug();
if (resolved != nullptr && !resolved->IsRuntimeMethod()) {
DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex();
return resolved;
@@ -7841,6 +7866,7 @@
bool is_static) {
DCHECK(dex_cache.Get() != nullptr);
ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
+ Thread::PoisonObjectPointersIfDebug();
if (resolved != nullptr) {
return resolved;
}
@@ -7883,6 +7909,7 @@
Handle<mirror::ClassLoader> class_loader) {
DCHECK(dex_cache.Get() != nullptr);
ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
+ Thread::PoisonObjectPointersIfDebug();
if (resolved != nullptr) {
return resolved;
}
@@ -8064,6 +8091,8 @@
"[Ljava/lang/reflect/Constructor;",
"[Ljava/lang/reflect/Field;",
"[Ljava/lang/reflect/Method;",
+ "Ljava/lang/invoke/MethodHandleImpl;",
+ "Ljava/lang/invoke/MethodType;",
"Ljava/lang/ClassLoader;",
"Ljava/lang/Throwable;",
"Ljava/lang/ClassNotFoundException;",
@@ -8166,7 +8195,7 @@
// Create PathClassLoader.
Handle<mirror::Class> h_path_class_class = hs.NewHandle(
- soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader));
+ soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
Handle<mirror::Object> h_path_class_loader = hs.NewHandle(
h_path_class_class->AllocObject(self));
DCHECK(h_path_class_loader.Get() != nullptr);
@@ -8183,7 +8212,7 @@
"Ljava/lang/ClassLoader;");
DCHECK(parent_field != nullptr);
mirror::Object* boot_cl =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self);
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self);
parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl);
// Make it a global ref and return.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 954af76..8f7051e 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -51,6 +51,7 @@
class DexCachePointerArray;
class DexCacheTest_Open_Test;
class IfTable;
+ class MethodType;
template<class T> class ObjectArray;
class StackTraceElement;
} // namespace mirror
@@ -99,6 +100,8 @@
kJavaLangReflectConstructorArrayClass,
kJavaLangReflectFieldArrayClass,
kJavaLangReflectMethodArrayClass,
+ kJavaLangInvokeMethodHandleImpl,
+ kJavaLangInvokeMethodType,
kJavaLangClassLoader,
kJavaLangThrowable,
kJavaLangClassNotFoundException,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 7023081..a5aa0d0 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -33,6 +33,8 @@
#include "mirror/dex_cache.h"
#include "mirror/executable.h"
#include "mirror/field.h"
+#include "mirror/method_type.h"
+#include "mirror/method_handle_impl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/proxy.h"
@@ -40,7 +42,7 @@
#include "mirror/stack_trace_element.h"
#include "mirror/string-inl.h"
#include "handle_scope-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
@@ -708,6 +710,27 @@
};
};
+struct MethodTypeOffsets : public CheckOffsets<mirror::MethodType> {
+ MethodTypeOffsets() : CheckOffsets<mirror::MethodType>(
+ false, "Ljava/lang/invoke/MethodType;") {
+ addOffset(OFFSETOF_MEMBER(mirror::MethodType, form_), "form");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodType, method_descriptor_), "methodDescriptor");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodType, p_types_), "ptypes");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodType, r_type_), "rtype");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodType, wrap_alt_), "wrapAlt");
+ }
+};
+
+struct MethodHandleImplOffsets : public CheckOffsets<mirror::MethodHandleImpl> {
+ MethodHandleImplOffsets() : CheckOffsets<mirror::MethodHandleImpl>(
+ false, "Ljava/lang/invoke/MethodHandle;") {
+ addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, art_field_or_method_), "artFieldOrMethod");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, as_type_cache_), "asTypeCache");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, handle_kind_), "handleKind");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, method_type_), "type");
+ }
+};
+
// C++ fields must exactly match the fields in the Java classes. If this fails,
// reorder the fields in the C++ class. Managed class fields are ordered by
// ClassLinker::LinkFields.
@@ -726,6 +749,8 @@
EXPECT_TRUE(AccessibleObjectOffsets().Check());
EXPECT_TRUE(FieldOffsets().Check());
EXPECT_TRUE(ExecutableOffsets().Check());
+ EXPECT_TRUE(MethodTypeOffsets().Check());
+ EXPECT_TRUE(MethodHandleImplOffsets().Check());
}
TEST_F(ClassLinkerTest, FindClassNonexistent) {
@@ -752,7 +777,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Nested"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Nested"))));
mirror::Class* outer = class_linker_->FindClass(soa.Self(), "LNested;", class_loader);
ASSERT_TRUE(outer != nullptr);
@@ -786,7 +811,7 @@
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass"))));
AssertNonExistentClass("LMyClass;");
mirror::Class* MyClass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader);
ASSERT_TRUE(MyClass != nullptr);
@@ -912,9 +937,9 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader_1(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass"))));
Handle<mirror::ClassLoader> class_loader_2(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass"))));
mirror::Class* MyClass_1 = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_1);
mirror::Class* MyClass_2 = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_2);
EXPECT_TRUE(MyClass_1 != nullptr);
@@ -926,7 +951,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Statics"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Statics"))));
Handle<mirror::Class> statics(
hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStatics;", class_loader)));
class_linker_->EnsureInitialized(soa.Self(), statics, true, true);
@@ -1003,7 +1028,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<6> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Interfaces"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Interfaces"))));
Handle<mirror::Class> I(
hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader)));
Handle<mirror::Class> J(
@@ -1072,7 +1097,7 @@
const DexFile* dex_file = GetFirstDexFile(jclass_loader);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader);
ArtMethod* clinit = klass->FindClassInitializer(kRuntimePointerSize);
ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;", kRuntimePointerSize);
@@ -1202,7 +1227,7 @@
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Statics"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Statics"))));
Handle<mirror::Class> statics(
hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStatics;", class_loader)));
@@ -1217,7 +1242,7 @@
StackHandleScope<3> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Statics"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Statics"))));
// java.lang.Object is a bootstrap class.
Handle<mirror::Class> jlo_class(
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 11722b2..eda1ddd 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -47,7 +47,7 @@
#include "os.h"
#include "primitive.h"
#include "runtime-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "well_known_classes.h"
@@ -511,12 +511,12 @@
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(jclass_loader));
+ soa.Decode<mirror::ClassLoader>(jclass_loader));
DCHECK_EQ(class_loader->GetClass(),
- soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader));
+ soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader).Decode());
DCHECK_EQ(class_loader->GetParent()->GetClass(),
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader));
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader).Decode());
// The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
// We need to get the DexPathList and loop through it.
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 6ed44fc..0206cae 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -48,7 +48,7 @@
#include "mirror/throwable.h"
#include "reflection.h"
#include "safe_map.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "handle_scope-inl.h"
@@ -390,7 +390,8 @@
return nullptr;
}
- mirror::Class* java_lang_Thread = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
+ ObjPtr<mirror::Class> java_lang_Thread =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread);
if (!java_lang_Thread->IsAssignableFrom(thread_peer->GetClass())) {
// This isn't a thread.
*error = JDWP::ERR_INVALID_THREAD;
@@ -431,21 +432,22 @@
return JDWP::JT_CLASS_OBJECT;
}
{
- mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
+ ObjPtr<mirror::Class> thread_class =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread);
if (thread_class->IsAssignableFrom(c)) {
return JDWP::JT_THREAD;
}
}
{
- mirror::Class* thread_group_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup);
+ ObjPtr<mirror::Class> thread_group_class =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ThreadGroup);
if (thread_group_class->IsAssignableFrom(c)) {
return JDWP::JT_THREAD_GROUP;
}
}
{
- mirror::Class* class_loader_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader);
+ ObjPtr<mirror::Class> class_loader_class =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ClassLoader);
if (class_loader_class->IsAssignableFrom(c)) {
return JDWP::JT_CLASS_LOADER;
}
@@ -1946,7 +1948,8 @@
}
{
ScopedObjectAccessUnchecked soa(Thread::Current());
- mirror::Class* java_lang_String = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_String);
+ ObjPtr<mirror::Class> java_lang_String =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_String);
if (!java_lang_String->IsAssignableFrom(obj->GetClass())) {
// This isn't a string.
return JDWP::ERR_INVALID_STRING;
@@ -2014,7 +2017,7 @@
expandBufAddObjectId(pReply, JDWP::ObjectId(0));
error = JDWP::ERR_NONE;
} else if (error == JDWP::ERR_NONE) {
- mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread);
CHECK(c != nullptr);
ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group);
CHECK(f != nullptr);
@@ -2038,7 +2041,8 @@
*error = JDWP::ERR_INVALID_OBJECT;
return nullptr;
}
- mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup);
+ ObjPtr<mirror::Class> c =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ThreadGroup);
CHECK(c != nullptr);
if (!c->IsAssignableFrom(thread_group->GetClass())) {
// This is not a java.lang.ThreadGroup.
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index e0d5337..5763479 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -255,7 +255,7 @@
}
mirror::Class* annotation_member_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::libcore_reflect_AnnotationMember);
+ soa.Decode<mirror::Class>(WellKnownClasses::libcore_reflect_AnnotationMember).Decode();
mirror::Class* annotation_member_array_class =
class_linker->FindArrayClass(self, &annotation_member_class);
if (annotation_member_array_class == nullptr) {
@@ -572,7 +572,7 @@
*annotation_ptr = annotation;
if (result_style == DexFile::kAllObjects && primitive_type != Primitive::kPrimVoid) {
- element_object = BoxPrimitive(primitive_type, annotation_value->value_);
+ element_object = BoxPrimitive(primitive_type, annotation_value->value_).Decode();
set_object = true;
}
@@ -782,7 +782,7 @@
ScopedObjectAccessUnchecked soa(self);
StackHandleScope<2> hs(self);
Handle<mirror::Class> annotation_array_class(hs.NewHandle(
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array)));
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array)));
if (annotation_set == nullptr) {
return mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), 0);
}
@@ -840,7 +840,7 @@
ScopedObjectAccessUnchecked soa(self);
StackHandleScope<1> hs(self);
mirror::Class* annotation_array_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array).Decode();
mirror::Class* annotation_array_array_class =
Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class);
if (annotation_array_array_class == nullptr) {
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index 8dd5f37..8e1501f 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -24,7 +24,7 @@
#include "dex_file-inl.h"
#include "mem_map.h"
#include "os.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"
diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc
index c5a4d75..e392870 100644
--- a/runtime/dex_file_verifier_test.cc
+++ b/runtime/dex_file_verifier_test.cc
@@ -27,7 +27,7 @@
#include "common_runtime_test.h"
#include "dex_file-inl.h"
#include "leb128.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"
diff --git a/runtime/dex_method_iterator_test.cc b/runtime/dex_method_iterator_test.cc
index 2681ad0..9f28c8c 100644
--- a/runtime/dex_method_iterator_test.cc
+++ b/runtime/dex_method_iterator_test.cc
@@ -19,7 +19,7 @@
#include "base/stl_util.h"
#include "common_runtime_test.h"
#include "oat_file.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index fd9ffbd..38ee468 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -33,7 +33,7 @@
#include "nth_caller_visitor.h"
#include "oat_quick_method_header.h"
#include "reflection.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "well_known_classes.h"
namespace art {
@@ -160,12 +160,12 @@
} else {
JValue jv;
jv.SetJ(args.at(i).j);
- mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
+ mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv).Decode();
if (val == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
return zero;
}
- soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set<false>(i, val);
+ soa.Decode<mirror::ObjectArray<mirror::Object>>(args_jobj)->Set<false>(i, val);
}
}
}
@@ -187,13 +187,13 @@
return zero;
} else {
ArtMethod* interface_method =
- soa.Decode<mirror::Method*>(interface_method_jobj)->GetArtMethod();
+ soa.Decode<mirror::Method>(interface_method_jobj)->GetArtMethod();
// This can cause thread suspension.
PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
mirror::Class* result_type = interface_method->GetReturnType(true /* resolve */, pointer_size);
- mirror::Object* result_ref = soa.Decode<mirror::Object*>(result);
+ ObjPtr<mirror::Object> result_ref = soa.Decode<mirror::Object>(result);
JValue result_unboxed;
- if (!UnboxPrimitiveForResult(result_ref, result_type, &result_unboxed)) {
+ if (!UnboxPrimitiveForResult(result_ref.Decode(), result_type, &result_unboxed)) {
DCHECK(soa.Self()->IsExceptionPending());
return zero;
}
@@ -207,9 +207,9 @@
bool declares_exception = false;
{
ScopedAssertNoThreadSuspension ants(__FUNCTION__);
- mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
+ ObjPtr<mirror::Object> rcvr = soa.Decode<mirror::Object>(rcvr_jobj);
mirror::Class* proxy_class = rcvr->GetClass();
- mirror::Method* interface_method = soa.Decode<mirror::Method*>(interface_method_jobj);
+ ObjPtr<mirror::Method> interface_method = soa.Decode<mirror::Method>(interface_method_jobj);
ArtMethod* proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(
interface_method->GetArtMethod(), kRuntimePointerSize);
auto virtual_methods = proxy_class->GetVirtualMethodsSlice(kRuntimePointerSize);
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index 22226c1..fd23ced 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -18,7 +18,7 @@
#include "base/logging.h"
#include "entrypoints/entrypoint_utils.h"
#include "mirror/object-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
namespace art {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index cfd948e..c52bc8e 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -36,7 +36,7 @@
#include "oat_quick_method_header.h"
#include "quick_exception_handler.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "debugger.h"
@@ -834,7 +834,7 @@
void BuildQuickArgumentVisitor::FixupReferences() {
// Fixup any references which may have changed.
for (const auto& pair : references_) {
- pair.second->Assign(soa_->Decode<mirror::Object*>(pair.first));
+ pair.second->Assign(soa_->Decode<mirror::Object>(pair.first).Decode());
soa_->Env()->DeleteLocalRef(pair.first);
}
}
@@ -926,7 +926,7 @@
void RememberForGcArgumentVisitor::FixupReferences() {
// Fixup any references which may have changed.
for (const auto& pair : references_) {
- pair.second->Assign(soa_->Decode<mirror::Object*>(pair.first));
+ pair.second->Assign(soa_->Decode<mirror::Object>(pair.first).Decode());
soa_->Env()->DeleteLocalRef(pair.first);
}
}
diff --git a/runtime/gc/accounting/card_table_test.cc b/runtime/gc/accounting/card_table_test.cc
index 819cb85..67ab14c 100644
--- a/runtime/gc/accounting/card_table_test.cc
+++ b/runtime/gc/accounting/card_table_test.cc
@@ -23,7 +23,7 @@
#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
#include "mirror/string-inl.h" // Strings are easiest to allocate
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_pool.h"
#include "utils.h"
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index ab8942a..8b91075 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -32,7 +32,7 @@
#include "intern_table.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "thread_list.h"
#include "well_known_classes.h"
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index ad3dd33..b89d99c 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -41,7 +41,7 @@
#include "mark_sweep-inl.h"
#include "mirror/object-inl.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "thread_list.h"
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index b0ca18e..6d61c64 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -50,6 +50,7 @@
CHECK_EQ(self->GetState(), kRunnable);
self->AssertThreadSuspensionIsAllowable();
self->AssertNoPendingException();
+ self->PoisonObjectPointers();
}
// Need to check that we arent the large object allocator since the large object allocation code
// path this function. If we didn't check we would have an infinite loop.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 4e6dd2b..88e4624 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -61,6 +61,7 @@
#include "intern_table.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
+#include "obj_ptr-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
@@ -69,7 +70,7 @@
#include "reflection.h"
#include "runtime.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "handle_scope-inl.h"
#include "thread_list.h"
#include "well_known_classes.h"
@@ -1507,13 +1508,14 @@
<< static_cast<int>(100 * managed_utilization) << "%.";
}
-bool Heap::IsValidObjectAddress(const mirror::Object* obj) const {
+bool Heap::IsValidObjectAddress(ObjPtr<mirror::Object> obj) const {
// Note: we deliberately don't take the lock here, and mustn't test anything that would require
// taking the lock.
if (obj == nullptr) {
return true;
}
- return IsAligned<kObjectAlignment>(obj) && FindSpaceFromObject(obj, true) != nullptr;
+ return IsAligned<kObjectAlignment>(obj.Decode()) &&
+ FindSpaceFromObject(obj.Decode(), true) != nullptr;
}
bool Heap::IsNonDiscontinuousSpaceHeapAddress(const mirror::Object* obj) const {
@@ -3565,9 +3567,9 @@
max_allowed_footprint_ = max_allowed_footprint;
}
-bool Heap::IsMovableObject(const mirror::Object* obj) const {
+bool Heap::IsMovableObject(ObjPtr<mirror::Object> obj) const {
if (kMovingCollector) {
- space::Space* space = FindContinuousSpaceFromObject(obj, true);
+ space::Space* space = FindContinuousSpaceFromObject(obj.Decode(), true);
if (space != nullptr) {
// TODO: Check large object?
return space->CanMoveObjects();
@@ -3727,7 +3729,7 @@
args[0].l = arg.get();
InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_FinalizerReference_add, args);
// Restore object in case it gets moved.
- *object = soa.Decode<mirror::Object*>(arg.get());
+ *object = soa.Decode<mirror::Object>(arg.get()).Decode();
}
void Heap::RequestConcurrentGCAndSaveObject(Thread* self, bool force_full, mirror::Object** obj) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 10bebef..e32f057 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -34,6 +34,7 @@
#include "gc/collector_type.h"
#include "gc/space/large_object_space.h"
#include "globals.h"
+#include "obj_ptr.h"
#include "object_callbacks.h"
#include "offsets.h"
#include "process_state.h"
@@ -274,7 +275,7 @@
// A weaker test than IsLiveObject or VerifyObject that doesn't require the heap lock,
// and doesn't abort on error, allowing the caller to report more
// meaningful diagnostics.
- bool IsValidObjectAddress(const mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsValidObjectAddress(ObjPtr<mirror::Object> obj) const REQUIRES_SHARED(Locks::mutator_lock_);
// Faster alternative to IsHeapAddress since finding if an object is in the large object space is
// very slow.
@@ -290,7 +291,7 @@
REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
// Returns true if there is any chance that the object (obj) will move.
- bool IsMovableObject(const mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsMovableObject(ObjPtr<mirror::Object> obj) const REQUIRES_SHARED(Locks::mutator_lock_);
// Enables us to compacting GC until objects are released.
void IncrementDisableMovingGC(Thread* self) REQUIRES(!*gc_complete_lock_);
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index a3cefd9..515a6fd 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -22,7 +22,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index e172f85..9694597 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -24,7 +24,7 @@
#include "reference_processor-inl.h"
#include "reflection.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "task_processor.h"
#include "utils.h"
#include "well_known_classes.h"
diff --git a/runtime/gc/reference_queue_test.cc b/runtime/gc/reference_queue_test.cc
index 2a1635d..5b8a3c2 100644
--- a/runtime/gc/reference_queue_test.cc
+++ b/runtime/gc/reference_queue_test.cc
@@ -20,7 +20,7 @@
#include "reference_queue.h"
#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index 16d1f93..0030326 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -27,7 +27,7 @@
#include "base/stl_util.h"
#include "image.h"
#include "os.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "space-inl.h"
#include "thread-inl.h"
diff --git a/runtime/gc/space/space_create_test.cc b/runtime/gc/space/space_create_test.cc
index 170f927..7bc4dc4 100644
--- a/runtime/gc/space/space_create_test.cc
+++ b/runtime/gc/space/space_create_test.cc
@@ -18,7 +18,7 @@
#include "dlmalloc_space.h"
#include "rosalloc_space.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index bd600fe..17d7c87 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -26,7 +26,7 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
#include "zygote_space.h"
diff --git a/runtime/gc/system_weak_test.cc b/runtime/gc/system_weak_test.cc
index 7c1ec8a..af8a444 100644
--- a/runtime/gc/system_weak_test.cc
+++ b/runtime/gc/system_weak_test.cc
@@ -26,7 +26,7 @@
#include "handle_scope-inl.h"
#include "heap.h"
#include "mirror/string.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
namespace art {
diff --git a/runtime/gc/task_processor.cc b/runtime/gc/task_processor.cc
index a49121b..0704a68 100644
--- a/runtime/gc/task_processor.cc
+++ b/runtime/gc/task_processor.cc
@@ -17,7 +17,7 @@
#include "task_processor.h"
#include "base/time_utils.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
namespace gc {
diff --git a/runtime/handle.h b/runtime/handle.h
index d4c13d4..c41010a 100644
--- a/runtime/handle.h
+++ b/runtime/handle.h
@@ -23,6 +23,7 @@
#include "base/mutex.h"
#include "base/value_object.h"
#include "jni.h"
+#include "obj_ptr.h"
#include "stack_reference.h"
namespace art {
@@ -130,6 +131,14 @@
return old;
}
+ ALWAYS_INLINE T* Assign(ObjPtr<T> reference) REQUIRES_SHARED(Locks::mutator_lock_) {
+ StackReference<mirror::Object>* ref = Handle<T>::GetReference();
+ T* old = down_cast<T*>(ref->AsMirrorPtr());
+ ref->Assign(reference.Decode());
+ return old;
+ }
+
+
template<typename S>
explicit MutableHandle(const MutableHandle<S>& handle) REQUIRES_SHARED(Locks::mutator_lock_)
: Handle<T>(handle) {
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index 2e1b8ed..75a0391 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -21,6 +21,7 @@
#include "base/mutex.h"
#include "handle.h"
+#include "obj_ptr-inl.h"
#include "thread-inl.h"
#include "verify_object-inl.h"
@@ -107,12 +108,21 @@
return h;
}
+template<size_t kNumReferences> template<class MirrorType, bool kPoison>
+inline MutableHandle<MirrorType> StackHandleScope<kNumReferences>::NewHandle(
+ ObjPtr<MirrorType, kPoison> object) {
+ return NewHandle(object.Decode());
+}
+
template<size_t kNumReferences> template<class T>
inline HandleWrapper<T> StackHandleScope<kNumReferences>::NewHandleWrapper(T** object) {
- SetReference(pos_, *object);
- MutableHandle<T> h(GetHandle<T>(pos_));
- pos_++;
- return HandleWrapper<T>(object, h);
+ return HandleWrapper<T>(object, NewHandle(*object));
+}
+
+template<size_t kNumReferences> template<class T>
+inline HandleWrapperObjPtr<T> StackHandleScope<kNumReferences>::NewHandleWrapper(
+ ObjPtr<T>* object) {
+ return HandleWrapperObjPtr<T>(object, NewHandle(*object));
}
template<size_t kNumReferences>
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index 37eed99..2b283ae 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -28,6 +28,9 @@
#include "verify_object.h"
namespace art {
+
+template<class MirrorType, bool kPoison> class ObjPtr;
+
namespace mirror {
class Object;
}
@@ -125,7 +128,7 @@
};
// A wrapper which wraps around Object** and restores the pointer in the destructor.
-// TODO: Add more functionality.
+// TODO: Delete
template<class T>
class HandleWrapper : public MutableHandle<T> {
public:
@@ -143,6 +146,26 @@
T** const obj_;
};
+
+// A wrapper which wraps around ObjPtr<Object>* and restores the pointer in the destructor.
+// TODO: Add more functionality.
+template<class T>
+class HandleWrapperObjPtr : public MutableHandle<T> {
+ public:
+ HandleWrapperObjPtr(ObjPtr<T>* obj, const MutableHandle<T>& handle)
+ : MutableHandle<T>(handle), obj_(obj) {}
+
+ HandleWrapperObjPtr(const HandleWrapperObjPtr&) = default;
+
+ ~HandleWrapperObjPtr() {
+ *obj_ = ObjPtr<T>(MutableHandle<T>::Get());
+ }
+
+ private:
+ ObjPtr<T>* const obj_;
+};
+
+
// Scoped handle storage of a fixed size that is usually stack allocated.
template<size_t kNumReferences>
class PACKED(4) StackHandleScope FINAL : public HandleScope {
@@ -157,6 +180,14 @@
ALWAYS_INLINE HandleWrapper<T> NewHandleWrapper(T** object)
REQUIRES_SHARED(Locks::mutator_lock_);
+ template<class T>
+ ALWAYS_INLINE HandleWrapperObjPtr<T> NewHandleWrapper(ObjPtr<T>* object)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ template<class MirrorType, bool kPoison>
+ ALWAYS_INLINE MutableHandle<MirrorType> NewHandle(ObjPtr<MirrorType, kPoison> object)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/handle_scope_test.cc b/runtime/handle_scope_test.cc
index 58f3800..c269a37 100644
--- a/runtime/handle_scope_test.cc
+++ b/runtime/handle_scope_test.cc
@@ -17,7 +17,7 @@
#include "base/enums.h"
#include "gtest/gtest.h"
#include "handle_scope-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
namespace art {
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 921dde1..ecb2157 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -59,7 +59,7 @@
#include "mirror/object-inl.h"
#include "os.h"
#include "safe_map.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
namespace art {
diff --git a/runtime/image.cc b/runtime/image.cc
index 7e6790a..299d5fd 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -25,7 +25,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '3', '0', '\0' };
+const uint8_t ImageHeader::kImageVersion[] = { '0', '3', '1', '\0' };
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index 1f39a1e..202e472 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -21,7 +21,7 @@
#include "nth_caller_visitor.h"
#include "reference_table.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "utils.h"
#include "verify_object-inl.h"
diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc
index 61bcadd..58d487d 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -19,7 +19,7 @@
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "mirror/object-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/instrumentation_test.cc b/runtime/instrumentation_test.cc
index abe3184..7f9f04f 100644
--- a/runtime/instrumentation_test.cc
+++ b/runtime/instrumentation_test.cc
@@ -25,7 +25,7 @@
#include "handle_scope-inl.h"
#include "jvalue.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
#include "thread-inl.h"
@@ -458,7 +458,7 @@
instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
ClassLinker* class_linker = runtime->GetClassLinker();
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
+ Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
ASSERT_TRUE(klass != nullptr);
ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
@@ -505,7 +505,7 @@
instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
ClassLinker* class_linker = runtime->GetClassLinker();
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
+ Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
ASSERT_TRUE(klass != nullptr);
ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
diff --git a/runtime/intern_table_test.cc b/runtime/intern_table_test.cc
index 620e15b..74cec57 100644
--- a/runtime/intern_table_test.cc
+++ b/runtime/intern_table_test.cc
@@ -20,7 +20,7 @@
#include "mirror/object.h"
#include "handle_scope-inl.h"
#include "mirror/string.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 0003e72..c270df7 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -23,7 +23,7 @@
#include "interpreter_mterp_impl.h"
#include "interpreter_switch_impl.h"
#include "mirror/string-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "stack.h"
#include "unstarted_runtime.h"
@@ -51,7 +51,7 @@
ScopedThreadStateChange tsc(self, kNative);
jresult = fn(soa.Env(), klass.get());
}
- result->SetL(soa.Decode<Object*>(jresult));
+ result->SetL(soa.Decode<Object>(jresult).Decode());
} else if (shorty == "V") {
typedef void (fntype)(JNIEnv*, jclass);
fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
@@ -93,7 +93,7 @@
ScopedThreadStateChange tsc(self, kNative);
jresult = fn(soa.Env(), klass.get(), arg0.get());
}
- result->SetL(soa.Decode<Object*>(jresult));
+ result->SetL(soa.Decode<Object>(jresult).Decode());
} else if (shorty == "IIZ") {
typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
@@ -191,7 +191,7 @@
ScopedThreadStateChange tsc(self, kNative);
jresult = fn(soa.Env(), rcvr.get());
}
- result->SetL(soa.Decode<Object*>(jresult));
+ result->SetL(soa.Decode<Object>(jresult).Decode());
} else if (shorty == "V") {
typedef void (fntype)(JNIEnv*, jobject);
fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
@@ -212,7 +212,7 @@
ScopedThreadStateChange tsc(self, kNative);
jresult = fn(soa.Env(), rcvr.get(), arg0.get());
}
- result->SetL(soa.Decode<Object*>(jresult));
+ result->SetL(soa.Decode<Object>(jresult).Decode());
ScopedThreadStateChange tsc(self, kNative);
} else if (shorty == "III") {
typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 814adf7..0feb013 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -254,9 +254,9 @@
DCHECK_LT(string_idx % mirror::DexCache::kDexCacheStringCacheSize,
declaring_class->GetDexFile().NumStringIds());
mirror::String* string_ptr =
- mirror::StringDexCachePair::LookupString(declaring_class->GetDexCacheStrings(),
- string_idx,
- mirror::DexCache::kDexCacheStringCacheSize).Read();
+ mirror::StringDexCachePair::Lookup(declaring_class->GetDexCacheStrings(),
+ string_idx,
+ mirror::DexCache::kDexCacheStringCacheSize).Read();
if (UNLIKELY(string_ptr == nullptr)) {
StackHandleScope<1> hs(self);
Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 98e358b..39846da 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -1619,9 +1619,9 @@
uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
ScopedObjectAccessUnchecked soa(self);
if (Runtime::Current()->IsActiveTransaction()) {
- result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<true>(soa)));
+ result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<true>(soa)).Decode());
} else {
- result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<false>(soa)));
+ result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace<false>(soa)).Decode());
}
}
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index ba751ec..6a4add3 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -31,7 +31,7 @@
#include "mirror/class_loader.h"
#include "mirror/string-inl.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "transaction.h"
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 979495a..0c752ef 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -36,7 +36,7 @@
#include "runtime-inl.h"
#include "runtime_options.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "thread_list.h"
@@ -532,17 +532,17 @@
return true;
}
-jobject JavaVMExt::AddGlobalRef(Thread* self, mirror::Object* obj) {
+jobject JavaVMExt::AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) {
// Check for null after decoding the object to handle cleared weak globals.
if (obj == nullptr) {
return nullptr;
}
WriterMutexLock mu(self, globals_lock_);
- IndirectRef ref = globals_.Add(IRT_FIRST_SEGMENT, obj);
+ IndirectRef ref = globals_.Add(IRT_FIRST_SEGMENT, obj.Decode());
return reinterpret_cast<jobject>(ref);
}
-jweak JavaVMExt::AddWeakGlobalRef(Thread* self, mirror::Object* obj) {
+jweak JavaVMExt::AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) {
if (obj == nullptr) {
return nullptr;
}
@@ -550,7 +550,7 @@
while (UNLIKELY(!MayAccessWeakGlobals(self))) {
weak_globals_add_condition_.WaitHoldingLocks(self);
}
- IndirectRef ref = weak_globals_.Add(IRT_FIRST_SEGMENT, obj);
+ IndirectRef ref = weak_globals_.Add(IRT_FIRST_SEGMENT, obj.Decode());
return reinterpret_cast<jweak>(ref);
}
@@ -755,15 +755,15 @@
ScopedObjectAccess soa(env);
// As the incoming class loader is reachable/alive during the call of this function,
// it's okay to decode it without worrying about unexpectedly marking it alive.
- mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(class_loader);
+ ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(class_loader);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (class_linker->IsBootClassLoader(soa, loader)) {
+ if (class_linker->IsBootClassLoader(soa, loader.Decode())) {
loader = nullptr;
class_loader = nullptr;
}
- class_loader_allocator = class_linker->GetAllocatorForClassLoader(loader);
+ class_loader_allocator = class_linker->GetAllocatorForClassLoader(loader.Decode());
CHECK(class_loader_allocator != nullptr);
}
if (library != nullptr) {
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index a10a72f..558ffff 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -22,6 +22,7 @@
#include "base/macros.h"
#include "base/mutex.h"
#include "indirect_reference_table.h"
+#include "obj_ptr.h"
#include "reference_table.h"
namespace art {
@@ -123,10 +124,10 @@
void BroadcastForNewWeakGlobals() REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!weak_globals_lock_);
- jobject AddGlobalRef(Thread* self, mirror::Object* obj)
+ jobject AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!globals_lock_);
- jweak AddWeakGlobalRef(Thread* self, mirror::Object* obj)
+ jweak AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!weak_globals_lock_);
void DeleteGlobalRef(Thread* self, jobject obj) REQUIRES(!globals_lock_);
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index e2d29fe..6aebe9f 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -30,7 +30,7 @@
#include "jdwp/jdwp_expand_buf.h"
#include "jdwp/jdwp_priv.h"
#include "jdwp/object_registry.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "handle_scope-inl.h"
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index f6008ac..0f2d188 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -31,7 +31,7 @@
#include "jdwp/jdwp_expand_buf.h"
#include "jdwp/jdwp_priv.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"
diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc
index dbf04fe..e3bf3e5 100644
--- a/runtime/jdwp/jdwp_main.cc
+++ b/runtime/jdwp/jdwp_main.cc
@@ -25,7 +25,7 @@
#include "base/time_utils.h"
#include "debugger.h"
#include "jdwp/jdwp_priv.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc
index 5989b61..9ba62c9 100644
--- a/runtime/jdwp/object_registry.cc
+++ b/runtime/jdwp/object_registry.cc
@@ -19,7 +19,7 @@
#include "handle_scope-inl.h"
#include "jni_internal.h"
#include "mirror/class.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index c9227b1..2c6b249 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -32,7 +32,7 @@
#include "linear_alloc.h"
#include "mem_map.h"
#include "oat_file-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
namespace art {
diff --git a/runtime/jit/profile_compilation_info_test.cc b/runtime/jit/profile_compilation_info_test.cc
index c8f4d94..764458a 100644
--- a/runtime/jit/profile_compilation_info_test.cc
+++ b/runtime/jit/profile_compilation_info_test.cc
@@ -26,7 +26,7 @@
#include "mirror/class_loader.h"
#include "handle_scope-inl.h"
#include "jit/offline_profiling_info.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index a4bc3fc..d23821b 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -26,7 +26,7 @@
#include "base/time_utils.h"
#include "compiler_filter.h"
#include "oat_file_manager.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/jit/profiling_info.cc b/runtime/jit/profiling_info.cc
index 216df2f..6ba187e 100644
--- a/runtime/jit/profiling_info.cc
+++ b/runtime/jit/profiling_info.cc
@@ -20,7 +20,7 @@
#include "dex_instruction.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
namespace art {
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index a11f9ab..7b27578 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -52,7 +52,7 @@
#include "reflection.h"
#include "runtime.h"
#include "safe_map.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "thread.h"
#include "utf.h"
@@ -108,7 +108,7 @@
"%s is null at index %d", kind, idx);
}
-static mirror::Class* EnsureInitialized(Thread* self, mirror::Class* klass)
+static ObjPtr<mirror::Class> EnsureInitialized(Thread* self, ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (LIKELY(klass->IsInitialized())) {
return klass;
@@ -124,7 +124,7 @@
static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class,
const char* name, const char* sig, bool is_static)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(jni_class));
+ ObjPtr<mirror::Class> c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class>(jni_class));
if (c == nullptr) {
return nullptr;
}
@@ -143,31 +143,31 @@
}
}
if (method == nullptr || method->IsStatic() != is_static) {
- ThrowNoSuchMethodError(soa, c, name, sig, is_static ? "static" : "non-static");
+ ThrowNoSuchMethodError(soa, c.Decode(), name, sig, is_static ? "static" : "non-static");
return nullptr;
}
return soa.EncodeMethod(method);
}
-static mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa)
+static ObjPtr<mirror::ClassLoader> GetClassLoader(const ScopedObjectAccess& soa)
REQUIRES_SHARED(Locks::mutator_lock_) {
ArtMethod* method = soa.Self()->GetCurrentMethod(nullptr);
// If we are running Runtime.nativeLoad, use the overriding ClassLoader it set.
if (method == soa.DecodeMethod(WellKnownClasses::java_lang_Runtime_nativeLoad)) {
- return soa.Decode<mirror::ClassLoader*>(soa.Self()->GetClassLoaderOverride());
+ return soa.Decode<mirror::ClassLoader>(soa.Self()->GetClassLoaderOverride());
}
// If we have a method, use its ClassLoader for context.
if (method != nullptr) {
return method->GetDeclaringClass()->GetClassLoader();
}
// We don't have a method, so try to use the system ClassLoader.
- mirror::ClassLoader* class_loader =
- soa.Decode<mirror::ClassLoader*>(Runtime::Current()->GetSystemClassLoader());
+ ObjPtr<mirror::ClassLoader> class_loader =
+ soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader());
if (class_loader != nullptr) {
return class_loader;
}
// See if the override ClassLoader is set for gtests.
- class_loader = soa.Decode<mirror::ClassLoader*>(soa.Self()->GetClassLoaderOverride());
+ class_loader = soa.Decode<mirror::ClassLoader>(soa.Self()->GetClassLoaderOverride());
if (class_loader != nullptr) {
// If so, CommonCompilerTest should have marked the runtime as a compiler not compiling an
// image.
@@ -184,7 +184,7 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
StackHandleScope<2> hs(soa.Self());
Handle<mirror::Class> c(
- hs.NewHandle(EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(jni_class))));
+ hs.NewHandle(EnsureInitialized(soa.Self(), soa.Decode<mirror::Class>(jni_class))));
if (c.Get() == nullptr) {
return nullptr;
}
@@ -272,7 +272,7 @@
if (mid == nullptr) {
ScopedObjectAccess soa(env);
LOG(ERROR) << "No <init>" << signature << " in "
- << PrettyClass(soa.Decode<mirror::Class*>(exception_class));
+ << PrettyClass(soa.Decode<mirror::Class>(exception_class));
return JNI_ERR;
}
@@ -282,7 +282,7 @@
return JNI_ERR;
}
ScopedObjectAccess soa(env);
- soa.Self()->SetException(soa.Decode<mirror::Throwable*>(exception.get()));
+ soa.Self()->SetException(soa.Decode<mirror::Throwable>(exception.get()).Decode());
return JNI_OK;
}
@@ -363,12 +363,12 @@
static jfieldID FromReflectedField(JNIEnv* env, jobject jlr_field) {
CHECK_NON_NULL_ARGUMENT(jlr_field);
ScopedObjectAccess soa(env);
- mirror::Object* obj_field = soa.Decode<mirror::Object*>(jlr_field);
+ ObjPtr<mirror::Object> obj_field = soa.Decode<mirror::Object>(jlr_field);
if (obj_field->GetClass() != mirror::Field::StaticClass()) {
// Not even a java.lang.reflect.Field, return null. TODO, is this check necessary?
return nullptr;
}
- auto* field = static_cast<mirror::Field*>(obj_field);
+ ObjPtr<mirror::Field> field = down_cast<mirror::Field*>(obj_field.Decode());
return soa.EncodeField(field->GetArtField());
}
@@ -398,14 +398,14 @@
static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
CHECK_NON_NULL_ARGUMENT(java_object);
ScopedObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
return soa.AddLocalReference<jclass>(o->GetClass());
}
static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
CHECK_NON_NULL_ARGUMENT(java_class);
ScopedObjectAccess soa(env);
- mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
return soa.AddLocalReference<jclass>(c->IsInterface() ? nullptr : c->GetSuperClass());
}
@@ -415,9 +415,9 @@
CHECK_NON_NULL_ARGUMENT_RETURN(java_class1, JNI_FALSE);
CHECK_NON_NULL_ARGUMENT_RETURN(java_class2, JNI_FALSE);
ScopedObjectAccess soa(env);
- mirror::Class* c1 = soa.Decode<mirror::Class*>(java_class1);
- mirror::Class* c2 = soa.Decode<mirror::Class*>(java_class2);
- return c2->IsAssignableFrom(c1) ? JNI_TRUE : JNI_FALSE;
+ ObjPtr<mirror::Class> c1 = soa.Decode<mirror::Class>(java_class1);
+ ObjPtr<mirror::Class> c2 = soa.Decode<mirror::Class>(java_class2);
+ return c2->IsAssignableFrom(c1.Decode()) ? JNI_TRUE : JNI_FALSE;
}
static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) {
@@ -427,19 +427,19 @@
return JNI_TRUE;
} else {
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
- mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
return obj->InstanceOf(c) ? JNI_TRUE : JNI_FALSE;
}
}
static jint Throw(JNIEnv* env, jthrowable java_exception) {
ScopedObjectAccess soa(env);
- mirror::Throwable* exception = soa.Decode<mirror::Throwable*>(java_exception);
+ ObjPtr<mirror::Throwable> exception = soa.Decode<mirror::Throwable>(java_exception);
if (exception == nullptr) {
return JNI_ERR;
}
- soa.Self()->SetException(exception);
+ soa.Self()->SetException(exception.Decode());
return JNI_OK;
}
@@ -509,7 +509,7 @@
static jobject PopLocalFrame(JNIEnv* env, jobject java_survivor) {
ScopedObjectAccess soa(env);
- mirror::Object* survivor = soa.Decode<mirror::Object*>(java_survivor);
+ ObjPtr<mirror::Object> survivor = soa.Decode<mirror::Object>(java_survivor);
soa.Env()->PopFrame();
return soa.AddLocalReference<jobject>(survivor);
}
@@ -522,8 +522,8 @@
static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
ScopedObjectAccess soa(env);
- mirror::Object* decoded_obj = soa.Decode<mirror::Object*>(obj);
- return soa.Vm()->AddGlobalRef(soa.Self(), decoded_obj);
+ ObjPtr<mirror::Object> decoded_obj = soa.Decode<mirror::Object>(obj);
+ return soa.Vm()->AddGlobalRef(soa.Self(), decoded_obj.Decode());
}
static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
@@ -534,8 +534,8 @@
static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
ScopedObjectAccess soa(env);
- mirror::Object* decoded_obj = soa.Decode<mirror::Object*>(obj);
- return soa.Vm()->AddWeakGlobalRef(soa.Self(), decoded_obj);
+ ObjPtr<mirror::Object> decoded_obj = soa.Decode<mirror::Object>(obj);
+ return soa.Vm()->AddWeakGlobalRef(soa.Self(), decoded_obj.Decode());
}
static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
@@ -546,7 +546,7 @@
static jobject NewLocalRef(JNIEnv* env, jobject obj) {
ScopedObjectAccess soa(env);
- mirror::Object* decoded_obj = soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> decoded_obj = soa.Decode<mirror::Object>(obj);
// Check for null after decoding the object to handle cleared weak globals.
if (decoded_obj == nullptr) {
return nullptr;
@@ -579,7 +579,7 @@
return JNI_TRUE;
} else {
ScopedObjectAccess soa(env);
- return (soa.Decode<mirror::Object*>(obj1) == soa.Decode<mirror::Object*>(obj2))
+ return (soa.Decode<mirror::Object>(obj1) == soa.Decode<mirror::Object>(obj2))
? JNI_TRUE : JNI_FALSE;
}
}
@@ -587,7 +587,7 @@
static jobject AllocObject(JNIEnv* env, jclass java_class) {
CHECK_NON_NULL_ARGUMENT(java_class);
ScopedObjectAccess soa(env);
- mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(java_class));
+ ObjPtr<mirror::Class> c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class>(java_class));
if (c == nullptr) {
return nullptr;
}
@@ -613,7 +613,8 @@
CHECK_NON_NULL_ARGUMENT(java_class);
CHECK_NON_NULL_ARGUMENT(mid);
ScopedObjectAccess soa(env);
- mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(java_class));
+ ObjPtr<mirror::Class> c = EnsureInitialized(soa.Self(),
+ soa.Decode<mirror::Class>(java_class));
if (c == nullptr) {
return nullptr;
}
@@ -639,7 +640,8 @@
CHECK_NON_NULL_ARGUMENT(java_class);
CHECK_NON_NULL_ARGUMENT(mid);
ScopedObjectAccess soa(env);
- mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(java_class));
+ ObjPtr<mirror::Class> c = EnsureInitialized(soa.Self(),
+ soa.Decode<mirror::Class>(java_class));
if (c == nullptr) {
return nullptr;
}
@@ -1223,9 +1225,9 @@
CHECK_NON_NULL_ARGUMENT(obj);
CHECK_NON_NULL_ARGUMENT(fid);
ScopedObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
ArtField* f = soa.DecodeField(fid);
- return soa.AddLocalReference<jobject>(f->GetObject(o));
+ return soa.AddLocalReference<jobject>(f->GetObject(o.Decode()));
}
static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
@@ -1239,27 +1241,27 @@
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_object);
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
ScopedObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
- mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
+ ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value);
ArtField* f = soa.DecodeField(fid);
- f->SetObject<false>(o, v);
+ f->SetObject<false>(o.Decode(), v.Decode());
}
static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
ScopedObjectAccess soa(env);
- mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
+ ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value);
ArtField* f = soa.DecodeField(fid);
- f->SetObject<false>(f->GetDeclaringClass(), v);
+ f->SetObject<false>(f->GetDeclaringClass(), v.Decode());
}
#define GET_PRIMITIVE_FIELD(fn, instance) \
CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(instance); \
CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
ScopedObjectAccess soa(env); \
- mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \
ArtField* f = soa.DecodeField(fid); \
- return f->Get ##fn (o)
+ return f->Get ##fn (o.Decode())
#define GET_STATIC_PRIMITIVE_FIELD(fn) \
CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
@@ -1271,9 +1273,9 @@
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(instance); \
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
ScopedObjectAccess soa(env); \
- mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \
ArtField* f = soa.DecodeField(fid); \
- f->Set ##fn <false>(o, value)
+ f->Set ##fn <false>(o.Decode(), value)
#define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
@@ -1657,20 +1659,20 @@
static jsize GetStringLength(JNIEnv* env, jstring java_string) {
CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string);
ScopedObjectAccess soa(env);
- return soa.Decode<mirror::String*>(java_string)->GetLength();
+ return soa.Decode<mirror::String>(java_string)->GetLength();
}
static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string);
ScopedObjectAccess soa(env);
- return soa.Decode<mirror::String*>(java_string)->GetUtfLength();
+ return soa.Decode<mirror::String>(java_string)->GetUtfLength();
}
static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
jchar* buf) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
ScopedObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
if (start < 0 || length < 0 || length > s->GetLength() - start) {
ThrowSIOOBE(soa, start, length, s->GetLength());
} else {
@@ -1690,7 +1692,7 @@
char* buf) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
ScopedObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
if (start < 0 || length < 0 || length > s->GetLength() - start) {
ThrowSIOOBE(soa, start, length, s->GetLength());
} else {
@@ -1710,7 +1712,7 @@
static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* is_copy) {
CHECK_NON_NULL_ARGUMENT(java_string);
ScopedObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
gc::Heap* heap = Runtime::Current()->GetHeap();
if (heap->IsMovableObject(s) || s->IsCompressed()) {
jchar* chars = new jchar[s->GetLength()];
@@ -1736,7 +1738,7 @@
static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar* chars) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
ScopedObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
if (s->IsCompressed() || (s->IsCompressed() == false && chars != s->GetValue())) {
delete[] chars;
}
@@ -1745,11 +1747,11 @@
static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* is_copy) {
CHECK_NON_NULL_ARGUMENT(java_string);
ScopedObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
gc::Heap* heap = Runtime::Current()->GetHeap();
if (heap->IsMovableObject(s)) {
StackHandleScope<1> hs(soa.Self());
- HandleWrapper<mirror::String> h(hs.NewHandleWrapper(&s));
+ HandleWrapperObjPtr<mirror::String> h(hs.NewHandleWrapper(&s));
if (!kUseReadBarrier) {
heap->IncrementDisableMovingGC(soa.Self());
} else {
@@ -1782,7 +1784,7 @@
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
ScopedObjectAccess soa(env);
gc::Heap* heap = Runtime::Current()->GetHeap();
- mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
if (heap->IsMovableObject(s)) {
if (!kUseReadBarrier) {
heap->DecrementDisableMovingGC(soa.Self());
@@ -1803,7 +1805,7 @@
*is_copy = JNI_TRUE;
}
ScopedObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_string);
size_t byte_count = s->GetUtfLength();
char* bytes = new char[byte_count + 1];
CHECK(bytes != nullptr); // bionic aborts anyway.
@@ -1826,7 +1828,7 @@
static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_array);
ScopedObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(java_array);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_array);
if (UNLIKELY(!obj->IsArrayInstance())) {
soa.Vm()->JniAbortF("GetArrayLength", "not an array: %s", PrettyTypeOf(obj).c_str());
return 0;
@@ -1838,8 +1840,8 @@
static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index) {
CHECK_NON_NULL_ARGUMENT(java_array);
ScopedObjectAccess soa(env);
- mirror::ObjectArray<mirror::Object>* array =
- soa.Decode<mirror::ObjectArray<mirror::Object>*>(java_array);
+ ObjPtr<mirror::ObjectArray<mirror::Object>> array =
+ soa.Decode<mirror::ObjectArray<mirror::Object>>(java_array);
return soa.AddLocalReference<jobject>(array->Get(index));
}
@@ -1847,10 +1849,10 @@
jobject java_value) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
ScopedObjectAccess soa(env);
- mirror::ObjectArray<mirror::Object>* array =
- soa.Decode<mirror::ObjectArray<mirror::Object>*>(java_array);
- mirror::Object* value = soa.Decode<mirror::Object*>(java_value);
- array->Set<false>(index, value);
+ ObjPtr<mirror::ObjectArray<mirror::Object>> array =
+ soa.Decode<mirror::ObjectArray<mirror::Object>>(java_array);
+ ObjPtr<mirror::Object> value = soa.Decode<mirror::Object>(java_value);
+ array->Set<false>(index, value.Decode());
}
static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
@@ -1893,7 +1895,7 @@
ScopedObjectAccess soa(env);
mirror::Class* array_class;
{
- mirror::Class* element_class = soa.Decode<mirror::Class*>(element_jclass);
+ mirror::Class* element_class = soa.Decode<mirror::Class>(element_jclass).Decode();
if (UNLIKELY(element_class->IsPrimitive())) {
soa.Vm()->JniAbortF("NewObjectArray", "not an object type: %s",
PrettyDescriptor(element_class).c_str());
@@ -1910,7 +1912,7 @@
mirror::ObjectArray<mirror::Object>* result =
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), array_class, length);
if (result != nullptr && initial_element != nullptr) {
- mirror::Object* initial_object = soa.Decode<mirror::Object*>(initial_element);
+ ObjPtr<mirror::Object> initial_object = soa.Decode<mirror::Object>(initial_element);
if (initial_object != nullptr) {
mirror::Class* element_class = result->GetClass()->GetComponentType();
if (UNLIKELY(!element_class->IsAssignableFrom(initial_object->GetClass()))) {
@@ -1921,7 +1923,7 @@
return nullptr;
} else {
for (jsize i = 0; i < length; ++i) {
- result->SetWithoutChecks<false>(i, initial_object);
+ result->SetWithoutChecks<false>(i, initial_object.Decode());
}
}
}
@@ -1936,7 +1938,7 @@
static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray java_array, jboolean* is_copy) {
CHECK_NON_NULL_ARGUMENT(java_array);
ScopedObjectAccess soa(env);
- mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
+ ObjPtr<mirror::Array> array = soa.Decode<mirror::Array>(java_array);
if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) {
soa.Vm()->JniAbortF("GetPrimitiveArrayCritical", "expected primitive array, given %s",
PrettyDescriptor(array->GetClass()).c_str());
@@ -1952,7 +1954,7 @@
heap->IncrementDisableThreadFlip(soa.Self());
}
// Re-decode in case the object moved since IncrementDisableGC waits for GC to complete.
- array = soa.Decode<mirror::Array*>(java_array);
+ array = soa.Decode<mirror::Array>(java_array);
}
if (is_copy != nullptr) {
*is_copy = JNI_FALSE;
@@ -1964,14 +1966,14 @@
jint mode) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
ScopedObjectAccess soa(env);
- mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
+ ObjPtr<mirror::Array> array = soa.Decode<mirror::Array>(java_array);
if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) {
soa.Vm()->JniAbortF("ReleasePrimitiveArrayCritical", "expected primitive array, given %s",
PrettyDescriptor(array->GetClass()).c_str());
return;
}
const size_t component_size = array->GetClass()->GetComponentSize();
- ReleasePrimitiveArray(soa, array, component_size, elements, mode);
+ ReleasePrimitiveArray(soa, array.Decode(), component_size, elements, mode);
}
static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
@@ -2145,7 +2147,7 @@
}
CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class, JNI_ERR);
ScopedObjectAccess soa(env);
- mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
if (UNLIKELY(method_count == 0)) {
LOG(WARNING) << "JNI RegisterNativeMethods: attempt to register 0 native methods for "
<< PrettyDescriptor(c);
@@ -2157,13 +2159,13 @@
const char* sig = methods[i].signature;
const void* fnPtr = methods[i].fnPtr;
if (UNLIKELY(name == nullptr)) {
- ReportInvalidJNINativeMethod(soa, c, "method name", i, return_errors);
+ ReportInvalidJNINativeMethod(soa, c.Decode(), "method name", i, return_errors);
return JNI_ERR;
} else if (UNLIKELY(sig == nullptr)) {
- ReportInvalidJNINativeMethod(soa, c, "method signature", i, return_errors);
+ ReportInvalidJNINativeMethod(soa, c.Decode(), "method signature", i, return_errors);
return JNI_ERR;
} else if (UNLIKELY(fnPtr == nullptr)) {
- ReportInvalidJNINativeMethod(soa, c, "native function", i, return_errors);
+ ReportInvalidJNINativeMethod(soa, c.Decode(), "native function", i, return_errors);
return JNI_ERR;
}
bool is_fast = false;
@@ -2206,17 +2208,17 @@
// the parent.
ArtMethod* m = nullptr;
bool warn_on_going_to_parent = down_cast<JNIEnvExt*>(env)->vm->IsCheckJniEnabled();
- for (mirror::Class* current_class = c;
+ for (ObjPtr<mirror::Class> current_class = c;
current_class != nullptr;
current_class = current_class->GetSuperClass()) {
// Search first only comparing methods which are native.
- m = FindMethod<true>(current_class, name, sig);
+ m = FindMethod<true>(current_class.Decode(), name, sig);
if (m != nullptr) {
break;
}
// Search again comparing to all methods, to find non-native methods that match.
- m = FindMethod<false>(current_class, name, sig);
+ m = FindMethod<false>(current_class.Decode(), name, sig);
if (m != nullptr) {
break;
}
@@ -2238,14 +2240,14 @@
<< "Failed to register native method "
<< PrettyDescriptor(c) << "." << name << sig << " in "
<< c->GetDexCache()->GetLocation()->ToModifiedUtf8();
- ThrowNoSuchMethodError(soa, c, name, sig, "static or non-static");
+ ThrowNoSuchMethodError(soa, c.Decode(), name, sig, "static or non-static");
return JNI_ERR;
} else if (!m->IsNative()) {
LOG(return_errors ? ::android::base::ERROR : ::android::base::FATAL)
<< "Failed to register non-native method "
<< PrettyDescriptor(c) << "." << name << sig
<< " as native";
- ThrowNoSuchMethodError(soa, c, name, sig, "native");
+ ThrowNoSuchMethodError(soa, c.Decode(), name, sig, "native");
return JNI_ERR;
}
@@ -2260,7 +2262,7 @@
static jint UnregisterNatives(JNIEnv* env, jclass java_class) {
CHECK_NON_NULL_ARGUMENT_RETURN(java_class, JNI_ERR);
ScopedObjectAccess soa(env);
- mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
@@ -2283,24 +2285,24 @@
static jint MonitorEnter(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR);
ScopedObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
o = o->MonitorEnter(soa.Self());
if (soa.Self()->IsExceptionPending()) {
return JNI_ERR;
}
- soa.Env()->monitors.Add(o);
+ soa.Env()->monitors.Add(o.Decode());
return JNI_OK;
}
static jint MonitorExit(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR);
ScopedObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
o->MonitorExit(soa.Self());
if (soa.Self()->IsExceptionPending()) {
return JNI_ERR;
}
- soa.Env()->monitors.Remove(o);
+ soa.Env()->monitors.Remove(o.Decode());
return JNI_OK;
}
@@ -2409,7 +2411,7 @@
static ArtArrayT* DecodeAndCheckArrayType(ScopedObjectAccess& soa, JArrayT java_array,
const char* fn_name, const char* operation)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ArtArrayT* array = soa.Decode<ArtArrayT*>(java_array);
+ ObjPtr<ArtArrayT> array = soa.Decode<ArtArrayT>(java_array);
if (UNLIKELY(ArtArrayT::GetArrayClass() != array->GetClass())) {
soa.Vm()->JniAbortF(fn_name,
"attempt to %s %s primitive array elements with an object of type %s",
@@ -2419,7 +2421,7 @@
return nullptr;
}
DCHECK_EQ(sizeof(ElementT), array->GetClass()->GetComponentSize());
- return array;
+ return array.Decode();
}
template <typename ArrayT, typename ElementT, typename ArtArrayT>
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index fe0081c..9bd6f6d 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -22,7 +22,7 @@
#include "java_vm_ext.h"
#include "jni_env_ext.h"
#include "mirror/string-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
namespace art {
@@ -58,7 +58,7 @@
void ExpectException(jclass exception_class) {
ScopedObjectAccess soa(env_);
EXPECT_TRUE(env_->ExceptionCheck())
- << PrettyDescriptor(soa.Decode<mirror::Class*>(exception_class));
+ << PrettyDescriptor(soa.Decode<mirror::Class>(exception_class));
jthrowable exception = env_->ExceptionOccurred();
EXPECT_NE(nullptr, exception);
env_->ExceptionClear();
@@ -619,7 +619,7 @@
class_loader_ = LoadDex("MyClassNatives");
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader_)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_)));
mirror::Class* c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader);
const auto pointer_size = class_linker_->GetImagePointerSize();
ArtMethod* method = direct ? c->FindDirectMethod(method_name, method_sig, pointer_size) :
@@ -1598,7 +1598,7 @@
TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
jstring s = env_->NewStringUTF("hello");
ScopedObjectAccess soa(env_);
- mirror::String* s_m = soa.Decode<mirror::String*>(s);
+ ObjPtr<mirror::String> s_m = soa.Decode<mirror::String>(s);
ASSERT_TRUE(s != nullptr);
jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
@@ -2236,7 +2236,7 @@
static bool IsLocked(JNIEnv* env, jobject jobj) {
ScopedObjectAccess soa(env);
- LockWord lock_word = soa.Decode<mirror::Object*>(jobj)->GetLockWord(true);
+ LockWord lock_word = soa.Decode<mirror::Object>(jobj)->GetLockWord(true);
switch (lock_word.GetState()) {
case LockWord::kHashCode:
case LockWord::kUnlocked:
diff --git a/runtime/jobject_comparator.cc b/runtime/jobject_comparator.cc
index 1f424b3..443f095 100644
--- a/runtime/jobject_comparator.cc
+++ b/runtime/jobject_comparator.cc
@@ -19,7 +19,7 @@
#include "mirror/array-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -32,8 +32,8 @@
}
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
- Handle<mirror::Object> obj1(hs.NewHandle(soa.Decode<mirror::Object*>(jobj1)));
- Handle<mirror::Object> obj2(hs.NewHandle(soa.Decode<mirror::Object*>(jobj2)));
+ Handle<mirror::Object> obj1(hs.NewHandle(soa.Decode<mirror::Object>(jobj1)));
+ Handle<mirror::Object> obj2(hs.NewHandle(soa.Decode<mirror::Object>(jobj2)));
if (obj1.Get() == nullptr) {
return true;
} else if (obj2.Get() == nullptr) {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 548087e..6c1259b 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -54,9 +54,10 @@
class DexCache;
class IfTable;
class Method;
-struct StringDexCachePair;
+template <typename T> struct PACKED(8) DexCachePair;
-using StringDexCacheType = std::atomic<mirror::StringDexCachePair>;
+using StringDexCachePair = DexCachePair<mirror::String>;
+using StringDexCacheType = std::atomic<StringDexCachePair>;
// C++ mirror of java.lang.Class
class MANAGED Class FINAL : public Object {
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 30bf390..477402a 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -40,7 +40,7 @@
inline mirror::String* DexCache::GetResolvedString(uint32_t string_idx) {
DCHECK_LT(string_idx, GetDexFile()->NumStringIds());
- return StringDexCachePair::LookupString(GetStrings(), string_idx, NumStrings()).Read();
+ return StringDexCachePair::Lookup(GetStrings(), string_idx, NumStrings()).Read();
}
inline void DexCache::SetResolvedString(uint32_t string_idx, mirror::String* resolved) {
@@ -62,10 +62,10 @@
DCHECK(Runtime::Current()->IsAotCompiler());
StringDexCacheType* slot = &GetStrings()[slot_idx];
// This is racy but should only be called from the transactional interpreter.
- if (slot->load(std::memory_order_relaxed).string_index == string_idx) {
+ if (slot->load(std::memory_order_relaxed).index == string_idx) {
StringDexCachePair cleared(
nullptr,
- StringDexCachePair::InvalidStringIndexForSlot(slot_idx));
+ StringDexCachePair::InvalidIndexForSlot(slot_idx));
slot->store(cleared, std::memory_order_relaxed);
}
}
@@ -156,11 +156,11 @@
mirror::StringDexCacheType* strings = GetStrings();
for (size_t i = 0, num_strings = NumStrings(); i != num_strings; ++i) {
StringDexCachePair source = strings[i].load(std::memory_order_relaxed);
- mirror::String* before = source.string_pointer.Read<kReadBarrierOption>();
+ mirror::String* before = source.object.Read<kReadBarrierOption>();
GcRoot<mirror::String> root(before);
visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
if (root.Read() != before) {
- source.string_pointer = GcRoot<String>(root.Read());
+ source.object = GcRoot<String>(root.Read());
strings[i].store(source, std::memory_order_relaxed);
}
}
@@ -181,9 +181,9 @@
mirror::StringDexCacheType* src = GetStrings();
for (size_t i = 0, count = NumStrings(); i < count; ++i) {
StringDexCachePair source = src[i].load(std::memory_order_relaxed);
- mirror::String* ptr = source.string_pointer.Read<kReadBarrierOption>();
+ mirror::String* ptr = source.object.Read<kReadBarrierOption>();
mirror::String* new_source = visitor(ptr);
- source.string_pointer = GcRoot<String>(new_source);
+ source.object = GcRoot<String>(new_source);
dest[i].store(source, std::memory_order_relaxed);
}
}
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 7d4021f..d81dedc 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -35,9 +35,9 @@
class String;
-struct PACKED(8) StringDexCachePair {
- GcRoot<String> string_pointer;
- uint32_t string_index;
+template <typename T> struct PACKED(8) DexCachePair {
+ GcRoot<T> object;
+ uint32_t index;
// The array is initially [ {0,0}, {0,0}, {0,0} ... ]
// We maintain the invariant that once a dex cache entry is populated,
// the pointer is always non-0
@@ -45,47 +45,51 @@
// {non-0, non-0} OR {0,0}
//
// It's generally sufficiently enough then to check if the
- // lookup string index matches the stored string index (for a >0 string index)
+ // lookup index matches the stored index (for a >0 lookup index)
// because if it's true the pointer is also non-null.
//
// For the 0th entry which is a special case, the value is either
// {0,0} (initial state) or {non-0, 0} which indicates
- // that a valid string is stored at that index for a dex string id of 0.
+ // that a valid object is stored at that index for a dex section id of 0.
//
- // As an optimization, we want to avoid branching on the string pointer since
- // it's always non-null if the string id branch succeeds (except for the 0th string id).
+ // As an optimization, we want to avoid branching on the object pointer since
+ // it's always non-null if the id branch succeeds (except for the 0th id).
// Set the initial state for the 0th entry to be {0,1} which is guaranteed to fail
- // the lookup string id == stored id branch.
- StringDexCachePair(String* string, uint32_t string_idx)
- : string_pointer(string),
- string_index(string_idx) {}
- StringDexCachePair() = default;
- StringDexCachePair(const StringDexCachePair&) = default;
- StringDexCachePair& operator=(const StringDexCachePair&) = default;
+ // the lookup id == stored id branch.
+ DexCachePair(T* object, uint32_t index)
+ : object(object),
+ index(index) {}
+ DexCachePair() = default;
+ DexCachePair(const DexCachePair<T>&) = default;
+ DexCachePair& operator=(const DexCachePair<T>&) = default;
- static void Initialize(StringDexCacheType* strings) {
- mirror::StringDexCachePair first_elem;
- first_elem.string_pointer = GcRoot<String>(nullptr);
- first_elem.string_index = InvalidStringIndexForSlot(0);
- strings[0].store(first_elem, std::memory_order_relaxed);
+ static void Initialize(std::atomic<DexCachePair<T>>* dex_cache) {
+ DexCachePair<T> first_elem;
+ first_elem.object = GcRoot<T>(nullptr);
+ first_elem.index = InvalidIndexForSlot(0);
+ dex_cache[0].store(first_elem, std::memory_order_relaxed);
}
- static GcRoot<String> LookupString(StringDexCacheType* dex_cache,
- uint32_t string_idx,
- uint32_t cache_size) {
- StringDexCachePair index_string = dex_cache[string_idx % cache_size]
- .load(std::memory_order_relaxed);
- if (string_idx != index_string.string_index) return GcRoot<String>(nullptr);
- DCHECK(!index_string.string_pointer.IsNull());
- return index_string.string_pointer;
+ static GcRoot<T> Lookup(std::atomic<DexCachePair<T>>* dex_cache,
+ uint32_t idx,
+ uint32_t cache_size) {
+ DexCachePair<T> element = dex_cache[idx % cache_size].load(std::memory_order_relaxed);
+ if (idx != element.index) {
+ return GcRoot<T>(nullptr);
+ }
+
+ DCHECK(!element.object.IsNull());
+ return element.object;
}
- static uint32_t InvalidStringIndexForSlot(uint32_t slot) {
+ static uint32_t InvalidIndexForSlot(uint32_t slot) {
// Since the cache size is a power of two, 0 will always map to slot 0.
// Use 1 for slot 0 and 0 for all other slots.
return (slot == 0) ? 1u : 0u;
}
};
+
+using StringDexCachePair = DexCachePair<mirror::String>;
using StringDexCacheType = std::atomic<StringDexCachePair>;
// C++ mirror of java.lang.DexCache.
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index 43ba362..ac04200 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -24,7 +24,7 @@
#include "mirror/class_loader-inl.h"
#include "mirror/dex_cache-inl.h"
#include "handle_scope-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
namespace mirror {
@@ -56,7 +56,7 @@
ClassLinker* const class_linker = runtime->GetClassLinker();
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ soa.Decode<mirror::ClassLoader>(jclass_loader)));
mirror::Class* klass = class_linker->FindClass(soa.Self(), "LMain;", class_loader);
ASSERT_TRUE(klass != nullptr);
LinearAlloc* const linear_alloc = klass->GetClassLoader()->GetAllocator();
@@ -72,7 +72,7 @@
ClassLinker* const class_linker = runtime->GetClassLinker();
StackHandleScope<3> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> klass1 =
hs.NewHandle(class_linker->FindClass(soa.Self(), "Lpackage1/Package1;", class_loader));
ASSERT_TRUE(klass1.Get() != nullptr);
diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc
new file mode 100644
index 0000000..fdfaaa8
--- /dev/null
+++ b/runtime/mirror/method_handle_impl.cc
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "method_handle_impl.h"
+
+#include "class-inl.h"
+#include "gc_root-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<mirror::Class> MethodHandleImpl::static_class_;
+
+void MethodHandleImpl::SetClass(Class* klass) {
+ CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ static_class_ = GcRoot<Class>(klass);
+}
+
+void MethodHandleImpl::ResetClass() {
+ CHECK(!static_class_.IsNull());
+ static_class_ = GcRoot<Class>(nullptr);
+}
+
+void MethodHandleImpl::VisitRoots(RootVisitor* visitor) {
+ static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+} // namespace mirror
+} // namespace art
diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h
new file mode 100644
index 0000000..a0aae3c
--- /dev/null
+++ b/runtime/mirror/method_handle_impl.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
+#define ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
+
+#include "class.h"
+#include "gc_root.h"
+#include "object.h"
+#include "method_type.h"
+
+namespace art {
+
+struct MethodHandleImplOffsets;
+
+namespace mirror {
+
+// C++ mirror of java.lang.invoke.MethodHandle
+class MANAGED MethodHandle : public Object {
+ public:
+ mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetFieldObject<mirror::MethodType>(OFFSET_OF_OBJECT_MEMBER(MethodHandle, method_type_));
+ }
+
+ ArtMethod* GetTargetMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return reinterpret_cast<ArtMethod*>(
+ GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_)));
+ }
+
+ private:
+ HeapReference<mirror::Object> as_type_cache_;
+ HeapReference<mirror::MethodType> method_type_;
+ uint64_t art_field_or_method_;
+ uint32_t handle_kind_;
+
+ private:
+ static MemberOffset AsTypeCacheOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodHandle, as_type_cache_));
+ }
+ static MemberOffset MethodTypeOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodHandle, method_type_));
+ }
+ static MemberOffset ArtFieldOrMethodOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodHandle, art_field_or_method_));
+ }
+ static MemberOffset HandleKindOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodHandle, handle_kind_));
+ }
+
+ friend struct art::MethodHandleImplOffsets; // for verifying offset information
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandle);
+};
+
+// C++ mirror of java.lang.invoke.MethodHandleImpl
+class MANAGED MethodHandleImpl : public MethodHandle {
+ public:
+ static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return static_class_.Read();
+ }
+
+ static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
+ static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
+
+ private:
+ static GcRoot<mirror::Class> static_class_; // java.lang.invoke.MethodHandleImpl.class
+
+ friend struct art::MethodHandleImplOffsets; // for verifying offset information
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandleImpl);
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
diff --git a/runtime/mirror/method_type.cc b/runtime/mirror/method_type.cc
new file mode 100644
index 0000000..ba6ea5e
--- /dev/null
+++ b/runtime/mirror/method_type.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "method_type.h"
+
+#include "class-inl.h"
+#include "gc_root-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<mirror::Class> MethodType::static_class_;
+
+mirror::MethodType* MethodType::Create(Thread* const self,
+ Handle<Class> return_type,
+ Handle<ObjectArray<Class>> param_types) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::MethodType> mt(
+ hs.NewHandle(static_cast<MethodType*>(StaticClass()->AllocObject(self))));
+
+ // TODO: Do we ever create a MethodType during a transaction ? There doesn't
+ // seem like a good reason to do a polymorphic invoke that results in the
+ // resolution of a method type in an unstarted runtime.
+ mt->SetFieldObject<false>(FormOffset(), nullptr);
+ mt->SetFieldObject<false>(MethodDescriptorOffset(), nullptr);
+ mt->SetFieldObject<false>(RTypeOffset(), return_type.Get());
+ mt->SetFieldObject<false>(PTypesOffset(), param_types.Get());
+ mt->SetFieldObject<false>(WrapAltOffset(), nullptr);
+
+ return mt.Get();
+}
+
+bool MethodType::IsExactMatch(mirror::MethodType* other) REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (GetRType() != other->GetRType()) {
+ return false;
+ }
+
+ mirror::ObjectArray<Class>* const p_types = GetPTypes();
+ const int32_t params_length = p_types->GetLength();
+
+ mirror::ObjectArray<Class>* const other_p_types = other->GetPTypes();
+ if (params_length != other_p_types->GetLength()) {
+ return false;
+ }
+
+ for (int32_t i = 0; i < params_length; ++i) {
+ if (p_types->GetWithoutChecks(i) != other_p_types->GetWithoutChecks(i)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void MethodType::SetClass(Class* klass) {
+ CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ static_class_ = GcRoot<Class>(klass);
+}
+
+void MethodType::ResetClass() {
+ CHECK(!static_class_.IsNull());
+ static_class_ = GcRoot<Class>(nullptr);
+}
+
+void MethodType::VisitRoots(RootVisitor* visitor) {
+ static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+} // namespace mirror
+} // namespace art
diff --git a/runtime/mirror/method_type.h b/runtime/mirror/method_type.h
new file mode 100644
index 0000000..5b50409
--- /dev/null
+++ b/runtime/mirror/method_type.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_METHOD_TYPE_H_
+#define ART_RUNTIME_MIRROR_METHOD_TYPE_H_
+
+#include "object.h"
+#include "string.h"
+#include "mirror/object_array.h"
+#include "utils.h"
+
+namespace art {
+
+struct MethodTypeOffsets;
+
+namespace mirror {
+
+// C++ mirror of java.lang.invoke.MethodType
+class MANAGED MethodType : public Object {
+ public:
+ static mirror::MethodType* Create(Thread* const self,
+ Handle<Class> return_type,
+ Handle<ObjectArray<Class>> param_types)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
+
+ static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return static_class_.Read();
+ }
+
+ ObjectArray<Class>* GetPTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetFieldObject<ObjectArray<Class>>(OFFSET_OF_OBJECT_MEMBER(MethodType, p_types_));
+ }
+
+ Class* GetRType() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(MethodType, r_type_));
+ }
+
+ static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
+ static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Returns true iff. |other| is an exact match for this method type, i.e
+ // iff. they have the same return types and parameter types.
+ bool IsExactMatch(mirror::MethodType* other) REQUIRES_SHARED(Locks::mutator_lock_);
+
+ private:
+ static MemberOffset FormOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodType, form_));
+ }
+
+ static MemberOffset MethodDescriptorOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodType, method_descriptor_));
+ }
+
+ static MemberOffset PTypesOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodType, p_types_));
+ }
+
+ static MemberOffset RTypeOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodType, r_type_));
+ }
+
+ static MemberOffset WrapAltOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(MethodType, wrap_alt_));
+ }
+
+ HeapReference<mirror::Object> form_; // Unused in the runtime
+ HeapReference<mirror::String> method_descriptor_; // Unused in the runtime
+ HeapReference<ObjectArray<mirror::Class>> p_types_;
+ HeapReference<mirror::Class> r_type_;
+ HeapReference<mirror::Object> wrap_alt_; // Unused in the runtime
+
+ static GcRoot<mirror::Class> static_class_; // java.lang.invoke.MethodType.class
+
+ friend struct art::MethodTypeOffsets; // for verifying offset information
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MethodType);
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_METHOD_TYPE_H_
diff --git a/runtime/mirror/method_type_test.cc b/runtime/mirror/method_type_test.cc
new file mode 100644
index 0000000..a968bff
--- /dev/null
+++ b/runtime/mirror/method_type_test.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "method_type.h"
+
+#include <string>
+#include <vector>
+
+#include "class_linker.h"
+#include "common_runtime_test.h"
+#include "handle_scope-inl.h"
+#include "runtime/mirror/class.h"
+#include "runtime/mirror/class_loader.h"
+#include "scoped_thread_state_change.h"
+
+namespace art {
+namespace mirror {
+
+class MethodTypeTest : public CommonRuntimeTest {};
+
+static std::string FullyQualifiedType(const std::string& shorthand) {
+ return "Ljava/lang/" + shorthand + ";";
+}
+
+static mirror::MethodType* CreateMethodType(const std::string& return_type,
+ const std::vector<std::string>& param_types) {
+ CHECK_LT(param_types.size(), 3u);
+
+ Runtime* const runtime = Runtime::Current();
+ ClassLinker* const class_linker = runtime->GetClassLinker();
+ Thread* const self = Thread::Current();
+
+ ScopedObjectAccess soa(self);
+ StackHandleScope<5> hs(soa.Self());
+
+ Handle<mirror::ClassLoader> boot_class_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
+
+ Handle<mirror::Class> return_clazz = hs.NewHandle(class_linker->FindClass(
+ soa.Self(), FullyQualifiedType(return_type).c_str(), boot_class_loader));
+ CHECK(return_clazz.Get() != nullptr);
+
+ mirror::Class* class_type = mirror::Class::GetJavaLangClass();
+ mirror::Class* class_array_type = class_linker->FindArrayClass(self, &class_type);
+ Handle<mirror::ObjectArray<mirror::Class>> param_classes = hs.NewHandle(
+ mirror::ObjectArray<mirror::Class>::Alloc(self, class_array_type, param_types.size()));
+
+ for (uint32_t i = 0; i < param_types.size(); ++i) {
+ Handle<mirror::Class> param = hs.NewHandle(class_linker->FindClass(
+ soa.Self(), FullyQualifiedType(param_types[i]).c_str(), boot_class_loader));
+ param_classes->Set(i, param.Get());
+ }
+
+ return mirror::MethodType::Create(self, return_clazz, param_classes);
+}
+
+
+TEST_F(MethodTypeTest, IsExactMatch) {
+ ScopedObjectAccess soa(Thread::Current());
+ {
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::MethodType> mt1 = hs.NewHandle(CreateMethodType("String", { "Integer" }));
+ Handle<mirror::MethodType> mt2 = hs.NewHandle(CreateMethodType("String", { "Integer" }));
+ ASSERT_TRUE(mt1->IsExactMatch(mt2.Get()));
+ }
+
+ // Mismatched return type.
+ {
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::MethodType> mt1 = hs.NewHandle(CreateMethodType("String", { "Integer" }));
+ Handle<mirror::MethodType> mt2 = hs.NewHandle(CreateMethodType("Integer", { "Integer" }));
+ ASSERT_FALSE(mt1->IsExactMatch(mt2.Get()));
+ }
+
+ // Mismatched param types.
+ {
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::MethodType> mt1 = hs.NewHandle(CreateMethodType("String", { "Integer" }));
+ Handle<mirror::MethodType> mt2 = hs.NewHandle(CreateMethodType("String", { "String" }));
+ ASSERT_FALSE(mt1->IsExactMatch(mt2.Get()));
+ }
+
+ // Wrong number of param types.
+ {
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::MethodType> mt1 = hs.NewHandle(
+ CreateMethodType("String", { "String", "String" }));
+ Handle<mirror::MethodType> mt2 = hs.NewHandle(CreateMethodType("String", { "String" }));
+ ASSERT_FALSE(mt1->IsExactMatch(mt2.Get()));
+ }
+}
+
+} // namespace mirror
+} // namespace art
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 0f5cbb2..ad7558c 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -31,6 +31,7 @@
#include "lock_word-inl.h"
#include "monitor.h"
#include "object_array-inl.h"
+#include "obj_ptr-inl.h"
#include "read_barrier-inl.h"
#include "reference.h"
#include "runtime.h"
@@ -281,7 +282,7 @@
}
template<VerifyObjectFlags kVerifyFlags>
-inline bool Object::InstanceOf(Class* klass) {
+inline bool Object::InstanceOf(ObjPtr<Class> klass) {
DCHECK(klass != nullptr);
DCHECK(GetClass<kVerifyNone>() != nullptr);
return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
@@ -509,7 +510,7 @@
template GetObjectSize<kNewFlags, kReadBarrierOption>();
}
DCHECK_GE(result, sizeof(Object))
- << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>());
+ << " class=" << PrettyClass(GetClass<kNewFlags, kReadBarrierOption>());
return result;
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 262cb57..10faf60 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -20,6 +20,7 @@
#include "base/casts.h"
#include "base/enums.h"
#include "globals.h"
+#include "obj_ptr.h"
#include "object_reference.h"
#include "offsets.h"
#include "verify_object.h"
@@ -120,7 +121,7 @@
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool VerifierInstanceOf(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE bool InstanceOf(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ ALWAYS_INLINE bool InstanceOf(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index f4ecfb5..40ee3a2 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -38,7 +38,7 @@
#include "obj_ptr.h"
#include "object-inl.h"
#include "object_array-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "string-inl.h"
namespace art {
@@ -365,7 +365,7 @@
const DexFile* dex_file = GetFirstDexFile(class_loader);
StackHandleScope<2> hs(soa.Self());
- Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<ClassLoader*>(class_loader)));
+ Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<ClassLoader>(class_loader)));
Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", loader);
ArtMethod* clinit = klass->FindClassInitializer(kRuntimePointerSize);
const DexFile::TypeId* klass_type_id = dex_file->FindTypeId("LStaticsFromCode;");
@@ -495,8 +495,8 @@
jobject jclass_loader_1 = LoadDex("ProtoCompare");
jobject jclass_loader_2 = LoadDex("ProtoCompare2");
StackHandleScope<4> hs(soa.Self());
- Handle<ClassLoader> class_loader_1(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader_1)));
- Handle<ClassLoader> class_loader_2(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader_2)));
+ Handle<ClassLoader> class_loader_1(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader_1)));
+ Handle<ClassLoader> class_loader_2(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader_2)));
Class* klass1 = linker->FindClass(soa.Self(), "LProtoCompare;", class_loader_1);
ASSERT_TRUE(klass1 != nullptr);
@@ -538,7 +538,7 @@
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("XandY");
StackHandleScope<3> hs(soa.Self());
- Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader)));
+ Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader)));
Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
@@ -575,7 +575,7 @@
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("XandY");
StackHandleScope<1> hs(soa.Self());
- Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader)));
+ Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader)));
Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
@@ -613,7 +613,7 @@
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("XandY");
StackHandleScope<1> hs(soa.Self());
- Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader)));
+ Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader)));
Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
ASSERT_TRUE(X != nullptr);
@@ -746,25 +746,25 @@
ObjPtr<mirror::Object, /*kPoison*/ true> null_ptr;
EXPECT_TRUE(null_ptr.IsNull());
EXPECT_TRUE(null_ptr.IsValid());
- EXPECT_TRUE(null_ptr.Get() == nullptr);
+ EXPECT_TRUE(null_ptr.Decode() == nullptr);
EXPECT_TRUE(null_ptr == nullptr);
EXPECT_TRUE(null_ptr == null_ptr);
EXPECT_FALSE(null_ptr != null_ptr);
EXPECT_FALSE(null_ptr != nullptr);
null_ptr.AssertValid();
- Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader)));
+ Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader)));
Handle<mirror::Class> h_X(
hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)));
ObjPtr<Class, /*kPoison*/ true> X(h_X.Get());
EXPECT_TRUE(!X.IsNull());
EXPECT_TRUE(X.IsValid());
- EXPECT_TRUE(X.Get() != nullptr);
- EXPECT_EQ(h_X.Get(), X.Get());
+ EXPECT_TRUE(X.Decode() != nullptr);
+ EXPECT_EQ(h_X.Get(), X.Decode());
// FindClass may cause thread suspension, it should invalidate X.
ObjPtr<Class, /*kPoison*/ true> Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader));
EXPECT_TRUE(!Y.IsNull());
EXPECT_TRUE(Y.IsValid());
- EXPECT_TRUE(Y.Get() != nullptr);
+ EXPECT_TRUE(Y.Decode() != nullptr);
// Should IsNull be safe to call on null ObjPtr? I'll allow it for now.
EXPECT_TRUE(!X.IsNull());
@@ -773,7 +773,7 @@
X.Assign(h_X.Get());
EXPECT_TRUE(!X.IsNull());
EXPECT_TRUE(X.IsValid());
- EXPECT_EQ(h_X.Get(), X.Get());
+ EXPECT_EQ(h_X.Get(), X.Decode());
// Allow thread suspension to invalidate Y.
soa.Self()->AllowThreadSuspension();
@@ -784,7 +784,7 @@
ObjPtr<mirror::Object, /*kPoison*/ false> unpoisoned;
EXPECT_TRUE(unpoisoned.IsNull());
EXPECT_TRUE(unpoisoned.IsValid());
- EXPECT_TRUE(unpoisoned.Get() == nullptr);
+ EXPECT_TRUE(unpoisoned.Decode() == nullptr);
EXPECT_TRUE(unpoisoned == nullptr);
EXPECT_TRUE(unpoisoned == unpoisoned);
EXPECT_FALSE(unpoisoned != unpoisoned);
@@ -793,7 +793,7 @@
unpoisoned = h_X.Get();
EXPECT_FALSE(unpoisoned.IsNull());
EXPECT_TRUE(unpoisoned == h_X.Get());
- EXPECT_EQ(unpoisoned.Get(), h_X.Get());
+ EXPECT_EQ(unpoisoned.Decode(), h_X.Get());
}
} // namespace mirror
diff --git a/runtime/modifiers.h b/runtime/modifiers.h
index fd7a125..dd32df6 100644
--- a/runtime/modifiers.h
+++ b/runtime/modifiers.h
@@ -67,6 +67,7 @@
// Set by the verifier for a method that could not be verified to follow structured locking.
static constexpr uint32_t kAccMustCountLocks = 0x02000000; // method (runtime)
+static constexpr uint32_t kAccIntrinsic = 0x80000000; // method (runtime)
// Special runtime-only flags.
// Interface and all its super-interfaces with default methods have been recursively initialized.
@@ -76,6 +77,9 @@
// class/ancestor overrides finalize()
static constexpr uint32_t kAccClassIsFinalizable = 0x80000000;
+static constexpr uint32_t kAccFlagsNotUsedByIntrinsic = 0x007FFFFF;
+static constexpr uint32_t kAccMaxIntrinsic = 0xFF;
+
// Valid (meaningful) bits for a field.
static constexpr uint32_t kAccValidFieldFlags = kAccPublic | kAccPrivate | kAccProtected |
kAccStatic | kAccFinal | kAccVolatile | kAccTransient | kAccSynthetic | kAccEnum;
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 49b83a7..3bc1b06 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -30,7 +30,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "thread_list.h"
#include "verifier/method_verifier.h"
diff --git a/runtime/monitor_pool_test.cc b/runtime/monitor_pool_test.cc
index e1837f5..a111c6c 100644
--- a/runtime/monitor_pool_test.cc
+++ b/runtime/monitor_pool_test.cc
@@ -17,7 +17,7 @@
#include "monitor_pool.h"
#include "common_runtime_test.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
diff --git a/runtime/monitor_test.cc b/runtime/monitor_test.cc
index ac6a4f3..4ee46dc 100644
--- a/runtime/monitor_test.cc
+++ b/runtime/monitor_test.cc
@@ -27,7 +27,7 @@
#include "mirror/class-inl.h"
#include "mirror/string-inl.h" // Strings are easiest to allocate
#include "object_lock.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_pool.h"
namespace art {
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 384de34..0677d5b 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -34,7 +34,7 @@
#include "oat_file_manager.h"
#include "os.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "utils.h"
@@ -217,7 +217,7 @@
bool all_deleted = true;
{
ScopedObjectAccess soa(env);
- mirror::Object* dex_files_object = soa.Decode<mirror::Object*>(cookie);
+ ObjPtr<mirror::Object> dex_files_object = soa.Decode<mirror::Object>(cookie);
mirror::LongArray* long_dex_files = dex_files_object->AsLongArray();
// Delete dex files associated with this dalvik.system.DexFile since there should not be running
// code using it. dex_files is a vector due to multidex.
@@ -277,7 +277,7 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
class_linker->RegisterDexFile(*dex_file, class_loader.Get());
mirror::Class* result = class_linker->DefineClass(soa.Self(),
descriptor.c_str(),
@@ -287,7 +287,7 @@
*dex_class_def);
// Add the used dex file. This only required for the DexFile.loadClass API since normal
// class loaders already keep their dex files live.
- class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object*>(dexFile),
+ class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile).Decode(),
class_loader.Get());
if (result != nullptr) {
VLOG(class_linker) << "DexFile_defineClassNative returning " << result
diff --git a/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc b/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc
index 94933bc..fdced21 100644
--- a/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc
+++ b/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc
@@ -24,7 +24,7 @@
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
#include "oat_file.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedUtfChars.h"
namespace art {
@@ -148,7 +148,7 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<1> handle_scope(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- handle_scope.NewHandle(soa.Decode<mirror::ClassLoader*>(loader)));
+ handle_scope.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
class_linker->RegisterDexFile(*dex_file, class_loader.Get());
mirror::Class* result = class_linker->DefineClass(
soa.Self(), class_descriptor, hash, class_loader, *dex_file, *dex_class_def);
@@ -157,7 +157,7 @@
// InMemoryClassLoader/DexData instance now that a class has
// been loaded.
class_linker->InsertDexFileInToClassLoader(
- soa.Decode<mirror::Object*>(dexData), class_loader.Get());
+ soa.Decode<mirror::Object>(dexData).Decode(), class_loader.Get());
return soa.AddLocalReference<jclass>(result);
}
}
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index f09c067..73c4664 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -36,7 +36,7 @@
#include "mirror/class.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "trace.h"
#include "well_known_classes.h"
@@ -259,11 +259,11 @@
ScopedObjectAccess soa(env);
gc::Heap* const heap = Runtime::Current()->GetHeap();
// Caller's responsibility to do GC if desired.
- mirror::Class* c = soa.Decode<mirror::Class*>(javaClass);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass);
if (c == nullptr) {
return 0;
}
- std::vector<mirror::Class*> classes {c};
+ std::vector<mirror::Class*> classes {c.Decode()};
uint64_t count = 0;
heap->CountInstances(classes, countAssignable, &count);
return count;
@@ -274,7 +274,8 @@
ScopedObjectAccess soa(env);
gc::Heap* const heap = Runtime::Current()->GetHeap();
// Caller's responsibility to do GC if desired.
- auto* decoded_classes = soa.Decode<mirror::ObjectArray<mirror::Class>*>(javaClasses);
+ ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
+ soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
if (decoded_classes == nullptr) {
return nullptr;
}
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index d88c9d4..c7fb44ec 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -46,8 +46,8 @@
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "runtime.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "thread_list.h"
@@ -74,7 +74,7 @@
ThrowNegativeArraySizeException(length);
return nullptr;
}
- mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
+ mirror::Class* element_class = soa.Decode<mirror::Class>(javaElementClass).Decode();
if (UNLIKELY(element_class == nullptr)) {
ThrowNullPointerException("element class == null");
return nullptr;
@@ -99,7 +99,7 @@
ThrowNegativeArraySizeException(length);
return nullptr;
}
- mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
+ mirror::Class* element_class = soa.Decode<mirror::Class>(javaElementClass).Decode();
if (UNLIKELY(element_class == nullptr)) {
ThrowNullPointerException("element class == null");
return nullptr;
@@ -122,12 +122,12 @@
return 0;
}
ScopedFastNativeObjectAccess soa(env);
- mirror::Array* array = soa.Decode<mirror::Array*>(javaArray);
+ ObjPtr<mirror::Array> array = soa.Decode<mirror::Array>(javaArray);
if (!array->IsArrayInstance()) {
ThrowIllegalArgumentException("not an array");
return 0;
}
- if (Runtime::Current()->GetHeap()->IsMovableObject(array)) {
+ if (Runtime::Current()->GetHeap()->IsMovableObject(array.Decode())) {
ThrowRuntimeException("Trying to get address of movable array object");
return 0;
}
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 9da40b9..0dd8cdd 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -22,8 +22,8 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
namespace art {
@@ -31,7 +31,7 @@
static jobject GetThreadStack(const ScopedFastNativeObjectAccess& soa, jobject peer)
REQUIRES_SHARED(Locks::mutator_lock_) {
jobject trace = nullptr;
- if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) {
+ if (soa.Decode<mirror::Object>(peer) == soa.Self()->GetPeer()) {
trace = soa.Self()->CreateInternalStackTrace<false>(soa);
} else {
// Suspend thread to build stack trace.
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index fe3cbe7..a78909b 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -24,7 +24,7 @@
#include "jit/jit.h"
#include "jni_internal.h"
#include "JNIHelp.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedUtfChars.h"
#include "thread-inl.h"
#include "trace.h"
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index af9b68f..34bd57b 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -33,9 +33,10 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
+#include "obj_ptr-inl.h"
#include "reflection.h"
-#include "scoped_thread_state_change.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_thread_state_change-inl.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "utf.h"
@@ -43,10 +44,10 @@
namespace art {
-ALWAYS_INLINE static inline mirror::Class* DecodeClass(
+ALWAYS_INLINE static inline ObjPtr<mirror::Class> DecodeClass(
const ScopedFastNativeObjectAccess& soa, jobject java_class)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
DCHECK(c != nullptr);
DCHECK(c->IsClass());
// TODO: we could EnsureInitialized here, rather than on every reflective get/set or invoke .
@@ -75,16 +76,19 @@
std::string descriptor(DotToDescriptor(name.c_str()));
StackHandleScope<2> hs(soa.Self());
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
+ Handle<mirror::ClassLoader> class_loader(
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<mirror::Class> c(
hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader)));
if (c.Get() == nullptr) {
ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
env->ExceptionClear();
- jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
- WellKnownClasses::java_lang_ClassNotFoundException_init,
- javaName, cause.get()));
+ jthrowable cnfe = reinterpret_cast<jthrowable>(
+ env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
+ WellKnownClasses::java_lang_ClassNotFoundException_init,
+ javaName,
+ cause.get()));
if (cnfe != nullptr) {
// Make sure allocation didn't fail with an OOME.
env->Throw(cnfe);
@@ -100,18 +104,18 @@
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- mirror::Class* const c = DecodeClass(soa, javaThis);
+ ObjPtr<mirror::Class> c = DecodeClass(soa, javaThis);
return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
}
static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Class* c = DecodeClass(soa, javaThis);
+ ObjPtr<mirror::Class> c = DecodeClass(soa, javaThis);
return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
}
static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
- Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
+ Thread* self, ObjPtr<mirror::Class> klass, bool public_only, bool force_resolve)
REQUIRES_SHARED(Locks::mutator_lock_) {
StackHandleScope<1> hs(self);
IterationRange<StrideIterator<ArtField>> ifields = klass->GetIFields();
@@ -191,8 +195,8 @@
// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
// fast.
-ALWAYS_INLINE static inline ArtField* FindFieldByName(
- Thread* self ATTRIBUTE_UNUSED, mirror::String* name, LengthPrefixedArray<ArtField>* fields)
+ALWAYS_INLINE static inline ArtField* FindFieldByName(ObjPtr<mirror::String> name,
+ LengthPrefixedArray<ArtField>* fields)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (fields == nullptr) {
return nullptr;
@@ -236,14 +240,15 @@
return nullptr;
}
-ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
- Thread* self, mirror::Class* c, mirror::String* name)
+ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(Thread* self,
+ ObjPtr<mirror::Class> c,
+ ObjPtr<mirror::String> name)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ArtField* art_field = FindFieldByName(self, name, c->GetIFieldsPtr());
+ ArtField* art_field = FindFieldByName(name, c->GetIFieldsPtr());
if (art_field != nullptr) {
return mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, art_field, true);
}
- art_field = FindFieldByName(self, name, c->GetSFieldsPtr());
+ art_field = FindFieldByName(name, c->GetSFieldsPtr());
if (art_field != nullptr) {
return mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, art_field, true);
}
@@ -251,7 +256,7 @@
}
static mirror::Field* GetPublicFieldRecursive(
- Thread* self, mirror::Class* clazz, mirror::String* name)
+ Thread* self, ObjPtr<mirror::Class> clazz, ObjPtr<mirror::String> name)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(clazz != nullptr);
DCHECK(name != nullptr);
@@ -301,7 +306,7 @@
static jobject Class_getPublicFieldRecursive(JNIEnv* env, jobject javaThis, jstring name) {
ScopedFastNativeObjectAccess soa(env);
- auto* name_string = soa.Decode<mirror::String*>(name);
+ auto name_string = soa.Decode<mirror::String>(name);
if (UNLIKELY(name_string == nullptr)) {
ThrowNullPointerException("name == null");
return nullptr;
@@ -312,16 +317,18 @@
static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
ScopedFastNativeObjectAccess soa(env);
- auto* name_string = soa.Decode<mirror::String*>(name);
- if (name_string == nullptr) {
+ StackHandleScope<3> hs(soa.Self());
+ Handle<mirror::String> h_string = hs.NewHandle(soa.Decode<mirror::String>(name));
+ if (h_string.Get() == nullptr) {
ThrowNullPointerException("name == null");
return nullptr;
}
- auto* klass = DecodeClass(soa, javaThis);
- mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
- if (result == nullptr) {
- std::string name_str = name_string->ToModifiedUtf8();
- if (name_str == "value" && klass->IsStringClass()) {
+ Handle<mirror::Class> h_klass = hs.NewHandle(DecodeClass(soa, javaThis));
+ Handle<mirror::Field> result =
+ hs.NewHandle(GetDeclaredField(soa.Self(), h_klass.Get(), h_string.Get()));
+ if (result.Get() == nullptr) {
+ std::string name_str = h_string->ToModifiedUtf8();
+ if (name_str == "value" && h_klass->IsStringClass()) {
// We log the error for this specific case, as the user might just swallow the exception.
// This helps diagnose crashes when applications rely on the String#value field being
// there.
@@ -332,11 +339,11 @@
}
// We may have a pending exception if we failed to resolve.
if (!soa.Self()->IsExceptionPending()) {
- ThrowNoSuchFieldException(DecodeClass(soa, javaThis), name_str.c_str());
+ ThrowNoSuchFieldException(h_klass.Get(), name_str.c_str());
}
return nullptr;
}
- return soa.AddLocalReference<jobject>(result);
+ return soa.AddLocalReference<jobject>(result.Get());
}
static jobject Class_getDeclaredConstructorInternal(
@@ -344,11 +351,11 @@
ScopedFastNativeObjectAccess soa(env);
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
DCHECK(!Runtime::Current()->IsActiveTransaction());
- mirror::Constructor* result = mirror::Class::GetDeclaredConstructorInternal<kRuntimePointerSize,
- false>(
+ ObjPtr<mirror::Constructor> result =
+ mirror::Class::GetDeclaredConstructorInternal<kRuntimePointerSize, false>(
soa.Self(),
- DecodeClass(soa, javaThis),
- soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
+ DecodeClass(soa, javaThis).Decode(),
+ soa.Decode<mirror::ObjectArray<mirror::Class>>(args).Decode());
return soa.AddLocalReference<jobject>(result);
}
@@ -398,9 +405,9 @@
DCHECK(!Runtime::Current()->IsActiveTransaction());
mirror::Method* result = mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(
soa.Self(),
- DecodeClass(soa, javaThis),
- soa.Decode<mirror::String*>(name),
- soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
+ DecodeClass(soa, javaThis).Decode(),
+ soa.Decode<mirror::String>(name).Decode(),
+ soa.Decode<mirror::ObjectArray<mirror::Class>>(args).Decode());
return soa.AddLocalReference<jobject>(result);
}
@@ -453,7 +460,7 @@
if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
return nullptr;
}
- Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationClass)));
+ Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class>(annotationClass)));
return soa.AddLocalReference<jobject>(
annotations::GetAnnotationForClass(klass, annotation_class));
}
@@ -464,10 +471,12 @@
Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
// Return an empty array instead of a null pointer.
- mirror::Class* annotation_array_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
+ ObjPtr<mirror::Class> annotation_array_class =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
mirror::ObjectArray<mirror::Object>* empty_array =
- mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
+ mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(),
+ annotation_array_class.Decode(),
+ 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForClass(klass));
@@ -519,8 +528,8 @@
}
mirror::Object* method = annotations::GetEnclosingMethod(klass);
if (method != nullptr) {
- if (method->GetClass() ==
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor)) {
+ if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) ==
+ method->GetClass()) {
return soa.AddLocalReference<jobject>(method);
}
}
@@ -536,8 +545,8 @@
}
mirror::Object* method = annotations::GetEnclosingMethod(klass);
if (method != nullptr) {
- if (method->GetClass() ==
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method)) {
+ if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) ==
+ method->GetClass()) {
return soa.AddLocalReference<jobject>(method);
}
}
@@ -598,7 +607,7 @@
if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
return false;
}
- Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+ Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
return annotations::IsClassAnnotationPresent(klass, annotation_class);
}
@@ -669,7 +678,10 @@
caller.Assign(GetCallingClass(soa.Self(), 1));
}
if (UNLIKELY(caller.Get() != nullptr && !VerifyAccess(
- receiver.Get(), declaring_class, constructor->GetAccessFlags(), caller.Get()))) {
+ MakeObjPtr(receiver.Get()),
+ MakeObjPtr(declaring_class),
+ constructor->GetAccessFlags(),
+ MakeObjPtr(caller.Get())))) {
soa.Self()->ThrowNewExceptionF(
"Ljava/lang/IllegalAccessException;", "%s is not accessible from %s",
PrettyMethod(constructor).c_str(), PrettyClass(caller.Get()).c_str());
diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc
index f0140a3..5efafe7 100644
--- a/runtime/native/java_lang_DexCache.cc
+++ b/runtime/native/java_lang_DexCache.cc
@@ -21,14 +21,14 @@
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes.h"
namespace art {
static jobject DexCache_getDexNative(JNIEnv* env, jobject javaDexCache) {
ScopedFastNativeObjectAccess soa(env);
- mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+ ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
// Should only be called while holding the lock on the dex cache.
DCHECK_EQ(dex_cache->GetLockOwnerThreadId(), soa.Self()->GetThreadId());
const DexFile* dex_file = dex_cache->GetDexFile();
@@ -51,14 +51,14 @@
static jobject DexCache_getResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index) {
ScopedFastNativeObjectAccess soa(env);
- mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+ ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
CHECK_LT(static_cast<size_t>(type_index), dex_cache->NumResolvedTypes());
return soa.AddLocalReference<jobject>(dex_cache->GetResolvedType(type_index));
}
static jobject DexCache_getResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index) {
ScopedFastNativeObjectAccess soa(env);
- mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+ ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
return soa.AddLocalReference<jobject>(dex_cache->GetResolvedString(string_index));
}
@@ -66,17 +66,17 @@
static void DexCache_setResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index,
jobject type) {
ScopedFastNativeObjectAccess soa(env);
- mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+ ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
CHECK_LT(static_cast<size_t>(type_index), dex_cache->NumResolvedTypes());
- dex_cache->SetResolvedType(type_index, soa.Decode<mirror::Class*>(type));
+ dex_cache->SetResolvedType(type_index, soa.Decode<mirror::Class>(type).Decode());
}
static void DexCache_setResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index,
jobject string) {
ScopedFastNativeObjectAccess soa(env);
- mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+ ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
- dex_cache->SetResolvedString(string_index, soa.Decode<mirror::String*>(string));
+ dex_cache->SetResolvedString(string_index, soa.Decode<mirror::String>(string).Decode());
}
static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc
index 2a36059..6493865 100644
--- a/runtime/native/java_lang_Object.cc
+++ b/runtime/native/java_lang_Object.cc
@@ -18,39 +18,35 @@
#include "jni_internal.h"
#include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
namespace art {
static jobject Object_internalClone(JNIEnv* env, jobject java_this) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_this);
return soa.AddLocalReference<jobject>(o->Clone(soa.Self()));
}
static void Object_notify(JNIEnv* env, jobject java_this) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->Notify(soa.Self());
+ soa.Decode<mirror::Object>(java_this)->Notify(soa.Self());
}
static void Object_notifyAll(JNIEnv* env, jobject java_this) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->NotifyAll(soa.Self());
+ soa.Decode<mirror::Object>(java_this)->NotifyAll(soa.Self());
}
static void Object_wait(JNIEnv* env, jobject java_this) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->Wait(soa.Self());
+ soa.Decode<mirror::Object>(java_this)->Wait(soa.Self());
}
static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
- o->Wait(soa.Self(), ms, ns);
+ soa.Decode<mirror::Object>(java_this)->Wait(soa.Self(), ms, ns);
}
static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc
index aa64b79..b3a967d 100644
--- a/runtime/native/java_lang_String.cc
+++ b/runtime/native/java_lang_String.cc
@@ -22,8 +22,8 @@
#include "mirror/object-inl.h"
#include "mirror/string.h"
#include "mirror/string-inl.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "verify_object-inl.h"
@@ -31,7 +31,7 @@
static jchar String_charAt(JNIEnv* env, jobject java_this, jint index) {
ScopedFastNativeObjectAccess soa(env);
- return soa.Decode<mirror::String*>(java_this)->CharAt(index);
+ return soa.Decode<mirror::String>(java_this)->CharAt(index);
}
static jint String_compareTo(JNIEnv* env, jobject java_this, jobject java_rhs) {
@@ -40,7 +40,8 @@
ThrowNullPointerException("rhs == null");
return -1;
} else {
- return soa.Decode<mirror::String*>(java_this)->CompareTo(soa.Decode<mirror::String*>(java_rhs));
+ return soa.Decode<mirror::String>(java_this)->CompareTo(
+ soa.Decode<mirror::String>(java_rhs).Decode());
}
}
@@ -51,8 +52,8 @@
return nullptr;
}
StackHandleScope<2> hs(soa.Self());
- Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String*>(java_this)));
- Handle<mirror::String> string_arg(hs.NewHandle(soa.Decode<mirror::String*>(java_string_arg)));
+ Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
+ Handle<mirror::String> string_arg(hs.NewHandle(soa.Decode<mirror::String>(java_string_arg)));
int32_t length_this = string_this->GetLength();
int32_t length_arg = string_arg->GetLength();
if (length_arg > 0 && length_this > 0) {
@@ -67,13 +68,13 @@
ScopedFastNativeObjectAccess soa(env);
// This method does not handle supplementary characters. They're dealt with in managed code.
DCHECK_LE(ch, 0xffff);
- return soa.Decode<mirror::String*>(java_this)->FastIndexOf(ch, start);
+ return soa.Decode<mirror::String>(java_this)->FastIndexOf(ch, start);
}
static jstring String_fastSubstring(JNIEnv* env, jobject java_this, jint start, jint length) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String*>(java_this)));
+ Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
mirror::String* result = mirror::String::AllocFromString<true>(soa.Self(), length, string_this,
start, allocator_type);
@@ -84,25 +85,24 @@
jcharArray buffer, jint index) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray*>(buffer)));
- soa.Decode<mirror::String*>(java_this)->GetChars(start, end, char_array, index);
+ Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray>(buffer)));
+ soa.Decode<mirror::String>(java_this)->GetChars(start, end, char_array, index);
}
static jstring String_intern(JNIEnv* env, jobject java_this) {
ScopedFastNativeObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_this);
- mirror::String* result = s->Intern();
+ ObjPtr<mirror::String> result = soa.Decode<mirror::String>(java_this)->Intern();
return soa.AddLocalReference<jstring>(result);
}
static void String_setCharAt(JNIEnv* env, jobject java_this, jint index, jchar c) {
ScopedFastNativeObjectAccess soa(env);
- soa.Decode<mirror::String*>(java_this)->SetCharAt(index, c);
+ soa.Decode<mirror::String>(java_this)->SetCharAt(index, c);
}
static jcharArray String_toCharArray(JNIEnv* env, jobject java_this) {
ScopedFastNativeObjectAccess soa(env);
- mirror::String* s = soa.Decode<mirror::String*>(java_this);
+ ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_this);
return soa.AddLocalReference<jcharArray>(s->ToCharArray(soa.Self()));
}
diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc
index 5a219ef..119f2b8 100644
--- a/runtime/native/java_lang_StringFactory.cc
+++ b/runtime/native/java_lang_StringFactory.cc
@@ -20,8 +20,8 @@
#include "jni_internal.h"
#include "mirror/object-inl.h"
#include "mirror/string.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
@@ -35,7 +35,7 @@
return nullptr;
}
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ByteArray> byte_array(hs.NewHandle(soa.Decode<mirror::ByteArray*>(java_data)));
+ Handle<mirror::ByteArray> byte_array(hs.NewHandle(soa.Decode<mirror::ByteArray>(java_data)));
int32_t data_size = byte_array->GetLength();
if ((offset | byte_count) < 0 || byte_count > data_size - offset) {
soa.Self()->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
@@ -56,7 +56,7 @@
DCHECK(java_data != nullptr);
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray*>(java_data)));
+ Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray>(java_data)));
gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
mirror::String* result = mirror::String::AllocFromCharArray<true>(soa.Self(), char_count,
char_array, offset,
@@ -71,7 +71,7 @@
return nullptr;
}
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String*>(to_copy)));
+ Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(to_copy)));
gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
mirror::String* result = mirror::String::AllocFromString<true>(soa.Self(), string->GetLength(),
string, 0, allocator_type);
diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc
index 1b399aa..8b9d0c7 100644
--- a/runtime/native/java_lang_System.cc
+++ b/runtime/native/java_lang_System.cc
@@ -24,7 +24,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
namespace art {
@@ -60,14 +60,14 @@
}
// Make sure source and destination are both arrays.
- mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
+ ObjPtr<mirror::Object> srcObject = soa.Decode<mirror::Object>(javaSrc);
if (UNLIKELY(!srcObject->IsArrayInstance())) {
- ThrowArrayStoreException_NotAnArray("source", srcObject);
+ ThrowArrayStoreException_NotAnArray("source", srcObject.Decode());
return;
}
- mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
+ ObjPtr<mirror::Object> dstObject = soa.Decode<mirror::Object>(javaDst);
if (UNLIKELY(!dstObject->IsArrayInstance())) {
- ThrowArrayStoreException_NotAnArray("destination", dstObject);
+ ThrowArrayStoreException_NotAnArray("destination", dstObject.Decode());
return;
}
mirror::Array* srcArray = srcObject->AsArray();
@@ -164,8 +164,8 @@
inline void System_arraycopyTUnchecked(JNIEnv* env, jobject javaSrc, jint srcPos,
jobject javaDst, jint dstPos, jint count) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
- mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
+ ObjPtr<mirror::Object> srcObject = soa.Decode<mirror::Object>(javaSrc);
+ ObjPtr<mirror::Object> dstObject = soa.Decode<mirror::Object>(javaDst);
DCHECK(dstObject != nullptr);
mirror::Array* srcArray = srcObject->AsArray();
mirror::Array* dstArray = dstObject->AsArray();
@@ -228,7 +228,7 @@
return 0;
}
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
+ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(javaObject);
return static_cast<jint>(o->IdentityHashCode());
}
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index a742e81..0635261 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -20,8 +20,8 @@
#include "jni_internal.h"
#include "monitor.h"
#include "mirror/object.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedUtfChars.h"
#include "thread.h"
#include "thread_list.h"
@@ -109,14 +109,14 @@
static jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject java_thread, jobject java_object) {
ScopedObjectAccess soa(env);
- mirror::Object* object = soa.Decode<mirror::Object*>(java_object);
+ ObjPtr<mirror::Object> object = soa.Decode<mirror::Object>(java_object);
if (object == nullptr) {
ThrowNullPointerException("object == null");
return JNI_FALSE;
}
MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
Thread* thread = Thread::FromManagedThread(soa, java_thread);
- return thread->HoldsLock(object);
+ return thread->HoldsLock(object.Decode());
}
static void Thread_nativeInterrupt(JNIEnv* env, jobject java_thread) {
@@ -132,7 +132,7 @@
ScopedUtfChars name(env, java_name);
{
ScopedObjectAccess soa(env);
- if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) {
+ if (soa.Decode<mirror::Object>(peer) == soa.Self()->GetPeer()) {
soa.Self()->SetThreadName(name.c_str());
return;
}
@@ -172,8 +172,8 @@
static void Thread_sleep(JNIEnv* env, jclass, jobject java_lock, jlong ms, jint ns) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* lock = soa.Decode<mirror::Object*>(java_lock);
- Monitor::Wait(Thread::Current(), lock, ms, ns, true, kSleeping);
+ ObjPtr<mirror::Object> lock = soa.Decode<mirror::Object>(java_lock);
+ Monitor::Wait(Thread::Current(), lock.Decode(), ms, ns, true, kSleeping);
}
/*
diff --git a/runtime/native/java_lang_Throwable.cc b/runtime/native/java_lang_Throwable.cc
index cb8a869..ff3e044 100644
--- a/runtime/native/java_lang_Throwable.cc
+++ b/runtime/native/java_lang_Throwable.cc
@@ -17,7 +17,7 @@
#include "java_lang_Throwable.h"
#include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "thread.h"
namespace art {
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 6f735aa..0694c4d 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -20,7 +20,7 @@
#include "jni_internal.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "ScopedUtfChars.h"
#include "zip_archive.h"
@@ -29,7 +29,7 @@
static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader,
jstring javaName) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(javaLoader);
+ ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(javaLoader);
ScopedUtfChars name(env, javaName);
if (name.c_str() == nullptr) {
return nullptr;
@@ -37,7 +37,10 @@
ClassLinker* cl = Runtime::Current()->GetClassLinker();
std::string descriptor(DotToDescriptor(name.c_str()));
const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor.c_str());
- mirror::Class* c = cl->LookupClass(soa.Self(), descriptor.c_str(), descriptor_hash, loader);
+ mirror::Class* c = cl->LookupClass(soa.Self(),
+ descriptor.c_str(),
+ descriptor_hash,
+ loader.Decode());
if (c != nullptr && c->IsResolved()) {
return soa.AddLocalReference<jclass>(c);
}
diff --git a/runtime/native/java_lang_ref_FinalizerReference.cc b/runtime/native/java_lang_ref_FinalizerReference.cc
index 0532c35..08bcc38 100644
--- a/runtime/native/java_lang_ref_FinalizerReference.cc
+++ b/runtime/native/java_lang_ref_FinalizerReference.cc
@@ -21,14 +21,15 @@
#include "jni_internal.h"
#include "mirror/object-inl.h"
#include "mirror/reference-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
namespace art {
static jboolean FinalizerReference_makeCircularListIfUnenqueued(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
- mirror::FinalizerReference* const ref = soa.Decode<mirror::FinalizerReference*>(javaThis);
- return Runtime::Current()->GetHeap()->GetReferenceProcessor()->MakeCircularListIfUnenqueued(ref);
+ ObjPtr<mirror::FinalizerReference> ref = soa.Decode<mirror::FinalizerReference>(javaThis);
+ return Runtime::Current()->GetHeap()->GetReferenceProcessor()->MakeCircularListIfUnenqueued(
+ ref.Decode());
}
static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_ref_Reference.cc b/runtime/native/java_lang_ref_Reference.cc
index d232059..9a088ed 100644
--- a/runtime/native/java_lang_ref_Reference.cc
+++ b/runtime/native/java_lang_ref_Reference.cc
@@ -21,15 +21,15 @@
#include "jni_internal.h"
#include "mirror/object-inl.h"
#include "mirror/reference-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
namespace art {
static jobject Reference_getReferent(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Reference* const ref = soa.Decode<mirror::Reference*>(javaThis);
+ ObjPtr<mirror::Reference> ref = soa.Decode<mirror::Reference>(javaThis);
mirror::Object* const referent =
- Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(soa.Self(), ref);
+ Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(soa.Self(), ref.Decode());
return soa.AddLocalReference<jobject>(referent);
}
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index beb953b..3718ce8 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -22,7 +22,7 @@
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "handle_scope-inl.h"
namespace art {
@@ -32,15 +32,15 @@
ScopedFastNativeObjectAccess soa(env);
DCHECK(javaElementClass != nullptr);
StackHandleScope<2> hs(soa.Self());
- Handle<mirror::Class> element_class(hs.NewHandle(soa.Decode<mirror::Class*>(javaElementClass)));
+ Handle<mirror::Class> element_class(hs.NewHandle(soa.Decode<mirror::Class>(javaElementClass)));
DCHECK(element_class->IsClass());
DCHECK(javaDimArray != nullptr);
- mirror::Object* dimensions_obj = soa.Decode<mirror::Object*>(javaDimArray);
+ ObjPtr<mirror::Object> dimensions_obj = soa.Decode<mirror::Object>(javaDimArray);
DCHECK(dimensions_obj->IsArrayInstance());
DCHECK_EQ(dimensions_obj->GetClass()->GetComponentType()->GetPrimitiveType(),
Primitive::kPrimInt);
Handle<mirror::IntArray> dimensions_array(
- hs.NewHandle(down_cast<mirror::IntArray*>(dimensions_obj)));
+ hs.NewHandle(down_cast<mirror::IntArray*>(dimensions_obj.Decode())));
mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(), element_class,
dimensions_array);
return soa.AddLocalReference<jobject>(new_array);
@@ -53,7 +53,7 @@
ThrowNegativeArraySizeException(length);
return nullptr;
}
- mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
+ mirror::Class* element_class = soa.Decode<mirror::Class>(javaElementClass).Decode();
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
mirror::Class* array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index d001d0c..7de0147 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -26,7 +26,7 @@
#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "reflection.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes.h"
namespace art {
@@ -60,7 +60,7 @@
*/
static jobject Constructor_newInstance0(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Constructor* m = soa.Decode<mirror::Constructor*>(javaMethod);
+ ObjPtr<mirror::Constructor> m = soa.Decode<mirror::Constructor>(javaMethod);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> c(hs.NewHandle(m->GetDeclaringClass()));
if (UNLIKELY(c->IsAbstract())) {
@@ -73,7 +73,7 @@
if (!m->IsAccessible() && !c->IsPublic()) {
// Go 2 frames back, this method is always called from newInstance0, which is called from
// Constructor.newInstance(Object... args).
- auto* caller = GetCallingClass(soa.Self(), 2);
+ ObjPtr<mirror::Class> caller = GetCallingClass(soa.Self(), 2);
// If caller is null, then we called from JNI, just avoid the check since JNI avoids most
// access checks anyways. TODO: Investigate if this the correct behavior.
if (caller != nullptr && !caller->CanAccess(c.Get())) {
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index f345c09..c7c8008 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -25,7 +25,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "reflection.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes.h"
namespace art {
@@ -35,10 +35,10 @@
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
if (method->GetDeclaringClass()->IsProxyClass()) {
// Return an empty array instead of a null pointer.
- mirror::Class* annotation_array_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
- mirror::ObjectArray<mirror::Object>* empty_array =
- mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
+ ObjPtr<mirror::Class> annotation_array_class =
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
+ ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
+ mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class.Decode(), 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
}
return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForMethod(method));
@@ -53,7 +53,7 @@
if (method->IsProxyMethod()) {
return nullptr;
} else {
- Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+ Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
return soa.AddLocalReference<jobject>(annotations::GetAnnotationForMethod(method, klass));
}
}
@@ -84,7 +84,7 @@
Thread* self = soa.Self();
StackHandleScope<8> hs(self);
- Handle<mirror::Method> executable = hs.NewHandle(soa.Decode<mirror::Method*>(javaMethod));
+ Handle<mirror::Method> executable = hs.NewHandle(soa.Decode<mirror::Method>(javaMethod));
ArtMethod* art_method = executable.Get()->GetArtMethod();
if (art_method->GetDeclaringClass()->IsProxyClass()) {
return nullptr;
@@ -122,7 +122,7 @@
// Instantiate a Parameter[] to hold the result.
Handle<mirror::Class> parameter_array_class =
hs.NewHandle(
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Parameter__array));
+ soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Parameter__array));
Handle<mirror::ObjectArray<mirror::Object>> parameter_array =
hs.NewHandle(
mirror::ObjectArray<mirror::Object>::Alloc(self,
@@ -134,7 +134,7 @@
}
Handle<mirror::Class> parameter_class =
- hs.NewHandle(soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Parameter));
+ hs.NewHandle(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Parameter));
ArtMethod* parameter_init =
soa.DecodeMethod(WellKnownClasses::java_lang_reflect_Parameter_init);
@@ -186,7 +186,7 @@
return false;
}
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+ Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
return annotations::IsMethodAnnotationPresent(method, klass);
}
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 412445f..2519225 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -25,7 +25,7 @@
#include "mirror/class-inl.h"
#include "mirror/field.h"
#include "reflection-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "utils.h"
namespace art {
@@ -43,9 +43,13 @@
PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
return false;
}
- mirror::Class* calling_class = nullptr;
- if (!VerifyAccess(self, obj, field->GetDeclaringClass(), field->GetAccessFlags(),
- &calling_class, 1)) {
+ ObjPtr<mirror::Class> calling_class;
+ if (!VerifyAccess(self,
+ MakeObjPtr(obj),
+ MakeObjPtr(field->GetDeclaringClass()),
+ field->GetAccessFlags(),
+ &calling_class,
+ 1)) {
ThrowIllegalAccessException(
StringPrintf("Class %s cannot access %s field %s of class %s",
calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
@@ -123,8 +127,8 @@
*class_or_rcvr = declaringClass;
return true;
}
- *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
- if (!VerifyObjectIsClass(*class_or_rcvr, declaringClass)) {
+ *class_or_rcvr = soa.Decode<mirror::Object>(j_rcvr).Decode();
+ if (!VerifyObjectIsClass(MakeObjPtr(*class_or_rcvr), MakeObjPtr(declaringClass))) {
DCHECK(soa.Self()->IsExceptionPending());
return false;
}
@@ -133,7 +137,7 @@
static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+ mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
DCHECK(soa.Self()->IsExceptionPending());
@@ -152,14 +156,14 @@
DCHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
- return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value));
+ return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value).Decode());
}
template<Primitive::Type kPrimitiveType>
ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField,
jobject javaObj) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+ mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
DCHECK(soa.Self()->IsExceptionPending());
@@ -303,7 +307,7 @@
static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+ mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
// Check that the receiver is non-null and an instance of the field's declaring class.
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
@@ -321,9 +325,12 @@
}
// We now don't expect suspension unless an exception is thrown.
// Unbox the value, if necessary.
- mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
+ ObjPtr<mirror::Object> boxed_value = soa.Decode<mirror::Object>(javaValue);
JValue unboxed_value;
- if (!UnboxPrimitiveForField(boxed_value, field_type, f->GetArtField(), &unboxed_value)) {
+ if (!UnboxPrimitiveForField(boxed_value,
+ MakeObjPtr(field_type),
+ f->GetArtField(),
+ &unboxed_value)) {
DCHECK(soa.Self()->IsExceptionPending());
return;
}
@@ -339,7 +346,7 @@
static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
const JValue& new_value) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+ mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
mirror::Object* o = nullptr;
if (!CheckReceiver(soa, javaObj, &f, &o)) {
return;
@@ -419,21 +426,22 @@
static jobject Field_getAnnotationNative(JNIEnv* env, jobject javaField, jclass annotationType) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+ ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
if (field->GetDeclaringClass()->IsProxyClass()) {
return nullptr;
}
- Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+ Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
return soa.AddLocalReference<jobject>(annotations::GetAnnotationForField(field, klass));
}
static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) {
ScopedFastNativeObjectAccess soa(env);
- ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+ ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
if (field->GetDeclaringClass()->IsProxyClass()) {
// Return an empty array instead of a null pointer.
mirror::Class* annotation_array_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
+ soa.Decode<mirror::Class>(
+ WellKnownClasses::java_lang_annotation_Annotation__array).Decode();
mirror::ObjectArray<mirror::Object>* empty_array =
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
return soa.AddLocalReference<jobjectArray>(empty_array);
@@ -443,7 +451,7 @@
static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField) {
ScopedFastNativeObjectAccess soa(env);
- ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+ ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
if (field->GetDeclaringClass()->IsProxyClass()) {
return nullptr;
}
@@ -454,11 +462,11 @@
jclass annotationType) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+ ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
if (field->GetDeclaringClass()->IsProxyClass()) {
return false;
}
- Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+ Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
return annotations::IsFieldAnnotationPresent(field, klass);
}
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index b8efb14..b5f2f7c 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -26,7 +26,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "reflection.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc
index c2a803c..6060b8a 100644
--- a/runtime/native/java_lang_reflect_Parameter.cc
+++ b/runtime/native/java_lang_reflect_Parameter.cc
@@ -21,7 +21,7 @@
#include "dex_file-inl.h"
#include "dex_file_annotations.h"
#include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "utils.h"
namespace art {
@@ -53,7 +53,7 @@
}
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+ Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
return soa.AddLocalReference<jobject>(
annotations::GetAnnotationForMethodParameter(method, parameterIndex, klass));
}
diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc
index 4a6ab40..ece0338 100644
--- a/runtime/native/java_lang_reflect_Proxy.cc
+++ b/runtime/native/java_lang_reflect_Proxy.cc
@@ -21,7 +21,7 @@
#include "mirror/class_loader.h"
#include "mirror/object_array.h"
#include "mirror/string.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "verify_object-inl.h"
namespace art {
diff --git a/runtime/native/libcore_util_CharsetUtils.cc b/runtime/native/libcore_util_CharsetUtils.cc
index 64d56f6..2590452 100644
--- a/runtime/native/libcore_util_CharsetUtils.cc
+++ b/runtime/native/libcore_util_CharsetUtils.cc
@@ -18,7 +18,7 @@
#include "mirror/string.h"
#include "mirror/string-inl.h"
#include "native/libcore_util_CharsetUtils.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "ScopedPrimitiveArray.h"
#include "unicode/utf16.h"
@@ -154,7 +154,7 @@
jchar maxValidChar) {
ScopedObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String*>(java_string)));
+ Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
if (string.Get() == nullptr) {
return nullptr;
}
@@ -191,7 +191,7 @@
jint length) {
ScopedObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String*>(java_string)));
+ Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
if (string.Get() == nullptr) {
return nullptr;
}
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
index 0ab2979..5356498 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
@@ -19,7 +19,7 @@
#include "base/logging.h"
#include "debugger.h"
#include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "ScopedPrimitiveArray.h"
namespace art {
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index 9ed0e7e..ca17c26 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -20,7 +20,7 @@
#include "base/mutex.h"
#include "debugger.h"
#include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "thread_list.h"
diff --git a/runtime/native/scoped_fast_native_object_access-inl.h b/runtime/native/scoped_fast_native_object_access-inl.h
new file mode 100644
index 0000000..1d73813
--- /dev/null
+++ b/runtime/native/scoped_fast_native_object_access-inl.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_INL_H_
+#define ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_INL_H_
+
+#include "scoped_fast_native_object_access.h"
+
+#include "art_method-inl.h"
+#include "scoped_thread_state_change-inl.h"
+
+namespace art {
+
+inline ScopedFastNativeObjectAccess::ScopedFastNativeObjectAccess(JNIEnv* env)
+ : ScopedObjectAccessAlreadyRunnable(env) {
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+ DCHECK((*Self()->GetManagedStack()->GetTopQuickFrame())->IsFastNative());
+ // Don't work with raw objects in non-runnable states.
+ DCHECK_EQ(Self()->GetState(), kRunnable);
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_INL_H_
diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h
index c4a33df..6a9365d 100644
--- a/runtime/native/scoped_fast_native_object_access.h
+++ b/runtime/native/scoped_fast_native_object_access.h
@@ -17,7 +17,8 @@
#ifndef ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
#define ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
-#include "art_method-inl.h"
+#include <jni.h>
+
#include "scoped_thread_state_change.h"
namespace art {
@@ -26,18 +27,11 @@
// JNI methods.
class ScopedFastNativeObjectAccess : public ScopedObjectAccessAlreadyRunnable {
public:
- explicit ScopedFastNativeObjectAccess(JNIEnv* env)
+ ALWAYS_INLINE explicit ScopedFastNativeObjectAccess(JNIEnv* env)
REQUIRES(!Locks::thread_suspend_count_lock_)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
- : ScopedObjectAccessAlreadyRunnable(env) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK((*Self()->GetManagedStack()->GetTopQuickFrame())->IsFastNative());
- // Don't work with raw objects in non-runnable states.
- DCHECK_EQ(Self()->GetState(), kRunnable);
- }
+ SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
- ~ScopedFastNativeObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {
- }
+ ALWAYS_INLINE ~ScopedFastNativeObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
private:
DISALLOW_COPY_AND_ASSIGN(ScopedFastNativeObjectAccess);
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 472340c..2fae3cc 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -21,7 +21,7 @@
#include "mirror/array.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
#include <unistd.h>
#include <stdlib.h>
@@ -33,61 +33,64 @@
static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jint expectedValue, jint newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
// JNI must use non transactional mode.
bool success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
- expectedValue, newValue);
+ expectedValue,
+ newValue);
return success ? JNI_TRUE : JNI_FALSE;
}
static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jlong expectedValue, jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
// JNI must use non transactional mode.
bool success = obj->CasFieldStrongSequentiallyConsistent64<false>(MemberOffset(offset),
- expectedValue, newValue);
+ expectedValue,
+ newValue);
return success ? JNI_TRUE : JNI_FALSE;
}
static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jobject javaExpectedValue, jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue);
- mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ ObjPtr<mirror::Object> expectedValue = soa.Decode<mirror::Object>(javaExpectedValue);
+ ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
// JNI must use non transactional mode.
if (kUseReadBarrier) {
// Need to make sure the reference stored in the field is a to-space one before attempting the
// CAS or the CAS could fail incorrectly.
mirror::HeapReference<mirror::Object>* field_addr =
reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
- reinterpret_cast<uint8_t*>(obj) + static_cast<size_t>(offset));
+ reinterpret_cast<uint8_t*>(obj.Decode()) + static_cast<size_t>(offset));
ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /*kAlwaysUpdateField*/true>(
- obj,
+ obj.Decode(),
MemberOffset(offset),
field_addr);
}
bool success = obj->CasFieldStrongSequentiallyConsistentObject<false>(MemberOffset(offset),
- expectedValue, newValue);
+ expectedValue.Decode(),
+ newValue.Decode());
return success ? JNI_TRUE : JNI_FALSE;
}
static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
return obj->GetField32(MemberOffset(offset));
}
static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
return obj->GetField32Volatile(MemberOffset(offset));
}
static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
// JNI must use non transactional mode.
obj->SetField32<false>(MemberOffset(offset), newValue);
}
@@ -95,7 +98,7 @@
static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jint newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
// JNI must use non transactional mode.
obj->SetField32Volatile<false>(MemberOffset(offset), newValue);
}
@@ -103,7 +106,7 @@
static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jint newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
QuasiAtomic::ThreadFenceRelease();
// JNI must use non transactional mode.
obj->SetField32<false>(MemberOffset(offset), newValue);
@@ -111,19 +114,19 @@
static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
return obj->GetField64(MemberOffset(offset));
}
static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
return obj->GetField64Volatile(MemberOffset(offset));
}
static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
// JNI must use non transactional mode.
obj->SetField64<false>(MemberOffset(offset), newValue);
}
@@ -131,7 +134,7 @@
static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
// JNI must use non transactional mode.
obj->SetField64Volatile<false>(MemberOffset(offset), newValue);
}
@@ -139,7 +142,7 @@
static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jlong newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
QuasiAtomic::ThreadFenceRelease();
// JNI must use non transactional mode.
obj->SetField64<false>(MemberOffset(offset), newValue);
@@ -147,56 +150,56 @@
static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ ObjPtr<mirror::Object> value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
return soa.AddLocalReference<jobject>(value);
}
static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ ObjPtr<mirror::Object> value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
return soa.AddLocalReference<jobject>(value);
}
static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
// JNI must use non transactional mode.
- obj->SetFieldObject<false>(MemberOffset(offset), newValue);
+ obj->SetFieldObject<false>(MemberOffset(offset), newValue.Decode());
}
static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
// JNI must use non transactional mode.
- obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue);
+ obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue.Decode());
}
static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jobject javaNewValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
QuasiAtomic::ThreadFenceRelease();
// JNI must use non transactional mode.
- obj->SetFieldObject<false>(MemberOffset(offset), newValue);
+ obj->SetFieldObject<false>(MemberOffset(offset), newValue.Decode());
}
static jint Unsafe_getArrayBaseOffsetForComponentType(JNIEnv* env, jclass, jobject component_class) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Class* component = soa.Decode<mirror::Class*>(component_class);
+ ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
Primitive::Type primitive_type = component->GetPrimitiveType();
return mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value();
}
static jint Unsafe_getArrayIndexScaleForComponentType(JNIEnv* env, jclass, jobject component_class) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Class* component = soa.Decode<mirror::Class*>(component_class);
+ ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
Primitive::Type primitive_type = component->GetPrimitiveType();
return Primitive::ComponentSize(primitive_type);
}
@@ -289,16 +292,16 @@
static void Unsafe_copyMemory(JNIEnv *env, jobject unsafe ATTRIBUTE_UNUSED, jlong src,
jlong dst, jlong size) {
- if (size == 0) {
- return;
- }
- // size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
- ScopedFastNativeObjectAccess soa(env);
- ThrowIllegalAccessException("wrong number of bytes");
- }
- size_t sz = (size_t)size;
- memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), sz);
+ if (size == 0) {
+ return;
+ }
+ // size is nonnegative and fits into size_t
+ if (size < 0 || size != (jlong)(size_t) size) {
+ ScopedFastNativeObjectAccess soa(env);
+ ThrowIllegalAccessException("wrong number of bytes");
+ }
+ size_t sz = (size_t)size;
+ memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), sz);
}
template<typename T>
@@ -306,12 +309,12 @@
size_t array_offset,
size_t size)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const T* src = reinterpret_cast<T*>(srcAddr);
- size_t sz = size / sizeof(T);
- size_t of = array_offset / sizeof(T);
- for (size_t i = 0; i < sz; ++i) {
- array->Set(i + of, *(src + i));
- }
+ const T* src = reinterpret_cast<T*>(srcAddr);
+ size_t sz = size / sizeof(T);
+ size_t of = array_offset / sizeof(T);
+ for (size_t i = 0; i < sz; ++i) {
+ array->Set(i + of, *(src + i));
+ }
}
template<typename T>
@@ -319,12 +322,12 @@
size_t array_offset,
size_t size)
REQUIRES_SHARED(Locks::mutator_lock_) {
- T* dst = reinterpret_cast<T*>(dstAddr);
- size_t sz = size / sizeof(T);
- size_t of = array_offset / sizeof(T);
- for (size_t i = 0; i < sz; ++i) {
- *(dst + i) = array->Get(i + of);
- }
+ T* dst = reinterpret_cast<T*>(dstAddr);
+ size_t sz = size / sizeof(T);
+ size_t of = array_offset / sizeof(T);
+ for (size_t i = 0; i < sz; ++i) {
+ *(dst + i) = array->Get(i + of);
+ }
}
static void Unsafe_copyMemoryToPrimitiveArray(JNIEnv *env,
@@ -333,29 +336,29 @@
jobject dstObj,
jlong dstOffset,
jlong size) {
- ScopedObjectAccess soa(env);
- if (size == 0) {
- return;
- }
- // size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
- ThrowIllegalAccessException("wrong number of bytes");
- }
- size_t sz = (size_t)size;
- size_t dst_offset = (size_t)dstOffset;
- mirror::Object* dst = soa.Decode<mirror::Object*>(dstObj);
- mirror::Class* component_type = dst->GetClass()->GetComponentType();
- if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
- copyToArray(srcAddr, dst->AsByteSizedArray(), dst_offset, sz);
- } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
- copyToArray(srcAddr, dst->AsShortSizedArray(), dst_offset, sz);
- } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
- copyToArray(srcAddr, dst->AsIntArray(), dst_offset, sz);
- } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
- copyToArray(srcAddr, dst->AsLongArray(), dst_offset, sz);
- } else {
- ThrowIllegalAccessException("not a primitive array");
- }
+ ScopedObjectAccess soa(env);
+ if (size == 0) {
+ return;
+ }
+ // size is nonnegative and fits into size_t
+ if (size < 0 || size != (jlong)(size_t) size) {
+ ThrowIllegalAccessException("wrong number of bytes");
+ }
+ size_t sz = (size_t)size;
+ size_t dst_offset = (size_t)dstOffset;
+ ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
+ mirror::Class* component_type = dst->GetClass()->GetComponentType();
+ if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
+ copyToArray(srcAddr, dst->AsByteSizedArray(), dst_offset, sz);
+ } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
+ copyToArray(srcAddr, dst->AsShortSizedArray(), dst_offset, sz);
+ } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
+ copyToArray(srcAddr, dst->AsIntArray(), dst_offset, sz);
+ } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
+ copyToArray(srcAddr, dst->AsLongArray(), dst_offset, sz);
+ } else {
+ ThrowIllegalAccessException("not a primitive array");
+ }
}
static void Unsafe_copyMemoryFromPrimitiveArray(JNIEnv *env,
@@ -364,85 +367,85 @@
jlong srcOffset,
jlong dstAddr,
jlong size) {
- ScopedObjectAccess soa(env);
- if (size == 0) {
- return;
- }
- // size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
- ThrowIllegalAccessException("wrong number of bytes");
- }
- size_t sz = (size_t)size;
- size_t src_offset = (size_t)srcOffset;
- mirror::Object* src = soa.Decode<mirror::Object*>(srcObj);
- mirror::Class* component_type = src->GetClass()->GetComponentType();
- if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
- copyFromArray(dstAddr, src->AsByteSizedArray(), src_offset, sz);
- } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
- copyFromArray(dstAddr, src->AsShortSizedArray(), src_offset, sz);
- } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
- copyFromArray(dstAddr, src->AsIntArray(), src_offset, sz);
- } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
- copyFromArray(dstAddr, src->AsLongArray(), src_offset, sz);
- } else {
- ThrowIllegalAccessException("not a primitive array");
- }
+ ScopedObjectAccess soa(env);
+ if (size == 0) {
+ return;
+ }
+ // size is nonnegative and fits into size_t
+ if (size < 0 || size != (jlong)(size_t) size) {
+ ThrowIllegalAccessException("wrong number of bytes");
+ }
+ size_t sz = (size_t)size;
+ size_t src_offset = (size_t)srcOffset;
+ ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
+ mirror::Class* component_type = src->GetClass()->GetComponentType();
+ if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
+ copyFromArray(dstAddr, src->AsByteSizedArray(), src_offset, sz);
+ } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
+ copyFromArray(dstAddr, src->AsShortSizedArray(), src_offset, sz);
+ } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
+ copyFromArray(dstAddr, src->AsIntArray(), src_offset, sz);
+ } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
+ copyFromArray(dstAddr, src->AsLongArray(), src_offset, sz);
+ } else {
+ ThrowIllegalAccessException("not a primitive array");
+ }
}
static jboolean Unsafe_getBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- return obj->GetFieldBoolean(MemberOffset(offset));
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ return obj->GetFieldBoolean(MemberOffset(offset));
}
static void Unsafe_putBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset, jboolean newValue) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- // JNI must use non transactional mode (SetField8 is non-transactional).
- obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ // JNI must use non transactional mode (SetField8 is non-transactional).
+ obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
}
static jbyte Unsafe_getByte(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- return obj->GetFieldByte(MemberOffset(offset));
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ return obj->GetFieldByte(MemberOffset(offset));
}
static void Unsafe_putByte(JNIEnv* env, jobject, jobject javaObj, jlong offset, jbyte newValue) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- // JNI must use non transactional mode.
- obj->SetFieldByte<false>(MemberOffset(offset), newValue);
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ // JNI must use non transactional mode.
+ obj->SetFieldByte<false>(MemberOffset(offset), newValue);
}
static jchar Unsafe_getChar(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- return obj->GetFieldChar(MemberOffset(offset));
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ return obj->GetFieldChar(MemberOffset(offset));
}
static void Unsafe_putChar(JNIEnv* env, jobject, jobject javaObj, jlong offset, jchar newValue) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- // JNI must use non transactional mode.
- obj->SetFieldChar<false>(MemberOffset(offset), newValue);
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ // JNI must use non transactional mode.
+ obj->SetFieldChar<false>(MemberOffset(offset), newValue);
}
static jshort Unsafe_getShort(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- return obj->GetFieldShort(MemberOffset(offset));
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ return obj->GetFieldShort(MemberOffset(offset));
}
static void Unsafe_putShort(JNIEnv* env, jobject, jobject javaObj, jlong offset, jshort newValue) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
- // JNI must use non transactional mode.
- obj->SetFieldShort<false>(MemberOffset(offset), newValue);
+ ScopedFastNativeObjectAccess soa(env);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+ // JNI must use non transactional mode.
+ obj->SetFieldShort<false>(MemberOffset(offset), newValue);
}
static jfloat Unsafe_getFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
union {int32_t val; jfloat converted;} conv;
conv.val = obj->GetField32(MemberOffset(offset));
return conv.converted;
@@ -450,7 +453,7 @@
static void Unsafe_putFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset, jfloat newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
union {int32_t converted; jfloat val;} conv;
conv.val = newValue;
// JNI must use non transactional mode.
@@ -459,7 +462,7 @@
static jdouble Unsafe_getDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
union {int64_t val; jdouble converted;} conv;
conv.val = obj->GetField64(MemberOffset(offset));
return conv.converted;
@@ -467,7 +470,7 @@
static void Unsafe_putDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset, jdouble newValue) {
ScopedFastNativeObjectAccess soa(env);
- mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+ ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
union {int64_t converted; jdouble val;} conv;
conv.val = newValue;
// JNI must use non transactional mode.
diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc
index 155c008..059dc5a 100644
--- a/runtime/native_bridge_art_interface.cc
+++ b/runtime/native_bridge_art_interface.cc
@@ -26,7 +26,7 @@
#include "base/macros.h"
#include "dex_file-inl.h"
#include "mirror/class-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "sigchain.h"
namespace art {
@@ -43,7 +43,7 @@
}
ScopedObjectAccess soa(env);
- mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(clazz);
uint32_t native_method_count = 0;
for (auto& m : c->GetMethods(kRuntimePointerSize)) {
@@ -58,7 +58,7 @@
return 0;
}
ScopedObjectAccess soa(env);
- mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
+ ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(clazz);
uint32_t count = 0;
for (auto& m : c->GetMethods(kRuntimePointerSize)) {
diff --git a/runtime/oat.h b/runtime/oat.h
index 12a8298..4d8687c 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- static constexpr uint8_t kOatVersion[] = { '0', '8', '7', '\0' };
+ static constexpr uint8_t kOatVersion[] = { '0', '8', '9', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 415f991..ff00451 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -27,7 +27,7 @@
#include "oat.h"
#include "os.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "utils.h"
namespace art {
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 6ec5e55..d18e946 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -33,7 +33,7 @@
#include "oat_file_assistant.h"
#include "oat_file_manager.h"
#include "os.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "utils.h"
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 6d4b2f6..acad2a9 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -30,7 +30,7 @@
#include "handle_scope-inl.h"
#include "mirror/class_loader.h"
#include "oat_file_assistant.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "thread_list.h"
@@ -294,8 +294,8 @@
}
// Unsupported class-loader?
- if (class_loader->GetClass() !=
- soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader)) {
+ if (soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader) !=
+ class_loader->GetClass()) {
VLOG(class_linker) << "Unsupported class-loader " << PrettyClass(class_loader->GetClass());
return false;
}
@@ -338,10 +338,10 @@
ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie);
ArtField* const dex_file_field =
soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
- const mirror::Class* const element_class = soa.Decode<mirror::Class*>(
+ ObjPtr<mirror::Class> const element_class = soa.Decode<mirror::Class>(
WellKnownClasses::dalvik_system_DexPathList__Element);
- const mirror::Class* const dexfile_class = soa.Decode<mirror::Class*>(
- WellKnownClasses::dalvik_system_DexFile);
+ ObjPtr<mirror::Class> const dexfile_class = soa.Decode<mirror::Class>(
+ WellKnownClasses::dalvik_system_DexFile);
// Collect all the dex files.
auto GetDexFilesFn = [&] (const DexFile* cp_dex_file)
@@ -361,9 +361,9 @@
// We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile.
mirror::Object* dex_file;
- if (element->GetClass() == element_class) {
+ if (element_class == element->GetClass()) {
dex_file = dex_file_field->GetObject(element);
- } else if (element->GetClass() == dexfile_class) {
+ } else if (dexfile_class == element->GetClass()) {
dex_file = element;
} else {
LOG(WARNING) << "Unsupported element in dex_elements: " << PrettyClass(element->GetClass());
@@ -442,9 +442,9 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(Thread::Current());
Handle<mirror::ClassLoader> h_class_loader =
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader));
Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
- hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>*>(dex_elements));
+ hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements));
if (h_class_loader.Get() != nullptr &&
GetDexFilesFromClassLoader(soa, h_class_loader.Get(), &queue)) {
class_loader_ok = true;
@@ -638,7 +638,7 @@
ScopedObjectAccess soa(self);
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> h_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
// Can not load app image without class loader.
if (h_loader.Get() != nullptr) {
std::string temp_error_msg;
diff --git a/runtime/oat_file_test.cc b/runtime/oat_file_test.cc
index a88553c..b416b9d 100644
--- a/runtime/oat_file_test.cc
+++ b/runtime/oat_file_test.cc
@@ -21,7 +21,7 @@
#include <gtest/gtest.h>
#include "common_runtime_test.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/oat_quick_method_header.cc b/runtime/oat_quick_method_header.cc
index 0ab2bfe..a68d9f8 100644
--- a/runtime/oat_quick_method_header.cc
+++ b/runtime/oat_quick_method_header.cc
@@ -17,7 +17,7 @@
#include "oat_quick_method_header.h"
#include "art_method.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
namespace art {
diff --git a/runtime/obj_ptr-inl.h b/runtime/obj_ptr-inl.h
new file mode 100644
index 0000000..1c698b5
--- /dev/null
+++ b/runtime/obj_ptr-inl.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_RUNTIME_OBJ_PTR_INL_H_
+#define ART_RUNTIME_OBJ_PTR_INL_H_
+
+#include "obj_ptr.h"
+#include "thread-inl.h"
+
+namespace art {
+
+template<class MirrorType, bool kPoison>
+inline bool ObjPtr<MirrorType, kPoison>::IsValid() const {
+ if (!kPoison || IsNull()) {
+ return true;
+ }
+ return GetCookie() == TrimCookie(Thread::Current()->GetPoisonObjectCookie());
+}
+
+template<class MirrorType, bool kPoison>
+inline void ObjPtr<MirrorType, kPoison>::AssertValid() const {
+ if (kPoison) {
+ CHECK(IsValid()) << "Stale object pointer " << DecodeUnchecked() << " , expected cookie "
+ << TrimCookie(Thread::Current()->GetPoisonObjectCookie()) << " but got " << GetCookie();
+ }
+}
+
+template<class MirrorType, bool kPoison>
+inline uintptr_t ObjPtr<MirrorType, kPoison>::Encode(MirrorType* ptr) {
+ uintptr_t ref = reinterpret_cast<uintptr_t>(ptr);
+ DCHECK_ALIGNED(ref, kObjectAlignment);
+ if (kPoison && ref != 0) {
+ DCHECK_LE(ref, 0xFFFFFFFFU);
+ ref >>= kObjectAlignmentShift;
+ // Put cookie in high bits.
+ Thread* self = Thread::Current();
+ DCHECK(self != nullptr);
+ ref |= self->GetPoisonObjectCookie() << kCookieShift;
+ }
+ return ref;
+}
+
+template<class MirrorType, bool kPoison>
+inline std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType, kPoison> ptr) {
+ // May be used for dumping bad pointers, do not use the checked version.
+ return os << ptr.DecodeUnchecked();
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_OBJ_PTR_INL_H_
diff --git a/runtime/mirror/obj_ptr.h b/runtime/obj_ptr.h
similarity index 72%
rename from runtime/mirror/obj_ptr.h
rename to runtime/obj_ptr.h
index 10378e8..d5ac33d 100644
--- a/runtime/mirror/obj_ptr.h
+++ b/runtime/obj_ptr.h
@@ -14,23 +14,20 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_MIRROR_OBJ_PTR_H_
-#define ART_RUNTIME_MIRROR_OBJ_PTR_H_
+#ifndef ART_RUNTIME_OBJ_PTR_H_
+#define ART_RUNTIME_OBJ_PTR_H_
+
+#include <ostream>
#include "base/mutex.h" // For Locks::mutator_lock_.
#include "globals.h"
#include "mirror/object_reference.h"
-#include "utils.h"
namespace art {
-namespace mirror {
-
-class Object;
// Value type representing a pointer to a mirror::Object of type MirrorType
// Pass kPoison as a template boolean for testing in non-debug builds.
-// Note that the functions are not 100% thread safe and may have spurious positive check passes in
-// these cases.
+// Since the cookie is thread based, it is not safe to share an ObjPtr between threads.
template<class MirrorType, bool kPoison = kIsDebugBuild>
class ObjPtr {
static constexpr size_t kCookieShift =
@@ -44,14 +41,19 @@
public:
ALWAYS_INLINE ObjPtr() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
- ALWAYS_INLINE explicit ObjPtr(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_)
- : reference_(Encode(ptr)) {}
+ ALWAYS_INLINE ObjPtr(std::nullptr_t) REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
- ALWAYS_INLINE explicit ObjPtr(const ObjPtr& other) REQUIRES_SHARED(Locks::mutator_lock_)
- = default;
+ template <typename Type>
+ ALWAYS_INLINE ObjPtr(Type* ptr) REQUIRES_SHARED(Locks::mutator_lock_)
+ : reference_(Encode(static_cast<MirrorType*>(ptr))) {}
+ template <typename Type>
+ ALWAYS_INLINE ObjPtr(const ObjPtr<Type>& other) REQUIRES_SHARED(Locks::mutator_lock_)
+ : reference_(Encode(static_cast<MirrorType*>(other.Decode()))) {}
+
+ template <typename Type>
ALWAYS_INLINE ObjPtr& operator=(const ObjPtr& other) {
- reference_ = other.reference_;
+ reference_ = Encode(static_cast<MirrorType*>(other.Decode()));
return *this;
}
@@ -65,10 +67,6 @@
}
ALWAYS_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
- return Get();
- }
-
- ALWAYS_INLINE MirrorType* Get() const REQUIRES_SHARED(Locks::mutator_lock_) {
return Decode();
}
@@ -76,19 +74,15 @@
return reference_ == 0;
}
- ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_) {
- if (!kPoison || IsNull()) {
- return true;
- }
- return GetCookie() == TrimCookie(Thread::Current()->GetPoisonObjectCookie());
+ // Decode makes sure that the object pointer is valid.
+ ALWAYS_INLINE MirrorType* Decode() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ AssertValid();
+ return DecodeUnchecked();
}
- ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_) {
- if (kPoison) {
- CHECK(IsValid()) << "Stale object pointer, expected cookie "
- << TrimCookie(Thread::Current()->GetPoisonObjectCookie()) << " but got " << GetCookie();
- }
- }
+ ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
+
+ ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE bool operator==(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
return Decode() == ptr.Decode();
@@ -114,6 +108,16 @@
return !IsNull();
}
+ // Decode unchecked does not check that object pointer is valid. Do not use if you can avoid it.
+ ALWAYS_INLINE MirrorType* DecodeUnchecked() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kPoison) {
+ return reinterpret_cast<MirrorType*>(
+ static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
+ } else {
+ return reinterpret_cast<MirrorType*>(reference_);
+ }
+ }
+
private:
// Trim off high bits of thread local cookie.
ALWAYS_INLINE static uintptr_t TrimCookie(uintptr_t cookie) {
@@ -124,36 +128,20 @@
return reference_ >> kCookieShift;
}
- ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
- uintptr_t ref = reinterpret_cast<uintptr_t>(ptr);
- if (kPoison && ref != 0) {
- DCHECK_LE(ref, 0xFFFFFFFFU);
- ref >>= kObjectAlignmentShift;
- // Put cookie in high bits.
- Thread* self = Thread::Current();
- DCHECK(self != nullptr);
- ref |= self->GetPoisonObjectCookie() << kCookieShift;
- }
- return ref;
- }
-
- // Decode makes sure that the object pointer is valid.
- ALWAYS_INLINE MirrorType* Decode() const REQUIRES_SHARED(Locks::mutator_lock_) {
- AssertValid();
- if (kPoison) {
- return reinterpret_cast<MirrorType*>(
- static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
- } else {
- return reinterpret_cast<MirrorType*>(reference_);
- }
- }
-
+ ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
// The encoded reference and cookie.
uintptr_t reference_;
};
+template<class MirrorType, bool kPoison = kIsDebugBuild>
+static inline ObjPtr<MirrorType, kPoison> MakeObjPtr(MirrorType* ptr) {
+ return ObjPtr<MirrorType, kPoison>(ptr);
+}
-} // namespace mirror
+template<class MirrorType, bool kPoison>
+ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType, kPoison> ptr)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
} // namespace art
-#endif // ART_RUNTIME_MIRROR_OBJ_PTR_H_
+#endif // ART_RUNTIME_OBJ_PTR_H_
diff --git a/runtime/openjdkjvm/OpenjdkJvm.cc b/runtime/openjdkjvm/OpenjdkJvm.cc
index 4a62ecd..d46d78c 100644
--- a/runtime/openjdkjvm/OpenjdkJvm.cc
+++ b/runtime/openjdkjvm/OpenjdkJvm.cc
@@ -43,7 +43,7 @@
#include "thread_list.h"
#include "runtime.h"
#include "handle_scope-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedUtfChars.h"
#include "mirror/class_loader.h"
#include "verify_object-inl.h"
@@ -52,7 +52,7 @@
#include "../../libcore/ojluni/src/main/native/jvm.h" // TODO(narayan): fix it
#include "jni_internal.h"
#include "mirror/string-inl.h"
-#include "native/scoped_fast_native_object_access.h"
+#include "native/scoped_fast_native_object_access-inl.h"
#include "ScopedLocalRef.h"
#include <sys/time.h>
#include <sys/socket.h>
@@ -286,9 +286,8 @@
JNIEXPORT jstring JVM_InternString(JNIEnv* env, jstring jstr) {
art::ScopedFastNativeObjectAccess soa(env);
- art::mirror::String* s = soa.Decode<art::mirror::String*>(jstr);
- art::mirror::String* result = s->Intern();
- return soa.AddLocalReference<jstring>(result);
+ art::ObjPtr<art::mirror::String> s = soa.Decode<art::mirror::String>(jstr);
+ return soa.AddLocalReference<jstring>(s->Intern());
}
JNIEXPORT jlong JVM_FreeMemory(void) {
@@ -364,8 +363,8 @@
JNIEXPORT void JVM_Sleep(JNIEnv* env, jclass threadClass ATTRIBUTE_UNUSED,
jobject java_lock, jlong millis) {
art::ScopedFastNativeObjectAccess soa(env);
- art::mirror::Object* lock = soa.Decode<art::mirror::Object*>(java_lock);
- art::Monitor::Wait(art::Thread::Current(), lock, millis, 0, true, art::kSleeping);
+ art::ObjPtr<art::mirror::Object> lock = soa.Decode<art::mirror::Object>(java_lock);
+ art::Monitor::Wait(art::Thread::Current(), lock.Decode(), millis, 0, true, art::kSleeping);
}
JNIEXPORT jobject JVM_CurrentThread(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED) {
@@ -395,19 +394,19 @@
JNIEXPORT jboolean JVM_HoldsLock(JNIEnv* env, jclass unused ATTRIBUTE_UNUSED, jobject jobj) {
art::ScopedObjectAccess soa(env);
- art::mirror::Object* object = soa.Decode<art::mirror::Object*>(jobj);
- if (object == NULL) {
+ art::ObjPtr<art::mirror::Object> object = soa.Decode<art::mirror::Object>(jobj);
+ if (object == nullptr) {
art::ThrowNullPointerException("object == null");
return JNI_FALSE;
}
- return soa.Self()->HoldsLock(object);
+ return soa.Self()->HoldsLock(object.Decode());
}
JNIEXPORT void JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring java_name) {
ScopedUtfChars name(env, java_name);
{
art::ScopedObjectAccess soa(env);
- if (soa.Decode<art::mirror::Object*>(jthread) == soa.Self()->GetPeer()) {
+ if (soa.Decode<art::mirror::Object>(jthread) == soa.Self()->GetPeer()) {
soa.Self()->SetThreadName(name.c_str());
return;
}
diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc
index b5622b5..ac348e7 100644
--- a/runtime/openjdkjvmti/transform.cc
+++ b/runtime/openjdkjvmti/transform.cc
@@ -43,7 +43,7 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader-inl.h"
#include "mirror/string-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
#include "transform.h"
#include "utf.h"
@@ -259,7 +259,7 @@
JNIEnv* jni_env = *jni_env_ptr;
art::ScopedObjectAccess soa(jni_env);
art::StackHandleScope<3> hs(art::Thread::Current());
- art::Handle<art::mirror::Class> hs_klass(hs.NewHandle(soa.Decode<art::mirror::Class*>(klass)));
+ art::Handle<art::mirror::Class> hs_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
*loader = soa.AddLocalReference<jobject>(hs_klass->GetClassLoader());
*name = art::mirror::Class::ComputeName(hs_klass)->ToModifiedUtf8();
// TODO is this always null?
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index e3f92c7..43b0b3d 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -23,7 +23,7 @@
#include "common_compiler_test.h"
#include "mirror/field-inl.h"
#include "mirror/method.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -108,7 +108,7 @@
jobject jclass_loader = LoadDex("Interfaces");
StackHandleScope<4> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> I(hs.NewHandle(
class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader)));
@@ -142,7 +142,7 @@
jobject jclass_loader = LoadDex("Interfaces");
StackHandleScope<9> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> I(hs.NewHandle(
class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader)));
@@ -200,7 +200,7 @@
jobject jclass_loader = LoadDex("Interfaces");
StackHandleScope<7> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> proxyClass0;
Handle<mirror::Class> proxyClass1;
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index 819e17a..489db9a 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -25,7 +25,7 @@
#include "mirror/string.h"
#include "primitive.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index f54d4ca..d7db8a4 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -23,14 +23,17 @@
#include "common_throws.h"
#include "jvalue.h"
#include "mirror/object-inl.h"
+#include "obj_ptr-inl.h"
#include "primitive.h"
#include "utils.h"
namespace art {
inline bool ConvertPrimitiveValue(bool unbox_for_result,
- Primitive::Type srcType, Primitive::Type dstType,
- const JValue& src, JValue* dst) {
+ Primitive::Type srcType,
+ Primitive::Type dstType,
+ const JValue& src,
+ JValue* dst) {
DCHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot);
if (LIKELY(srcType == dstType)) {
dst->SetJ(src.GetJ());
@@ -100,11 +103,11 @@
return false;
}
-inline bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
+inline bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) {
if (UNLIKELY(o == nullptr)) {
ThrowNullPointerException("null receiver");
return false;
- } else if (UNLIKELY(!o->InstanceOf(c))) {
+ } else if (UNLIKELY(!o->InstanceOf(c.Decode()))) {
InvalidReceiverError(o, c);
return false;
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 30b10d8..b663b4c 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -28,7 +28,7 @@
#include "mirror/executable.h"
#include "mirror/object_array-inl.h"
#include "nth_caller_visitor.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack_reference.h"
#include "well_known_classes.h"
@@ -72,8 +72,8 @@
num_bytes_ += 4;
}
- void Append(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
- Append(StackReference<mirror::Object>::FromMirrorPtr(obj).AsVRegValue());
+ void Append(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+ Append(StackReference<mirror::Object>::FromMirrorPtr(obj.Decode()).AsVRegValue());
}
void AppendWide(uint64_t value) {
@@ -95,7 +95,8 @@
}
void BuildArgArrayFromVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
- mirror::Object* receiver, va_list ap)
+ ObjPtr<mirror::Object> receiver,
+ va_list ap)
REQUIRES_SHARED(Locks::mutator_lock_) {
// Set receiver if non-null (method is not static)
if (receiver != nullptr) {
@@ -114,7 +115,7 @@
AppendFloat(va_arg(ap, jdouble));
break;
case 'L':
- Append(soa.Decode<mirror::Object*>(va_arg(ap, jobject)));
+ Append(soa.Decode<mirror::Object>(va_arg(ap, jobject)));
break;
case 'D':
AppendDouble(va_arg(ap, jdouble));
@@ -131,7 +132,7 @@
}
void BuildArgArrayFromJValues(const ScopedObjectAccessAlreadyRunnable& soa,
- mirror::Object* receiver, jvalue* args)
+ ObjPtr<mirror::Object> receiver, jvalue* args)
REQUIRES_SHARED(Locks::mutator_lock_) {
// Set receiver if non-null (method is not static)
if (receiver != nullptr) {
@@ -156,7 +157,7 @@
Append(args[args_offset].i);
break;
case 'L':
- Append(soa.Decode<mirror::Object*>(args[args_offset].l));
+ Append(soa.Decode<mirror::Object>(args[args_offset].l));
break;
case 'D':
case 'J':
@@ -212,8 +213,9 @@
PrettyDescriptor(found_descriptor).c_str()).c_str());
}
- bool BuildArgArrayFromObjectArray(mirror::Object* receiver,
- mirror::ObjectArray<mirror::Object>* args, ArtMethod* m)
+ bool BuildArgArrayFromObjectArray(ObjPtr<mirror::Object> receiver,
+ ObjPtr<mirror::ObjectArray<mirror::Object>> args,
+ ArtMethod* m)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile::TypeList* classes = m->GetParameterTypeList();
// Set receiver if non-null (method is not static)
@@ -221,13 +223,13 @@
Append(receiver);
}
for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
- mirror::Object* arg = args->Get(args_offset);
+ ObjPtr<mirror::Object> arg(args->Get(args_offset));
if (((shorty_[i] == 'L') && (arg != nullptr)) || ((arg == nullptr && shorty_[i] != 'L'))) {
PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- mirror::Class* dst_class =
+ ObjPtr<mirror::Class> dst_class(
m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_,
true /* resolve */,
- pointer_size);
+ pointer_size));
if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) {
ThrowIllegalArgumentException(
StringPrintf("method %s argument %zd has type %s, got %s",
@@ -240,15 +242,15 @@
}
#define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
- if (LIKELY(arg != nullptr && arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
+ if (LIKELY(arg != nullptr && arg->GetClass()->DescriptorEquals(match_descriptor))) { \
ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
- append(primitive_field-> get_fn(arg));
+ append(primitive_field-> get_fn(arg.Decode()));
#define DO_ARG(match_descriptor, get_fn, append) \
} else if (LIKELY(arg != nullptr && \
arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
- append(primitive_field-> get_fn(arg));
+ append(primitive_field-> get_fn(arg.Decode()));
#define DO_FAIL(expected) \
} else { \
@@ -362,9 +364,9 @@
PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
for (uint32_t i = 0; i < num_params; i++) {
uint16_t type_idx = params->GetTypeItem(i).type_idx_;
- mirror::Class* param_type = m->GetClassFromTypeIndex(type_idx,
- true /* resolve*/,
- pointer_size);
+ ObjPtr<mirror::Class> param_type(m->GetClassFromTypeIndex(type_idx,
+ true /* resolve*/,
+ pointer_size));
if (param_type == nullptr) {
CHECK(self->IsExceptionPending());
LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
@@ -376,7 +378,7 @@
// TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension,
// this is a hard to fix problem since the args can contain Object*, we need to save and
// restore them by using a visitor similar to the ones used in the trampoline entrypoints.
- mirror::Object* argument =
+ ObjPtr<mirror::Object> argument =
(reinterpret_cast<StackReference<mirror::Object>*>(&args[i + offset]))->AsMirrorPtr();
if (argument != nullptr && !argument->InstanceOf(param_type)) {
LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of "
@@ -423,7 +425,7 @@
}
}
-static ArtMethod* FindVirtualMethod(mirror::Object* receiver, ArtMethod* method)
+static ArtMethod* FindVirtualMethod(ObjPtr<mirror::Object> receiver, ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) {
return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method, kRuntimePointerSize);
}
@@ -457,7 +459,7 @@
// Replace calls to String.<init> with equivalent StringFactory call.
method = WellKnownClasses::StringInitToStringFactory(method);
}
- mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj);
uint32_t shorty_len = 0;
const char* shorty =
method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
@@ -488,7 +490,7 @@
// Replace calls to String.<init> with equivalent StringFactory call.
method = WellKnownClasses::StringInitToStringFactory(method);
}
- mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj);
uint32_t shorty_len = 0;
const char* shorty =
method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
@@ -513,7 +515,7 @@
return JValue();
}
- mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj);
ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
if (is_string_init) {
@@ -545,7 +547,7 @@
return JValue();
}
- mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
+ ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj);
ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
if (is_string_init) {
@@ -578,21 +580,20 @@
return nullptr;
}
- auto* executable = soa.Decode<mirror::Executable*>(javaMethod);
+ ObjPtr<mirror::Executable> executable = soa.Decode<mirror::Executable>(javaMethod);
const bool accessible = executable->IsAccessible();
ArtMethod* m = executable->GetArtMethod();
- mirror::Class* declaring_class = m->GetDeclaringClass();
+ ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();
if (UNLIKELY(!declaring_class->IsInitialized())) {
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::Class> h_class(hs.NewHandle(declaring_class));
+ HandleWrapperObjPtr<mirror::Class> h_class(hs.NewHandleWrapper(&declaring_class));
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), h_class, true, true)) {
return nullptr;
}
- declaring_class = h_class.Get();
}
- mirror::Object* receiver = nullptr;
+ ObjPtr<mirror::Object> receiver;
if (!m->IsStatic()) {
// Replace calls to String.<init> with equivalent StringFactory call.
if (declaring_class->IsStringClass() && m->IsConstructor()) {
@@ -600,7 +601,7 @@
CHECK(javaReceiver == nullptr);
} else {
// Check that the receiver is non-null and an instance of the field's declaring class.
- receiver = soa.Decode<mirror::Object*>(javaReceiver);
+ receiver = soa.Decode<mirror::Object>(javaReceiver);
if (!VerifyObjectIsClass(receiver, declaring_class)) {
return nullptr;
}
@@ -611,7 +612,8 @@
}
// Get our arrays of arguments and their types, and check they're the same size.
- auto* objects = soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
+ ObjPtr<mirror::ObjectArray<mirror::Object>> objects =
+ soa.Decode<mirror::ObjectArray<mirror::Object>>(javaArgs);
auto* np_method = m->GetInterfaceMethodIfProxy(kRuntimePointerSize);
const DexFile::TypeList* classes = np_method->GetParameterTypeList();
uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
@@ -623,7 +625,7 @@
}
// If method is not set to be accessible, verify it can be accessed by the caller.
- mirror::Class* calling_class = nullptr;
+ ObjPtr<mirror::Class> calling_class;
if (!accessible && !VerifyAccess(soa.Self(),
receiver,
declaring_class,
@@ -674,12 +676,13 @@
}
// Box if necessary and return.
- return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
+ return soa.AddLocalReference<jobject>(
+ BoxPrimitive(Primitive::GetType(shorty[0]), result).Decode());
}
-mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) {
+ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value) {
if (src_class == Primitive::kPrimNot) {
- return value.GetL();
+ return MakeObjPtr(value.GetL());
}
if (src_class == Primitive::kPrimVoid) {
// There's no such thing as a void field, and void methods invoked via reflection return null.
@@ -750,8 +753,9 @@
return "result";
}
-static bool UnboxPrimitive(mirror::Object* o,
- mirror::Class* dst_class, ArtField* f,
+static bool UnboxPrimitive(ObjPtr<mirror::Object> o,
+ ObjPtr<mirror::Class> dst_class,
+ ArtField* f,
JValue* unboxed_value)
REQUIRES_SHARED(Locks::mutator_lock_) {
bool unbox_for_result = (f == nullptr);
@@ -769,7 +773,7 @@
}
return false;
}
- unboxed_value->SetL(o);
+ unboxed_value->SetL(o.Decode());
return true;
}
if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) {
@@ -791,34 +795,34 @@
}
JValue boxed_value;
- mirror::Class* klass = o->GetClass();
- mirror::Class* src_class = nullptr;
+ ObjPtr<mirror::Class> klass = o->GetClass();
+ ObjPtr<mirror::Class> src_class = nullptr;
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
src_class = class_linker->FindPrimitiveClass('Z');
- boxed_value.SetZ(primitive_field->GetBoolean(o));
+ boxed_value.SetZ(primitive_field->GetBoolean(o.Decode()));
} else if (klass->DescriptorEquals("Ljava/lang/Byte;")) {
src_class = class_linker->FindPrimitiveClass('B');
- boxed_value.SetB(primitive_field->GetByte(o));
+ boxed_value.SetB(primitive_field->GetByte(o.Decode()));
} else if (klass->DescriptorEquals("Ljava/lang/Character;")) {
src_class = class_linker->FindPrimitiveClass('C');
- boxed_value.SetC(primitive_field->GetChar(o));
+ boxed_value.SetC(primitive_field->GetChar(o.Decode()));
} else if (klass->DescriptorEquals("Ljava/lang/Float;")) {
src_class = class_linker->FindPrimitiveClass('F');
- boxed_value.SetF(primitive_field->GetFloat(o));
+ boxed_value.SetF(primitive_field->GetFloat(o.Decode()));
} else if (klass->DescriptorEquals("Ljava/lang/Double;")) {
src_class = class_linker->FindPrimitiveClass('D');
- boxed_value.SetD(primitive_field->GetDouble(o));
+ boxed_value.SetD(primitive_field->GetDouble(o.Decode()));
} else if (klass->DescriptorEquals("Ljava/lang/Integer;")) {
src_class = class_linker->FindPrimitiveClass('I');
- boxed_value.SetI(primitive_field->GetInt(o));
+ boxed_value.SetI(primitive_field->GetInt(o.Decode()));
} else if (klass->DescriptorEquals("Ljava/lang/Long;")) {
src_class = class_linker->FindPrimitiveClass('J');
- boxed_value.SetJ(primitive_field->GetLong(o));
+ boxed_value.SetJ(primitive_field->GetLong(o.Decode()));
} else if (klass->DescriptorEquals("Ljava/lang/Short;")) {
src_class = class_linker->FindPrimitiveClass('S');
- boxed_value.SetS(primitive_field->GetShort(o));
+ boxed_value.SetS(primitive_field->GetShort(o.Decode()));
} else {
std::string temp;
ThrowIllegalArgumentException(
@@ -833,28 +837,36 @@
boxed_value, unboxed_value);
}
-bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f,
+bool UnboxPrimitiveForField(ObjPtr<mirror::Object> o,
+ ObjPtr<mirror::Class> dst_class,
+ ArtField* f,
JValue* unboxed_value) {
DCHECK(f != nullptr);
return UnboxPrimitive(o, dst_class, f, unboxed_value);
}
-bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value) {
+bool UnboxPrimitiveForResult(ObjPtr<mirror::Object> o,
+ ObjPtr<mirror::Class> dst_class,
+ JValue* unboxed_value) {
return UnboxPrimitive(o, dst_class, nullptr, unboxed_value);
}
-mirror::Class* GetCallingClass(Thread* self, size_t num_frames) {
+ObjPtr<mirror::Class> GetCallingClass(Thread* self, size_t num_frames) {
NthCallerVisitor visitor(self, num_frames);
visitor.WalkStack();
return visitor.caller != nullptr ? visitor.caller->GetDeclaringClass() : nullptr;
}
-bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
- uint32_t access_flags, mirror::Class** calling_class, size_t num_frames) {
+bool VerifyAccess(Thread* self,
+ ObjPtr<mirror::Object> obj,
+ ObjPtr<mirror::Class> declaring_class,
+ uint32_t access_flags,
+ ObjPtr<mirror::Class>* calling_class,
+ size_t num_frames) {
if ((access_flags & kAccPublic) != 0) {
return true;
}
- auto* klass = GetCallingClass(self, num_frames);
+ ObjPtr<mirror::Class> klass = GetCallingClass(self, num_frames);
if (UNLIKELY(klass == nullptr)) {
// The caller is an attached native thread.
return false;
@@ -863,10 +875,10 @@
return VerifyAccess(obj, declaring_class, access_flags, klass);
}
-bool VerifyAccess(mirror::Object* obj,
- mirror::Class* declaring_class,
+bool VerifyAccess(ObjPtr<mirror::Object> obj,
+ ObjPtr<mirror::Class> declaring_class,
uint32_t access_flags,
- mirror::Class* calling_class) {
+ ObjPtr<mirror::Class> calling_class) {
if (calling_class == declaring_class) {
return true;
}
@@ -876,16 +888,16 @@
}
if ((access_flags & kAccProtected) != 0) {
if (obj != nullptr && !obj->InstanceOf(calling_class) &&
- !declaring_class->IsInSamePackage(calling_class)) {
+ !declaring_class->IsInSamePackage(calling_class.Decode())) {
return false;
- } else if (declaring_class->IsAssignableFrom(calling_class)) {
+ } else if (declaring_class->IsAssignableFrom(calling_class.Decode())) {
return true;
}
}
- return declaring_class->IsInSamePackage(calling_class);
+ return declaring_class->IsInSamePackage(calling_class.Decode());
}
-void InvalidReceiverError(mirror::Object* o, mirror::Class* c) {
+void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) {
std::string expected_class_name(PrettyDescriptor(c));
std::string actual_class_name(PrettyTypeOf(o));
ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
@@ -895,18 +907,18 @@
// This only works if there's one reference which points to the object in obj.
// Will need to be fixed if there's cases where it's not.
-void UpdateReference(Thread* self, jobject obj, mirror::Object* result) {
+void UpdateReference(Thread* self, jobject obj, ObjPtr<mirror::Object> result) {
IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
IndirectRefKind kind = GetIndirectRefKind(ref);
if (kind == kLocal) {
- self->GetJniEnv()->locals.Update(obj, result);
+ self->GetJniEnv()->locals.Update(obj, result.Decode());
} else if (kind == kHandleScopeOrInvalid) {
LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid";
} else if (kind == kGlobal) {
- self->GetJniEnv()->vm->UpdateGlobal(self, ref, result);
+ self->GetJniEnv()->vm->UpdateGlobal(self, ref, result.Decode());
} else {
DCHECK_EQ(kind, kWeakGlobal);
- self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result);
+ self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result.Decode());
}
}
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 208b533..6e5ef71 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -19,6 +19,7 @@
#include "base/mutex.h"
#include "jni.h"
+#include "obj_ptr.h"
#include "primitive.h"
namespace art {
@@ -32,62 +33,85 @@
class ScopedObjectAccessAlreadyRunnable;
class ShadowFrame;
-mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value)
+ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value)
REQUIRES_SHARED(Locks::mutator_lock_);
-bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f,
+
+bool UnboxPrimitiveForField(ObjPtr<mirror::Object> o,
+ ObjPtr<mirror::Class> dst_class,
+ ArtField* f,
JValue* unboxed_value)
REQUIRES_SHARED(Locks::mutator_lock_);
-bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value)
+
+bool UnboxPrimitiveForResult(ObjPtr<mirror::Object> o,
+ ObjPtr<mirror::Class> dst_class,
+ JValue* unboxed_value)
REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE bool ConvertPrimitiveValue(bool unbox_for_result,
- Primitive::Type src_class, Primitive::Type dst_class,
- const JValue& src, JValue* dst)
+ Primitive::Type src_class,
+ Primitive::Type dst_class,
+ const JValue& src,
+ JValue* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
-JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
+JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
+ jobject obj,
+ jmethodID mid,
va_list args)
REQUIRES_SHARED(Locks::mutator_lock_);
-JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
+JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
+ jobject obj,
+ jmethodID mid,
jvalue* args)
REQUIRES_SHARED(Locks::mutator_lock_);
JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
- jobject obj, jmethodID mid, jvalue* args)
+ jobject obj,
+ jmethodID mid,
+ jvalue* args)
REQUIRES_SHARED(Locks::mutator_lock_);
JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
- jobject obj, jmethodID mid, va_list args)
+ jobject obj,
+ jmethodID mid,
+ va_list args)
REQUIRES_SHARED(Locks::mutator_lock_);
// num_frames is number of frames we look up for access check.
-jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject method, jobject receiver,
- jobject args, size_t num_frames = 1)
+jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa,
+ jobject method,
+ jobject receiver,
+ jobject args,
+ size_t num_frames = 1)
REQUIRES_SHARED(Locks::mutator_lock_);
-ALWAYS_INLINE bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
+ALWAYS_INLINE bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c)
REQUIRES_SHARED(Locks::mutator_lock_);
-bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class,
- uint32_t access_flags, mirror::Class** calling_class, size_t num_frames)
+bool VerifyAccess(Thread* self,
+ ObjPtr<mirror::Object> obj,
+ ObjPtr<mirror::Class> declaring_class,
+ uint32_t access_flags,
+ ObjPtr<mirror::Class>* calling_class,
+ size_t num_frames)
REQUIRES_SHARED(Locks::mutator_lock_);
// This version takes a known calling class.
-bool VerifyAccess(mirror::Object* obj,
- mirror::Class* declaring_class,
+bool VerifyAccess(ObjPtr<mirror::Object> obj,
+ ObjPtr<mirror::Class> declaring_class,
uint32_t access_flags,
- mirror::Class* calling_class)
+ ObjPtr<mirror::Class> calling_class)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get the calling class by using a stack visitor, may return null for unattached native threads.
-mirror::Class* GetCallingClass(Thread* self, size_t num_frames)
+ObjPtr<mirror::Class> GetCallingClass(Thread* self, size_t num_frames)
REQUIRES_SHARED(Locks::mutator_lock_);
-void InvalidReceiverError(mirror::Object* o, mirror::Class* c)
+void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c)
REQUIRES_SHARED(Locks::mutator_lock_);
-void UpdateReference(Thread* self, jobject obj, mirror::Object* result)
+void UpdateReference(Thread* self, jobject obj, ObjPtr<mirror::Object> result)
REQUIRES_SHARED(Locks::mutator_lock_);
} // namespace art
diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc
index 4876ff0..189ed03 100644
--- a/runtime/reflection_test.cc
+++ b/runtime/reflection_test.cc
@@ -23,7 +23,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "common_compiler_test.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -93,16 +93,12 @@
StackHandleScope<2> hs(self);
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(
- ScopedObjectAccessUnchecked(self).Decode<mirror::ClassLoader*>(jclass_loader)));
- if (is_static) {
- MakeExecutable(ScopedObjectAccessUnchecked(self).Decode<mirror::ClassLoader*>(jclass_loader),
- class_name);
- } else {
+ ScopedObjectAccessUnchecked(self).Decode<mirror::ClassLoader>(jclass_loader)));
+ if (!is_static) {
MakeExecutable(nullptr, "java.lang.Class");
MakeExecutable(nullptr, "java.lang.Object");
- MakeExecutable(ScopedObjectAccessUnchecked(self).Decode<mirror::ClassLoader*>(jclass_loader),
- class_name);
}
+ MakeExecutable(class_loader.Get(), class_name);
mirror::Class* c = class_linker_->FindClass(self, DotToDescriptor(class_name).c_str(),
class_loader);
@@ -512,7 +508,7 @@
jobject jclass_loader = LoadDex("Main");
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
CompileDirectMethod(class_loader, "Main", "main", "([Ljava/lang/String;)V");
mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 5bb38f5..df0dca0 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -88,6 +88,8 @@
#include "mirror/class_loader.h"
#include "mirror/field.h"
#include "mirror/method.h"
+#include "mirror/method_handle_impl.h"
+#include "mirror/method_type.h"
#include "mirror/stack_trace_element.h"
#include "mirror/throwable.h"
#include "monitor.h"
@@ -131,7 +133,7 @@
#include "reflection.h"
#include "runtime_options.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "sigchain.h"
#include "signal_catcher.h"
#include "signal_set.h"
@@ -528,7 +530,7 @@
StackHandleScope<2> hs(soa.Self());
Handle<mirror::Class> class_loader_class(
- hs.NewHandle(soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader)));
+ hs.NewHandle(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ClassLoader)));
CHECK(cl->EnsureInitialized(soa.Self(), class_loader_class, true, true));
ArtMethod* getSystemClassLoader = class_loader_class->FindDirectMethod(
@@ -543,7 +545,7 @@
soa.Self()->SetClassLoaderOverride(system_class_loader.get());
Handle<mirror::Class> thread_class(
- hs.NewHandle(soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread)));
+ hs.NewHandle(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread)));
CHECK(cl->EnsureInitialized(soa.Self(), thread_class, true, true));
ArtField* contextClassLoader =
@@ -551,8 +553,9 @@
CHECK(contextClassLoader != nullptr);
// We can't run in a transaction yet.
- contextClassLoader->SetObject<false>(soa.Self()->GetPeer(),
- soa.Decode<mirror::ClassLoader*>(system_class_loader.get()));
+ contextClassLoader->SetObject<false>(
+ soa.Self()->GetPeer(),
+ soa.Decode<mirror::ClassLoader>(system_class_loader.get()).Decode());
return env->NewGlobalRef(system_class_loader.get());
}
@@ -1547,6 +1550,8 @@
mirror::String::VisitRoots(visitor);
mirror::Throwable::VisitRoots(visitor);
mirror::Field::VisitRoots(visitor);
+ mirror::MethodType::VisitRoots(visitor);
+ mirror::MethodHandleImpl::VisitRoots(visitor);
// Visit all the primitive array types classes.
mirror::PrimitiveArray<uint8_t>::VisitRoots(visitor); // BooleanArray
mirror::PrimitiveArray<int8_t>::VisitRoots(visitor); // ByteArray
diff --git a/runtime/scoped_thread_state_change-inl.h b/runtime/scoped_thread_state_change-inl.h
new file mode 100644
index 0000000..cf020d0
--- /dev/null
+++ b/runtime/scoped_thread_state_change-inl.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_
+#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_
+
+#include "scoped_thread_state_change.h"
+
+#include "jni_env_ext-inl.h"
+#include "obj_ptr-inl.h"
+#include "thread-inl.h"
+
+namespace art {
+
+inline ScopedThreadStateChange::ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
+ : self_(self), thread_state_(new_thread_state), expected_has_no_thread_(false) {
+ if (UNLIKELY(self_ == nullptr)) {
+ // Value chosen arbitrarily and won't be used in the destructor since thread_ == null.
+ old_thread_state_ = kTerminated;
+ Runtime* runtime = Runtime::Current();
+ CHECK(runtime == nullptr || !runtime->IsStarted() || runtime->IsShuttingDown(self_));
+ } else {
+ DCHECK_EQ(self, Thread::Current());
+ // Read state without locks, ok as state is effectively thread local and we're not interested
+ // in the suspend count (this will be handled in the runnable transitions).
+ old_thread_state_ = self->GetState();
+ if (old_thread_state_ != new_thread_state) {
+ if (new_thread_state == kRunnable) {
+ self_->TransitionFromSuspendedToRunnable();
+ } else if (old_thread_state_ == kRunnable) {
+ self_->TransitionFromRunnableToSuspended(new_thread_state);
+ } else {
+ // A suspended transition to another effectively suspended transition, ok to use Unsafe.
+ self_->SetState(new_thread_state);
+ }
+ }
+ }
+}
+
+inline ScopedThreadStateChange::~ScopedThreadStateChange() {
+ if (UNLIKELY(self_ == nullptr)) {
+ if (!expected_has_no_thread_) {
+ Runtime* runtime = Runtime::Current();
+ bool shutting_down = (runtime == nullptr) || runtime->IsShuttingDown(nullptr);
+ CHECK(shutting_down);
+ }
+ } else {
+ if (old_thread_state_ != thread_state_) {
+ if (old_thread_state_ == kRunnable) {
+ self_->TransitionFromSuspendedToRunnable();
+ } else if (thread_state_ == kRunnable) {
+ self_->TransitionFromRunnableToSuspended(old_thread_state_);
+ } else {
+ // A suspended transition to another effectively suspended transition, ok to use Unsafe.
+ self_->SetState(old_thread_state_);
+ }
+ }
+ }
+}
+
+template<typename T>
+inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(mirror::Object* obj) const {
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+ DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
+ DCHECK_NE(obj, Runtime::Current()->GetClearedJniWeakGlobal());
+ return obj == nullptr ? nullptr : Env()->AddLocalReference<T>(obj);
+}
+
+template<typename T, typename MirrorType, bool kPoison>
+inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(
+ ObjPtr<MirrorType, kPoison> obj) const {
+ return AddLocalReference<T>(obj.Decode());
+}
+
+template<typename T, bool kPoison>
+inline ObjPtr<T, kPoison> ScopedObjectAccessAlreadyRunnable::Decode(jobject obj) const {
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+ DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
+ return down_cast<T*>(Self()->DecodeJObject(obj));
+}
+
+inline ArtField* ScopedObjectAccessAlreadyRunnable::DecodeField(jfieldID fid) const {
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+ DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
+ return reinterpret_cast<ArtField*>(fid);
+}
+
+inline jfieldID ScopedObjectAccessAlreadyRunnable::EncodeField(ArtField* field) const {
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+ DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
+ return reinterpret_cast<jfieldID>(field);
+}
+
+inline ArtMethod* ScopedObjectAccessAlreadyRunnable::DecodeMethod(jmethodID mid) const {
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+ DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
+ return reinterpret_cast<ArtMethod*>(mid);
+}
+
+inline jmethodID ScopedObjectAccessAlreadyRunnable::EncodeMethod(ArtMethod* method) const {
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+ DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
+ return reinterpret_cast<jmethodID>(method);
+}
+
+inline bool ScopedObjectAccessAlreadyRunnable::IsRunnable() const {
+ return self_->GetState() == kRunnable;
+}
+
+inline ScopedObjectAccessAlreadyRunnable::ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
+ : self_(ThreadForEnv(env)), env_(down_cast<JNIEnvExt*>(env)), vm_(env_->vm) {}
+
+inline ScopedObjectAccessAlreadyRunnable::ScopedObjectAccessAlreadyRunnable(Thread* self)
+ : self_(self),
+ env_(down_cast<JNIEnvExt*>(self->GetJniEnv())),
+ vm_(env_ != nullptr ? env_->vm : nullptr) {}
+
+inline ScopedObjectAccessUnchecked::ScopedObjectAccessUnchecked(JNIEnv* env)
+ : ScopedObjectAccessAlreadyRunnable(env), tsc_(Self(), kRunnable) {
+ Self()->VerifyStack();
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+}
+
+inline ScopedObjectAccessUnchecked::ScopedObjectAccessUnchecked(Thread* self)
+ : ScopedObjectAccessAlreadyRunnable(self), tsc_(self, kRunnable) {
+ Self()->VerifyStack();
+ Locks::mutator_lock_->AssertSharedHeld(Self());
+}
+
+inline ScopedThreadSuspension::ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
+ : self_(self), suspended_state_(suspended_state) {
+ DCHECK(self_ != nullptr);
+ self_->TransitionFromRunnableToSuspended(suspended_state);
+}
+
+inline ScopedThreadSuspension::~ScopedThreadSuspension() {
+ DCHECK_EQ(self_->GetState(), suspended_state_);
+ self_->TransitionFromSuspendedToRunnable();
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index 8a1aca5..175bec5 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -17,85 +17,43 @@
#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
-#include "base/casts.h"
-#include "java_vm_ext.h"
-#include "jni_env_ext-inl.h"
#include "art_field.h"
-#include "read_barrier.h"
-#include "thread-inl.h"
+#include "base/casts.h"
+#include "base/value_object.h"
+#include "java_vm_ext.h"
+#include "thread_state.h"
#include "verify_object.h"
namespace art {
+struct JNIEnvExt;
+template<class MirrorType, bool kPoison> class ObjPtr;
+
// Scoped change into and out of a particular state. Handles Runnable transitions that require
// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
// ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
// the unchecked variant doesn't aid annotalysis.
class ScopedThreadStateChange : public ValueObject {
public:
- ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
- REQUIRES(!Locks::thread_suspend_count_lock_) ALWAYS_INLINE
- : self_(self), thread_state_(new_thread_state), expected_has_no_thread_(false) {
- if (UNLIKELY(self_ == nullptr)) {
- // Value chosen arbitrarily and won't be used in the destructor since thread_ == null.
- old_thread_state_ = kTerminated;
- Runtime* runtime = Runtime::Current();
- CHECK(runtime == nullptr || !runtime->IsStarted() || runtime->IsShuttingDown(self_));
- } else {
- DCHECK_EQ(self, Thread::Current());
- // Read state without locks, ok as state is effectively thread local and we're not interested
- // in the suspend count (this will be handled in the runnable transitions).
- old_thread_state_ = self->GetState();
- if (old_thread_state_ != new_thread_state) {
- if (new_thread_state == kRunnable) {
- self_->TransitionFromSuspendedToRunnable();
- } else if (old_thread_state_ == kRunnable) {
- self_->TransitionFromRunnableToSuspended(new_thread_state);
- } else {
- // A suspended transition to another effectively suspended transition, ok to use Unsafe.
- self_->SetState(new_thread_state);
- }
- }
- }
- }
+ ALWAYS_INLINE ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
+ REQUIRES(!Locks::thread_suspend_count_lock_);
- ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_) ALWAYS_INLINE {
- if (UNLIKELY(self_ == nullptr)) {
- if (!expected_has_no_thread_) {
- Runtime* runtime = Runtime::Current();
- bool shutting_down = (runtime == nullptr) || runtime->IsShuttingDown(nullptr);
- CHECK(shutting_down);
- }
- } else {
- if (old_thread_state_ != thread_state_) {
- if (old_thread_state_ == kRunnable) {
- self_->TransitionFromSuspendedToRunnable();
- } else if (thread_state_ == kRunnable) {
- self_->TransitionFromRunnableToSuspended(old_thread_state_);
- } else {
- // A suspended transition to another effectively suspended transition, ok to use Unsafe.
- self_->SetState(old_thread_state_);
- }
- }
- }
- }
+ ALWAYS_INLINE ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_);
- Thread* Self() const {
+ ALWAYS_INLINE Thread* Self() const {
return self_;
}
protected:
// Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*.
- ScopedThreadStateChange()
- : self_(nullptr), thread_state_(kTerminated), old_thread_state_(kTerminated),
- expected_has_no_thread_(true) {}
+ ScopedThreadStateChange() {}
- Thread* const self_;
- const ThreadState thread_state_;
+ Thread* const self_ = nullptr;
+ const ThreadState thread_state_ = kTerminated;
private:
- ThreadState old_thread_state_;
- const bool expected_has_no_thread_;
+ ThreadState old_thread_state_ = kTerminated;
+ const bool expected_has_no_thread_ = true;
friend class ScopedObjectAccessUnchecked;
DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
@@ -129,62 +87,34 @@
* This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
* it's best if we don't grab a mutex.
*/
+ template<typename T, typename MirrorType, bool kPoison = kIsDebugBuild>
+ T AddLocalReference(ObjPtr<MirrorType, kPoison> obj) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // TODO: Delete
template<typename T>
- T AddLocalReference(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
- DCHECK_NE(obj, Runtime::Current()->GetClearedJniWeakGlobal());
- return obj == nullptr ? nullptr : Env()->AddLocalReference<T>(obj);
- }
+ T AddLocalReference(mirror::Object* obj) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
- template<typename T>
- T Decode(jobject obj) const
- REQUIRES_SHARED(Locks::mutator_lock_) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
- return down_cast<T>(Self()->DecodeJObject(obj));
- }
+ template<typename T, bool kPoison = kIsDebugBuild>
+ ObjPtr<T, kPoison> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
- ArtField* DecodeField(jfieldID fid) const
- REQUIRES_SHARED(Locks::mutator_lock_) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
- return reinterpret_cast<ArtField*>(fid);
- }
+ ArtField* DecodeField(jfieldID fid) const REQUIRES_SHARED(Locks::mutator_lock_);
- jfieldID EncodeField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
- return reinterpret_cast<jfieldID>(field);
- }
+ jfieldID EncodeField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_);
- ArtMethod* DecodeMethod(jmethodID mid) const REQUIRES_SHARED(Locks::mutator_lock_) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
- return reinterpret_cast<ArtMethod*>(mid);
- }
+ ArtMethod* DecodeMethod(jmethodID mid) const REQUIRES_SHARED(Locks::mutator_lock_);
- jmethodID EncodeMethod(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
- DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
- return reinterpret_cast<jmethodID>(method);
- }
+ jmethodID EncodeMethod(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsRunnable() const {
- return self_->GetState() == kRunnable;
- }
+ ALWAYS_INLINE bool IsRunnable() const;
protected:
- explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
- REQUIRES(!Locks::thread_suspend_count_lock_) ALWAYS_INLINE
- : self_(ThreadForEnv(env)), env_(down_cast<JNIEnvExt*>(env)), vm_(env_->vm) {
- }
+ ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
+ REQUIRES(!Locks::thread_suspend_count_lock_);
- explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
- REQUIRES(!Locks::thread_suspend_count_lock_) ALWAYS_INLINE
- : self_(self), env_(down_cast<JNIEnvExt*>(self->GetJniEnv())),
- vm_(env_ != nullptr ? env_->vm : nullptr) {
- }
+ ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
+ REQUIRES(!Locks::thread_suspend_count_lock_);
// Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
// change into Runnable or acquire a share on the mutator_lock_.
@@ -192,8 +122,7 @@
: self_(nullptr), env_(nullptr), vm_(down_cast<JavaVMExt*>(vm)) {}
// Here purely to force inlining.
- ~ScopedObjectAccessAlreadyRunnable() ALWAYS_INLINE {
- }
+ ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
// Self thread, can be null.
Thread* const self_;
@@ -219,19 +148,11 @@
// the mutator_lock_ will be acquired on construction.
class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
public:
- explicit ScopedObjectAccessUnchecked(JNIEnv* env)
- REQUIRES(!Locks::thread_suspend_count_lock_) ALWAYS_INLINE
- : ScopedObjectAccessAlreadyRunnable(env), tsc_(Self(), kRunnable) {
- Self()->VerifyStack();
- Locks::mutator_lock_->AssertSharedHeld(Self());
- }
+ ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
+ REQUIRES(!Locks::thread_suspend_count_lock_);
- explicit ScopedObjectAccessUnchecked(Thread* self)
- REQUIRES(!Locks::thread_suspend_count_lock_) ALWAYS_INLINE
- : ScopedObjectAccessAlreadyRunnable(self), tsc_(self, kRunnable) {
- Self()->VerifyStack();
- Locks::mutator_lock_->AssertSharedHeld(Self());
- }
+ ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
+ REQUIRES(!Locks::thread_suspend_count_lock_);
// Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
// change into Runnable or acquire a share on the mutator_lock_.
@@ -249,28 +170,24 @@
// Annotalysis helping variant of the above.
class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
public:
- explicit ScopedObjectAccess(JNIEnv* env)
+ ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
REQUIRES(!Locks::thread_suspend_count_lock_)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
- : ScopedObjectAccessUnchecked(env) {
- }
+ SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
+ : ScopedObjectAccessUnchecked(env) {}
- explicit ScopedObjectAccess(Thread* self)
+ ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
REQUIRES(!Locks::thread_suspend_count_lock_)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
- : ScopedObjectAccessUnchecked(self) {
- }
+ SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
+ : ScopedObjectAccessUnchecked(self) {}
- ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {
- // Base class will release share of lock. Invoked after this destructor.
- }
+ // Base class will release share of lock. Invoked after this destructor.
+ ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {}
private:
// TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
// routines operating with just a VM are sound, they are not, but when you have just a VM
// you cannot call the unsound routines.
- explicit ScopedObjectAccess(JavaVM* vm)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
+ explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
: ScopedObjectAccessUnchecked(vm) {}
friend class ScopedCheck;
@@ -280,19 +197,11 @@
// Annotalysis helper for going to a suspended state from runnable.
class ScopedThreadSuspension : public ValueObject {
public:
- explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
+ ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
- UNLOCK_FUNCTION(Locks::mutator_lock_)
- ALWAYS_INLINE
- : self_(self), suspended_state_(suspended_state) {
- DCHECK(self_ != nullptr);
- self_->TransitionFromRunnableToSuspended(suspended_state);
- }
+ UNLOCK_FUNCTION(Locks::mutator_lock_);
- ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {
- DCHECK_EQ(self_->GetState(), suspended_state_);
- self_->TransitionFromSuspendedToRunnable();
- }
+ ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
private:
Thread* const self_;
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 848c0e3..674459d 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -34,7 +34,7 @@
#include "gc/heap.h"
#include "os.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "signal_set.h"
#include "thread.h"
#include "thread_list.h"
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index 298a974..bb6eb79 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -59,6 +59,8 @@
if (UNLIKELY(TestAllFlags())) {
CheckSuspend();
}
+ // Invalidate the current thread's object pointers (ObjPtr) to catch possible moving GC bugs due
+ // to missing handles.
PoisonObjectPointers();
}
@@ -173,6 +175,9 @@
inline void Thread::TransitionFromRunnableToSuspended(ThreadState new_state) {
AssertThreadSuspensionIsAllowable();
+ if (kIsDebugBuild) {
+ PoisonObjectPointers();
+ }
DCHECK_EQ(this, Thread::Current());
// Change to non-runnable state, thereby appearing suspended to the system.
TransitionToSuspendedAndRunCheckpoints(new_state);
@@ -303,6 +308,12 @@
tlsPtr_.thread_local_alloc_stack_top = nullptr;
}
+inline void Thread::PoisonObjectPointersIfDebug() {
+ if (kIsDebugBuild) {
+ Thread::Current()->PoisonObjectPointers();
+ }
+}
+
} // namespace art
#endif // ART_RUNTIME_THREAD_INL_H_
diff --git a/runtime/thread.cc b/runtime/thread.cc
index d0ea2d7..ec1bb3f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -59,12 +59,13 @@
#include "native_stack_dump.h"
#include "nth_caller_visitor.h"
#include "oat_quick_method_header.h"
+#include "obj_ptr-inl.h"
#include "object_lock.h"
#include "quick_exception_handler.h"
#include "quick/quick_method_frame_info.h"
#include "reflection.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "stack.h"
@@ -406,7 +407,7 @@
// Copy peer into self, deleting global reference when done.
CHECK(self->tlsPtr_.jpeer != nullptr);
- self->tlsPtr_.opeer = soa.Decode<mirror::Object*>(self->tlsPtr_.jpeer);
+ self->tlsPtr_.opeer = soa.Decode<mirror::Object>(self->tlsPtr_.jpeer).Decode();
self->GetJniEnv()->DeleteGlobalRef(self->tlsPtr_.jpeer);
self->tlsPtr_.jpeer = nullptr;
self->SetThreadName(self->GetThreadName(soa)->ToModifiedUtf8().c_str());
@@ -444,7 +445,7 @@
Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa,
jobject java_thread) {
- return FromManagedThread(soa, soa.Decode<mirror::Object*>(java_thread));
+ return FromManagedThread(soa, soa.Decode<mirror::Object>(java_thread).Decode());
}
static size_t FixStackSize(size_t stack_size) {
@@ -563,7 +564,7 @@
ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
mirror::String* java_name = reinterpret_cast<mirror::String*>(f->GetObject(
- soa.Decode<mirror::Object*>(java_peer)));
+ soa.Decode<mirror::Object>(java_peer).Decode()));
std::string thread_name;
if (java_name != nullptr) {
thread_name = java_name->ToModifiedUtf8();
@@ -802,7 +803,7 @@
}
{
ScopedObjectAccess soa(this);
- tlsPtr_.opeer = soa.Decode<mirror::Object*>(peer.get());
+ tlsPtr_.opeer = soa.Decode<mirror::Object>(peer.get()).Decode();
}
env->CallNonvirtualVoidMethod(peer.get(),
WellKnownClasses::java_lang_Thread,
@@ -844,9 +845,11 @@
soa.DecodeField(WellKnownClasses::java_lang_Thread_daemon)->
SetBoolean<kTransactionActive>(tlsPtr_.opeer, thread_is_daemon);
soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->
- SetObject<kTransactionActive>(tlsPtr_.opeer, soa.Decode<mirror::Object*>(thread_group));
+ SetObject<kTransactionActive>(tlsPtr_.opeer,
+ soa.Decode<mirror::Object>(thread_group).Decode());
soa.DecodeField(WellKnownClasses::java_lang_Thread_name)->
- SetObject<kTransactionActive>(tlsPtr_.opeer, soa.Decode<mirror::Object*>(thread_name));
+ SetObject<kTransactionActive>(tlsPtr_.opeer,
+ soa.Decode<mirror::Object>(thread_name).Decode());
soa.DecodeField(WellKnownClasses::java_lang_Thread_priority)->
SetInt<kTransactionActive>(tlsPtr_.opeer, thread_priority);
}
@@ -2123,7 +2126,7 @@
int* stack_depth) {
// Decode the internal stack trace into the depth, method trace and PC trace.
// Subtract one for the methods and PC trace.
- int32_t depth = soa.Decode<mirror::Array*>(internal)->GetLength() - 1;
+ int32_t depth = soa.Decode<mirror::Array>(internal)->GetLength() - 1;
DCHECK_GE(depth, 0);
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
@@ -2135,7 +2138,7 @@
result = output_array;
// ...adjusting the number of frames we'll write to not exceed the array length.
const int32_t traces_length =
- soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(result)->GetLength();
+ soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>>(result)->GetLength();
depth = std::min(depth, traces_length);
} else {
// Create java_trace array and place in local reference table
@@ -2153,7 +2156,7 @@
for (int32_t i = 0; i < depth; ++i) {
mirror::ObjectArray<mirror::Object>* decoded_traces =
- soa.Decode<mirror::Object*>(internal)->AsObjectArray<mirror::Object>();
+ soa.Decode<mirror::Object>(internal)->AsObjectArray<mirror::Object>();
// Methods and dex PC trace is element 0.
DCHECK(decoded_traces->Get(0)->IsIntArray() || decoded_traces->Get(0)->IsLongArray());
mirror::PointerArray* const method_trace =
@@ -2205,7 +2208,7 @@
return nullptr;
}
// We are called from native: use non-transactional mode.
- soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(result)->Set<false>(i, obj);
+ soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>>(result)->Set<false>(i, obj);
}
return result;
}
@@ -3044,11 +3047,10 @@
interpreter::EnterInterpreterFromDeoptimize(this, shadow_frame, from_code, result);
}
-void Thread::SetException(mirror::Throwable* new_exception) {
+void Thread::SetException(ObjPtr<mirror::Throwable> new_exception) {
CHECK(new_exception != nullptr);
// TODO: DCHECK(!IsExceptionPending());
- tlsPtr_.exception = new_exception;
- // LOG(ERROR) << new_exception->Dump();
+ tlsPtr_.exception = new_exception.Decode();
}
} // namespace art
diff --git a/runtime/thread.h b/runtime/thread.h
index fb6bde6..f2c22d1 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -366,7 +366,7 @@
void AssertNoPendingException() const;
void AssertNoPendingExceptionForNewException(const char* msg) const;
- void SetException(mirror::Throwable* new_exception) REQUIRES_SHARED(Locks::mutator_lock_);
+ void SetException(ObjPtr<mirror::Throwable> new_exception) REQUIRES_SHARED(Locks::mutator_lock_);
void ClearException() REQUIRES_SHARED(Locks::mutator_lock_) {
tlsPtr_.exception = nullptr;
@@ -475,6 +475,8 @@
++poison_object_cookie_;
}
+ ALWAYS_INLINE static void PoisonObjectPointersIfDebug();
+
ALWAYS_INLINE uintptr_t GetPoisonObjectCookie() const {
return poison_object_cookie_;
}
@@ -900,7 +902,9 @@
// Returns the fake exception used to activate deoptimization.
static mirror::Throwable* GetDeoptimizationException() {
- return reinterpret_cast<mirror::Throwable*>(-1);
+ // Note that the mirror::Throwable must be aligned to kObjectAlignment or else it cannot be
+ // represented by ObjPtr.
+ return reinterpret_cast<mirror::Throwable*>(0x100);
}
// Currently deoptimization invokes verifier which can trigger class loading
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 17c6c2e..e2aca6a 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -36,7 +36,7 @@
#include "lock_word.h"
#include "monitor.h"
#include "native_stack_dump.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "trace.h"
#include "well_known_classes.h"
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 23591c2..f846746 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -37,7 +37,7 @@
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "os.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedLocalRef.h"
#include "thread.h"
#include "thread_list.h"
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 82e529c..77c2b76 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -22,7 +22,7 @@
#include "common_runtime_test.h"
#include "dex_file.h"
#include "mirror/array-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -36,7 +36,7 @@
jobject jclass_loader = LoadDex("Transaction");
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
ASSERT_TRUE(class_loader.Get() != nullptr);
// Load and initialize java.lang.ExceptionInInitializerError and the exception class used
@@ -173,7 +173,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<4> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
ASSERT_TRUE(class_loader.Get() != nullptr);
Handle<mirror::Class> h_klass(
@@ -271,7 +271,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<5> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
ASSERT_TRUE(class_loader.Get() != nullptr);
Handle<mirror::Class> h_klass(
@@ -373,7 +373,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<4> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
ASSERT_TRUE(class_loader.Get() != nullptr);
Handle<mirror::Class> h_klass(
@@ -490,7 +490,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<3> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
ASSERT_TRUE(class_loader.Get() != nullptr);
Handle<mirror::Class> h_klass(
@@ -539,7 +539,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
ASSERT_TRUE(class_loader.Get() != nullptr);
Handle<mirror::Class> h_klass(
@@ -563,7 +563,7 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
ASSERT_TRUE(class_loader.Get() != nullptr);
Handle<mirror::Class> h_klass(
diff --git a/runtime/type_lookup_table_test.cc b/runtime/type_lookup_table_test.cc
index ea4d8b5..ec38b41 100644
--- a/runtime/type_lookup_table_test.cc
+++ b/runtime/type_lookup_table_test.cc
@@ -19,7 +19,7 @@
#include "common_runtime_test.h"
#include "dex_file-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "type_lookup_table.h"
#include "utf-inl.h"
diff --git a/runtime/utils.cc b/runtime/utils.cc
index b52e2f2..a40e313 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -37,8 +37,9 @@
#include "mirror/object_array-inl.h"
#include "mirror/string.h"
#include "oat_quick_method_header.h"
+#include "obj_ptr-inl.h"
#include "os.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "utf-inl.h"
#if defined(__APPLE__)
@@ -270,14 +271,14 @@
}
}
-std::string PrettyDescriptor(mirror::String* java_descriptor) {
+std::string PrettyStringDescriptor(ObjPtr<mirror::String> java_descriptor) {
if (java_descriptor == nullptr) {
return "null";
}
return PrettyDescriptor(java_descriptor->ToModifiedUtf8().c_str());
}
-std::string PrettyDescriptor(mirror::Class* klass) {
+std::string PrettyDescriptor(ObjPtr<mirror::Class> klass) {
if (klass == nullptr) {
return "null";
}
@@ -456,7 +457,7 @@
return result;
}
-std::string PrettyTypeOf(mirror::Object* obj) {
+std::string PrettyTypeOf(ObjPtr<mirror::Object> obj) {
if (obj == nullptr) {
return "null";
}
@@ -471,7 +472,7 @@
return result;
}
-std::string PrettyClass(mirror::Class* c) {
+std::string PrettyClass(ObjPtr<mirror::Class> c) {
if (c == nullptr) {
return "null";
}
@@ -482,7 +483,7 @@
return result;
}
-std::string PrettyClassAndClassLoader(mirror::Class* c) {
+std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c) {
if (c == nullptr) {
return "null";
}
diff --git a/runtime/utils.h b/runtime/utils.h
index e65b947..ea9e8f7 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -33,6 +33,7 @@
#include "base/mutex.h"
#include "base/stringpiece.h"
#include "globals.h"
+#include "obj_ptr.h"
#include "primitive.h"
class BacktraceMap;
@@ -135,10 +136,10 @@
// Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
// "[[I" would be "int[][]", "[Ljava/lang/String;" would be
// "java.lang.String[]", and so forth.
-std::string PrettyDescriptor(mirror::String* descriptor)
+std::string PrettyStringDescriptor(ObjPtr<mirror::String> descriptor)
REQUIRES_SHARED(Locks::mutator_lock_);
std::string PrettyDescriptor(const char* descriptor);
-std::string PrettyDescriptor(mirror::Class* klass)
+std::string PrettyDescriptor(ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
std::string PrettyDescriptor(Primitive::Type type);
@@ -158,7 +159,7 @@
// So given an instance of java.lang.String, the output would
// be "java.lang.String". Given an array of int, the output would be "int[]".
// Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyTypeOf(mirror::Object* obj)
+std::string PrettyTypeOf(ObjPtr<mirror::Object> obj)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns a human-readable form of the type at an index in the specified dex file.
@@ -167,11 +168,11 @@
// Returns a human-readable form of the name of the given class.
// Given String.class, the output would be "java.lang.Class<java.lang.String>".
-std::string PrettyClass(mirror::Class* c)
+std::string PrettyClass(ObjPtr<mirror::Class> c)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns a human-readable form of the name of the given class with its class loader.
-std::string PrettyClassAndClassLoader(mirror::Class* c)
+std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns a human-readable version of the Java part of the access flags, e.g., "private static "
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index 3ba20a4..ef42222 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -26,7 +26,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "handle_scope-inl.h"
#include "base/memory_tool.h"
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 13ef043..87b6dc3 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -46,7 +46,7 @@
#include "reg_type-inl.h"
#include "register_line-inl.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "utils.h"
#include "verifier_deps.h"
#include "handle_scope-inl.h"
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 646987a..837ee2d 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -22,7 +22,7 @@
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "dex_file.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "verifier_log_mode.h"
namespace art {
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 3bc2acc..a84668b 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -27,7 +27,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "reg_type_cache-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include <limits>
#include <sstream>
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index f2411b5..49dac26 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -24,7 +24,7 @@
#include "common_runtime_test.h"
#include "reg_type_cache-inl.h"
#include "reg_type-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
diff --git a/runtime/verifier/verifier_deps_test.cc b/runtime/verifier/verifier_deps_test.cc
index bbaf59f..4533464 100644
--- a/runtime/verifier/verifier_deps_test.cc
+++ b/runtime/verifier/verifier_deps_test.cc
@@ -25,7 +25,7 @@
#include "mirror/class_loader.h"
#include "runtime.h"
#include "thread.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
namespace verifier {
@@ -58,7 +58,7 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
StackHandleScope<1> hs(Thread::Current());
Handle<mirror::ClassLoader> class_loader_handle(
- hs.NewHandle(soa->Decode<mirror::ClassLoader*>(class_loader_)));
+ hs.NewHandle(soa->Decode<mirror::ClassLoader>(class_loader_)));
mirror::Class* klass = class_linker_->FindClass(Thread::Current(),
name.c_str(),
class_loader_handle);
@@ -84,8 +84,8 @@
SetVerifierDeps(dex_files);
- mirror::ClassLoader* loader = soa->Decode<mirror::ClassLoader*>(class_loader_);
- class_linker_->RegisterDexFile(*dex_file_, loader);
+ ObjPtr<mirror::ClassLoader> loader = soa->Decode<mirror::ClassLoader>(class_loader_);
+ class_linker_->RegisterDexFile(*dex_file_, loader.Decode());
klass_Main_ = FindClassByName("LMain;", soa);
CHECK(klass_Main_ != nullptr);
@@ -97,7 +97,7 @@
StackHandleScope<2> hs(Thread::Current());
Handle<mirror::ClassLoader> class_loader_handle(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader_)));
+ hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_)));
Handle<mirror::DexCache> dex_cache_handle(hs.NewHandle(klass_Main_->GetDexCache()));
const DexFile::ClassDef* class_def = klass_Main_->GetClassDef();
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index e5216fb..4dcf58f 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -25,7 +25,7 @@
#include "mirror/class.h"
#include "mirror/throwable.h"
#include "ScopedLocalRef.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
diff --git a/test/004-ThreadStress/thread_stress.cc b/test/004-ThreadStress/thread_stress.cc
index 573c352..8ae3dfb 100644
--- a/test/004-ThreadStress/thread_stress.cc
+++ b/test/004-ThreadStress/thread_stress.cc
@@ -19,18 +19,18 @@
#include "jni.h"
#include "mirror/string.h"
#include "mirror/throwable.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
extern "C" JNIEXPORT void JNICALL Java_Main_printString(JNIEnv*, jclass, jstring s) {
ScopedObjectAccess soa(Thread::Current());
- std::cout << soa.Decode<mirror::String*>(s)->ToModifiedUtf8();
+ std::cout << soa.Decode<mirror::String>(s)->ToModifiedUtf8();
}
extern "C" JNIEXPORT void JNICALL Java_Main_printThrowable(JNIEnv*, jclass, jthrowable t) {
ScopedObjectAccess soa(Thread::Current());
- std::cout << soa.Decode<mirror::Throwable*>(t)->Dump();
+ std::cout << soa.Decode<mirror::Throwable>(t)->Dump();
}
} // namespace art
diff --git a/test/004-UnsafeTest/unsafe_test.cc b/test/004-UnsafeTest/unsafe_test.cc
index 3b0cf23..4f6ae5a 100644
--- a/test/004-UnsafeTest/unsafe_test.cc
+++ b/test/004-UnsafeTest/unsafe_test.cc
@@ -20,20 +20,20 @@
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
extern "C" JNIEXPORT jint JNICALL Java_Main_vmArrayBaseOffset(JNIEnv* env, jclass, jobject classObj) {
ScopedObjectAccess soa(env);
- mirror::Class* klass = soa.Decode<mirror::Class*>(classObj);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(classObj);
return mirror::Array::DataOffset(
Primitive::ComponentSize(klass->GetComponentType()->GetPrimitiveType())).Int32Value();
}
extern "C" JNIEXPORT jint JNICALL Java_Main_vmArrayIndexScale(JNIEnv* env, jclass, jobject classObj) {
ScopedObjectAccess soa(env);
- mirror::Class* klass = soa.Decode<mirror::Class*>(classObj);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(classObj);
return Primitive::ComponentSize(klass->GetComponentType()->GetPrimitiveType());
}
diff --git a/test/054-uncaught/src/Main.java b/test/054-uncaught/src/Main.java
index 90a2311..688a2a4 100644
--- a/test/054-uncaught/src/Main.java
+++ b/test/054-uncaught/src/Main.java
@@ -41,7 +41,7 @@
ThreadDeathHandler defHandler = new ThreadDeathHandler("DEFAULT");
ThreadDeathHandler threadHandler = new ThreadDeathHandler("THREAD");
- System.out.println("Test " + which);
+ System.err.println("Test " + which);
switch (which) {
case 1: {
Thread.setDefaultUncaughtExceptionHandler(defHandler);
diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc
index c6a2e9a..56c0dcd 100644
--- a/test/117-nopatchoat/nopatchoat.cc
+++ b/test/117-nopatchoat/nopatchoat.cc
@@ -20,7 +20,7 @@
#include "gc/space/image_space.h"
#include "mirror/class-inl.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread.h"
namespace art {
@@ -29,7 +29,7 @@
public:
static const OatFile::OatDexFile* getOatDexFile(jclass cls) {
ScopedObjectAccess soa(Thread::Current());
- mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
const DexFile& dex_file = klass->GetDexFile();
return dex_file.GetOatDexFile();
}
diff --git a/test/1337-gc-coverage/gc_coverage.cc b/test/1337-gc-coverage/gc_coverage.cc
index 7cf30bd..1e60bd9 100644
--- a/test/1337-gc-coverage/gc_coverage.cc
+++ b/test/1337-gc-coverage/gc_coverage.cc
@@ -17,7 +17,7 @@
#include "gc/heap.h"
#include "jni.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
@@ -43,7 +43,7 @@
extern "C" JNIEXPORT jlong JNICALL Java_Main_objectAddress(JNIEnv* env, jclass, jobject object) {
ScopedObjectAccess soa(env);
- return reinterpret_cast<jlong>(soa.Decode<mirror::Object*>(object));
+ return reinterpret_cast<jlong>(soa.Decode<mirror::Object>(object).Decode());
}
extern "C" JNIEXPORT jboolean JNICALL Java_Main_supportCollectorTransition(JNIEnv*, jclass) {
diff --git a/test/148-multithread-gc-annotations/gc_coverage.cc b/test/148-multithread-gc-annotations/gc_coverage.cc
index 263eefd..cb12df4 100644
--- a/test/148-multithread-gc-annotations/gc_coverage.cc
+++ b/test/148-multithread-gc-annotations/gc_coverage.cc
@@ -17,7 +17,7 @@
#include "gc/heap.h"
#include "jni.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
namespace art {
@@ -35,7 +35,7 @@
extern "C" JNIEXPORT jlong JNICALL Java_MovingGCThread_objectAddress(JNIEnv* env, jclass, jobject object) {
ScopedObjectAccess soa(env);
- return reinterpret_cast<jlong>(soa.Decode<mirror::Object*>(object));
+ return reinterpret_cast<jlong>(soa.Decode<mirror::Object>(object).Decode());
}
} // namespace
diff --git a/test/454-get-vreg/get_vreg_jni.cc b/test/454-get-vreg/get_vreg_jni.cc
index 5762754..9058af4 100644
--- a/test/454-get-vreg/get_vreg_jni.cc
+++ b/test/454-get-vreg/get_vreg_jni.cc
@@ -18,7 +18,7 @@
#include "art_method-inl.h"
#include "jni.h"
#include "oat_quick_method_header.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
@@ -123,7 +123,7 @@
extern "C" JNIEXPORT jint JNICALL Java_Main_doNativeCall(JNIEnv*, jobject value) {
ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<Context> context(Context::Create());
- TestVisitor visitor(soa.Self(), context.get(), soa.Decode<mirror::Object*>(value));
+ TestVisitor visitor(soa.Self(), context.get(), soa.Decode<mirror::Object>(value).Decode());
visitor.WalkStack();
return visitor.found_method_index_;
}
diff --git a/test/457-regs/regs_jni.cc b/test/457-regs/regs_jni.cc
index 08db775..f62a77d 100644
--- a/test/457-regs/regs_jni.cc
+++ b/test/457-regs/regs_jni.cc
@@ -18,7 +18,7 @@
#include "art_method-inl.h"
#include "jni.h"
#include "oat_quick_method_header.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
@@ -139,7 +139,7 @@
JNIEnv*, jclass value ATTRIBUTE_UNUSED, jobject main, jint int_value, jfloat float_value) {
ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<Context> context(Context::Create());
- CHECK(soa.Decode<mirror::Object*>(main) == nullptr);
+ CHECK(soa.Decode<mirror::Object>(main) == nullptr);
CHECK_EQ(int_value, 0);
int32_t cast = bit_cast<int32_t, float>(float_value);
CHECK_EQ(cast, 0);
diff --git a/test/461-get-reference-vreg/get_reference_vreg_jni.cc b/test/461-get-reference-vreg/get_reference_vreg_jni.cc
index 8122c6d..7b1ab9c 100644
--- a/test/461-get-reference-vreg/get_reference_vreg_jni.cc
+++ b/test/461-get-reference-vreg/get_reference_vreg_jni.cc
@@ -17,7 +17,7 @@
#include "arch/context.h"
#include "art_method-inl.h"
#include "jni.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
@@ -70,7 +70,7 @@
extern "C" JNIEXPORT jint JNICALL Java_Main_doNativeCallRef(JNIEnv*, jobject value) {
ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<Context> context(Context::Create());
- TestVisitor visitor(soa.Self(), context.get(), soa.Decode<mirror::Object*>(value));
+ TestVisitor visitor(soa.Self(), context.get(), soa.Decode<mirror::Object>(value).Decode());
visitor.WalkStack();
return visitor.found_method_index_;
}
diff --git a/test/466-get-live-vreg/get_live_vreg_jni.cc b/test/466-get-live-vreg/get_live_vreg_jni.cc
index 3618b4f..d3a033b 100644
--- a/test/466-get-live-vreg/get_live_vreg_jni.cc
+++ b/test/466-get-live-vreg/get_live_vreg_jni.cc
@@ -18,7 +18,7 @@
#include "art_method-inl.h"
#include "jni.h"
#include "oat_quick_method_header.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
diff --git a/test/497-inlining-and-class-loader/clear_dex_cache.cc b/test/497-inlining-and-class-loader/clear_dex_cache.cc
index 1597c4a..3f2df29 100644
--- a/test/497-inlining-and-class-loader/clear_dex_cache.cc
+++ b/test/497-inlining-and-class-loader/clear_dex_cache.cc
@@ -17,7 +17,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "jni.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
@@ -29,7 +29,7 @@
jclass,
jclass cls) {
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache = soa.Decode<mirror::Class*>(cls)->GetDexCache();
+ mirror::DexCache* dex_cache = soa.Decode<mirror::Class>(cls)->GetDexCache();
size_t num_methods = dex_cache->NumResolvedMethods();
ArtMethod** methods = dex_cache->GetResolvedMethods();
CHECK_EQ(num_methods != 0u, methods != nullptr);
@@ -43,7 +43,7 @@
array = env->NewLongArray(num_methods);
}
CHECK(array != nullptr);
- mirror::PointerArray* pointer_array = soa.Decode<mirror::PointerArray*>(array);
+ mirror::PointerArray* pointer_array = soa.Decode<mirror::PointerArray>(array).Decode();
for (size_t i = 0; i != num_methods; ++i) {
ArtMethod* method = mirror::DexCache::GetElementPtrSize(methods, i, kRuntimePointerSize);
pointer_array->SetElementPtrSize(i, method, kRuntimePointerSize);
@@ -54,11 +54,11 @@
extern "C" JNIEXPORT void JNICALL Java_Main_restoreResolvedMethods(
JNIEnv*, jclass, jclass cls, jobject old_cache) {
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache = soa.Decode<mirror::Class*>(cls)->GetDexCache();
+ mirror::DexCache* dex_cache = soa.Decode<mirror::Class>(cls)->GetDexCache();
size_t num_methods = dex_cache->NumResolvedMethods();
- ArtMethod** methods = soa.Decode<mirror::Class*>(cls)->GetDexCache()->GetResolvedMethods();
+ ArtMethod** methods = soa.Decode<mirror::Class>(cls)->GetDexCache()->GetResolvedMethods();
CHECK_EQ(num_methods != 0u, methods != nullptr);
- mirror::PointerArray* old = soa.Decode<mirror::PointerArray*>(old_cache);
+ ObjPtr<mirror::PointerArray> old = soa.Decode<mirror::PointerArray>(old_cache);
CHECK_EQ(methods != nullptr, old != nullptr);
CHECK_EQ(num_methods, static_cast<size_t>(old->GetLength()));
for (size_t i = 0; i != num_methods; ++i) {
diff --git a/test/543-env-long-ref/env_long_ref.cc b/test/543-env-long-ref/env_long_ref.cc
index 557def6..cd127ef 100644
--- a/test/543-env-long-ref/env_long_ref.cc
+++ b/test/543-env-long-ref/env_long_ref.cc
@@ -17,7 +17,7 @@
#include "arch/context.h"
#include "art_method-inl.h"
#include "jni.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
@@ -43,7 +43,7 @@
uint32_t value = 0;
CHECK(GetVReg(m, 1, kReferenceVReg, &value));
CHECK_EQ(reinterpret_cast<mirror::Object*>(value),
- soa_.Decode<mirror::Object*>(expected_value_));
+ soa_.Decode<mirror::Object>(expected_value_).Decode());
}
return true;
}
diff --git a/test/566-polymorphic-inlining/polymorphic_inline.cc b/test/566-polymorphic-inlining/polymorphic_inline.cc
index 89293cc..00c1b02 100644
--- a/test/566-polymorphic-inlining/polymorphic_inline.cc
+++ b/test/566-polymorphic-inlining/polymorphic_inline.cc
@@ -20,14 +20,14 @@
#include "jit/jit_code_cache.h"
#include "jit/profiling_info.h"
#include "oat_quick_method_header.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack_map.h"
namespace art {
static void do_checks(jclass cls, const char* method_name) {
ScopedObjectAccess soa(Thread::Current());
- mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
jit::Jit* jit = Runtime::Current()->GetJit();
jit::JitCodeCache* code_cache = jit->GetCodeCache();
ArtMethod* method = klass->FindDeclaredDirectMethodByName(method_name, kRuntimePointerSize);
@@ -53,7 +53,7 @@
static void allocate_profiling_info(jclass cls, const char* method_name) {
ScopedObjectAccess soa(Thread::Current());
- mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
ArtMethod* method = klass->FindDeclaredDirectMethodByName(method_name, kRuntimePointerSize);
ProfilingInfo::Create(soa.Self(), method, /* retry_allocation */ true);
}
diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc
index adda3cc..50e8382 100644
--- a/test/570-checker-osr/osr.cc
+++ b/test/570-checker-osr/osr.cc
@@ -19,7 +19,7 @@
#include "jit/jit_code_cache.h"
#include "jit/profiling_info.h"
#include "oat_quick_method_header.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedUtfChars.h"
#include "stack_map.h"
diff --git a/test/595-profile-saving/profile-saving.cc b/test/595-profile-saving/profile-saving.cc
index a265dce..bf3d812 100644
--- a/test/595-profile-saving/profile-saving.cc
+++ b/test/595-profile-saving/profile-saving.cc
@@ -24,7 +24,7 @@
#include "mirror/class-inl.h"
#include "oat_file_assistant.h"
#include "oat_file_manager.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedUtfChars.h"
#include "thread.h"
@@ -74,7 +74,7 @@
ScopedUtfChars filename_chars(env, filename);
CHECK(filename_chars.c_str() != nullptr);
ScopedObjectAccess soa(Thread::Current());
- const DexFile* dex_file = soa.Decode<mirror::Class*>(cls)->GetDexCache()->GetDexFile();
+ const DexFile* dex_file = soa.Decode<mirror::Class>(cls)->GetDexCache()->GetDexFile();
return ProfileSaver::HasSeenMethod(std::string(filename_chars.c_str()),
dex_file,
static_cast<uint16_t>(method_index));
diff --git a/test/596-app-images/app_images.cc b/test/596-app-images/app_images.cc
index a5bbf5f..78cc3fd 100644
--- a/test/596-app-images/app_images.cc
+++ b/test/596-app-images/app_images.cc
@@ -26,7 +26,7 @@
#include "jni.h"
#include "mirror/class.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
namespace art {
@@ -48,13 +48,13 @@
extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkAppImageContains(JNIEnv*, jclass, jclass c) {
ScopedObjectAccess soa(Thread::Current());
- mirror::Class* klass_ptr = soa.Decode<mirror::Class*>(c);
+ ObjPtr<mirror::Class> klass_ptr = soa.Decode<mirror::Class>(c);
for (auto* space : Runtime::Current()->GetHeap()->GetContinuousSpaces()) {
if (space->IsImageSpace()) {
auto* image_space = space->AsImageSpace();
const auto& image_header = image_space->GetImageHeader();
if (image_header.IsAppImage()) {
- if (image_space->HasAddress(klass_ptr)) {
+ if (image_space->HasAddress(klass_ptr.Decode())) {
return JNI_TRUE;
}
}
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index fd1ba02..4248148 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -24,7 +24,7 @@
#include "mirror/class-inl.h"
#include "oat_quick_method_header.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "ScopedUtfChars.h"
#include "thread-inl.h"
@@ -35,7 +35,7 @@
extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasOatFile(JNIEnv* env, jclass cls) {
ScopedObjectAccess soa(env);
- mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
const DexFile& dex_file = klass->GetDexFile();
const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
return (oat_dex_file != nullptr) ? JNI_TRUE : JNI_FALSE;
@@ -75,7 +75,7 @@
extern "C" JNIEXPORT jboolean JNICALL Java_Main_compiledWithOptimizing(JNIEnv* env, jclass cls) {
ScopedObjectAccess soa(env);
- mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
const DexFile& dex_file = klass->GetDexFile();
const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
if (oat_dex_file == nullptr) {
@@ -134,7 +134,7 @@
ScopedUtfChars chars(env, method_name);
CHECK(chars.c_str() != nullptr);
- method = soa.Decode<mirror::Class*>(cls)->FindDeclaredDirectMethodByName(
+ method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
chars.c_str(), kRuntimePointerSize);
}
diff --git a/test/common/stack_inspect.cc b/test/common/stack_inspect.cc
index 85ea1c8..d2aacf0 100644
--- a/test/common/stack_inspect.cc
+++ b/test/common/stack_inspect.cc
@@ -21,7 +21,7 @@
#include "mirror/class-inl.h"
#include "nth_caller_visitor.h"
#include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread-inl.h"
@@ -62,7 +62,7 @@
static jboolean IsManaged(JNIEnv* env, jclass cls, size_t level) {
ScopedObjectAccess soa(env);
- mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
+ ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
const DexFile& dex_file = klass->GetDexFile();
const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
if (oat_dex_file == nullptr) {
diff --git a/tools/jfuzz/run_jfuzz_test.py b/tools/jfuzz/run_jfuzz_test.py
index 54f9bb4..fd8415d 100755
--- a/tools/jfuzz/run_jfuzz_test.py
+++ b/tools/jfuzz/run_jfuzz_test.py
@@ -450,13 +450,13 @@
os.mkdir(ddir)
for f in glob('*.txt') + ['Test.java']:
shutil.copy(f, ddir)
- # Maybe run bisection bug search.
- if (retc1 in BISECTABLE_RET_CODES and retc2 in BISECTABLE_RET_CODES and
- not (self._true_divergence_only and RetCode.TIMEOUT in (retc1, retc2))):
- self.MaybeBisectDivergence(retc1, retc2, is_output_divergence)
- # Call reporting script.
- if self._report_script:
- self.RunReportScript(retc1, retc2, is_output_divergence)
+ if not (self._true_divergence_only and RetCode.TIMEOUT in (retc1, retc2)):
+ # Maybe run bisection bug search.
+ if retc1 in BISECTABLE_RET_CODES and retc2 in BISECTABLE_RET_CODES:
+ self.MaybeBisectDivergence(retc1, retc2, is_output_divergence)
+ # Call reporting script.
+ if self._report_script:
+ self.RunReportScript(retc1, retc2, is_output_divergence)
def RunReportScript(self, retc1, retc2, is_output_divergence):
"""Runs report script."""
diff --git a/tools/jfuzz/run_jfuzz_test_nightly.py b/tools/jfuzz/run_jfuzz_test_nightly.py
index cd338fb..29595f2 100755
--- a/tools/jfuzz/run_jfuzz_test_nightly.py
+++ b/tools/jfuzz/run_jfuzz_test_nightly.py
@@ -16,9 +16,14 @@
import argparse
import os
+import re
+import shutil
import subprocess
import sys
+from glob import glob
+
+from tempfile import mkdtemp
from tempfile import TemporaryFile
# Default arguments for run_jfuzz_test.py.
@@ -51,15 +56,29 @@
for proc in processes:
proc.kill()
# Output results.
+ output_dirs = []
for i, output_file in enumerate(output_files):
output_file.seek(0)
output_str = output_file.read().decode('ascii')
output_file.close()
+ # Extract output directory. Example match: 'Directory : /tmp/tmp8ltpfjng'.
+ directory_match = re.search(r'Directory[^:]*: ([^\n]+)\n', output_str)
+ if directory_match:
+ output_dirs.append(directory_match.group(1))
print('Tester', i)
if output_str.find(SUCCESS_STRING) == NOT_FOUND:
print(output_str)
else:
print(SUCCESS_STRING)
+ # Gather divergences.
+ global_out_dir = mkdtemp('jfuzz_nightly')
+ divergence_nr = 1
+ for out_dir in output_dirs:
+ for divergence_dir in glob(out_dir + '/divergence*/'):
+ shutil.copytree(divergence_dir,
+ global_out_dir + '/divergence' + str(divergence_nr))
+ divergence_nr += 1
+ print('Global output directory:', global_out_dir)
if __name__ == '__main__':
main(sys.argv)