diff options
234 files changed, 3405 insertions, 5446 deletions
diff --git a/Android.bp b/Android.bp deleted file mode 100644 index 34a646915f..0000000000 --- a/Android.bp +++ /dev/null @@ -1,56 +0,0 @@ -// TODO: These should be handled with transitive static library dependencies -art_static_dependencies = [ - // Note: the order is important because of static linking resolution. - "libziparchive", - "libnativehelper", - "libnativebridge", - "libnativeloader", - "libsigchain_dummy", - "liblog", - "libz", - "libbacktrace", - "libcutils", - "libunwindstack", - "libutils", - "libbase", - "liblz4", - "liblzma", - "libmetricslogger_static", -] - -subdirs = [ - "adbconnection", - "benchmark", - "build", - "cmdline", - "compiler", - "dalvikvm", - "dex2oat", - "dexdump", - "dexlayout", - "dexlist", - "dexoptanalyzer", - "disassembler", - "dt_fd_forward", - "dt_fd_forward/export", - "imgdiag", - "libartbase", - "libdexfile", - "libprofile", - "oatdump", - "openjdkjvm", - "openjdkjvmti", - "patchoat", - "profman", - "runtime", - "sigchainlib", - "simulator", - "test", - "tools", - "tools/breakpoint-logger", - "tools/cpp-define-generator", - "tools/dmtracedump", - "tools/hiddenapi", - "tools/titrace", - "tools/wrapagentproperties", -] diff --git a/build/art.go b/build/art.go index 61b1a4e501..6c084867a7 100644 --- a/build/art.go +++ b/build/art.go @@ -283,6 +283,7 @@ func init() { android.RegisterModuleType("art_cc_test_library", artTestLibrary) android.RegisterModuleType("art_cc_defaults", artDefaultsFactory) android.RegisterModuleType("libart_cc_defaults", libartDefaultsFactory) + android.RegisterModuleType("libart_static_cc_defaults", libartStaticDefaultsFactory) android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory) android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory) } @@ -336,6 +337,33 @@ func libartDefaultsFactory() android.Module { return module } +func libartStaticDefaultsFactory() android.Module { + c := &codegenProperties{} + module := cc.DefaultsFactory(c) + android.AddLoadHook(module, func(ctx android.LoadHookContext) { + codegen(ctx, c, true) + + type props struct { + Target struct { + Android struct { + Static_libs []string + } + } + } + + p := &props{} + // TODO: express this in .bp instead b/79671158 + if !envTrue(ctx, "ART_TARGET_LINUX") { + p.Target.Android.Static_libs = []string{ + "libmetricslogger_static", + } + } + ctx.AppendProperties(p) + }) + + return module +} + func artLibrary() android.Module { m, _ := cc.NewLibrary(android.HostAndDeviceSupported) module := m.Init() diff --git a/cmdline/cmdline_parser_test.cc b/cmdline/cmdline_parser_test.cc index 42c6a5ff59..97daafadd8 100644 --- a/cmdline/cmdline_parser_test.cc +++ b/cmdline/cmdline_parser_test.cc @@ -131,7 +131,7 @@ class CmdlineParserTest : public ::testing::Test { art::InitLogging(nullptr, art::Runtime::Abort); // argv = null } - virtual void SetUp() { + void SetUp() override { parser_ = ParsedOptions::MakeParser(false); // do not ignore unrecognized options } diff --git a/compiler/Android.bp b/compiler/Android.bp index c36553779e..c2f8e3c66e 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -191,6 +191,15 @@ art_cc_defaults { export_include_dirs: ["."], } +cc_defaults { + name: "libart-compiler_static_base_defaults", + static_libs: [ + "libbase", + "libcutils", + "liblzma", + ], +} + gensrcs { name: "art_compiler_operator_srcs", cmd: "$(location generate_operator_out) art/compiler $(in) > $(out)", @@ -260,6 +269,18 @@ art_cc_library { }, } +cc_defaults { + name: "libart-compiler_static_defaults", + defaults: [ + "libart-compiler_static_base_defaults", + "libart_static_defaults", + "libartbase_static_defaults", + "libdexfile_static_defaults", + "libprofile_static_defaults", + ], + static_libs: ["libart-compiler"], +} + art_cc_library { name: "libartd-compiler", defaults: [ @@ -302,6 +323,18 @@ art_cc_library { ], } +cc_defaults { + name: "libartd-compiler_static_defaults", + defaults: [ + "libart-compiler_static_base_defaults", + "libartd_static_defaults", + "libartbased_static_defaults", + "libdexfiled_static_defaults", + "libprofiled_static_defaults", + ], + static_libs: ["libartd-compiler"], +} + art_cc_library { name: "libart-compiler-gtest", defaults: ["libart-gtest-defaults"], diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index d603d9673c..586891a3ff 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -108,7 +108,7 @@ void CommonCompilerTest::MakeExecutable(const void* code_start, size_t code_leng int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC); CHECK_EQ(result, 0); - FlushInstructionCache(reinterpret_cast<char*>(base), reinterpret_cast<char*>(base + len)); + FlushInstructionCache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len)); } void CommonCompilerTest::MakeExecutable(ObjPtr<mirror::ClassLoader> class_loader, diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index f6afe2c958..95d08b3c64 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2564,8 +2564,8 @@ static void CompileDexFile(CompilerDriver* driver, thread_pool); auto compile = [&context, &compile_fn](size_t class_def_index) { - ScopedTrace trace(__FUNCTION__); const DexFile& dex_file = *context.GetDexFile(); + SCOPED_TRACE << "compile " << dex_file.GetLocation() << "@" << class_def_index; ClassLinker* class_linker = context.GetClassLinker(); jobject jclass_loader = context.GetClassLoader(); ClassReference ref(&dex_file, class_def_index); diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc index fd17364c26..80c0a6883d 100644 --- a/compiler/exception_test.cc +++ b/compiler/exception_test.cc @@ -50,7 +50,7 @@ class ExceptionTest : public CommonRuntimeTest { // which always points to the first source statement. static constexpr const uint32_t kDexPc = 0; - virtual void SetUp() { + void SetUp() override { CommonRuntimeTest::SetUp(); ScopedObjectAccess soa(Thread::Current()); diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc index 6d135a9bfb..43169ba7eb 100644 --- a/compiler/optimizing/code_generator_vector_arm64.cc +++ b/compiler/optimizing/code_generator_vector_arm64.cc @@ -1354,6 +1354,7 @@ void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) { Register scratch; switch (instruction->GetPackedType()) { + case DataType::Type::kInt16: // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt. case DataType::Type::kUint16: DCHECK_EQ(8u, instruction->GetVectorLength()); // Special handling of compressed/uncompressed string load. @@ -1385,7 +1386,6 @@ void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) { case DataType::Type::kBool: case DataType::Type::kUint8: case DataType::Type::kInt8: - case DataType::Type::kInt16: case DataType::Type::kInt32: case DataType::Type::kFloat32: case DataType::Type::kInt64: diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc index 086ae07a06..2502275b3a 100644 --- a/compiler/optimizing/code_generator_vector_x86.cc +++ b/compiler/optimizing/code_generator_vector_x86.cc @@ -1205,6 +1205,7 @@ void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) { XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>(); bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16); switch (instruction->GetPackedType()) { + case DataType::Type::kInt16: // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt. case DataType::Type::kUint16: DCHECK_EQ(8u, instruction->GetVectorLength()); // Special handling of compressed/uncompressed string load. @@ -1232,7 +1233,6 @@ void InstructionCodeGeneratorX86::VisitVecLoad(HVecLoad* instruction) { case DataType::Type::kBool: case DataType::Type::kUint8: case DataType::Type::kInt8: - case DataType::Type::kInt16: case DataType::Type::kInt32: case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc index 4d31ab68d1..4a67dafd8a 100644 --- a/compiler/optimizing/code_generator_vector_x86_64.cc +++ b/compiler/optimizing/code_generator_vector_x86_64.cc @@ -1178,6 +1178,7 @@ void InstructionCodeGeneratorX86_64::VisitVecLoad(HVecLoad* instruction) { XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>(); bool is_aligned16 = instruction->GetAlignment().IsAlignedAt(16); switch (instruction->GetPackedType()) { + case DataType::Type::kInt16: // (short) s.charAt(.) can yield HVecLoad/Int16/StringCharAt. case DataType::Type::kUint16: DCHECK_EQ(8u, instruction->GetVectorLength()); // Special handling of compressed/uncompressed string load. @@ -1205,7 +1206,6 @@ void InstructionCodeGeneratorX86_64::VisitVecLoad(HVecLoad* instruction) { case DataType::Type::kBool: case DataType::Type::kUint8: case DataType::Type::kInt8: - case DataType::Type::kInt16: case DataType::Type::kInt32: case DataType::Type::kInt64: DCHECK_LE(2u, instruction->GetVectorLength()); diff --git a/compiler/optimizing/constructor_fence_redundancy_elimination.cc b/compiler/optimizing/constructor_fence_redundancy_elimination.cc index 3cb8bf2f47..3a1a9e023d 100644 --- a/compiler/optimizing/constructor_fence_redundancy_elimination.cc +++ b/compiler/optimizing/constructor_fence_redundancy_elimination.cc @@ -78,7 +78,7 @@ class CFREVisitor : public HGraphVisitor { VisitSetLocation(instruction, value); } - void VisitDeoptimize(HDeoptimize* instruction ATTRIBUTE_UNUSED) { + void VisitDeoptimize(HDeoptimize* instruction ATTRIBUTE_UNUSED) override { // Pessimize: Merge all fences. MergeCandidateFences(); } diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 2757f7b719..bb96c211cb 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -2146,22 +2146,6 @@ void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) { ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo(); if (argument_rti.IsValid() && argument_rti.IsStringClass()) { optimizations.SetArgumentIsString(); - } else if (kUseReadBarrier) { - DCHECK(instruction->GetResolvedMethod() != nullptr); - DCHECK(instruction->GetResolvedMethod()->GetDeclaringClass()->IsStringClass() || - // Object.equals() can be devirtualized to String.equals(). - instruction->GetResolvedMethod()->GetDeclaringClass()->IsObjectClass()); - Runtime* runtime = Runtime::Current(); - // For AOT, we always assume that the boot image shall contain the String.class and - // we do not need a read barrier for boot image classes as they are non-moveable. - // For JIT, check if we actually have a boot image; if we do, the String.class - // should also be non-moveable. - if (runtime->IsAotCompiler() || runtime->GetHeap()->HasBootImageSpace()) { - DCHECK(runtime->IsAotCompiler() || - !runtime->GetHeap()->IsMovableObject( - instruction->GetResolvedMethod()->GetDeclaringClass())); - optimizations.SetNoReadBarrierForStringClass(); - } } } } diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 06e2fbb355..2d93f234be 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -219,7 +219,6 @@ class StringEqualsOptimizations : public IntrinsicOptimizations { INTRINSIC_OPTIMIZATION(ArgumentNotNull, 0); INTRINSIC_OPTIMIZATION(ArgumentIsString, 1); - INTRINSIC_OPTIMIZATION(NoReadBarrierForStringClass, 2); private: DISALLOW_COPY_AND_ASSIGN(StringEqualsOptimizations); diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 1abfcb022b..7684dc79f2 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -1398,13 +1398,6 @@ static const char* GetConstString(HInstruction* candidate, uint32_t* utf16_lengt } void IntrinsicLocationsBuilderARM64::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index 1127fb8191..bc59fcf50c 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -1458,13 +1458,6 @@ static const char* GetConstString(HInstruction* candidate, uint32_t* utf16_lengt } void IntrinsicLocationsBuilderARMVIXL::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); InvokeRuntimeCallingConventionARMVIXL calling_convention; diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 771714bf41..6f7f5e49c1 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -1516,13 +1516,6 @@ void IntrinsicCodeGeneratorMIPS::VisitStringCompareTo(HInvoke* invoke) { // boolean java.lang.String.equals(Object anObject) void IntrinsicLocationsBuilderMIPS::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index 4a1bd5b7b2..2eb252908c 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -1369,13 +1369,6 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringCompareTo(HInvoke* invoke) { // boolean java.lang.String.equals(Object anObject) void IntrinsicLocationsBuilderMIPS64::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index d33c0c344e..3504d7a6f8 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -922,13 +922,6 @@ void IntrinsicCodeGeneratorX86::VisitStringCompareTo(HInvoke* invoke) { } void IntrinsicLocationsBuilderX86::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index ae889744ad..96f6eaaf33 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -1230,13 +1230,6 @@ void IntrinsicCodeGeneratorX86_64::VisitStringCompareTo(HInvoke* invoke) { } void IntrinsicLocationsBuilderX86_64::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index 7f71745a43..b33d0f488e 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -692,7 +692,7 @@ class LSEVisitor : public HGraphDelegateVisitor { VisitSetLocation(instruction, idx, instruction->InputAt(2)); } - void VisitDeoptimize(HDeoptimize* instruction) { + void VisitDeoptimize(HDeoptimize* instruction) override { const ScopedArenaVector<HInstruction*>& heap_values = heap_values_for_[instruction->GetBlock()->GetBlockId()]; for (HInstruction* heap_value : heap_values) { diff --git a/compiler/optimizing/optimizing_cfi_test.cc b/compiler/optimizing/optimizing_cfi_test.cc index be1f7ea5b4..a52031cced 100644 --- a/compiler/optimizing/optimizing_cfi_test.cc +++ b/compiler/optimizing/optimizing_cfi_test.cc @@ -128,7 +128,7 @@ class OptimizingCFITest : public CFITest, public OptimizingUnitTestHelper { public: InternalCodeAllocator() {} - virtual uint8_t* Allocate(size_t size) { + uint8_t* Allocate(size_t size) override { memory_.resize(size); return memory_.data(); } diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 0a747053cf..ff1207abab 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -79,7 +79,7 @@ class CodeVectorAllocator final : public CodeAllocator { explicit CodeVectorAllocator(ArenaAllocator* allocator) : memory_(allocator->Adapter(kArenaAllocCodeBuffer)) {} - virtual uint8_t* Allocate(size_t size) { + uint8_t* Allocate(size_t size) override { memory_.resize(size); return &memory_[0]; } diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index a9d590232c..9079658e1c 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -114,9 +114,9 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { void VisitCheckCast(HCheckCast* instr) override; void VisitBoundType(HBoundType* instr) override; void VisitNullCheck(HNullCheck* instr) override; - void VisitPhi(HPhi* phi); + void VisitPhi(HPhi* phi) override; - void VisitBasicBlock(HBasicBlock* block); + void VisitBasicBlock(HBasicBlock* block) override; void ProcessWorklist(); private: diff --git a/compiler/utils/mips/assembler_mips32r5_test.cc b/compiler/utils/mips/assembler_mips32r5_test.cc index f9919f52b5..bd73c12dc5 100644 --- a/compiler/utils/mips/assembler_mips32r5_test.cc +++ b/compiler/utils/mips/assembler_mips32r5_test.cc @@ -229,7 +229,7 @@ class AssemblerMIPS32r5Test : public AssemblerTest<mips::MipsAssembler, STLDeleteElements(&vec_registers_); } - std::vector<mips::MipsLabel> GetAddresses() { + std::vector<mips::MipsLabel> GetAddresses() override { UNIMPLEMENTED(FATAL) << "Feature not implemented yet"; UNREACHABLE(); } diff --git a/compiler/utils/mips/assembler_mips32r6_test.cc b/compiler/utils/mips/assembler_mips32r6_test.cc index 1ec7a6a3e0..9637c25e7e 100644 --- a/compiler/utils/mips/assembler_mips32r6_test.cc +++ b/compiler/utils/mips/assembler_mips32r6_test.cc @@ -242,7 +242,7 @@ class AssemblerMIPS32r6Test : public AssemblerTest<mips::MipsAssembler, STLDeleteElements(&vec_registers_); } - std::vector<mips::MipsLabel> GetAddresses() { + std::vector<mips::MipsLabel> GetAddresses() override { UNIMPLEMENTED(FATAL) << "Feature not implemented yet"; UNREACHABLE(); } diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc index 9527fa6ddd..f137c60eb8 100644 --- a/compiler/utils/mips/assembler_mips_test.cc +++ b/compiler/utils/mips/assembler_mips_test.cc @@ -176,7 +176,7 @@ class AssemblerMIPSTest : public AssemblerTest<mips::MipsAssembler, STLDeleteElements(&fp_registers_); } - std::vector<mips::MipsLabel> GetAddresses() { + std::vector<mips::MipsLabel> GetAddresses() override { UNIMPLEMENTED(FATAL) << "Feature not implemented yet"; UNREACHABLE(); } diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc index 4ceb356910..3218ae3a90 100644 --- a/compiler/utils/mips64/assembler_mips64_test.cc +++ b/compiler/utils/mips64/assembler_mips64_test.cc @@ -240,7 +240,7 @@ class AssemblerMIPS64Test : public AssemblerTest<mips64::Mips64Assembler, STLDeleteElements(&vec_registers_); } - std::vector<mips64::Mips64Label> GetAddresses() { + std::vector<mips64::Mips64Label> GetAddresses() override { UNIMPLEMENTED(FATAL) << "Feature not implemented yet"; UNREACHABLE(); } diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc index e1de1f172f..65711e0855 100644 --- a/compiler/utils/x86_64/assembler_x86_64_test.cc +++ b/compiler/utils/x86_64/assembler_x86_64_test.cc @@ -297,7 +297,7 @@ class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler, STLDeleteElements(&fp_registers_); } - std::vector<x86_64::Address> GetAddresses() { + std::vector<x86_64::Address> GetAddresses() override { return addresses_; } diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc index 81932a90ce..523c90b8ef 100644 --- a/compiler/verifier_deps_test.cc +++ b/compiler/verifier_deps_test.cc @@ -52,7 +52,7 @@ class VerifierDepsCompilerCallbacks : public CompilerCallbacks { bool IsRelocationPossible() override { return false; } verifier::VerifierDeps* GetVerifierDeps() const override { return deps_; } - void SetVerifierDeps(verifier::VerifierDeps* deps) { deps_ = deps; } + void SetVerifierDeps(verifier::VerifierDeps* deps) override { deps_ = deps; } private: verifier::VerifierDeps* deps_; @@ -60,7 +60,7 @@ class VerifierDepsCompilerCallbacks : public CompilerCallbacks { class VerifierDepsTest : public CommonCompilerTest { public: - void SetUpRuntimeOptions(RuntimeOptions* options) { + void SetUpRuntimeOptions(RuntimeOptions* options) override { CommonCompilerTest::SetUpRuntimeOptions(options); callbacks_.reset(new VerifierDepsCompilerCallbacks()); } diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp index 88e69cdb2a..666db425bd 100644 --- a/dex2oat/Android.bp +++ b/dex2oat/Android.bp @@ -89,6 +89,20 @@ art_cc_defaults { }, } +cc_defaults { + name: "libart-dex2oat_static_base_defaults", + target: { + android: { + static_libs: ["libcutils"], + }, + }, + static_libs: [ + "libbase", + "liblz4", + "liblzma", + ], +} + gensrcs { name: "art_dex2oat_operator_srcs", cmd: "$(location generate_operator_out) art/dex2oat $(in) > $(out)", @@ -110,6 +124,20 @@ art_cc_static_library { ], } +cc_defaults { + name: "libart-dex2oat_static_defaults", + defaults: [ + "libart-dex2oat_static_base_defaults", + "libart_static_defaults", + "libprofile_static_defaults", + ], + static_libs: [ + "libart-compiler", + "libart-dexlayout", + "libart-dex2oat", + ], +} + art_cc_static_library { name: "libartd-dex2oat", defaults: [ @@ -124,6 +152,20 @@ art_cc_static_library { ], } +cc_defaults { + name: "libartd-dex2oat_static_defaults", + defaults: [ + "libart-dex2oat_static_base_defaults", + "libartd_static_defaults", + "libprofiled_static_defaults", + ], + static_libs: [ + "libartd-compiler", + "libartd-dexlayout", + "libartd-dex2oat", + ], +} + cc_library_headers { name: "dex2oat_headers", host_supported: true, @@ -255,7 +297,9 @@ cc_defaults { name: "dex2oats-defaults", device_supported: false, static_executable: true, - defaults: ["dex2oat-defaults"], + defaults: [ + "dex2oat-defaults", + ], target: { darwin: { enabled: false, @@ -269,22 +313,24 @@ cc_defaults { // Try to get rid of it. "-z muldefs", ], - static_libs: art_static_dependencies, + static_libs: [ + "libbase", + "liblz4", + "libsigchain_dummy", + ], } art_cc_binary { name: "dex2oats", - defaults: ["dex2oats-defaults"], - static_libs: [ - "libart-dex2oat", - "libart-compiler", - "libart-dexlayout", - "libart", - "libartbase", - "libdexfile", - "libprofile", - "libvixl-arm", - "libvixl-arm64", + defaults: [ + "dex2oats-defaults", + "libart_static_defaults", + "libart-compiler_static_defaults", + "libart-dexlayout_static_defaults", + "libartbase_static_defaults", + "libdexfile_static_defaults", + "libprofile_static_defaults", + "libart-dex2oat_static_defaults", ], } @@ -293,6 +339,13 @@ art_cc_binary { defaults: [ "art_debug_defaults", "dex2oats-defaults", + "libartd_static_defaults", + "libartd-compiler_static_defaults", + "libartd-dexlayout_static_defaults", + "libartbased_static_defaults", + "libdexfiled_static_defaults", + "libprofiled_static_defaults", + "libartd-dex2oat_static_defaults", ], target: { linux_glibc_x86_64: { @@ -301,17 +354,6 @@ art_cc_binary { }, // b/79417743, oatdump 32-bit tests failed with clang lld use_clang_lld: false, - static_libs: [ - "libartd-dex2oat", - "libartd-compiler", - "libartd-dexlayout", - "libartd", - "libartbased", - "libprofiled", - "libdexfiled", - "libvixld-arm", - "libvixld-arm64", - ], } art_cc_test { diff --git a/dex2oat/linker/elf_writer_quick.cc b/dex2oat/linker/elf_writer_quick.cc index 852293bdb8..9a7f93d9fc 100644 --- a/dex2oat/linker/elf_writer_quick.cc +++ b/dex2oat/linker/elf_writer_quick.cc @@ -68,7 +68,7 @@ class DebugInfoTask : public Task { debug_info_(debug_info) { } - void Run(Thread*) { + void Run(Thread*) override { result_ = debug::MakeMiniDebugInfo(isa_, instruction_set_features_, text_section_address_, diff --git a/dex2oat/linker/elf_writer_test.cc b/dex2oat/linker/elf_writer_test.cc index 40495f33ee..ef85fd16ff 100644 --- a/dex2oat/linker/elf_writer_test.cc +++ b/dex2oat/linker/elf_writer_test.cc @@ -34,7 +34,7 @@ namespace linker { class ElfWriterTest : public CommonCompilerTest { protected: - virtual void SetUp() { + void SetUp() override { ReserveImageSpace(); CommonCompilerTest::SetUp(); } diff --git a/dex2oat/linker/multi_oat_relative_patcher_test.cc b/dex2oat/linker/multi_oat_relative_patcher_test.cc index a5831b64b3..2610561683 100644 --- a/dex2oat/linker/multi_oat_relative_patcher_test.cc +++ b/dex2oat/linker/multi_oat_relative_patcher_test.cc @@ -96,12 +96,12 @@ class MultiOatRelativePatcherTest : public testing::Test { void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, const LinkerPatch& patch ATTRIBUTE_UNUSED, - uint32_t patch_offset ATTRIBUTE_UNUSED) { + uint32_t patch_offset ATTRIBUTE_UNUSED) override { LOG(FATAL) << "UNIMPLEMENTED"; } std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo( - uint32_t executable_offset ATTRIBUTE_UNUSED) { + uint32_t executable_offset ATTRIBUTE_UNUSED) override { LOG(FATAL) << "UNIMPLEMENTED"; UNREACHABLE(); } diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index f88d8d4cf6..e2db11f2aa 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -1671,7 +1671,7 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor { } } - virtual bool VisitComplete() { + bool VisitComplete() override { offset_ = writer_->relative_patcher_->WriteThunks(out_, offset_); if (UNLIKELY(offset_ == 0u)) { PLOG(ERROR) << "Failed to write final relative call thunks"; diff --git a/dex2oat/linker/relative_patcher.cc b/dex2oat/linker/relative_patcher.cc index 564cf30f19..45a4a226d9 100644 --- a/dex2oat/linker/relative_patcher.cc +++ b/dex2oat/linker/relative_patcher.cc @@ -79,7 +79,7 @@ std::unique_ptr<RelativePatcher> RelativePatcher::Create( void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code ATTRIBUTE_UNUSED, const LinkerPatch& patch ATTRIBUTE_UNUSED, - uint32_t patch_offset ATTRIBUTE_UNUSED) { + uint32_t patch_offset ATTRIBUTE_UNUSED) override { LOG(FATAL) << "Unexpected baker read barrier branch patch."; } diff --git a/dexdump/Android.bp b/dexdump/Android.bp index ac9a9a2932..3e576c82da 100644 --- a/dexdump/Android.bp +++ b/dexdump/Android.bp @@ -38,13 +38,13 @@ art_cc_binary { art_cc_binary { name: "dexdumps", - defaults: ["dexdump_defaults"], + defaults: [ + "dexdump_defaults", + "libartbase_static_defaults", + "libdexfile_static_defaults", + ], host_supported: true, device_supported: false, - static_libs: [ - "libdexfile", - "libartbase", - ] + art_static_dependencies, target: { darwin: { enabled: false, diff --git a/dexdump/dexdump_test.cc b/dexdump/dexdump_test.cc index 3a2d38dec6..bb6d4a4b9b 100644 --- a/dexdump/dexdump_test.cc +++ b/dexdump/dexdump_test.cc @@ -31,7 +31,7 @@ namespace art { class DexDumpTest : public CommonRuntimeTest { protected: - virtual void SetUp() { + void SetUp() override { CommonRuntimeTest::SetUp(); // Dogfood our own lib core dex file. dex_file_ = GetLibCoreDexFileNames()[0]; diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp index 147af0c6a9..24ee5f8532 100644 --- a/dexlayout/Android.bp +++ b/dexlayout/Android.bp @@ -32,6 +32,14 @@ art_cc_defaults { static_libs: ["libz"], } +cc_defaults { + name: "libart-dexlayout_static_base_defaults", + static_libs: [ + "libbase", + "libz", + ], +} + art_cc_library { name: "libart-dexlayout", defaults: [ @@ -53,6 +61,17 @@ art_cc_library { }, } +cc_defaults { + name: "libart-dexlayout_static_defaults", + defaults: [ + "libart-dexlayout_static_base_defaults", + "libartbase_static_defaults", + "libdexfile_static_defaults", + "libprofile_static_defaults", + ], + static_libs: ["libart-dexlayout"], +} + art_cc_library { name: "libartd-dexlayout", defaults: [ @@ -67,6 +86,17 @@ art_cc_library { } cc_defaults { + name: "libartd-dexlayout_static_defaults", + defaults: [ + "libart-dexlayout_static_base_defaults", + "libartbased_static_defaults", + "libdexfiled_static_defaults", + "libprofiled_static_defaults", + ], + static_libs: ["libartd-dexlayout"], +} + +cc_defaults { name: "dexlayout-defaults", defaults: ["art_defaults"], host_supported: true, diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index 178a4d4df1..598f7df778 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -215,7 +215,7 @@ class CollectionBase { uint32_t GetOffset() const { return offset_; } void SetOffset(uint32_t new_offset) { offset_ = new_offset; } - virtual uint32_t Size() const { return 0U; } + virtual uint32_t Size() const = 0; private: // Start out unassigned. diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index ca6ff9e514..947d3d5297 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -115,6 +115,8 @@ template<class T> class CollectionMap : public CollectionBase { return it != collection_.end() ? it->second : nullptr; } + uint32_t Size() const override { return size(); } + // Lower case for template interop with std::map. uint32_t size() const { return collection_.size(); } std::map<uint32_t, T*>& Collection() { return collection_; } diff --git a/dexlayout/dexdiag_test.cc b/dexlayout/dexdiag_test.cc index 60dd7e42a4..f936ff990c 100644 --- a/dexlayout/dexdiag_test.cc +++ b/dexlayout/dexdiag_test.cc @@ -34,7 +34,7 @@ static const char* kDexDiagBinaryName = "dexdiag"; class DexDiagTest : public CommonRuntimeTest { protected: - virtual void SetUp() { + void SetUp() override { CommonRuntimeTest::SetUp(); } diff --git a/dexlist/dexlist_test.cc b/dexlist/dexlist_test.cc index 68e67134cc..39e5f8cd99 100644 --- a/dexlist/dexlist_test.cc +++ b/dexlist/dexlist_test.cc @@ -33,7 +33,7 @@ namespace art { class DexListTest : public CommonRuntimeTest { protected: - virtual void SetUp() { + void SetUp() override { CommonRuntimeTest::SetUp(); // Dogfood our own lib core dex file. dex_file_ = GetLibCoreDexFileNames()[0]; diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc index ebc18fc5ff..51b3d753d7 100644 --- a/imgdiag/imgdiag.cc +++ b/imgdiag/imgdiag.cc @@ -26,6 +26,7 @@ #include <unordered_set> #include <vector> +#include <android-base/parseint.h> #include "android-base/stringprintf.h" #include "art_field-inl.h" @@ -1682,14 +1683,14 @@ struct ImgDiagArgs : public CmdlineArgs { if (option.starts_with("--image-diff-pid=")) { const char* image_diff_pid = option.substr(strlen("--image-diff-pid=")).data(); - if (!ParseInt(image_diff_pid, &image_diff_pid_)) { + if (!android::base::ParseInt(image_diff_pid, &image_diff_pid_)) { *error_msg = "Image diff pid out of range"; return kParseError; } } else if (option.starts_with("--zygote-diff-pid=")) { const char* zygote_diff_pid = option.substr(strlen("--zygote-diff-pid=")).data(); - if (!ParseInt(zygote_diff_pid, &zygote_diff_pid_)) { + if (!android::base::ParseInt(zygote_diff_pid, &zygote_diff_pid_)) { *error_msg = "Zygote diff pid out of range"; return kParseError; } @@ -1730,7 +1731,7 @@ struct ImgDiagArgs : public CmdlineArgs { return kParseOk; } - virtual std::string GetUsage() const { + std::string GetUsage() const override { std::string usage; usage += @@ -1760,7 +1761,7 @@ struct ImgDiagArgs : public CmdlineArgs { }; struct ImgDiagMain : public CmdlineMain<ImgDiagArgs> { - virtual bool ExecuteWithRuntime(Runtime* runtime) { + bool ExecuteWithRuntime(Runtime* runtime) override { CHECK(args_ != nullptr); return DumpImage(runtime, diff --git a/imgdiag/imgdiag_test.cc b/imgdiag/imgdiag_test.cc index cb40c7d89d..73df2a2b03 100644 --- a/imgdiag/imgdiag_test.cc +++ b/imgdiag/imgdiag_test.cc @@ -47,7 +47,7 @@ static const pid_t kImgDiagGuaranteedBadPid = (PID_MAX_LIMIT + 1); class ImgDiagTest : public CommonRuntimeTest { protected: - virtual void SetUp() { + void SetUp() override { CommonRuntimeTest::SetUp(); // We loaded the runtime with an explicit image. Therefore the image space must exist. diff --git a/libartbase/Android.bp b/libartbase/Android.bp index 4ee48da5e8..1b603b51e1 100644 --- a/libartbase/Android.bp +++ b/libartbase/Android.bp @@ -79,6 +79,30 @@ cc_defaults { export_shared_lib_headers: ["libbase"], } +cc_defaults { + name: "libartbase_static_base_defaults", + static_libs: [ + "libbase", + "libcutils", + "liblog", + "libutils", + "libz", + "libziparchive", + ], +} + +cc_defaults { + name: "libartbase_static_defaults", + defaults: ["libartbase_static_base_defaults"], + static_libs: ["libartbase"], +} + +cc_defaults { + name: "libartbased_static_defaults", + defaults: ["libartbase_static_base_defaults"], + static_libs: ["libartbased"], +} + gensrcs { name: "art_libartbase_operator_srcs", cmd: "$(location generate_operator_out) art/libartbase $(in) > $(out)", diff --git a/libartbase/base/allocator.cc b/libartbase/base/allocator.cc index 1bcfe8720a..6393672859 100644 --- a/libartbase/base/allocator.cc +++ b/libartbase/base/allocator.cc @@ -30,11 +30,11 @@ class MallocAllocator final : public Allocator { MallocAllocator() {} ~MallocAllocator() {} - void* Alloc(size_t size) { + void* Alloc(size_t size) override { return calloc(sizeof(uint8_t), size); } - void Free(void* p) { + void Free(void* p) override { free(p); } @@ -49,12 +49,12 @@ class NoopAllocator final : public Allocator { NoopAllocator() {} ~NoopAllocator() {} - void* Alloc(size_t size ATTRIBUTE_UNUSED) { + void* Alloc(size_t size ATTRIBUTE_UNUSED) override { LOG(FATAL) << "NoopAllocator::Alloc should not be called"; UNREACHABLE(); } - void Free(void* p ATTRIBUTE_UNUSED) { + void Free(void* p ATTRIBUTE_UNUSED) override { // Noop. } diff --git a/libartbase/base/arena_bit_vector.cc b/libartbase/base/arena_bit_vector.cc index c6d899313d..138a5df77f 100644 --- a/libartbase/base/arena_bit_vector.cc +++ b/libartbase/base/arena_bit_vector.cc @@ -62,11 +62,11 @@ class ArenaBitVectorAllocator final : public Allocator, private ArenaBitVectorAl UNREACHABLE(); } - virtual void* Alloc(size_t size) { + void* Alloc(size_t size) override { return allocator_->Alloc(size, this->Kind()); } - virtual void Free(void*) {} // Nop. + void Free(void*) override {} // Nop. private: ArenaBitVectorAllocator(ArenaAlloc* allocator, ArenaAllocKind kind) diff --git a/libartbase/base/unix_file/fd_file_test.cc b/libartbase/base/unix_file/fd_file_test.cc index 298b2d785f..9c39bb50ec 100644 --- a/libartbase/base/unix_file/fd_file_test.cc +++ b/libartbase/base/unix_file/fd_file_test.cc @@ -23,7 +23,7 @@ namespace unix_file { class FdFileTest : public RandomAccessFileTest { protected: - virtual RandomAccessFile* MakeTestFile() { + RandomAccessFile* MakeTestFile() override { FILE* tmp = tmpfile(); int fd = dup(fileno(tmp)); fclose(tmp); diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc index 761c6113d6..74cc5b97b2 100644 --- a/libartbase/base/utils.cc +++ b/libartbase/base/utils.cc @@ -38,6 +38,12 @@ #include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED #endif +#if defined(__BIONIC__) +// membarrier(2) is only supported for target builds (b/111199492). +#include <linux/membarrier.h> +#include <sys/syscall.h> +#endif + #if defined(__linux__) #include <linux/unistd.h> #endif @@ -207,4 +213,42 @@ void SleepForever() { } } +bool FlushInstructionPipeline() { + // membarrier(2) is only supported for target builds (b/111199492). +#if defined(__BIONIC__) + static constexpr int kSyncCoreMask = + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE | + MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE; + static bool have_probed = false; + static bool have_sync_core = false; + + if (UNLIKELY(!have_probed)) { + // Probe membarrier(2) commands supported by kernel. + int commands = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0); + if (commands >= 0) { + have_sync_core = (commands & kSyncCoreMask) == kSyncCoreMask; + if (have_sync_core) { + // Register with kernel that we'll be using the private expedited sync core command. + CheckedCall(syscall, + "membarrier register sync core", + __NR_membarrier, + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE, + 0); + } + } + have_probed = true; + } + + if (have_sync_core) { + CheckedCall(syscall, + "membarrier sync core", + __NR_membarrier, + MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE, + 0); + return true; + } +#endif // defined(__BIONIC__) + return false; +} + } // namespace art diff --git a/libartbase/base/utils.h b/libartbase/base/utils.h index ba61e1b0a3..d85960d811 100644 --- a/libartbase/base/utils.h +++ b/libartbase/base/utils.h @@ -24,6 +24,7 @@ #include <string> #include <android-base/logging.h> +#include <android-base/parseint.h> #include "casts.h" #include "enums.h" @@ -33,34 +34,6 @@ namespace art { -template <typename T> -bool ParseUint(const char *in, T* out) { - char* end; - unsigned long long int result = strtoull(in, &end, 0); // NOLINT(runtime/int) - if (in == end || *end != '\0') { - return false; - } - if (std::numeric_limits<T>::max() < result) { - return false; - } - *out = static_cast<T>(result); - return true; -} - -template <typename T> -bool ParseInt(const char* in, T* out) { - char* end; - long long int result = strtoll(in, &end, 0); // NOLINT(runtime/int) - if (in == end || *end != '\0') { - return false; - } - if (result < std::numeric_limits<T>::min() || std::numeric_limits<T>::max() < result) { - return false; - } - *out = static_cast<T>(result); - return true; -} - static inline uint32_t PointerToLowMemUInt32(const void* p) { uintptr_t intp = reinterpret_cast<uintptr_t>(p); DCHECK_LE(intp, 0xFFFFFFFFU); @@ -130,7 +103,7 @@ static void ParseIntOption(const StringPiece& option, DCHECK(option.starts_with(option_prefix)) << option << " " << option_prefix; const char* value_string = option.substr(option_prefix.size()).data(); int64_t parsed_integer_value = 0; - if (!ParseInt(value_string, &parsed_integer_value)) { + if (!android::base::ParseInt(value_string, &parsed_integer_value)) { usage("Failed to parse %s '%s' as an integer", option_name.c_str(), value_string); } *out = dchecked_integral_cast<T>(parsed_integer_value); @@ -179,16 +152,19 @@ static T GetRandomNumber(T min, T max) { // Sleep forever and never come back. NO_RETURN void SleepForever(); -inline void FlushInstructionCache(char* begin, char* end) { - __builtin___clear_cache(begin, end); +inline void FlushDataCache(void* begin, void* end) { + __builtin___clear_cache(reinterpret_cast<char*>(begin), reinterpret_cast<char*>(end)); } -inline void FlushDataCache(char* begin, char* end) { +inline void FlushInstructionCache(void* begin, void* end) { // Same as FlushInstructionCache for lack of other builtin. __builtin___clear_cache // flushes both caches. - __builtin___clear_cache(begin, end); + __builtin___clear_cache(reinterpret_cast<char*>(begin), reinterpret_cast<char*>(end)); } +// Flush instruction pipeline. Returns true on success, false if feature is unsupported. +bool FlushInstructionPipeline(); + template <typename T> constexpr PointerSize ConvertToPointerSize(T any) { if (any == 4 || any == 8) { diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp index 06fd19e2fe..49b1278fcb 100644 --- a/libdexfile/Android.bp +++ b/libdexfile/Android.bp @@ -72,6 +72,36 @@ cc_defaults { ], } +cc_defaults { + name: "libdexfile_static_base_defaults", + static_libs: [ + "libbase", + "libcutils", + "liblog", + "libutils", + "libz", + "libziparchive", + ], +} + +cc_defaults { + name: "libdexfile_static_defaults", + defaults: [ + "libartbase_static_defaults", + "libdexfile_static_base_defaults", + ], + static_libs: ["libdexfile"], +} + +cc_defaults { + name: "libdexfiled_static_defaults", + defaults: [ + "libartbased_static_defaults", + "libdexfile_static_base_defaults", + ], + static_libs: ["libdexfiled"], +} + gensrcs { name: "dexfile_operator_srcs", cmd: "$(location generate_operator_out) art/libdexfile $(in) > $(out)", diff --git a/libprofile/Android.bp b/libprofile/Android.bp index b9883f658d..edd9fa858b 100644 --- a/libprofile/Android.bp +++ b/libprofile/Android.bp @@ -56,6 +56,37 @@ cc_defaults { export_shared_lib_headers: ["libbase"], } +cc_defaults { + name: "libprofile_static_base_defaults", + static_libs: [ + "libbase", + "libcutils", + "libutils", + "libz", + "libziparchive", + ], +} + +cc_defaults { + name: "libprofile_static_defaults", + defaults: [ + "libprofile_static_base_defaults", + "libartbase_static_defaults", + "libdexfile_static_defaults", + ], + static_libs: ["libprofile"], +} + +cc_defaults { + name: "libprofiled_static_defaults", + defaults: [ + "libprofile_static_base_defaults", + "libartbased_static_defaults", + "libdexfiled_static_defaults", + ], + static_libs: ["libprofiled"], +} + art_cc_library { name: "libprofile", defaults: ["libprofile_defaults"], diff --git a/oatdump/Android.bp b/oatdump/Android.bp index 3cd8ae0f6d..7d82ebf182 100644 --- a/oatdump/Android.bp +++ b/oatdump/Android.bp @@ -66,7 +66,9 @@ cc_defaults { name: "oatdumps-defaults", device_supported: false, static_executable: true, - defaults: ["oatdump-defaults"], + defaults: [ + "oatdump-defaults", + ], target: { darwin: { enabled: false, @@ -80,18 +82,20 @@ cc_defaults { // Try to get rid of it. "-z muldefs", ], - static_libs: art_static_dependencies, + static_libs: ["libsigchain_dummy"], } art_cc_binary { name: "oatdumps", - defaults: ["oatdumps-defaults"], + defaults: [ + "libart_static_defaults", + "libartbase_static_defaults", + "libdexfile_static_defaults", + "libprofile_static_defaults", + "libart-compiler_static_defaults", + "oatdumps-defaults", + ], static_libs: [ - "libart", - "libdexfile", - "libprofile", - "libartbase", - "libart-compiler", "libart-disassembler", "libvixl-arm", "libvixl-arm64", @@ -102,6 +106,11 @@ art_cc_binary { name: "oatdumpds", defaults: [ "art_debug_defaults", + "libartd_static_defaults", + "libartbased_static_defaults", + "libdexfiled_static_defaults", + "libprofiled_static_defaults", + "libartd-compiler_static_defaults", "oatdumps-defaults", ], target: { @@ -110,15 +119,11 @@ art_cc_binary { }, }, static_libs: [ - "libartd", - "libdexfiled", - "libprofiled", - "libartbased", - "libartd-compiler", "libartd-disassembler", "libvixld-arm", "libvixld-arm64", ], + group_static_libs: true, } art_cc_test { diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index fc7f5b7666..51abaf441c 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -28,6 +28,7 @@ #include <vector> #include "android-base/logging.h" +#include "android-base/parseint.h" #include "android-base/stringprintf.h" #include "android-base/strings.h" @@ -3380,7 +3381,7 @@ struct OatdumpArgs : public CmdlineArgs { } else if (option.starts_with("--export-dex-to=")) { export_dex_location_ = option.substr(strlen("--export-dex-to=")).data(); } else if (option.starts_with("--addr2instr=")) { - if (!ParseUint(option.substr(strlen("--addr2instr=")).data(), &addr2instr_)) { + if (!android::base::ParseUint(option.substr(strlen("--addr2instr=")).data(), &addr2instr_)) { *error_msg = "Address conversion failed"; return kParseError; } @@ -3423,7 +3424,7 @@ struct OatdumpArgs : public CmdlineArgs { return kParseOk; } - virtual std::string GetUsage() const { + std::string GetUsage() const override { std::string usage; usage += @@ -3577,7 +3578,7 @@ struct OatdumpMain : public CmdlineMain<OatdumpArgs> { } } - virtual bool ExecuteWithRuntime(Runtime* runtime) { + bool ExecuteWithRuntime(Runtime* runtime) override { CHECK(args_ != nullptr); if (!args_->imt_dump_.empty() || args_->imt_stat_dump_) { diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc index f1d6fb0b5d..1ed615bf3e 100644 --- a/openjdkjvmti/ti_class.cc +++ b/openjdkjvmti/ti_class.cc @@ -267,7 +267,8 @@ struct ClassCallback : public art::ClassLoadCallback { } } - void ClassLoad(art::Handle<art::mirror::Class> klass) REQUIRES_SHARED(art::Locks::mutator_lock_) { + void ClassLoad(art::Handle<art::mirror::Class> klass) override + REQUIRES_SHARED(art::Locks::mutator_lock_) { if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kClassLoad)) { art::Thread* thread = art::Thread::Current(); ScopedLocalRef<jclass> jklass(thread->GetJniEnv(), @@ -289,7 +290,7 @@ struct ClassCallback : public art::ClassLoadCallback { void ClassPrepare(art::Handle<art::mirror::Class> temp_klass, art::Handle<art::mirror::Class> klass) - REQUIRES_SHARED(art::Locks::mutator_lock_) { + override REQUIRES_SHARED(art::Locks::mutator_lock_) { if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kClassPrepare)) { art::Thread* thread = art::Thread::Current(); if (temp_klass.Get() != klass.Get()) { diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc index 1588df4086..67645384ed 100644 --- a/openjdkjvmti/ti_method.cc +++ b/openjdkjvmti/ti_method.cc @@ -689,7 +689,7 @@ class GetLocalVariableClosure : public CommonLocalVariableClosure { val_(val), obj_val_(nullptr) {} - virtual jvmtiError GetResult() REQUIRES_SHARED(art::Locks::mutator_lock_) { + jvmtiError GetResult() override REQUIRES_SHARED(art::Locks::mutator_lock_) { if (result_ == OK && type_ == art::Primitive::kPrimNot) { val_->l = obj_val_.IsNull() ? nullptr diff --git a/openjdkjvmti/ti_monitor.cc b/openjdkjvmti/ti_monitor.cc index 6d3a37e333..df29098ec4 100644 --- a/openjdkjvmti/ti_monitor.cc +++ b/openjdkjvmti/ti_monitor.cc @@ -370,7 +370,7 @@ jvmtiError MonitorUtil::GetCurrentContendedMonitor(jvmtiEnv* env ATTRIBUTE_UNUSE public: GetContendedMonitorClosure() : out_(nullptr) {} - void Run(art::Thread* target_thread) REQUIRES_SHARED(art::Locks::mutator_lock_) { + void Run(art::Thread* target_thread) override REQUIRES_SHARED(art::Locks::mutator_lock_) { art::ScopedAssertNoThreadSuspension sants("GetContendedMonitorClosure::Run"); switch (target_thread->GetState()) { // These three we are actually currently waiting on a monitor and have sent the appropriate diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc index b6969afff1..e2b98b3021 100644 --- a/openjdkjvmti/ti_stack.cc +++ b/openjdkjvmti/ti_stack.cc @@ -79,7 +79,7 @@ struct GetStackTraceVisitor : public art::StackVisitor { GetStackTraceVisitor(const GetStackTraceVisitor&) = default; GetStackTraceVisitor(GetStackTraceVisitor&&) = default; - bool VisitFrame() REQUIRES_SHARED(art::Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(art::Locks::mutator_lock_) { art::ArtMethod* m = GetMethod(); if (m->IsRuntimeMethod()) { return true; @@ -662,7 +662,7 @@ struct GetFrameCountVisitor : public art::StackVisitor { : art::StackVisitor(thread, nullptr, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames), count(0) {} - bool VisitFrame() REQUIRES_SHARED(art::Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(art::Locks::mutator_lock_) { art::ArtMethod* m = GetMethod(); const bool do_count = !(m == nullptr || m->IsRuntimeMethod()); if (do_count) { @@ -734,7 +734,7 @@ struct GetLocationVisitor : public art::StackVisitor { caller(nullptr), caller_dex_pc(0) {} - bool VisitFrame() REQUIRES_SHARED(art::Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(art::Locks::mutator_lock_) { art::ArtMethod* m = GetMethod(); const bool do_count = !(m == nullptr || m->IsRuntimeMethod()); if (do_count) { diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc index e53309445d..41ef6c281d 100644 --- a/openjdkjvmti/ti_thread.cc +++ b/openjdkjvmti/ti_thread.cc @@ -1110,7 +1110,7 @@ jvmtiError ThreadUtil::StopThread(jvmtiEnv* env ATTRIBUTE_UNUSED, public: explicit StopThreadClosure(art::Handle<art::mirror::Throwable> except) : exception_(except) { } - void Run(art::Thread* me) REQUIRES_SHARED(art::Locks::mutator_lock_) { + void Run(art::Thread* me) override REQUIRES_SHARED(art::Locks::mutator_lock_) { // Make sure the thread is prepared to notice the exception. art::Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(me); me->SetAsyncException(exception_.Get()); diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index aaa3e8339f..5d38e8bfed 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -26,6 +26,7 @@ #include <vector> #include "android-base/file.h" +#include <android-base/parseint.h> #include "android-base/stringprintf.h" #include "android-base/strings.h" @@ -630,7 +631,7 @@ bool PatchOat::Patch(const std::string& image_location, std::string image_relocation_filename = output_image_relocation_directory + (android::base::StartsWith(original_image_filename, "/") ? "" : "/") - + original_image_filename.substr(original_image_filename.find_last_of("/")); + + original_image_filename.substr(original_image_filename.find_last_of('/')); int64_t input_image_size = input_image->GetLength(); if (input_image_size < 0) { LOG(ERROR) << "Error while getting input image size"; @@ -1272,7 +1273,7 @@ static int patchoat(int argc, char **argv) { } else if (option.starts_with("--base-offset-delta=")) { const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data(); base_delta_set = true; - if (!ParseInt(base_delta_str, &base_delta)) { + if (!android::base::ParseInt(base_delta_str, &base_delta)) { Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str); } } else if (option == "--dump-timings") { diff --git a/patchoat/patchoat_test.cc b/patchoat/patchoat_test.cc index 08bf31c4bd..6492b96b34 100644 --- a/patchoat/patchoat_test.cc +++ b/patchoat/patchoat_test.cc @@ -529,7 +529,7 @@ class PatchoatVerificationTest : public PatchoatTest { ASSERT_EQ(rel_shortened_basenames, relocated_image_shortened_basenames); } - virtual void TearDown() { + void TearDown() override { if (!dex2oat_orig_dir_.empty()) { ClearDirectory(dex2oat_orig_dir_.c_str(), /*recursive*/ true); rmdir(dex2oat_orig_dir_.c_str()); diff --git a/runtime/Android.bp b/runtime/Android.bp index 6ec626591a..1cebb06570 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -408,6 +408,49 @@ libart_cc_defaults { export_shared_lib_headers: ["libbase"], } +libart_static_cc_defaults { + name: "libart_static_base_defaults", + target: { + android: { + static_libs: ["libtombstoned_client_static"], + }, + }, + static_libs: [ + "libbacktrace", + "libbase", + "libcutils", + "liblog", + "liblz4", + "liblzma", + "libnativebridge", + "libnativeloader", + "libunwindstack", + "libz", + ], +} + +cc_defaults { + name: "libart_static_defaults", + defaults: [ + "libart_static_base_defaults", + "libartbase_static_defaults", + "libdexfile_static_defaults", + "libprofile_static_defaults", + ], + static_libs: ["libart"], +} + +cc_defaults { + name: "libartd_static_defaults", + defaults: [ + "libart_static_base_defaults", + "libartbased_static_defaults", + "libdexfiled_static_defaults", + "libprofiled_static_defaults", + ], + static_libs: ["libartd"], +} + gensrcs { name: "art_operator_srcs", cmd: "$(location generate_operator_out) art/runtime $(in) > $(out)", diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index f693524a6c..9b69166567 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -417,7 +417,6 @@ inline HiddenApiAccessFlags::ApiList ArtMethod::GetHiddenApiAccessFlags() case Intrinsics::kMemoryPokeIntNative: case Intrinsics::kMemoryPokeLongNative: case Intrinsics::kMemoryPokeShortNative: - return HiddenApiAccessFlags::kDarkGreylist; case Intrinsics::kVarHandleFullFence: case Intrinsics::kVarHandleAcquireFence: case Intrinsics::kVarHandleReleaseFence: diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc index 88075ba368..5ec24bce17 100644 --- a/runtime/barrier_test.cc +++ b/runtime/barrier_test.cc @@ -32,7 +32,7 @@ class CheckWaitTask : public Task { count1_(count1), count2_(count2) {} - void Run(Thread* self) { + void Run(Thread* self) override { LOG(INFO) << "Before barrier" << *self; ++*count1_; barrier_->Wait(self); @@ -40,7 +40,7 @@ class CheckWaitTask : public Task { LOG(INFO) << "After barrier" << *self; } - virtual void Finalize() { + void Finalize() override { delete this; } @@ -91,7 +91,7 @@ class CheckPassTask : public Task { count_(count), subtasks_(subtasks) {} - void Run(Thread* self) { + void Run(Thread* self) override { for (size_t i = 0; i < subtasks_; ++i) { ++*count_; // Pass through to next subtask. @@ -99,7 +99,7 @@ class CheckPassTask : public Task { } } - void Finalize() { + void Finalize() override { delete this; } private: diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index e19dedcebd..f355f5bada 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -431,6 +431,8 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b heap->IncrementDisableMovingGC(self); StackHandleScope<64> hs(self); // 64 is picked arbitrarily. auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_); + // Allocate the object as non-movable so that there are no cases where Object::IsClass returns + // the incorrect result when comparing to-space vs from-space. Handle<mirror::Class> java_lang_Class(hs.NewHandle(ObjPtr<mirror::Class>::DownCast(MakeObjPtr( heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor()))))); CHECK(java_lang_Class != nullptr); @@ -483,9 +485,17 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b mirror::ObjectArray<mirror::Object>::ClassSize(image_pointer_size_)))); object_array_class->SetComponentType(java_lang_Object.Get()); - // Setup String. + // Setup java.lang.String. + // + // We make this class non-movable for the unlikely case where it were to be + // moved by a sticky-bit (minor) collection when using the Generational + // Concurrent Copying (CC) collector, potentially creating a stale reference + // in the `klass_` field of one of its instances allocated in the Large-Object + // Space (LOS) -- see the comment about the dirty card scanning logic in + // art::gc::collector::ConcurrentCopying::MarkingPhase. Handle<mirror::Class> java_lang_String(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_)))); + AllocClass</* kMovable */ false>( + self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_)))); java_lang_String->SetStringClass(); mirror::Class::SetStatus(java_lang_String, ClassStatus::kResolved, self); @@ -528,13 +538,13 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Create int array type for native pointer arrays (for example vtables) on 32-bit archs. Handle<mirror::Class> int_array_class(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); + AllocPrimitiveArrayClass(self, java_lang_Class.Get()))); int_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveInt, this)); SetClassRoot(ClassRoot::kIntArrayClass, int_array_class.Get()); // Create long array type for native pointer arrays (for example vtables) on 64-bit archs. Handle<mirror::Class> long_array_class(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); + AllocPrimitiveArrayClass(self, java_lang_Class.Get()))); long_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveLong, this)); SetClassRoot(ClassRoot::kLongArrayClass, long_array_class.Get()); @@ -610,20 +620,29 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b CHECK_EQ(dalvik_system_ClassExt->GetObjectSize(), mirror::ClassExt::InstanceSize()); // Setup the primitive array type classes - can't be done until Object has a vtable. - SetClassRoot(ClassRoot::kBooleanArrayClass, FindSystemClass(self, "[Z")); + AllocAndSetPrimitiveArrayClassRoot(self, + java_lang_Class.Get(), + ClassRoot::kBooleanArrayClass, + ClassRoot::kPrimitiveBoolean, + "[Z"); - SetClassRoot(ClassRoot::kByteArrayClass, FindSystemClass(self, "[B")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kByteArrayClass, ClassRoot::kPrimitiveByte, "[B"); - SetClassRoot(ClassRoot::kCharArrayClass, FindSystemClass(self, "[C")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kCharArrayClass, ClassRoot::kPrimitiveChar, "[C"); - SetClassRoot(ClassRoot::kShortArrayClass, FindSystemClass(self, "[S")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kShortArrayClass, ClassRoot::kPrimitiveShort, "[S"); CheckSystemClass(self, int_array_class, "[I"); CheckSystemClass(self, long_array_class, "[J"); - SetClassRoot(ClassRoot::kFloatArrayClass, FindSystemClass(self, "[F")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kFloatArrayClass, ClassRoot::kPrimitiveFloat, "[F"); - SetClassRoot(ClassRoot::kDoubleArrayClass, FindSystemClass(self, "[D")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kDoubleArrayClass, ClassRoot::kPrimitiveDouble, "[D"); // Run Class through FindSystemClass. This initializes the dex_cache_ fields and register it // in class_table_. @@ -1140,7 +1159,7 @@ class VerifyDeclaringClassVisitor : public ArtMethodVisitor { VerifyDeclaringClassVisitor() REQUIRES_SHARED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) : live_bitmap_(Runtime::Current()->GetHeap()->GetLiveBitmap()) {} - virtual void Visit(ArtMethod* method) + void Visit(ArtMethod* method) override REQUIRES_SHARED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { ObjPtr<mirror::Class> klass = method->GetDeclaringClassUnchecked(); if (klass != nullptr) { @@ -1540,7 +1559,7 @@ static void VerifyAppImage(const ImageHeader& header, public: explicit VerifyClassInTableArtMethodVisitor(ClassTable* table) : table_(table) {} - virtual void Visit(ArtMethod* method) + void Visit(ArtMethod* method) override REQUIRES_SHARED(Locks::mutator_lock_, Locks::classlinker_classes_lock_) { ObjPtr<mirror::Class> klass = method->GetDeclaringClass(); if (klass != nullptr && !Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) { @@ -2165,13 +2184,14 @@ ObjPtr<mirror::DexCache> ClassLinker::AllocAndInitializeDexCache(Thread* self, return dex_cache; } +template <bool kMovable> ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, ObjPtr<mirror::Class> java_lang_Class, uint32_t class_size) { DCHECK_GE(class_size, sizeof(mirror::Class)); gc::Heap* heap = Runtime::Current()->GetHeap(); mirror::Class::InitializeClassVisitor visitor(class_size); - ObjPtr<mirror::Object> k = kMovingClasses ? + ObjPtr<mirror::Object> k = (kMovingClasses && kMovable) ? heap->AllocObject<true>(self, java_lang_Class, class_size, visitor) : heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size, visitor); if (UNLIKELY(k == nullptr)) { @@ -2185,6 +2205,18 @@ ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, uint32_t class_size) return AllocClass(self, GetClassRoot<mirror::Class>(this), class_size); } +ObjPtr<mirror::Class> ClassLinker::AllocPrimitiveArrayClass(Thread* self, + ObjPtr<mirror::Class> java_lang_Class) { + // We make this class non-movable for the unlikely case where it were to be + // moved by a sticky-bit (minor) collection when using the Generational + // Concurrent Copying (CC) collector, potentially creating a stale reference + // in the `klass_` field of one of its instances allocated in the Large-Object + // Space (LOS) -- see the comment about the dirty card scanning logic in + // art::gc::collector::ConcurrentCopying::MarkingPhase. + return AllocClass</* kMovable */ false>( + self, java_lang_Class, mirror::Array::ClassSize(image_pointer_size_)); +} + ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> ClassLinker::AllocStackTraceElementArray( Thread* self, size_t length) { @@ -3648,10 +3680,22 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::Object>>(this)); } else if (strcmp(descriptor, "[Ljava/lang/String;") == 0) { new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::String>>(this)); + } else if (strcmp(descriptor, "[Z") == 0) { + new_class.Assign(GetClassRoot<mirror::BooleanArray>(this)); + } else if (strcmp(descriptor, "[B") == 0) { + new_class.Assign(GetClassRoot<mirror::ByteArray>(this)); + } else if (strcmp(descriptor, "[C") == 0) { + new_class.Assign(GetClassRoot<mirror::CharArray>(this)); + } else if (strcmp(descriptor, "[S") == 0) { + new_class.Assign(GetClassRoot<mirror::ShortArray>(this)); } else if (strcmp(descriptor, "[I") == 0) { new_class.Assign(GetClassRoot<mirror::IntArray>(this)); } else if (strcmp(descriptor, "[J") == 0) { new_class.Assign(GetClassRoot<mirror::LongArray>(this)); + } else if (strcmp(descriptor, "[F") == 0) { + new_class.Assign(GetClassRoot<mirror::FloatArray>(this)); + } else if (strcmp(descriptor, "[D") == 0) { + new_class.Assign(GetClassRoot<mirror::DoubleArray>(this)); } } if (new_class == nullptr) { @@ -8607,6 +8651,19 @@ void ClassLinker::SetClassRoot(ClassRoot class_root, ObjPtr<mirror::Class> klass class_roots->Set<false>(index, klass); } +void ClassLinker::AllocAndSetPrimitiveArrayClassRoot(Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + ClassRoot primitive_array_class_root, + ClassRoot primitive_class_root, + const char* descriptor) { + StackHandleScope<1> hs(self); + Handle<mirror::Class> primitive_array_class(hs.NewHandle( + AllocPrimitiveArrayClass(self, java_lang_Class))); + primitive_array_class->SetComponentType(GetClassRoot(primitive_class_root, this)); + SetClassRoot(primitive_array_class_root, primitive_array_class.Get()); + CheckSystemClass(self, primitive_array_class, descriptor); +} + jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, const std::vector<const DexFile*>& dex_files, jclass loader_class, @@ -8941,7 +8998,7 @@ ObjPtr<mirror::IfTable> ClassLinker::AllocIfTable(Thread* self, size_t ifcount) ifcount * mirror::IfTable::kMax))); } -// Instantiate ResolveMethod. +// Instantiate ClassLinker::ResolveMethod. template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>( uint32_t method_idx, Handle<mirror::DexCache> dex_cache, @@ -8955,4 +9012,14 @@ template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kNoChec ArtMethod* referrer, InvokeType type); +// Instantiate ClassLinker::AllocClass. +template ObjPtr<mirror::Class> ClassLinker::AllocClass</* kMovable */ true>( + Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + uint32_t class_size); +template ObjPtr<mirror::Class> ClassLinker::AllocClass</* kMovable */ false>( + Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + uint32_t class_size); + } // namespace art diff --git a/runtime/class_linker.h b/runtime/class_linker.h index e4d9c96696..efe29d3127 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -775,7 +775,11 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); - // For early bootstrapping by Init + // For early bootstrapping by Init. + // If we do not allow moving classes (`art::kMovingClass` is false) or if + // parameter `kMovable` is false (or both), the class object is allocated in + // the non-moving space. + template <bool kMovable = true> ObjPtr<mirror::Class> AllocClass(Thread* self, ObjPtr<mirror::Class> java_lang_Class, uint32_t class_size) @@ -789,6 +793,12 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + // Allocate a primitive array class. + ObjPtr<mirror::Class> AllocPrimitiveArrayClass(Thread* self, + ObjPtr<mirror::Class> java_lang_Class) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!Roles::uninterruptible_); + ObjPtr<mirror::DexCache> AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location, Thread* self, const DexFile& dex_file) @@ -1206,6 +1216,20 @@ class ClassLinker { void SetClassRoot(ClassRoot class_root, ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); + // Allocate primitive array class for primitive with class root + // `primitive_class_root`, and associate it to class root + // `primitive_array_class_root`. + // + // Also check this class returned when searching system classes for + // `descriptor` matches the allocated class. + void AllocAndSetPrimitiveArrayClassRoot(Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + ClassRoot primitive_array_class_root, + ClassRoot primitive_class_root, + const char* descriptor) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!Roles::uninterruptible_); + // Return the quick generic JNI stub for testing. const void* GetRuntimeQuickGenericJniStub() const; diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 2bd541118b..f6b764ddc0 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -16,6 +16,8 @@ #include "class_loader_context.h" +#include <android-base/parseint.h> + #include "art_field-inl.h" #include "base/dchecked_vector.h" #include "base/stl_util.h" @@ -120,7 +122,7 @@ bool ClassLoaderContext::ParseClassLoaderSpec(const std::string& class_loader_sp return false; } uint32_t checksum = 0; - if (!ParseInt(dex_file_with_checksum[1].c_str(), &checksum)) { + if (!android::base::ParseInt(dex_file_with_checksum[1].c_str(), &checksum)) { return false; } class_loader_chain_.back().classpath.push_back(dex_file_with_checksum[0]); diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 366b5ec5e9..7103214df7 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -897,7 +897,7 @@ JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. - bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { + bool VisitFrame() override NO_THREAD_SAFETY_ANALYSIS { if (!GetMethod()->IsRuntimeMethod()) { Monitor::VisitLocks(this, AppendOwnedMonitors, this); ++current_stack_depth; @@ -2406,7 +2406,7 @@ static int GetStackDepth(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) { // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. - bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { + bool VisitFrame() override NO_THREAD_SAFETY_ANALYSIS { if (!GetMethod()->IsRuntimeMethod()) { ++depth; } @@ -2576,7 +2576,7 @@ struct GetThisVisitor : public StackVisitor { // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. - virtual bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { + bool VisitFrame() override NO_THREAD_SAFETY_ANALYSIS { if (frame_id != GetFrameId()) { return true; // continue } else { @@ -2618,7 +2618,7 @@ class FindFrameVisitor final : public StackVisitor { // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. - bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { + bool VisitFrame() override NO_THREAD_SAFETY_ANALYSIS { if (GetFrameId() != frame_id_) { return true; // Not our frame, carry on. } @@ -3831,7 +3831,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. - bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { + bool VisitFrame() override NO_THREAD_SAFETY_ANALYSIS { ArtMethod* m = GetMethod(); if (!m->IsRuntimeMethod()) { ++stack_depth; diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index e6f3d0b0d5..1045d2adc9 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -317,20 +317,9 @@ inline ArtField* FindFieldFromCode(uint32_t field_idx, ArtMethod* referrer, Thread* self, size_t expected_size) { - bool is_primitive; - bool is_set; - bool is_static; - switch (type) { - case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break; - case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break; - case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break; - case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break; - case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break; - case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break; - case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break; - case StaticPrimitiveWrite: // Keep GCC happy by having a default handler, fall-through. - default: is_primitive = true; is_set = true; is_static = true; break; - } + constexpr bool is_primitive = (type & FindFieldFlags::PrimitiveBit) != 0; + constexpr bool is_set = (type & FindFieldFlags::WriteBit) != 0; + constexpr bool is_static = (type & FindFieldFlags::StaticBit) != 0; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ArtField* resolved_field; @@ -611,22 +600,9 @@ inline ArtField* FindFieldFast(uint32_t field_idx, ArtMethod* referrer, FindFiel return nullptr; } // Check for incompatible class change. - bool is_primitive; - bool is_set; - bool is_static; - switch (type) { - case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break; - case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break; - case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break; - case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break; - case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break; - case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break; - case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break; - case StaticPrimitiveWrite: is_primitive = true; is_set = true; is_static = true; break; - default: - LOG(FATAL) << "UNREACHABLE"; - UNREACHABLE(); - } + const bool is_primitive = (type & FindFieldFlags::PrimitiveBit) != 0; + const bool is_set = (type & FindFieldFlags::WriteBit) != 0; + const bool is_static = (type & FindFieldFlags::StaticBit) != 0; if (UNLIKELY(resolved_field->IsStatic() != is_static)) { // Incompatible class change. return nullptr; diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 9d70b03dfa..c8bf6d08ab 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -103,16 +103,25 @@ ALWAYS_INLINE inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* kl REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); +enum FindFieldFlags { + InstanceBit = 1 << 0, + StaticBit = 1 << 1, + ObjectBit = 1 << 2, + PrimitiveBit = 1 << 3, + ReadBit = 1 << 4, + WriteBit = 1 << 5, +}; + // Type of find field operation for fast and slow case. enum FindFieldType { - InstanceObjectRead, - InstanceObjectWrite, - InstancePrimitiveRead, - InstancePrimitiveWrite, - StaticObjectRead, - StaticObjectWrite, - StaticPrimitiveRead, - StaticPrimitiveWrite, + InstanceObjectRead = InstanceBit | ObjectBit | ReadBit, + InstanceObjectWrite = InstanceBit | ObjectBit | WriteBit, + InstancePrimitiveRead = InstanceBit | PrimitiveBit | ReadBit, + InstancePrimitiveWrite = InstanceBit | PrimitiveBit | WriteBit, + StaticObjectRead = StaticBit | ObjectBit | ReadBit, + StaticObjectWrite = StaticBit | ObjectBit | WriteBit, + StaticPrimitiveRead = StaticBit | PrimitiveBit | ReadBit, + StaticPrimitiveWrite = StaticBit | PrimitiveBit | WriteBit, }; template<FindFieldType type, bool access_check> diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc index 62cc9dee27..d38e3edce9 100644 --- a/runtime/entrypoints/quick/quick_field_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc @@ -28,13 +28,6 @@ namespace art { -inline constexpr bool FindFieldTypeIsRead(FindFieldType type) { - return type == InstanceObjectRead || - type == InstancePrimitiveRead || - type == StaticObjectRead || - type == StaticPrimitiveRead; -} - // Helper function to do a null check after trying to resolve the field. Not for statics since obj // does not exist there. There is a suspend check, object is a double pointer to update the value // in the caller in case it moves. @@ -50,7 +43,7 @@ ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx, HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj)); ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size); if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) { - ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type)); + ThrowNullPointerExceptionForFieldAccess(field, (type & FindFieldFlags::ReadBit) != 0); return nullptr; } return field; diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index 3a800088ba..d91cc2437d 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -423,7 +423,7 @@ class ConcurrentCopying::ThreadFlipVisitor : public Closure, public RootVisitor void VisitRoots(mirror::Object*** roots, size_t count, - const RootInfo& info ATTRIBUTE_UNUSED) + const RootInfo& info ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { Thread* self = Thread::Current(); for (size_t i = 0; i < count; ++i) { @@ -440,7 +440,7 @@ class ConcurrentCopying::ThreadFlipVisitor : public Closure, public RootVisitor void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count, - const RootInfo& info ATTRIBUTE_UNUSED) + const RootInfo& info ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { Thread* self = Thread::Current(); for (size_t i = 0; i < count; ++i) { @@ -905,13 +905,8 @@ void ConcurrentCopying::MarkingPhase() { // during a minor (young-generation) collection: // - In the case where we run with a boot image, these classes are part of the image space, // which is an immune space. - // - In the case where we run without a boot image, these classes are allocated in the region - // space (main space), but they are not expected to move during a minor collection (this - // would only happen if those classes were allocated between a major and a minor - // collections, which is unlikely -- we don't expect any GC to happen before these - // fundamental classes are initialized). Note that these classes could move during a major - // collection though, but this is fine: in that case, the whole heap is traced and the card - // table logic below is not used. + // - In the case where we run without a boot image, these classes are allocated in the + // non-moving space (see art::ClassLinker::InitWithoutImage). Runtime::Current()->GetHeap()->GetCardTable()->Scan<false>( space->GetMarkBitmap(), space->Begin(), @@ -2331,6 +2326,7 @@ void ConcurrentCopying::AssertToSpaceInvariantInNonMovingSpace(mirror::Object* o CHECK(!region_space_->HasAddress(ref)) << "obj=" << obj << " ref=" << ref; // In a non-moving space. Check that the ref is marked. if (immune_spaces_.ContainsObject(ref)) { + // Immune space case. if (kUseBakerReadBarrier) { // Immune object may not be gray if called from the GC. if (Thread::Current() == thread_running_gc_ && !gc_grays_immune_objects_) { @@ -2344,28 +2340,68 @@ void ConcurrentCopying::AssertToSpaceInvariantInNonMovingSpace(mirror::Object* o << " updated_all_immune_objects=" << updated_all_immune_objects; } } else { + // Non-moving space and large-object space (LOS) cases. accounting::ContinuousSpaceBitmap* mark_bitmap = heap_mark_bitmap_->GetContinuousSpaceBitmap(ref); accounting::LargeObjectBitmap* los_bitmap = heap_mark_bitmap_->GetLargeObjectBitmap(ref); - bool is_los = mark_bitmap == nullptr; - if ((!is_los && mark_bitmap->Test(ref)) || - (is_los && los_bitmap->Test(ref))) { - // OK. - } else { - // If `ref` is on the allocation stack, then it may not be - // marked live, but considered marked/alive (but not - // necessarily on the live stack). - CHECK(IsOnAllocStack(ref)) - << "Unmarked ref that's not on the allocation stack." - << " obj=" << obj - << " ref=" << ref - << " rb_state=" << ref->GetReadBarrierState() - << " is_los=" << std::boolalpha << is_los << std::noboolalpha - << " is_marking=" << std::boolalpha << is_marking_ << std::noboolalpha - << " young_gen=" << std::boolalpha << young_gen_ << std::noboolalpha - << " self=" << Thread::Current(); - } + bool is_los = (mark_bitmap == nullptr); + + bool marked_in_non_moving_space_or_los = + (kUseBakerReadBarrier + && kEnableGenerationalConcurrentCopyingCollection + && young_gen_ + && !done_scanning_.load(std::memory_order_acquire)) + // Don't use the mark bitmap to ensure `ref` is marked: check that the + // read barrier state is gray instead. This is to take into account a + // potential race between two read barriers on the same reference when the + // young-generation collector is still scanning the dirty cards. + // + // For instance consider two concurrent read barriers on the same GC root + // reference during the dirty-card-scanning step of a young-generation + // collection. Both threads would call ReadBarrier::BarrierForRoot, which + // would: + // a. mark the reference (leading to a call to + // ConcurrentCopying::MarkNonMoving); then + // b. check the to-space invariant (leading to a call this + // ConcurrentCopying::AssertToSpaceInvariantInNonMovingSpace -- this + // method). + // + // In this situation, the following race could happen: + // 1. Thread A successfully changes `ref`'s read barrier state from + // non-gray (white) to gray (with AtomicSetReadBarrierState) in + // ConcurrentCopying::MarkNonMoving, then gets preempted. + // 2. Thread B also tries to change `ref`'s read barrier state with + // AtomicSetReadBarrierState from non-gray to gray in + // ConcurrentCopying::MarkNonMoving, but fails, as Thread A already + // changed it. + // 3. Because Thread B failed the previous CAS, it does *not* set the + // bit in the mark bitmap for `ref`. + // 4. Thread B checks the to-space invariant and calls + // ConcurrentCopying::AssertToSpaceInvariantInNonMovingSpace: the bit + // is not set in the mark bitmap for `ref`; checking that this bit is + // set to check the to-space invariant is therefore not a reliable + // test. + // 5. (Note that eventually, Thread A will resume its execution and set + // the bit for `ref` in the mark bitmap.) + ? (ref->GetReadBarrierState() == ReadBarrier::GrayState()) + // It is safe to use the heap mark bitmap otherwise. + : (!is_los && mark_bitmap->Test(ref)) || (is_los && los_bitmap->Test(ref)); + + // If `ref` is on the allocation stack, then it may not be + // marked live, but considered marked/alive (but not + // necessarily on the live stack). + CHECK(marked_in_non_moving_space_or_los || IsOnAllocStack(ref)) + << "Unmarked ref that's not on the allocation stack." + << " obj=" << obj + << " ref=" << ref + << " rb_state=" << ref->GetReadBarrierState() + << " is_los=" << std::boolalpha << is_los << std::noboolalpha + << " is_marking=" << std::boolalpha << is_marking_ << std::noboolalpha + << " young_gen=" << std::boolalpha << young_gen_ << std::noboolalpha + << " done_scanning=" + << std::boolalpha << done_scanning_.load(std::memory_order_acquire) << std::noboolalpha + << " self=" << Thread::Current(); } } diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 23b2719bf0..5f44a72e19 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -789,12 +789,12 @@ class MarkSweep::MarkStackTask : public Task { mark_stack_[mark_stack_pos_++].Assign(obj); } - virtual void Finalize() { + void Finalize() override { delete this; } // Scans all of the objects - virtual void Run(Thread* self ATTRIBUTE_UNUSED) + void Run(Thread* self ATTRIBUTE_UNUSED) override REQUIRES(Locks::heap_bitmap_lock_) REQUIRES_SHARED(Locks::mutator_lock_) { ScanObjectParallelVisitor visitor(this); @@ -852,11 +852,11 @@ class MarkSweep::CardScanTask : public MarkStackTask<false> { const uint8_t minimum_age_; const bool clear_card_; - virtual void Finalize() { + void Finalize() override { delete this; } - virtual void Run(Thread* self) NO_THREAD_SAFETY_ANALYSIS { + void Run(Thread* self) override NO_THREAD_SAFETY_ANALYSIS { ScanObjectParallelVisitor visitor(this); accounting::CardTable* card_table = mark_sweep_->GetHeap()->GetCardTable(); size_t cards_scanned = clear_card_ @@ -1009,12 +1009,12 @@ class MarkSweep::RecursiveMarkTask : public MarkStackTask<false> { const uintptr_t begin_; const uintptr_t end_; - virtual void Finalize() { + void Finalize() override { delete this; } // Scans all of the objects - virtual void Run(Thread* self) NO_THREAD_SAFETY_ANALYSIS { + void Run(Thread* self) override NO_THREAD_SAFETY_ANALYSIS { ScanObjectParallelVisitor visitor(this); bitmap_->VisitMarkedRange(begin_, end_, visitor); // Finish by emptying our local mark stack. diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 589e9a4826..b6610b7518 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -450,6 +450,7 @@ Heap::Heap(size_t initial_size, // Non moving space is always dlmalloc since we currently don't have support for multiple // active rosalloc spaces. const size_t size = non_moving_space_mem_map.Size(); + const void* non_moving_space_mem_map_begin = non_moving_space_mem_map.Begin(); non_moving_space_ = space::DlMallocSpace::CreateFromMemMap(std::move(non_moving_space_mem_map), "zygote / non moving space", kDefaultStartingSize, @@ -457,9 +458,9 @@ Heap::Heap(size_t initial_size, size, size, /* can_move_objects */ false); - non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity()); CHECK(non_moving_space_ != nullptr) << "Failed creating non moving space " - << non_moving_space_mem_map.Begin(); + << non_moving_space_mem_map_begin; + non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity()); AddSpace(non_moving_space_); } // Create other spaces based on whether or not we have a moving GC. @@ -2279,13 +2280,13 @@ class ZygoteCompactingCollector final : public collector::SemiSpace { } } - virtual bool ShouldSweepSpace(space::ContinuousSpace* space ATTRIBUTE_UNUSED) const { + bool ShouldSweepSpace(space::ContinuousSpace* space ATTRIBUTE_UNUSED) const override { // Don't sweep any spaces since we probably blasted the internal accounting of the free list // allocator. return false; } - virtual mirror::Object* MarkNonForwardedObject(mirror::Object* obj) + mirror::Object* MarkNonForwardedObject(mirror::Object* obj) override REQUIRES(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { size_t obj_size = obj->SizeOf<kDefaultVerifyFlags>(); size_t alloc_size = RoundUp(obj_size, kObjectAlignment); diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc index 7cbad3b523..05a04f21db 100644 --- a/runtime/gc/heap_test.cc +++ b/runtime/gc/heap_test.cc @@ -96,7 +96,7 @@ TEST_F(HeapTest, DumpGCPerformanceOnShutdown) { } class ZygoteHeapTest : public CommonRuntimeTest { - void SetUpRuntimeOptions(RuntimeOptions* options) { + void SetUpRuntimeOptions(RuntimeOptions* options) override { CommonRuntimeTest::SetUpRuntimeOptions(options); options->push_back(std::make_pair("-Xzygote", nullptr)); } diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc index 6caca84854..375412930b 100644 --- a/runtime/gc/heap_verification_test.cc +++ b/runtime/gc/heap_verification_test.cc @@ -83,7 +83,12 @@ TEST_F(VerificationTest, IsValidClassOrNotInHeap) { } TEST_F(VerificationTest, IsValidClassInHeap) { - TEST_DISABLED_FOR_MEMORY_TOOL_WITH_HEAP_POISONING(); + // Now that the String class is allocated in the non-moving space when the + // runtime is running without a boot image (which is the case in this gtest), + // and we run with AddressSanizer, it is possible that the (presumably + // invalid) memory location `uint_klass - kObjectAlignment` tested below is + // poisoned when running with AddressSanizer. Disable this test in that case. + TEST_DISABLED_FOR_MEMORY_TOOL(); ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope hs(soa.Self()); Handle<mirror::String> string( @@ -106,7 +111,13 @@ TEST_F(VerificationTest, DumpInvalidObjectInfo) { } TEST_F(VerificationTest, DumpValidObjectInfo) { - TEST_DISABLED_FOR_MEMORY_TOOL_WITH_HEAP_POISONING(); + // Now that the String class is allocated in the non-moving space when the + // runtime is running without a boot image (which is the case in this gtest), + // and we run with AddressSanizer, it is possible that the calls to + // Verification::DumpObjectInfo below involving the String class object + // (`string->GetClass()`, `uint_klass`, etc.) access poisoned memory when they + // call Verification::DumpRAMAroundAddress. Disable this test in that case. + TEST_DISABLED_FOR_MEMORY_TOOL(); ScopedLogSeverity sls(LogSeverity::INFO); ScopedObjectAccess soa(Thread::Current()); Runtime* const runtime = Runtime::Current(); @@ -126,7 +137,13 @@ TEST_F(VerificationTest, DumpValidObjectInfo) { } TEST_F(VerificationTest, LogHeapCorruption) { - TEST_DISABLED_FOR_MEMORY_TOOL_WITH_HEAP_POISONING(); + // Now that the String class is allocated in the non-moving space when the + // runtime is running without a boot image (which is the case in this gtest), + // and we run with AddressSanizer, it is possible that the call to + // Verification::LogHeapCorruption below involving the String class object + // (`string->GetClass()`) accesses poisoned memory when it calls + // Verification::DumpRAMAroundAddress. Disable this test in that case. + TEST_DISABLED_FOR_MEMORY_TOOL(); ScopedLogSeverity sls(LogSeverity::INFO); ScopedObjectAccess soa(Thread::Current()); Runtime* const runtime = Runtime::Current(); diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc index fe4124d788..c212bad530 100644 --- a/runtime/gc/reference_processor.cc +++ b/runtime/gc/reference_processor.cc @@ -276,7 +276,7 @@ class ClearedReferenceTask : public HeapTask { explicit ClearedReferenceTask(jobject cleared_references) : HeapTask(NanoTime()), cleared_references_(cleared_references) { } - virtual void Run(Thread* thread) { + void Run(Thread* thread) override { ScopedObjectAccess soa(thread); jvalue args[1]; args[0].l = cleared_references_; diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 3999e27333..316bfe1e25 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -1008,7 +1008,7 @@ class ImageSpace::Loader { } if (obj->IsClass()) { - mirror::Class* klass = obj->AsClass<kVerifyNone, kWithoutReadBarrier>(); + mirror::Class* klass = obj->AsClass<kVerifyNone>(); // Fixup super class before visiting instance fields which require // information from their super class to calculate offsets. mirror::Class* super_class = klass->GetSuperClass<kVerifyNone, kWithoutReadBarrier>(); @@ -1026,8 +1026,8 @@ class ImageSpace::Loader { *this); // Note that this code relies on no circular dependencies. // We want to use our own class loader and not the one in the image. - if (obj->IsClass<kVerifyNone, kWithoutReadBarrier>()) { - mirror::Class* as_klass = obj->AsClass<kVerifyNone, kWithoutReadBarrier>(); + if (obj->IsClass<kVerifyNone>()) { + mirror::Class* as_klass = obj->AsClass<kVerifyNone>(); FixupObjectAdapter visitor(boot_image_, boot_oat_, app_image_, app_oat_); as_klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(as_klass, pointer_size_, @@ -1099,7 +1099,7 @@ class ImageSpace::Loader { fixup_heap_objects_(fixup_heap_objects), pointer_size_(pointer_size) {} - virtual void Visit(ArtMethod* method) NO_THREAD_SAFETY_ANALYSIS { + void Visit(ArtMethod* method) override NO_THREAD_SAFETY_ANALYSIS { // TODO: Separate visitor for runtime vs normal methods. if (UNLIKELY(method->IsRuntimeMethod())) { ImtConflictTable* table = method->GetImtConflictTable(pointer_size_); @@ -1132,7 +1132,7 @@ class ImageSpace::Loader { template<typename... Args> explicit FixupArtFieldVisitor(Args... args) : FixupVisitor(args...) {} - virtual void Visit(ArtField* field) NO_THREAD_SAFETY_ANALYSIS { + void Visit(ArtField* field) override NO_THREAD_SAFETY_ANALYSIS { field->UpdateObjects(ForwardObjectAdapter(this)); } }; diff --git a/runtime/gc/space/large_object_space_test.cc b/runtime/gc/space/large_object_space_test.cc index 9baa016dcd..d55ccd6e40 100644 --- a/runtime/gc/space/large_object_space_test.cc +++ b/runtime/gc/space/large_object_space_test.cc @@ -128,7 +128,7 @@ class AllocRaceTask : public Task { AllocRaceTask(size_t id, size_t iterations, size_t size, LargeObjectSpace* los) : id_(id), iterations_(iterations), size_(size), los_(los) {} - void Run(Thread* self) { + void Run(Thread* self) override { for (size_t i = 0; i < iterations_ ; ++i) { size_t alloc_size, bytes_tl_bulk_allocated; mirror::Object* ptr = los_->Alloc(self, size_, &alloc_size, nullptr, @@ -140,7 +140,7 @@ class AllocRaceTask : public Task { } } - virtual void Finalize() { + void Finalize() override { delete this; } diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index b42433cad3..03fd964ffe 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -1385,7 +1385,7 @@ struct RuntimeMethodShortyVisitor : public StackVisitor { : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), shorty('V') {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); if (m != nullptr && !m->IsRuntimeMethod()) { // The first Java method. diff --git a/runtime/interpreter/mterp/arm/field.S b/runtime/interpreter/mterp/arm/field.S new file mode 100644 index 0000000000..c46878829e --- /dev/null +++ b/runtime/interpreter/mterp/arm/field.S @@ -0,0 +1,16 @@ +%default { } + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern $helper + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl $helper + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction diff --git a/runtime/interpreter/mterp/arm/op_iget.S b/runtime/interpreter/mterp/arm/op_iget.S index 1684a768df..1fa32faa99 100644 --- a/runtime/interpreter/mterp/arm/op_iget.S +++ b/runtime/interpreter/mterp/arm/op_iget.S @@ -1,26 +1,2 @@ %default { "is_object":"0", "helper":"MterpIGetU32"} - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self - bl $helper - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpPossibleException @ bail out - .if $is_object - SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 - .else - SET_VREG r0, r2 @ fp[A]<- r0 - .endif - ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/field.S" { } diff --git a/runtime/interpreter/mterp/arm/op_iget_wide.S b/runtime/interpreter/mterp/arm/op_iget_wide.S index 46e9ec869b..ede21ebd35 100644 --- a/runtime/interpreter/mterp/arm/op_iget_wide.S +++ b/runtime/interpreter/mterp/arm/op_iget_wide.S @@ -1,23 +1 @@ - /* - * 64-bit instance field get. - * - * for: iget-wide - */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self - bl MterpIGetU64 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpException @ bail out - CLEAR_SHADOW_PAIR r2, ip, lr @ Zero out the shadow regs - VREG_INDEX_TO_ADDR r3, r2 @ r3<- &fp[A] - stmia r3, {r0-r1} @ fp[A]<- r0/r1 - ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/op_iget.S" { "helper":"MterpIGetU64" } diff --git a/runtime/interpreter/mterp/arm/op_iput.S b/runtime/interpreter/mterp/arm/op_iput.S index a16795da64..6201d805f0 100644 --- a/runtime/interpreter/mterp/arm/op_iput.S +++ b/runtime/interpreter/mterp/arm/op_iput.S @@ -1,22 +1,2 @@ %default { "is_object":"0", "helper":"MterpIPutU32" } - /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern $helper - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - GET_VREG r2, r2 @ r2<- fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 - bl $helper - cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/field.S" { } diff --git a/runtime/interpreter/mterp/arm/op_iput_object.S b/runtime/interpreter/mterp/arm/op_iput_object.S index 4f401eb4f0..1003d10d4f 100644 --- a/runtime/interpreter/mterp/arm/op_iput_object.S +++ b/runtime/interpreter/mterp/arm/op_iput_object.S @@ -1,11 +1 @@ - EXPORT_PC - add r0, rFP, #OFF_FP_SHADOWFRAME - mov r1, rPC - mov r2, rINST - mov r3, rSELF - bl MterpIPutObj - cmp r0, #0 - beq MterpException - FETCH_ADVANCE_INST 2 @ advance rPC, load rINST - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/op_iput.S" { "is_object":"1", "helper":"MterpIPutObj" } diff --git a/runtime/interpreter/mterp/arm/op_iput_wide.S b/runtime/interpreter/mterp/arm/op_iput_wide.S index 6a414738d9..f2845ad29c 100644 --- a/runtime/interpreter/mterp/arm/op_iput_wide.S +++ b/runtime/interpreter/mterp/arm/op_iput_wide.S @@ -1,16 +1 @@ - /* iput-wide vA, vB, field@CCCC */ - .extern MterpIPutU64 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - VREG_INDEX_TO_ADDR r2, r2 @ r2<- &fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 - bl MterpIPutU64 - cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/op_iput.S" { "helper":"MterpIPutU64" } diff --git a/runtime/interpreter/mterp/arm/op_sget.S b/runtime/interpreter/mterp/arm/op_sget.S index 575a8c0760..b382de4c8d 100644 --- a/runtime/interpreter/mterp/arm/op_sget.S +++ b/runtime/interpreter/mterp/arm/op_sget.S @@ -1,27 +1,2 @@ %default { "is_object":"0", "helper":"MterpSGetU32" } - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - - .extern $helper - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl $helper - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r2, rINST, lsr #8 @ r2<- AA - PREFETCH_INST 2 - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out -.if $is_object - SET_VREG_OBJECT r0, r2 @ fp[AA]<- r0 -.else - SET_VREG r0, r2 @ fp[AA]<- r0 -.endif - ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip +%include "arm/field.S" { } diff --git a/runtime/interpreter/mterp/arm/op_sget_wide.S b/runtime/interpreter/mterp/arm/op_sget_wide.S index 5981ec4957..d6905df7d8 100644 --- a/runtime/interpreter/mterp/arm/op_sget_wide.S +++ b/runtime/interpreter/mterp/arm/op_sget_wide.S @@ -1,22 +1 @@ - /* - * SGET_WIDE handler wrapper. - * - */ - /* sget-wide vAA, field@BBBB */ - - .extern MterpSGetU64 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetU64 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r9, rINST, lsr #8 @ r9<- AA - VREG_INDEX_TO_ADDR lr, r9 @ r9<- &fp[AA] - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out - FETCH_ADVANCE_INST 2 @ advance rPC, load rINST - CLEAR_SHADOW_PAIR r9, r2, ip @ Zero out the shadow regs - stmia lr, {r0-r1} @ vAA/vAA+1<- r0/r1 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/op_sget.S" {"helper":"MterpSGetU64"} diff --git a/runtime/interpreter/mterp/arm/op_sput.S b/runtime/interpreter/mterp/arm/op_sput.S index c4a8978cd1..171f02444b 100644 --- a/runtime/interpreter/mterp/arm/op_sput.S +++ b/runtime/interpreter/mterp/arm/op_sput.S @@ -1,20 +1,2 @@ -%default { "helper":"MterpSPutU32"} - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r3, rINST, lsr #8 @ r3<- AA - GET_VREG r1, r3 @ r1<= fp[AA] - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl $helper - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%default { "is_object":"0", "helper":"MterpSPutU32"} +%include "arm/field.S" { } diff --git a/runtime/interpreter/mterp/arm/op_sput_object.S b/runtime/interpreter/mterp/arm/op_sput_object.S index c58918fbbb..8fcd52e2c4 100644 --- a/runtime/interpreter/mterp/arm/op_sput_object.S +++ b/runtime/interpreter/mterp/arm/op_sput_object.S @@ -1,11 +1 @@ - EXPORT_PC - add r0, rFP, #OFF_FP_SHADOWFRAME - mov r1, rPC - mov r2, rINST - mov r3, rSELF - bl MterpSPutObj - cmp r0, #0 - beq MterpException - FETCH_ADVANCE_INST 2 @ advance rPC, load rINST - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/op_sput.S" {"is_object":"1", "helper":"MterpSPutObj"} diff --git a/runtime/interpreter/mterp/arm/op_sput_wide.S b/runtime/interpreter/mterp/arm/op_sput_wide.S index 0ed4017ce9..c254f7834c 100644 --- a/runtime/interpreter/mterp/arm/op_sput_wide.S +++ b/runtime/interpreter/mterp/arm/op_sput_wide.S @@ -1,19 +1 @@ - /* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field@BBBB */ - .extern MterpSPutU64 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r1, rINST, lsr #8 @ r1<- AA - VREG_INDEX_TO_ADDR r1, r1 - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl MterpSPutU64 - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +%include "arm/op_sput.S" {"helper":"MterpSPutU64"} diff --git a/runtime/interpreter/mterp/arm64/field.S b/runtime/interpreter/mterp/arm64/field.S new file mode 100644 index 0000000000..631c8d191b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/field.S @@ -0,0 +1,15 @@ +%default { } + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern $helper + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl $helper + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iget.S b/runtime/interpreter/mterp/arm64/op_iget.S index cb453ac524..48b9cad44b 100644 --- a/runtime/interpreter/mterp/arm64/op_iget.S +++ b/runtime/interpreter/mterp/arm64/op_iget.S @@ -1,26 +1,2 @@ -%default { "extend":"", "is_object":"0", "helper":"MterpIGetU32"} - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self - bl $helper - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - $extend - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cbnz x3, MterpPossibleException // bail out - .if $is_object - SET_VREG_OBJECT w0, w2 // fp[A]<- w0 - .else - SET_VREG w0, w2 // fp[A]<- w0 - .endif - ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +%default { "is_object":"0", "helper":"MterpIGetU32"} +%include "arm64/field.S" { } diff --git a/runtime/interpreter/mterp/arm64/op_iget_boolean.S b/runtime/interpreter/mterp/arm64/op_iget_boolean.S index 3b17144478..9a83b2a596 100644 --- a/runtime/interpreter/mterp/arm64/op_iget_boolean.S +++ b/runtime/interpreter/mterp/arm64/op_iget_boolean.S @@ -1 +1 @@ -%include "arm64/op_iget.S" { "helper":"MterpIGetU8", "extend":"uxtb w0, w0" } +%include "arm64/op_iget.S" { "helper":"MterpIGetU8" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_byte.S b/runtime/interpreter/mterp/arm64/op_iget_byte.S index d5ef1d3c2b..f73e634621 100644 --- a/runtime/interpreter/mterp/arm64/op_iget_byte.S +++ b/runtime/interpreter/mterp/arm64/op_iget_byte.S @@ -1 +1 @@ -%include "arm64/op_iget.S" { "helper":"MterpIGetI8", "extend":"sxtb w0, w0" } +%include "arm64/op_iget.S" { "helper":"MterpIGetI8" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_char.S b/runtime/interpreter/mterp/arm64/op_iget_char.S index 68e1435201..a5efd9e3ed 100644 --- a/runtime/interpreter/mterp/arm64/op_iget_char.S +++ b/runtime/interpreter/mterp/arm64/op_iget_char.S @@ -1 +1 @@ -%include "arm64/op_iget.S" { "helper":"MterpIGetU16", "extend":"uxth w0, w0" } +%include "arm64/op_iget.S" { "helper":"MterpIGetU16" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_short.S b/runtime/interpreter/mterp/arm64/op_iget_short.S index 714f4b9aef..bb81c1708e 100644 --- a/runtime/interpreter/mterp/arm64/op_iget_short.S +++ b/runtime/interpreter/mterp/arm64/op_iget_short.S @@ -1 +1 @@ -%include "arm64/op_iget.S" { "helper":"MterpIGetI16", "extend":"sxth w0, w0" } +%include "arm64/op_iget.S" { "helper":"MterpIGetI16" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_wide.S b/runtime/interpreter/mterp/arm64/op_iget_wide.S index 4fc735ce6b..70061d6577 100644 --- a/runtime/interpreter/mterp/arm64/op_iget_wide.S +++ b/runtime/interpreter/mterp/arm64/op_iget_wide.S @@ -1,21 +1 @@ - /* - * 64-bit instance field get. - * - * for: iget-wide - */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self - bl MterpIGetU64 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cmp w3, #0 - cbnz w3, MterpException // bail out - SET_VREG_WIDE x0, w2 - ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from wINST - GOTO_OPCODE ip // jump to next instruction +%include "arm64/op_iget.S" { "helper":"MterpIGetU64" } diff --git a/runtime/interpreter/mterp/arm64/op_iput.S b/runtime/interpreter/mterp/arm64/op_iput.S index 5e21d5c6de..2bc3db9050 100644 --- a/runtime/interpreter/mterp/arm64/op_iput.S +++ b/runtime/interpreter/mterp/arm64/op_iput.S @@ -1,21 +1,2 @@ %default { "is_object":"0", "helper":"MterpIPutU32" } - /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field//CCCC */ - .extern $helper - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - GET_VREG w2, w2 // w2<- fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 - bl $helper - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +%include "arm64/field.S" { } diff --git a/runtime/interpreter/mterp/arm64/op_iput_object.S b/runtime/interpreter/mterp/arm64/op_iput_object.S index 0c0441a3f0..e9bb93f0a5 100644 --- a/runtime/interpreter/mterp/arm64/op_iput_object.S +++ b/runtime/interpreter/mterp/arm64/op_iput_object.S @@ -1,10 +1 @@ - EXPORT_PC - add x0, xFP, #OFF_FP_SHADOWFRAME - mov x1, xPC - mov w2, wINST - mov x3, xSELF - bl MterpIPutObj - cbz w0, MterpException - FETCH_ADVANCE_INST 2 // advance rPC, load rINST - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +%include "arm64/op_iput.S" { "is_object":"1", "helper":"MterpIPutObj" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_wide.S b/runtime/interpreter/mterp/arm64/op_iput_wide.S index be6aeb0e3d..e1fafad5a7 100644 --- a/runtime/interpreter/mterp/arm64/op_iput_wide.S +++ b/runtime/interpreter/mterp/arm64/op_iput_wide.S @@ -1,15 +1 @@ - /* iput-wide vA, vB, field//CCCC */ - .extern MterpIPutU64 - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - VREG_INDEX_TO_ADDR x2, x2 // w2<- &fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 - bl MterpIPutU64 - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from wINST - GOTO_OPCODE ip // jump to next instruction +%include "arm64/op_iput.S" { "helper":"MterpIPutU64" } diff --git a/runtime/interpreter/mterp/arm64/op_sget.S b/runtime/interpreter/mterp/arm64/op_sget.S index 00b07fa484..78e95b2e7c 100644 --- a/runtime/interpreter/mterp/arm64/op_sget.S +++ b/runtime/interpreter/mterp/arm64/op_sget.S @@ -1,27 +1,2 @@ -%default { "is_object":"0", "helper":"MterpSGetU32", "extend":"" } - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - - .extern $helper - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl $helper - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w2, wINST, #8 // w2<- AA - $extend - PREFETCH_INST 2 - cbnz x3, MterpException // bail out -.if $is_object - SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 -.else - SET_VREG w0, w2 // fp[AA]<- w0 -.endif - ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip +%default { "is_object":"0", "helper":"MterpSGetU32" } +%include "arm64/field.S" { } diff --git a/runtime/interpreter/mterp/arm64/op_sget_boolean.S b/runtime/interpreter/mterp/arm64/op_sget_boolean.S index 73f3a107f4..0cf9f09681 100644 --- a/runtime/interpreter/mterp/arm64/op_sget_boolean.S +++ b/runtime/interpreter/mterp/arm64/op_sget_boolean.S @@ -1 +1 @@ -%include "arm64/op_sget.S" {"helper":"MterpSGetU8", "extend":"uxtb w0, w0"} +%include "arm64/op_sget.S" {"helper":"MterpSGetU8"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_byte.S b/runtime/interpreter/mterp/arm64/op_sget_byte.S index 38c0da614f..7c88a81faa 100644 --- a/runtime/interpreter/mterp/arm64/op_sget_byte.S +++ b/runtime/interpreter/mterp/arm64/op_sget_byte.S @@ -1 +1 @@ -%include "arm64/op_sget.S" {"helper":"MterpSGetI8", "extend":"sxtb w0, w0"} +%include "arm64/op_sget.S" {"helper":"MterpSGetI8"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_char.S b/runtime/interpreter/mterp/arm64/op_sget_char.S index c0801bfa2b..883e944ce5 100644 --- a/runtime/interpreter/mterp/arm64/op_sget_char.S +++ b/runtime/interpreter/mterp/arm64/op_sget_char.S @@ -1 +1 @@ -%include "arm64/op_sget.S" {"helper":"MterpSGetU16", "extend":"uxth w0, w0"} +%include "arm64/op_sget.S" {"helper":"MterpSGetU16"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_short.S b/runtime/interpreter/mterp/arm64/op_sget_short.S index 81e043453e..6cb918433d 100644 --- a/runtime/interpreter/mterp/arm64/op_sget_short.S +++ b/runtime/interpreter/mterp/arm64/op_sget_short.S @@ -1 +1 @@ -%include "arm64/op_sget.S" {"helper":"MterpSGetI16", "extend":"sxth w0, w0"} +%include "arm64/op_sget.S" {"helper":"MterpSGetI16"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_wide.S b/runtime/interpreter/mterp/arm64/op_sget_wide.S index 546ab9482d..f5d182e96d 100644 --- a/runtime/interpreter/mterp/arm64/op_sget_wide.S +++ b/runtime/interpreter/mterp/arm64/op_sget_wide.S @@ -1,19 +1 @@ - /* - * SGET_WIDE handler wrapper. - * - */ - /* sget-wide vAA, field//BBBB */ - - .extern MterpSGetU64 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetU64 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w4, wINST, #8 // w4<- AA - cbnz x3, MterpException // bail out - FETCH_ADVANCE_INST 2 // advance rPC, load wINST - SET_VREG_WIDE x0, w4 - GET_INST_OPCODE ip // extract opcode from wINST - GOTO_OPCODE ip // jump to next instruction +%include "arm64/op_sget.S" {"helper":"MterpSGetU64"} diff --git a/runtime/interpreter/mterp/arm64/op_sput.S b/runtime/interpreter/mterp/arm64/op_sput.S index 7a0dc30c52..d229d0d899 100644 --- a/runtime/interpreter/mterp/arm64/op_sput.S +++ b/runtime/interpreter/mterp/arm64/op_sput.S @@ -1,19 +1,2 @@ -%default { "helper":"MterpSPutU32"} - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - EXPORT_PC - FETCH w0, 1 // r0<- field ref BBBB - lsr w3, wINST, #8 // r3<- AA - GET_VREG w1, w3 // r1<= fp[AA] - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl $helper - cbnz w0, MterpException // 0 on success - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +%default { "is_object":"0", "helper":"MterpSPutU32"} +%include "arm64/field.S" { } diff --git a/runtime/interpreter/mterp/arm64/op_sput_object.S b/runtime/interpreter/mterp/arm64/op_sput_object.S index a64965614b..536f1b16b8 100644 --- a/runtime/interpreter/mterp/arm64/op_sput_object.S +++ b/runtime/interpreter/mterp/arm64/op_sput_object.S @@ -1,10 +1 @@ - EXPORT_PC - add x0, xFP, #OFF_FP_SHADOWFRAME - mov x1, xPC - mov x2, xINST - mov x3, xSELF - bl MterpSPutObj - cbz w0, MterpException - FETCH_ADVANCE_INST 2 // advance rPC, load rINST - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +%include "arm64/op_sput.S" {"is_object":"1", "helper":"MterpSPutObj"} diff --git a/runtime/interpreter/mterp/arm64/op_sput_wide.S b/runtime/interpreter/mterp/arm64/op_sput_wide.S index 58b3c42333..b4be6b2987 100644 --- a/runtime/interpreter/mterp/arm64/op_sput_wide.S +++ b/runtime/interpreter/mterp/arm64/op_sput_wide.S @@ -1,18 +1 @@ - /* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field//BBBB */ - .extern MterpSPutU64 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - lsr w1, wINST, #8 // w1<- AA - VREG_INDEX_TO_ADDR x1, w1 - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl MterpSPutU64 - cbnz w0, MterpException // 0 on success, -1 on failure - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from wINST - GOTO_OPCODE ip // jump to next instruction +%include "arm64/op_sput.S" {"helper":"MterpSPutU64"} diff --git a/runtime/interpreter/mterp/mips/field.S b/runtime/interpreter/mterp/mips/field.S new file mode 100644 index 0000000000..1333ed77b7 --- /dev/null +++ b/runtime/interpreter/mterp/mips/field.S @@ -0,0 +1 @@ +TODO diff --git a/runtime/interpreter/mterp/mips/op_iget.S b/runtime/interpreter/mterp/mips/op_iget.S index 33717de640..e218272196 100644 --- a/runtime/interpreter/mterp/mips/op_iget.S +++ b/runtime/interpreter/mterp/mips/op_iget.S @@ -1,25 +1,2 @@ %default { "is_object":"0", "helper":"MterpIGetU32"} - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL($helper) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - .if $is_object - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[A] <- v0 - .else - SET_VREG_GOTO(v0, a2, t0) # fp[A] <- v0 - .endif +%include "mips/field.S" { } diff --git a/runtime/interpreter/mterp/mips/op_iget_wide.S b/runtime/interpreter/mterp/mips/op_iget_wide.S index 858a8898f4..885372a529 100644 --- a/runtime/interpreter/mterp/mips/op_iget_wide.S +++ b/runtime/interpreter/mterp/mips/op_iget_wide.S @@ -1,20 +1 @@ - /* - * 64-bit instance field get. - * - * for: iget-wide - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field byte offset - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetU64) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - SET_VREG64_GOTO(v0, v1, a2, t0) # fp[A] <- v0/v1 +%include "mips/op_iget.S" { "helper":"MterpIGetU64" } diff --git a/runtime/interpreter/mterp/mips/op_iput.S b/runtime/interpreter/mterp/mips/op_iput.S index 4dd4075e92..efbdfbad78 100644 --- a/runtime/interpreter/mterp/mips/op_iput.S +++ b/runtime/interpreter/mterp/mips/op_iput.S @@ -1,21 +1,2 @@ -%default { "helper":"MterpIPutU32" } - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern $helper - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - GET_VREG(a2, a2) # a2 <- fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL($helper) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +%default { "is_object":"0", "helper":"MterpIPutU32" } +%include "mips/field.S" { } diff --git a/runtime/interpreter/mterp/mips/op_iput_object.S b/runtime/interpreter/mterp/mips/op_iput_object.S index c96a4d4ec7..6f7e7b760f 100644 --- a/runtime/interpreter/mterp/mips/op_iput_object.S +++ b/runtime/interpreter/mterp/mips/op_iput_object.S @@ -1,16 +1 @@ - /* - * 32-bit instance field put. - * - * for: iput-object, iput-object-volatile - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - addu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - JAL(MterpIPutObj) - beqz v0, MterpException - FETCH_ADVANCE_INST(2) # advance rPC, load rINST - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +%include "mips/op_iput.S" { "is_object":"1", "helper":"MterpIPutObj" } diff --git a/runtime/interpreter/mterp/mips/op_iput_wide.S b/runtime/interpreter/mterp/mips/op_iput_wide.S index dccb6b71b1..fc862e4fa7 100644 --- a/runtime/interpreter/mterp/mips/op_iput_wide.S +++ b/runtime/interpreter/mterp/mips/op_iput_wide.S @@ -1,15 +1 @@ - /* iput-wide vA, vB, field@CCCC */ - .extern MterpIPutU64 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - EAS2(a2, rFP, a2) # a2 <- &fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL(MterpIPutU64) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +%include "mips/op_iput.S" { "helper":"MterpIPutU64" } diff --git a/runtime/interpreter/mterp/mips/op_sget.S b/runtime/interpreter/mterp/mips/op_sget.S index 8750a17a41..92d667335b 100644 --- a/runtime/interpreter/mterp/mips/op_sget.S +++ b/runtime/interpreter/mterp/mips/op_sget.S @@ -1,24 +1,2 @@ %default { "is_object":"0", "helper":"MterpSGetU32" } - /* - * General SGET handler. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern $helper - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL($helper) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA(a2) # a2 <- AA - PREFETCH_INST(2) - bnez a3, MterpException # bail out - ADVANCE(2) - GET_INST_OPCODE(t0) # extract opcode from rINST -.if $is_object - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[AA] <- v0 -.else - SET_VREG_GOTO(v0, a2, t0) # fp[AA] <- v0 -.endif +%include "mips/field.S" { } diff --git a/runtime/interpreter/mterp/mips/op_sget_wide.S b/runtime/interpreter/mterp/mips/op_sget_wide.S index 76f78cb35d..be4ae027cb 100644 --- a/runtime/interpreter/mterp/mips/op_sget_wide.S +++ b/runtime/interpreter/mterp/mips/op_sget_wide.S @@ -1,16 +1 @@ - /* - * 64-bit SGET handler. - */ - /* sget-wide vAA, field@BBBB */ - .extern MterpSGetU64 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetU64) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - bnez a3, MterpException - GET_OPA(a1) # a1 <- AA - FETCH_ADVANCE_INST(2) # advance rPC, load rINST - GET_INST_OPCODE(t0) # extract opcode from rINST - SET_VREG64_GOTO(v0, v1, a1, t0) # vAA/vAA+1 <- v0/v1 +%include "mips/op_sget.S" {"helper":"MterpSGetU64"} diff --git a/runtime/interpreter/mterp/mips/op_sput.S b/runtime/interpreter/mterp/mips/op_sput.S index 547de3964a..c858679762 100644 --- a/runtime/interpreter/mterp/mips/op_sput.S +++ b/runtime/interpreter/mterp/mips/op_sput.S @@ -1,19 +1,2 @@ -%default { "helper":"MterpSPutU32"} - /* - * General SPUT handler. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - GET_OPA(a3) # a3 <- AA - GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL($helper) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +%default { "is_object":"0", "helper":"MterpSPutU32"} +%include "mips/field.S" { } diff --git a/runtime/interpreter/mterp/mips/op_sput_object.S b/runtime/interpreter/mterp/mips/op_sput_object.S index 55c88a6816..683b76789d 100644 --- a/runtime/interpreter/mterp/mips/op_sput_object.S +++ b/runtime/interpreter/mterp/mips/op_sput_object.S @@ -1,16 +1 @@ - /* - * General 32-bit SPUT handler. - * - * for: sput-object, - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - addu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - JAL(MterpSPutObj) - beqz v0, MterpException - FETCH_ADVANCE_INST(2) # advance rPC, load rINST - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +%include "mips/op_sput.S" {"is_object":"1", "helper":"MterpSPutObj"} diff --git a/runtime/interpreter/mterp/mips/op_sput_wide.S b/runtime/interpreter/mterp/mips/op_sput_wide.S index cfaaaee6f3..1d2ed196f3 100644 --- a/runtime/interpreter/mterp/mips/op_sput_wide.S +++ b/runtime/interpreter/mterp/mips/op_sput_wide.S @@ -1,17 +1 @@ - /* - * 64-bit SPUT handler. - */ - /* sput-wide vAA, field@BBBB */ - .extern MterpSPutU64 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPA(a1) # a1 <- AA - EAS2(a1, rFP, a1) # a1 <- &fp[AA] - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL(MterpSPutU64) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +%include "mips/op_sput.S" {"helper":"MterpSPutU64"} diff --git a/runtime/interpreter/mterp/mips64/field.S b/runtime/interpreter/mterp/mips64/field.S new file mode 100644 index 0000000000..1333ed77b7 --- /dev/null +++ b/runtime/interpreter/mterp/mips64/field.S @@ -0,0 +1 @@ +TODO diff --git a/runtime/interpreter/mterp/mips64/op_iget.S b/runtime/interpreter/mterp/mips64/op_iget.S index a8ce94c3ba..e91f09923b 100644 --- a/runtime/interpreter/mterp/mips64/op_iget.S +++ b/runtime/interpreter/mterp/mips64/op_iget.S @@ -1,26 +1,2 @@ %default { "is_object":"0", "helper":"MterpIGetU32"} - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - .extern $helper - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal $helper - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - .if $is_object - SET_VREG_OBJECT v0, a2 # fp[A] <- v0 - .else - SET_VREG v0, a2 # fp[A] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%include "mips64/field.S" { } diff --git a/runtime/interpreter/mterp/mips64/op_iget_wide.S b/runtime/interpreter/mterp/mips64/op_iget_wide.S index 08bf544265..40f364571f 100644 --- a/runtime/interpreter/mterp/mips64/op_iget_wide.S +++ b/runtime/interpreter/mterp/mips64/op_iget_wide.S @@ -1,21 +1 @@ - /* - * 64-bit instance field get. - * - * for: iget-wide - */ - .extern MterpIGetU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetU64 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - SET_VREG_WIDE v0, a2 # fp[A] <- v0 - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%include "mips64/op_iget.S" { "helper":"MterpIGetU64" } diff --git a/runtime/interpreter/mterp/mips64/op_iput.S b/runtime/interpreter/mterp/mips64/op_iput.S index 9a789e612d..81ab911b5e 100644 --- a/runtime/interpreter/mterp/mips64/op_iput.S +++ b/runtime/interpreter/mterp/mips64/op_iput.S @@ -1,21 +1,2 @@ -%default { "helper":"MterpIPutU32" } - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field//CCCC */ - .extern $helper - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - GET_VREG a2, a2 # a2 <- fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal $helper - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%default { "is_object":"0", "helper":"MterpIPutU32" } +%include "mips64/field.S" { } diff --git a/runtime/interpreter/mterp/mips64/op_iput_object.S b/runtime/interpreter/mterp/mips64/op_iput_object.S index dd1938ec63..d3316dd756 100644 --- a/runtime/interpreter/mterp/mips64/op_iput_object.S +++ b/runtime/interpreter/mterp/mips64/op_iput_object.S @@ -1,11 +1 @@ - .extern MterpIPutObj - EXPORT_PC - daddu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - jal MterpIPutObj - beqzc v0, MterpException - FETCH_ADVANCE_INST 2 # advance rPC, load rINST - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%include "mips64/op_iput.S" { "is_object":"1", "helper":"MterpIPutObj" } diff --git a/runtime/interpreter/mterp/mips64/op_iput_wide.S b/runtime/interpreter/mterp/mips64/op_iput_wide.S index 62726908fb..05194b33f3 100644 --- a/runtime/interpreter/mterp/mips64/op_iput_wide.S +++ b/runtime/interpreter/mterp/mips64/op_iput_wide.S @@ -1,15 +1 @@ - /* iput-wide vA, vB, field//CCCC */ - .extern MterpIPutU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - dlsa a2, a2, rFP, 2 # a2 <- &fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal MterpIPutU64 - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%include "mips64/op_iput.S" { "helper":"MterpIPutU64" } diff --git a/runtime/interpreter/mterp/mips64/op_sget.S b/runtime/interpreter/mterp/mips64/op_sget.S index b7b0382b1c..200da35a12 100644 --- a/runtime/interpreter/mterp/mips64/op_sget.S +++ b/runtime/interpreter/mterp/mips64/op_sget.S @@ -1,26 +1,2 @@ -%default { "is_object":"0", "helper":"MterpSGetU32", "extend":"" } - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - .extern $helper - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal $helper - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a2, rINST, 8 # a2 <- AA - $extend - PREFETCH_INST 2 - bnez a3, MterpException # bail out - .if $is_object - SET_VREG_OBJECT v0, a2 # fp[AA] <- v0 - .else - SET_VREG v0, a2 # fp[AA] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 +%default { "is_object":"0", "helper":"MterpSGetU32" } +%include "mips64/field.S" { } diff --git a/runtime/interpreter/mterp/mips64/op_sget_boolean.S b/runtime/interpreter/mterp/mips64/op_sget_boolean.S index fe2deb1479..8abb396c57 100644 --- a/runtime/interpreter/mterp/mips64/op_sget_boolean.S +++ b/runtime/interpreter/mterp/mips64/op_sget_boolean.S @@ -1 +1 @@ -%include "mips64/op_sget.S" {"helper":"MterpSGetU8", "extend":"and v0, v0, 0xff"} +%include "mips64/op_sget.S" {"helper":"MterpSGetU8"} diff --git a/runtime/interpreter/mterp/mips64/op_sget_byte.S b/runtime/interpreter/mterp/mips64/op_sget_byte.S index a7e2bef4bc..68623f604c 100644 --- a/runtime/interpreter/mterp/mips64/op_sget_byte.S +++ b/runtime/interpreter/mterp/mips64/op_sget_byte.S @@ -1 +1 @@ -%include "mips64/op_sget.S" {"helper":"MterpSGetI8", "extend":"seb v0, v0"} +%include "mips64/op_sget.S" {"helper":"MterpSGetI8"} diff --git a/runtime/interpreter/mterp/mips64/op_sget_char.S b/runtime/interpreter/mterp/mips64/op_sget_char.S index ed86f32588..3c7b962813 100644 --- a/runtime/interpreter/mterp/mips64/op_sget_char.S +++ b/runtime/interpreter/mterp/mips64/op_sget_char.S @@ -1 +1 @@ -%include "mips64/op_sget.S" {"helper":"MterpSGetU16", "extend":"and v0, v0, 0xffff"} +%include "mips64/op_sget.S" {"helper":"MterpSGetU16"} diff --git a/runtime/interpreter/mterp/mips64/op_sget_short.S b/runtime/interpreter/mterp/mips64/op_sget_short.S index f708a201ce..9a8579ba5b 100644 --- a/runtime/interpreter/mterp/mips64/op_sget_short.S +++ b/runtime/interpreter/mterp/mips64/op_sget_short.S @@ -1 +1 @@ -%include "mips64/op_sget.S" {"helper":"MterpSGetI16", "extend":"seh v0, v0"} +%include "mips64/op_sget.S" {"helper":"MterpSGetI16"} diff --git a/runtime/interpreter/mterp/mips64/op_sget_wide.S b/runtime/interpreter/mterp/mips64/op_sget_wide.S index 7c31252aed..14f232c073 100644 --- a/runtime/interpreter/mterp/mips64/op_sget_wide.S +++ b/runtime/interpreter/mterp/mips64/op_sget_wide.S @@ -1,18 +1 @@ - /* - * SGET_WIDE handler wrapper. - * - */ - /* sget-wide vAA, field//BBBB */ - .extern MterpSGetU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetU64 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a4, rINST, 8 # a4 <- AA - bnez a3, MterpException # bail out - FETCH_ADVANCE_INST 2 # advance rPC, load rINST - SET_VREG_WIDE v0, a4 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%include "mips64/op_sget.S" {"helper":"MterpSGetU64"} diff --git a/runtime/interpreter/mterp/mips64/op_sput.S b/runtime/interpreter/mterp/mips64/op_sput.S index 28b8c3ea26..0bd683767f 100644 --- a/runtime/interpreter/mterp/mips64/op_sput.S +++ b/runtime/interpreter/mterp/mips64/op_sput.S @@ -1,20 +1,2 @@ -%default { "helper":"MterpSPutU32" } - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - .extern $helper - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a3, rINST, 8 # a3 <- AA - GET_VREG a1, a3 # a1 <- fp[AA] - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal $helper - bnezc v0, MterpException # 0 on success - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%default { "is_object":"0", "helper":"MterpSPutU32"} +%include "mips64/field.S" { } diff --git a/runtime/interpreter/mterp/mips64/op_sput_object.S b/runtime/interpreter/mterp/mips64/op_sput_object.S index ff43967666..09bd0fb7ba 100644 --- a/runtime/interpreter/mterp/mips64/op_sput_object.S +++ b/runtime/interpreter/mterp/mips64/op_sput_object.S @@ -1,11 +1 @@ - .extern MterpSPutObj - EXPORT_PC - daddu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - jal MterpSPutObj - beqzc v0, MterpException - FETCH_ADVANCE_INST 2 # advance rPC, load rINST - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%include "mips64/op_sput.S" {"is_object":"1", "helper":"MterpSPutObj"} diff --git a/runtime/interpreter/mterp/mips64/op_sput_wide.S b/runtime/interpreter/mterp/mips64/op_sput_wide.S index bfb6983bb4..070d17ff4d 100644 --- a/runtime/interpreter/mterp/mips64/op_sput_wide.S +++ b/runtime/interpreter/mterp/mips64/op_sput_wide.S @@ -1,18 +1 @@ - /* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field//BBBB */ - .extern MterpSPutU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a1, rINST, 8 # a2 <- AA - dlsa a1, a1, rFP, 2 - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal MterpSPutU64 - bnezc v0, MterpException # 0 on success, -1 on failure - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +%include "mips64/op_sput.S" {"helper":"MterpSPutU64"} diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc index 7b37c9aaef..65c1aa8a79 100644 --- a/runtime/interpreter/mterp/mterp.cc +++ b/runtime/interpreter/mterp/mterp.cc @@ -490,24 +490,6 @@ extern "C" size_t MterpNewInstance(ShadowFrame* shadow_frame, Thread* self, uint return true; } -extern "C" size_t MterpSPutObj(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr, - uint32_t inst_data, Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - const Instruction* inst = Instruction::At(dex_pc_ptr); - return DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, false, false> - (self, *shadow_frame, inst, inst_data); -} - -extern "C" size_t MterpIPutObj(ShadowFrame* shadow_frame, - uint16_t* dex_pc_ptr, - uint32_t inst_data, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - const Instruction* inst = Instruction::At(dex_pc_ptr); - return DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, false, false> - (self, *shadow_frame, inst, inst_data); -} - extern "C" size_t MterpIputObjectQuick(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr, uint32_t inst_data) @@ -681,352 +663,159 @@ extern "C" size_t MterpSuspendCheck(Thread* self) return MterpShouldSwitchInterpreters(); } -template<typename PrimType, typename RetType, typename Getter, FindFieldType kType> -NO_INLINE RetType artGetInstanceFromMterp(uint32_t field_idx, - mirror::Object* obj, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - StackHandleScope<1> hs(self); - HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(&obj)); // GC might move the object. - ArtField* field = FindFieldFromCode<kType, /* access_checks */ false>( +// Execute single field access instruction (get/put, static/instance). +// The template arguments reduce this to fairly small amount of code. +// It requires the target object and field to be already resolved. +template<typename PrimType, FindFieldType kAccessType> +ALWAYS_INLINE void MterpFieldAccess(Instruction* inst, + uint16_t inst_data, + ShadowFrame* shadow_frame, + ObjPtr<mirror::Object> obj, + MemberOffset offset, + bool is_volatile) + REQUIRES_SHARED(Locks::mutator_lock_) { + static_assert(std::is_integral<PrimType>::value, "Unexpected primitive type"); + constexpr bool kIsStatic = (kAccessType & FindFieldFlags::StaticBit) != 0; + constexpr bool kIsPrimitive = (kAccessType & FindFieldFlags::PrimitiveBit) != 0; + constexpr bool kIsRead = (kAccessType & FindFieldFlags::ReadBit) != 0; + + uint16_t vRegA = kIsStatic ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data); + if (kIsPrimitive) { + if (kIsRead) { + PrimType value = UNLIKELY(is_volatile) + ? obj->GetFieldPrimitive<PrimType, /*kIsVolatile*/ true>(offset) + : obj->GetFieldPrimitive<PrimType, /*kIsVolatile*/ false>(offset); + if (sizeof(PrimType) == sizeof(uint64_t)) { + shadow_frame->SetVRegLong(vRegA, value); // Set two consecutive registers. + } else { + shadow_frame->SetVReg(vRegA, static_cast<int32_t>(value)); // Sign/zero extend. + } + } else { // Write. + uint64_t value = (sizeof(PrimType) == sizeof(uint64_t)) + ? shadow_frame->GetVRegLong(vRegA) + : shadow_frame->GetVReg(vRegA); + if (UNLIKELY(is_volatile)) { + obj->SetFieldPrimitive<PrimType, /*kIsVolatile*/ true>(offset, value); + } else { + obj->SetFieldPrimitive<PrimType, /*kIsVolatile*/ false>(offset, value); + } + } + } else { // Object. + if (kIsRead) { + ObjPtr<mirror::Object> value = UNLIKELY(is_volatile) + ? obj->GetFieldObjectVolatile<mirror::Object>(offset) + : obj->GetFieldObject<mirror::Object>(offset); + shadow_frame->SetVRegReference(vRegA, value); + } else { // Write. + ObjPtr<mirror::Object> value = shadow_frame->GetVRegReference(vRegA); + if (UNLIKELY(is_volatile)) { + obj->SetFieldObjectVolatile</*kTransactionActive*/ false>(offset, value); + } else { + obj->SetFieldObject</*kTransactionActive*/ false>(offset, value); + } + } + } +} + +template<typename PrimType, FindFieldType kAccessType> +NO_INLINE bool MterpFieldAccessSlow(Instruction* inst, + uint16_t inst_data, + ShadowFrame* shadow_frame, + Thread* self) + REQUIRES_SHARED(Locks::mutator_lock_) { + constexpr bool kIsStatic = (kAccessType & FindFieldFlags::StaticBit) != 0; + constexpr bool kIsRead = (kAccessType & FindFieldFlags::ReadBit) != 0; + + // Update the dex pc in shadow frame, just in case anything throws. + shadow_frame->SetDexPCPtr(reinterpret_cast<uint16_t*>(inst)); + ArtMethod* referrer = shadow_frame->GetMethod(); + uint32_t field_idx = kIsStatic ? inst->VRegB_21c() : inst->VRegC_22c(); + ArtField* field = FindFieldFromCode<kAccessType, /* access_checks */ false>( field_idx, referrer, self, sizeof(PrimType)); if (UNLIKELY(field == nullptr)) { - return 0; // Will throw exception by checking with Thread::Current. + DCHECK(self->IsExceptionPending()); + return false; } - if (UNLIKELY(h == nullptr)) { - ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/ true); - return 0; // Will throw exception by checking with Thread::Current. + ObjPtr<mirror::Object> obj = kIsStatic + ? field->GetDeclaringClass().Ptr() + : shadow_frame->GetVRegReference(inst->VRegB_22c(inst_data)); + if (UNLIKELY(obj == nullptr)) { + ThrowNullPointerExceptionForFieldAccess(field, kIsRead); + return false; } - return Getter::Get(obj, field); + MterpFieldAccess<PrimType, kAccessType>( + inst, inst_data, shadow_frame, obj, field->GetOffset(), field->IsVolatile()); + return true; } -template<typename PrimType, typename RetType, typename Getter> -ALWAYS_INLINE RetType artGetInstanceFromMterpFast(uint32_t field_idx, - mirror::Object* obj, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - constexpr bool kIsObject = std::is_same<RetType, mirror::Object*>::value; - constexpr FindFieldType kType = kIsObject ? InstanceObjectRead : InstancePrimitiveRead; +template<typename PrimType, FindFieldType kAccessType> +ALWAYS_INLINE bool MterpFieldAccessFast(Instruction* inst, + uint16_t inst_data, + ShadowFrame* shadow_frame, + Thread* self) + REQUIRES_SHARED(Locks::mutator_lock_) { + constexpr bool kIsStatic = (kAccessType & FindFieldFlags::StaticBit) != 0; // This effectively inlines the fast path from ArtMethod::GetDexCache. // It avoids non-inlined call which in turn allows elimination of the prologue and epilogue. + ArtMethod* referrer = shadow_frame->GetMethod(); if (LIKELY(!referrer->IsObsolete())) { // Avoid read barriers, since we need only the pointer to the native (non-movable) // DexCache field array which we can get even through from-space objects. ObjPtr<mirror::Class> klass = referrer->GetDeclaringClass<kWithoutReadBarrier>(); mirror::DexCache* dex_cache = klass->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>(); + // Try to find the desired field in DexCache. + uint32_t field_idx = kIsStatic ? inst->VRegB_21c() : inst->VRegC_22c(); ArtField* field = dex_cache->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr & obj != nullptr)) { - if (kIsDebugBuild) { - // Compare the fast path and slow path. - StackHandleScope<1> hs(self); - HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(&obj)); // GC might move the object. - DCHECK_EQ(field, (FindFieldFromCode<kType, /* access_checks */ false>( + if (LIKELY(field != nullptr)) { + bool initialized = !kIsStatic || field->GetDeclaringClass()->IsInitialized(); + if (LIKELY(initialized)) { + DCHECK_EQ(field, (FindFieldFromCode<kAccessType, /* access_checks */ false>( field_idx, referrer, self, sizeof(PrimType)))); + ObjPtr<mirror::Object> obj = kIsStatic + ? field->GetDeclaringClass().Ptr() + : shadow_frame->GetVRegReference(inst->VRegB_22c(inst_data)); + if (LIKELY(kIsStatic || obj != nullptr)) { + MterpFieldAccess<PrimType, kAccessType>( + inst, inst_data, shadow_frame, obj, field->GetOffset(), field->IsVolatile()); + return true; + } } - return Getter::Get(obj, field); } } - // Slow path. Last and with identical arguments so that it becomes single instruction tail call. - return artGetInstanceFromMterp<PrimType, RetType, Getter, kType>(field_idx, obj, referrer, self); -} - -#define ART_GET_FIELD_FROM_MTERP(Suffix, Kind, PrimType, RetType, Ptr) \ -extern "C" RetType MterpIGet ## Suffix(uint32_t field_idx, \ - mirror::Object* obj, \ - ArtMethod* referrer, \ - Thread* self) \ - REQUIRES_SHARED(Locks::mutator_lock_) { \ - struct Getter { /* Specialize the field load depending on the field type */ \ - static RetType Get(mirror::Object* o, ArtField* f) REQUIRES_SHARED(Locks::mutator_lock_) { \ - return f->Get##Kind(o)Ptr; \ - } \ - }; \ - return artGetInstanceFromMterpFast<PrimType, RetType, Getter>(field_idx, obj, referrer, self); \ -} \ - -ART_GET_FIELD_FROM_MTERP(I8, Byte, int8_t, ssize_t, ) -ART_GET_FIELD_FROM_MTERP(U8, Boolean, uint8_t, size_t, ) -ART_GET_FIELD_FROM_MTERP(I16, Short, int16_t, ssize_t, ) -ART_GET_FIELD_FROM_MTERP(U16, Char, uint16_t, size_t, ) -ART_GET_FIELD_FROM_MTERP(U32, 32, uint32_t, size_t, ) -ART_GET_FIELD_FROM_MTERP(U64, 64, uint64_t, uint64_t, ) -ART_GET_FIELD_FROM_MTERP(Obj, Obj, mirror::HeapReference<mirror::Object>, mirror::Object*, .Ptr()) - -#undef ART_GET_FIELD_FROM_MTERP - -extern "C" ssize_t MterpIPutU8(uint32_t field_idx, - mirror::Object* obj, - uint8_t new_value, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr && obj != nullptr)) { - field->SetBoolean<false>(obj, new_value); - return 0; // success - } - return -1; // failure -} - -extern "C" ssize_t MterpIPutI8(uint32_t field_idx, - mirror::Object* obj, - uint8_t new_value, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr && obj != nullptr)) { - field->SetByte<false>(obj, new_value); - return 0; // success - } - return -1; // failure -} - -extern "C" ssize_t MterpIPutU16(uint32_t field_idx, - mirror::Object* obj, - uint16_t new_value, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr && obj != nullptr)) { - field->SetChar<false>(obj, new_value); - return 0; // success - } - return -1; // failure -} - -extern "C" ssize_t MterpIPutI16(uint32_t field_idx, - mirror::Object* obj, - uint16_t new_value, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr && obj != nullptr)) { - field->SetShort<false>(obj, new_value); - return 0; // success - } - return -1; // failure -} - -extern "C" ssize_t MterpIPutU32(uint32_t field_idx, - mirror::Object* obj, - uint32_t new_value, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr && obj != nullptr)) { - field->Set32<false>(obj, new_value); - return 0; // success - } - return -1; // failure -} - -extern "C" ssize_t MterpIPutU64(uint32_t field_idx, - mirror::Object* obj, - uint64_t* new_value, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr && obj != nullptr)) { - field->Set64<false>(obj, *new_value); - return 0; // success - } - return -1; // failure -} - -extern "C" ssize_t artSetObjInstanceFromMterp(uint32_t field_idx, - mirror::Object* obj, - mirror::Object* new_value, - ArtMethod* referrer) - REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx, kRuntimePointerSize); - if (LIKELY(field != nullptr && obj != nullptr)) { - field->SetObj<false>(obj, new_value); - return 0; // success - } - return -1; // failure -} -template <typename return_type, Primitive::Type primitive_type> -ALWAYS_INLINE return_type MterpGetStatic(uint32_t field_idx, - ArtMethod* referrer, - Thread* self, - return_type (ArtField::*func)(ObjPtr<mirror::Object>)) - REQUIRES_SHARED(Locks::mutator_lock_) { - return_type res = 0; // On exception, the result will be ignored. - ArtField* f = - FindFieldFromCode<StaticPrimitiveRead, false>(field_idx, - referrer, - self, - primitive_type); - if (LIKELY(f != nullptr)) { - ObjPtr<mirror::Object> obj = f->GetDeclaringClass(); - res = (f->*func)(obj); - } - return res; -} - -extern "C" int32_t MterpSGetU8(uint32_t field_idx, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpGetStatic<uint8_t, Primitive::kPrimBoolean>(field_idx, - referrer, - self, - &ArtField::GetBoolean); -} - -extern "C" int32_t MterpSGetI8(uint32_t field_idx, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpGetStatic<int8_t, Primitive::kPrimByte>(field_idx, - referrer, - self, - &ArtField::GetByte); -} - -extern "C" uint32_t MterpSGetU16(uint32_t field_idx, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpGetStatic<uint16_t, Primitive::kPrimChar>(field_idx, - referrer, - self, - &ArtField::GetChar); -} - -extern "C" int32_t MterpSGetI16(uint32_t field_idx, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpGetStatic<int16_t, Primitive::kPrimShort>(field_idx, - referrer, - self, - &ArtField::GetShort); -} - -extern "C" mirror::Object* MterpSGetObj(uint32_t field_idx, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpGetStatic<ObjPtr<mirror::Object>, Primitive::kPrimNot>(field_idx, - referrer, - self, - &ArtField::GetObject).Ptr(); -} - -extern "C" int32_t MterpSGetU32(uint32_t field_idx, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpGetStatic<int32_t, Primitive::kPrimInt>(field_idx, - referrer, - self, - &ArtField::GetInt); -} - -extern "C" int64_t MterpSGetU64(uint32_t field_idx, ArtMethod* referrer, Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpGetStatic<int64_t, Primitive::kPrimLong>(field_idx, - referrer, - self, - &ArtField::GetLong); -} - - -template <typename field_type, Primitive::Type primitive_type> -int MterpSetStatic(uint32_t field_idx, - field_type new_value, - ArtMethod* referrer, - Thread* self, - void (ArtField::*func)(ObjPtr<mirror::Object>, field_type val)) - REQUIRES_SHARED(Locks::mutator_lock_) { - int res = 0; // Assume success (following quick_field_entrypoints conventions) - ArtField* f = - FindFieldFromCode<StaticPrimitiveWrite, false>(field_idx, referrer, self, primitive_type); - if (LIKELY(f != nullptr)) { - ObjPtr<mirror::Object> obj = f->GetDeclaringClass(); - (f->*func)(obj, new_value); - } else { - res = -1; // Failure - } - return res; + // Slow path. Last and with identical arguments so that it becomes single instruction tail call. + return MterpFieldAccessSlow<PrimType, kAccessType>(inst, inst_data, shadow_frame, self); } -extern "C" int MterpSPutU8(uint32_t field_idx, - uint8_t new_value, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpSetStatic<uint8_t, Primitive::kPrimBoolean>(field_idx, - new_value, - referrer, - self, - &ArtField::SetBoolean<false>); +#define MTERP_FIELD_ACCESSOR(Name, PrimType, AccessType) \ +extern "C" bool Name(Instruction* inst, uint16_t inst_data, ShadowFrame* sf, Thread* self) \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + return MterpFieldAccessFast<PrimType, AccessType>(inst, inst_data, sf, self); \ } -extern "C" int MterpSPutI8(uint32_t field_idx, - int8_t new_value, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpSetStatic<int8_t, Primitive::kPrimByte>(field_idx, - new_value, - referrer, - self, - &ArtField::SetByte<false>); -} +#define MTERP_FIELD_ACCESSORS_FOR_TYPE(Sufix, PrimType, Kind) \ + MTERP_FIELD_ACCESSOR(MterpIGet##Sufix, PrimType, Instance##Kind##Read) \ + MTERP_FIELD_ACCESSOR(MterpIPut##Sufix, PrimType, Instance##Kind##Write) \ + MTERP_FIELD_ACCESSOR(MterpSGet##Sufix, PrimType, Static##Kind##Read) \ + MTERP_FIELD_ACCESSOR(MterpSPut##Sufix, PrimType, Static##Kind##Write) -extern "C" int MterpSPutU16(uint32_t field_idx, - uint16_t new_value, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpSetStatic<uint16_t, Primitive::kPrimChar>(field_idx, - new_value, - referrer, - self, - &ArtField::SetChar<false>); -} +MTERP_FIELD_ACCESSORS_FOR_TYPE(I8, int8_t, Primitive) +MTERP_FIELD_ACCESSORS_FOR_TYPE(U8, uint8_t, Primitive) +MTERP_FIELD_ACCESSORS_FOR_TYPE(I16, int16_t, Primitive) +MTERP_FIELD_ACCESSORS_FOR_TYPE(U16, uint16_t, Primitive) +MTERP_FIELD_ACCESSORS_FOR_TYPE(U32, uint32_t, Primitive) +MTERP_FIELD_ACCESSORS_FOR_TYPE(U64, uint64_t, Primitive) +MTERP_FIELD_ACCESSORS_FOR_TYPE(Obj, uint32_t, Object) -extern "C" int MterpSPutI16(uint32_t field_idx, - int16_t new_value, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpSetStatic<int16_t, Primitive::kPrimShort>(field_idx, - new_value, - referrer, - self, - &ArtField::SetShort<false>); -} - -extern "C" int MterpSPutU32(uint32_t field_idx, - int32_t new_value, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpSetStatic<int32_t, Primitive::kPrimInt>(field_idx, - new_value, - referrer, - self, - &ArtField::SetInt<false>); -} +// Check that the primitive type for Obj variant above is correct. +// It really must be primitive type for the templates to compile. +// In the case of objects, it is only used to get the field size. +static_assert(kHeapReferenceSize == sizeof(uint32_t), "Unexpected kHeapReferenceSize"); -extern "C" int MterpSPutU64(uint32_t field_idx, - int64_t* new_value, - ArtMethod* referrer, - Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_) { - return MterpSetStatic<int64_t, Primitive::kPrimLong>(field_idx, - *new_value, - referrer, - self, - &ArtField::SetLong<false>); -} +#undef MTERP_FIELD_ACCESSORS_FOR_TYPE +#undef MTERP_FIELD_ACCESSOR extern "C" mirror::Object* artAGetObjectFromMterp(mirror::Object* arr, int32_t index) diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S index 394a84924c..25512aec37 100644 --- a/runtime/interpreter/mterp/out/mterp_arm.S +++ b/runtime/interpreter/mterp/out/mterp_arm.S @@ -2246,309 +2246,260 @@ artMterpAsmInstructionStart = .L_op_nop .balign 128 .L_op_iget: /* 0x52 */ /* File: arm/op_iget.S */ +/* File: arm/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self + .extern MterpIGetU32 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIGetU32 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpPossibleException @ bail out - .if 0 - SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 - .else - SET_VREG r0, r2 @ fp[A]<- r0 - .endif + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_wide: /* 0x53 */ /* File: arm/op_iget_wide.S */ +/* File: arm/op_iget.S */ +/* File: arm/field.S */ /* - * 64-bit instance field get. - * - * for: iget-wide + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self + .extern MterpIGetU64 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIGetU64 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpException @ bail out - CLEAR_SHADOW_PAIR r2, ip, lr @ Zero out the shadow regs - VREG_INDEX_TO_ADDR r3, r2 @ r3<- &fp[A] - stmia r3, {r0-r1} @ fp[A]<- r0/r1 + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_iget_object: /* 0x54 */ /* File: arm/op_iget_object.S */ /* File: arm/op_iget.S */ +/* File: arm/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self + .extern MterpIGetObj + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIGetObj - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpPossibleException @ bail out - .if 1 - SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 - .else - SET_VREG r0, r2 @ fp[A]<- r0 - .endif + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_boolean: /* 0x55 */ /* File: arm/op_iget_boolean.S */ /* File: arm/op_iget.S */ +/* File: arm/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self + .extern MterpIGetU8 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIGetU8 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpPossibleException @ bail out - .if 0 - SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 - .else - SET_VREG r0, r2 @ fp[A]<- r0 - .endif + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_byte: /* 0x56 */ /* File: arm/op_iget_byte.S */ /* File: arm/op_iget.S */ +/* File: arm/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self + .extern MterpIGetI8 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIGetI8 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpPossibleException @ bail out - .if 0 - SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 - .else - SET_VREG r0, r2 @ fp[A]<- r0 - .endif + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_char: /* 0x57 */ /* File: arm/op_iget_char.S */ /* File: arm/op_iget.S */ +/* File: arm/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self + .extern MterpIGetU16 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIGetU16 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpPossibleException @ bail out - .if 0 - SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 - .else - SET_VREG r0, r2 @ fp[A]<- r0 - .endif + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_short: /* 0x58 */ /* File: arm/op_iget_short.S */ /* File: arm/op_iget.S */ +/* File: arm/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- referrer - mov r3, rSELF @ r3<- self + .extern MterpIGetI16 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIGetI16 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - ubfx r2, rINST, #8, #4 @ r2<- A - PREFETCH_INST 2 - cmp r3, #0 - bne MterpPossibleException @ bail out - .if 0 - SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 - .else - SET_VREG r0, r2 @ fp[A]<- r0 - .endif + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip @ extract opcode from rINST GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iput: /* 0x59 */ /* File: arm/op_iput.S */ +/* File: arm/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field@CCCC */ .extern MterpIPutU32 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - GET_VREG r2, r2 @ r2<- fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIPutU32 cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iput_wide: /* 0x5a */ /* File: arm/op_iput_wide.S */ - /* iput-wide vA, vB, field@CCCC */ +/* File: arm/op_iput.S */ +/* File: arm/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU64 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - VREG_INDEX_TO_ADDR r2, r2 @ r2<- &fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIPutU64 cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_iput_object: /* 0x5b */ /* File: arm/op_iput_object.S */ - EXPORT_PC - add r0, rFP, #OFF_FP_SHADOWFRAME - mov r1, rPC - mov r2, rINST - mov r3, rSELF - bl MterpIPutObj - cmp r0, #0 - beq MterpException - FETCH_ADVANCE_INST 2 @ advance rPC, load rINST - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +/* File: arm/op_iput.S */ +/* File: arm/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIPutObj + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpIPutObj + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_iput_boolean: /* 0x5c */ /* File: arm/op_iput_boolean.S */ /* File: arm/op_iput.S */ +/* File: arm/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field@CCCC */ .extern MterpIPutU8 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - GET_VREG r2, r2 @ r2<- fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIPutU8 cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2556,27 +2507,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_byte: /* 0x5d */ /* File: arm/op_iput_byte.S */ /* File: arm/op_iput.S */ +/* File: arm/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field@CCCC */ .extern MterpIPutI8 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - GET_VREG r2, r2 @ r2<- fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIPutI8 cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2584,27 +2531,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_char: /* 0x5e */ /* File: arm/op_iput_char.S */ /* File: arm/op_iput.S */ +/* File: arm/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field@CCCC */ .extern MterpIPutU16 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - GET_VREG r2, r2 @ r2<- fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIPutU16 cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2612,118 +2555,93 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_short: /* 0x5f */ /* File: arm/op_iput_short.S */ /* File: arm/op_iput.S */ +/* File: arm/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field@CCCC */ .extern MterpIPutI16 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref CCCC - mov r1, rINST, lsr #12 @ r1<- B - GET_VREG r1, r1 @ r1<- fp[B], the object pointer - ubfx r2, rINST, #8, #4 @ r2<- A - GET_VREG r2, r2 @ r2<- fp[A] - ldr r3, [rFP, #OFF_FP_METHOD] @ r3<- referrer - PREFETCH_INST 2 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode bl MterpIPutI16 cmp r0, #0 - bne MterpPossibleException - ADVANCE 2 @ advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sget: /* 0x60 */ /* File: arm/op_sget.S */ +/* File: arm/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - .extern MterpSGetU32 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetU32 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r2, rINST, lsr #8 @ r2<- AA - PREFETCH_INST 2 - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out -.if 0 - SET_VREG_OBJECT r0, r2 @ fp[AA]<- r0 -.else - SET_VREG r0, r2 @ fp[AA]<- r0 -.endif + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSGetU32 + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sget_wide: /* 0x61 */ /* File: arm/op_sget_wide.S */ +/* File: arm/op_sget.S */ +/* File: arm/field.S */ /* - * SGET_WIDE handler wrapper. - * + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* sget-wide vAA, field@BBBB */ - .extern MterpSGetU64 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetU64 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r9, rINST, lsr #8 @ r9<- AA - VREG_INDEX_TO_ADDR lr, r9 @ r9<- &fp[AA] - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out - FETCH_ADVANCE_INST 2 @ advance rPC, load rINST - CLEAR_SHADOW_PAIR r9, r2, ip @ Zero out the shadow regs - stmia lr, {r0-r1} @ vAA/vAA+1<- r0/r1 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSGetU64 + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_sget_object: /* 0x62 */ /* File: arm/op_sget_object.S */ /* File: arm/op_sget.S */ +/* File: arm/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - .extern MterpSGetObj - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetObj - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r2, rINST, lsr #8 @ r2<- AA - PREFETCH_INST 2 - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out -.if 1 - SET_VREG_OBJECT r0, r2 @ fp[AA]<- r0 -.else - SET_VREG r0, r2 @ fp[AA]<- r0 -.endif + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSGetObj + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2731,32 +2649,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_boolean: /* 0x63 */ /* File: arm/op_sget_boolean.S */ /* File: arm/op_sget.S */ +/* File: arm/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - .extern MterpSGetU8 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetU8 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r2, rINST, lsr #8 @ r2<- AA - PREFETCH_INST 2 - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out -.if 0 - SET_VREG_OBJECT r0, r2 @ fp[AA]<- r0 -.else - SET_VREG r0, r2 @ fp[AA]<- r0 -.endif + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSGetU8 + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2764,32 +2673,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_byte: /* 0x64 */ /* File: arm/op_sget_byte.S */ /* File: arm/op_sget.S */ +/* File: arm/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - .extern MterpSGetI8 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetI8 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r2, rINST, lsr #8 @ r2<- AA - PREFETCH_INST 2 - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out -.if 0 - SET_VREG_OBJECT r0, r2 @ fp[AA]<- r0 -.else - SET_VREG r0, r2 @ fp[AA]<- r0 -.endif + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSGetI8 + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2797,32 +2697,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_char: /* 0x65 */ /* File: arm/op_sget_char.S */ /* File: arm/op_sget.S */ +/* File: arm/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - .extern MterpSGetU16 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetU16 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r2, rINST, lsr #8 @ r2<- AA - PREFETCH_INST 2 - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out -.if 0 - SET_VREG_OBJECT r0, r2 @ fp[AA]<- r0 -.else - SET_VREG r0, r2 @ fp[AA]<- r0 -.endif + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSGetU16 + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2830,122 +2721,117 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_short: /* 0x66 */ /* File: arm/op_sget_short.S */ /* File: arm/op_sget.S */ +/* File: arm/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - .extern MterpSGetI16 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - ldr r1, [rFP, #OFF_FP_METHOD] - mov r2, rSELF - bl MterpSGetI16 - ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] - mov r2, rINST, lsr #8 @ r2<- AA - PREFETCH_INST 2 - cmp r3, #0 @ Fail to resolve? - bne MterpException @ bail out -.if 0 - SET_VREG_OBJECT r0, r2 @ fp[AA]<- r0 -.else - SET_VREG r0, r2 @ fp[AA]<- r0 -.endif + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSGetI16 + cmp r0, #0 + beq MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sput: /* 0x67 */ /* File: arm/op_sput.S */ +/* File: arm/field.S */ /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r3, rINST, lsr #8 @ r3<- AA - GET_VREG r1, r3 @ r1<= fp[AA] - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl MterpSPutU32 - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + .extern MterpSPutU32 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSPutU32 + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sput_wide: /* 0x68 */ /* File: arm/op_sput_wide.S */ +/* File: arm/op_sput.S */ +/* File: arm/field.S */ /* - * SPUT_WIDE handler wrapper. - * + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* sput-wide vAA, field@BBBB */ .extern MterpSPutU64 - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r1, rINST, lsr #8 @ r1<- AA - VREG_INDEX_TO_ADDR r1, r1 - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl MterpSPutU64 - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSPutU64 + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_sput_object: /* 0x69 */ /* File: arm/op_sput_object.S */ - EXPORT_PC - add r0, rFP, #OFF_FP_SHADOWFRAME - mov r1, rPC - mov r2, rINST - mov r3, rSELF - bl MterpSPutObj - cmp r0, #0 - beq MterpException - FETCH_ADVANCE_INST 2 @ advance rPC, load rINST - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction +/* File: arm/op_sput.S */ +/* File: arm/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutObj + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSPutObj + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_sput_boolean: /* 0x6a */ /* File: arm/op_sput_boolean.S */ /* File: arm/op_sput.S */ +/* File: arm/field.S */ /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r3, rINST, lsr #8 @ r3<- AA - GET_VREG r1, r3 @ r1<= fp[AA] - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl MterpSPutU8 - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + .extern MterpSPutU8 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSPutU8 + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2953,25 +2839,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_byte: /* 0x6b */ /* File: arm/op_sput_byte.S */ /* File: arm/op_sput.S */ +/* File: arm/field.S */ /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r3, rINST, lsr #8 @ r3<- AA - GET_VREG r1, r3 @ r1<= fp[AA] - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl MterpSPutI8 - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + .extern MterpSPutI8 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSPutI8 + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -2979,25 +2863,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_char: /* 0x6c */ /* File: arm/op_sput_char.S */ /* File: arm/op_sput.S */ +/* File: arm/field.S */ /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r3, rINST, lsr #8 @ r3<- AA - GET_VREG r1, r3 @ r1<= fp[AA] - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl MterpSPutU16 - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + .extern MterpSPutU16 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSPutU16 + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ @@ -3005,25 +2887,23 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_short: /* 0x6d */ /* File: arm/op_sput_short.S */ /* File: arm/op_sput.S */ +/* File: arm/field.S */ /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field@BBBB */ - EXPORT_PC - FETCH r0, 1 @ r0<- field ref BBBB - mov r3, rINST, lsr #8 @ r3<- AA - GET_VREG r1, r3 @ r1<= fp[AA] - ldr r2, [rFP, #OFF_FP_METHOD] - mov r3, rSELF - PREFETCH_INST 2 @ Get next inst, but don't advance rPC - bl MterpSPutI16 - cmp r0, #0 @ 0 on success, -1 on failure - bne MterpException - ADVANCE 2 @ Past exception point - now advance rPC - GET_INST_OPCODE ip @ extract opcode from rINST - GOTO_OPCODE ip @ jump to next instruction + .extern MterpSPutI16 + mov r0, rPC @ arg0: Instruction* inst + mov r1, rINST @ arg1: uint16_t inst_data + add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf + mov r3, rSELF @ arg3: Thread* self + PREFETCH_INST 2 @ prefetch next opcode + bl MterpSPutI16 + cmp r0, #0 + beq MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip @ extract opcode from rINST + GOTO_OPCODE ip @ jump to next instruction + /* ------------------------------ */ diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S index 5f4aa4f256..fd60c95a37 100644 --- a/runtime/interpreter/mterp/out/mterp_arm64.S +++ b/runtime/interpreter/mterp/out/mterp_arm64.S @@ -2183,303 +2183,249 @@ artMterpAsmInstructionStart = .L_op_nop .balign 128 .L_op_iget: /* 0x52 */ /* File: arm64/op_iget.S */ +/* File: arm64/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self + .extern MterpIGetU32 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIGetU32 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cbnz x3, MterpPossibleException // bail out - .if 0 - SET_VREG_OBJECT w0, w2 // fp[A]<- w0 - .else - SET_VREG w0, w2 // fp[A]<- w0 - .endif + cbz x0, MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_wide: /* 0x53 */ /* File: arm64/op_iget_wide.S */ +/* File: arm64/op_iget.S */ +/* File: arm64/field.S */ /* - * 64-bit instance field get. - * - * for: iget-wide + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self + .extern MterpIGetU64 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIGetU64 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cmp w3, #0 - cbnz w3, MterpException // bail out - SET_VREG_WIDE x0, w2 + cbz x0, MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from wINST + GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_iget_object: /* 0x54 */ /* File: arm64/op_iget_object.S */ /* File: arm64/op_iget.S */ +/* File: arm64/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self + .extern MterpIGetObj + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIGetObj - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cbnz x3, MterpPossibleException // bail out - .if 1 - SET_VREG_OBJECT w0, w2 // fp[A]<- w0 - .else - SET_VREG w0, w2 // fp[A]<- w0 - .endif + cbz x0, MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_boolean: /* 0x55 */ /* File: arm64/op_iget_boolean.S */ /* File: arm64/op_iget.S */ +/* File: arm64/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self + .extern MterpIGetU8 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIGetU8 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - uxtb w0, w0 - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cbnz x3, MterpPossibleException // bail out - .if 0 - SET_VREG_OBJECT w0, w2 // fp[A]<- w0 - .else - SET_VREG w0, w2 // fp[A]<- w0 - .endif + cbz x0, MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_byte: /* 0x56 */ /* File: arm64/op_iget_byte.S */ /* File: arm64/op_iget.S */ +/* File: arm64/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self + .extern MterpIGetI8 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIGetI8 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - sxtb w0, w0 - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cbnz x3, MterpPossibleException // bail out - .if 0 - SET_VREG_OBJECT w0, w2 // fp[A]<- w0 - .else - SET_VREG w0, w2 // fp[A]<- w0 - .endif + cbz x0, MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_char: /* 0x57 */ /* File: arm64/op_iget_char.S */ /* File: arm64/op_iget.S */ +/* File: arm64/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self + .extern MterpIGetU16 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIGetU16 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - uxth w0, w0 - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cbnz x3, MterpPossibleException // bail out - .if 0 - SET_VREG_OBJECT w0, w2 // fp[A]<- w0 - .else - SET_VREG w0, w2 // fp[A]<- w0 - .endif + cbz x0, MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iget_short: /* 0x58 */ /* File: arm64/op_iget_short.S */ /* File: arm64/op_iget.S */ +/* File: arm64/field.S */ /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer - mov x3, xSELF // w3<- self + .extern MterpIGetI16 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIGetI16 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - sxth w0, w0 - ubfx w2, wINST, #8, #4 // w2<- A - PREFETCH_INST 2 - cbnz x3, MterpPossibleException // bail out - .if 0 - SET_VREG_OBJECT w0, w2 // fp[A]<- w0 - .else - SET_VREG w0, w2 // fp[A]<- w0 - .endif + cbz x0, MterpPossibleException ADVANCE 2 GET_INST_OPCODE ip // extract opcode from rINST GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iput: /* 0x59 */ /* File: arm64/op_iput.S */ +/* File: arm64/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field//CCCC */ .extern MterpIPutU32 - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - GET_VREG w2, w2 // w2<- fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIPutU32 - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_iput_wide: /* 0x5a */ /* File: arm64/op_iput_wide.S */ - /* iput-wide vA, vB, field//CCCC */ +/* File: arm64/op_iput.S */ +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU64 - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - VREG_INDEX_TO_ADDR x2, x2 // w2<- &fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIPutU64 - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from wINST - GOTO_OPCODE ip // jump to next instruction + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_iput_object: /* 0x5b */ /* File: arm64/op_iput_object.S */ - EXPORT_PC - add x0, xFP, #OFF_FP_SHADOWFRAME - mov x1, xPC - mov w2, wINST - mov x3, xSELF - bl MterpIPutObj - cbz w0, MterpException - FETCH_ADVANCE_INST 2 // advance rPC, load rINST - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +/* File: arm64/op_iput.S */ +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIPutObj + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpIPutObj + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_iput_boolean: /* 0x5c */ /* File: arm64/op_iput_boolean.S */ /* File: arm64/op_iput.S */ +/* File: arm64/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field//CCCC */ .extern MterpIPutU8 - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - GET_VREG w2, w2 // w2<- fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIPutU8 - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2487,26 +2433,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_byte: /* 0x5d */ /* File: arm64/op_iput_byte.S */ /* File: arm64/op_iput.S */ +/* File: arm64/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field//CCCC */ .extern MterpIPutI8 - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - GET_VREG w2, w2 // w2<- fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIPutI8 - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2514,26 +2456,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_char: /* 0x5e */ /* File: arm64/op_iput_char.S */ /* File: arm64/op_iput.S */ +/* File: arm64/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field//CCCC */ .extern MterpIPutU16 - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - GET_VREG w2, w2 // w2<- fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIPutU16 - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2541,114 +2479,89 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_short: /* 0x5f */ /* File: arm64/op_iput_short.S */ /* File: arm64/op_iput.S */ +/* File: arm64/field.S */ /* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vA, vB, field//CCCC */ .extern MterpIPutI16 - EXPORT_PC - FETCH w0, 1 // w0<- field ref CCCC - lsr w1, wINST, #12 // w1<- B - GET_VREG w1, w1 // w1<- fp[B], the object pointer - ubfx w2, wINST, #8, #4 // w2<- A - GET_VREG w2, w2 // w2<- fp[A] - ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer - PREFETCH_INST 2 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode bl MterpIPutI16 - cbnz w0, MterpPossibleException - ADVANCE 2 // advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sget: /* 0x60 */ /* File: arm64/op_sget.S */ +/* File: arm64/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field//BBBB */ - .extern MterpSGetU32 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetU32 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w2, wINST, #8 // w2<- AA - - PREFETCH_INST 2 - cbnz x3, MterpException // bail out -.if 0 - SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 -.else - SET_VREG w0, w2 // fp[AA]<- w0 -.endif + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSGetU32 + cbz x0, MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sget_wide: /* 0x61 */ /* File: arm64/op_sget_wide.S */ - /* - * SGET_WIDE handler wrapper. - * - */ - /* sget-wide vAA, field//BBBB */ +/* File: arm64/op_sget.S */ +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSGetU64 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSGetU64 + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + - .extern MterpGet64StaticFromCode - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetU64 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w4, wINST, #8 // w4<- AA - cbnz x3, MterpException // bail out - FETCH_ADVANCE_INST 2 // advance rPC, load wINST - SET_VREG_WIDE x0, w4 - GET_INST_OPCODE ip // extract opcode from wINST - GOTO_OPCODE ip // jump to next instruction /* ------------------------------ */ .balign 128 .L_op_sget_object: /* 0x62 */ /* File: arm64/op_sget_object.S */ /* File: arm64/op_sget.S */ +/* File: arm64/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field//BBBB */ - .extern MterpSGetObj - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetObj - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w2, wINST, #8 // w2<- AA - - PREFETCH_INST 2 - cbnz x3, MterpException // bail out -.if 1 - SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 -.else - SET_VREG w0, w2 // fp[AA]<- w0 -.endif + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSGetObj + cbz x0, MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2656,32 +2569,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_boolean: /* 0x63 */ /* File: arm64/op_sget_boolean.S */ /* File: arm64/op_sget.S */ +/* File: arm64/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field//BBBB */ - .extern MterpSGetU8 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetU8 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w2, wINST, #8 // w2<- AA - uxtb w0, w0 - PREFETCH_INST 2 - cbnz x3, MterpException // bail out -.if 0 - SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 -.else - SET_VREG w0, w2 // fp[AA]<- w0 -.endif + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSGetU8 + cbz x0, MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2689,32 +2592,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_byte: /* 0x64 */ /* File: arm64/op_sget_byte.S */ /* File: arm64/op_sget.S */ +/* File: arm64/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field//BBBB */ - .extern MterpSGetI8 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetI8 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w2, wINST, #8 // w2<- AA - sxtb w0, w0 - PREFETCH_INST 2 - cbnz x3, MterpException // bail out -.if 0 - SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 -.else - SET_VREG w0, w2 // fp[AA]<- w0 -.endif + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSGetI8 + cbz x0, MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2722,32 +2615,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_char: /* 0x65 */ /* File: arm64/op_sget_char.S */ /* File: arm64/op_sget.S */ +/* File: arm64/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field//BBBB */ - .extern MterpSGetU16 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetU16 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w2, wINST, #8 // w2<- AA - uxth w0, w0 - PREFETCH_INST 2 - cbnz x3, MterpException // bail out -.if 0 - SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 -.else - SET_VREG w0, w2 // fp[AA]<- w0 -.endif + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSGetU16 + cbz x0, MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2755,118 +2638,112 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_short: /* 0x66 */ /* File: arm64/op_sget_short.S */ /* File: arm64/op_sget.S */ +/* File: arm64/field.S */ /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* op vAA, field//BBBB */ - .extern MterpSGetI16 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - ldr x1, [xFP, #OFF_FP_METHOD] - mov x2, xSELF - bl MterpSGetI16 - ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] - lsr w2, wINST, #8 // w2<- AA - sxth w0, w0 - PREFETCH_INST 2 - cbnz x3, MterpException // bail out -.if 0 - SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 -.else - SET_VREG w0, w2 // fp[AA]<- w0 -.endif + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSGetI16 + cbz x0, MterpPossibleException ADVANCE 2 - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sput: /* 0x67 */ /* File: arm64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - EXPORT_PC - FETCH w0, 1 // r0<- field ref BBBB - lsr w3, wINST, #8 // r3<- AA - GET_VREG w1, w3 // r1<= fp[AA] - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl MterpSPutU32 - cbnz w0, MterpException // 0 on success - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutU32 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSPutU32 + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ .balign 128 .L_op_sput_wide: /* 0x68 */ /* File: arm64/op_sput_wide.S */ +/* File: arm64/op_sput.S */ +/* File: arm64/field.S */ /* - * SPUT_WIDE handler wrapper. - * + * General field read / write (iget-* iput-* sget-* sput-*). */ - /* sput-wide vAA, field//BBBB */ .extern MterpSPutU64 - EXPORT_PC - FETCH w0, 1 // w0<- field ref BBBB - lsr w1, wINST, #8 // w1<- AA - VREG_INDEX_TO_ADDR x1, w1 - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl MterpSPutU64 - cbnz w0, MterpException // 0 on success, -1 on failure - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from wINST - GOTO_OPCODE ip // jump to next instruction + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSPutU64 + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_sput_object: /* 0x69 */ /* File: arm64/op_sput_object.S */ - EXPORT_PC - add x0, xFP, #OFF_FP_SHADOWFRAME - mov x1, xPC - mov x2, xINST - mov x3, xSELF - bl MterpSPutObj - cbz w0, MterpException - FETCH_ADVANCE_INST 2 // advance rPC, load rINST - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +/* File: arm64/op_sput.S */ +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutObj + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSPutObj + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + /* ------------------------------ */ .balign 128 .L_op_sput_boolean: /* 0x6a */ /* File: arm64/op_sput_boolean.S */ /* File: arm64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - EXPORT_PC - FETCH w0, 1 // r0<- field ref BBBB - lsr w3, wINST, #8 // r3<- AA - GET_VREG w1, w3 // r1<= fp[AA] - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl MterpSPutU8 - cbnz w0, MterpException // 0 on success - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutU8 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSPutU8 + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2874,24 +2751,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_byte: /* 0x6b */ /* File: arm64/op_sput_byte.S */ /* File: arm64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - EXPORT_PC - FETCH w0, 1 // r0<- field ref BBBB - lsr w3, wINST, #8 // r3<- AA - GET_VREG w1, w3 // r1<= fp[AA] - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl MterpSPutI8 - cbnz w0, MterpException // 0 on success - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutI8 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSPutI8 + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2899,24 +2774,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_char: /* 0x6c */ /* File: arm64/op_sput_char.S */ /* File: arm64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - EXPORT_PC - FETCH w0, 1 // r0<- field ref BBBB - lsr w3, wINST, #8 // r3<- AA - GET_VREG w1, w3 // r1<= fp[AA] - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl MterpSPutU16 - cbnz w0, MterpException // 0 on success - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutU16 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSPutU16 + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ @@ -2924,24 +2797,22 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_short: /* 0x6d */ /* File: arm64/op_sput_short.S */ /* File: arm64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - EXPORT_PC - FETCH w0, 1 // r0<- field ref BBBB - lsr w3, wINST, #8 // r3<- AA - GET_VREG w1, w3 // r1<= fp[AA] - ldr x2, [xFP, #OFF_FP_METHOD] - mov x3, xSELF - PREFETCH_INST 2 // Get next inst, but don't advance rPC - bl MterpSPutI16 - cbnz w0, MterpException // 0 on success - ADVANCE 2 // Past exception point - now advance rPC - GET_INST_OPCODE ip // extract opcode from rINST - GOTO_OPCODE ip // jump to next instruction +/* File: arm64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutI16 + mov x0, xPC // arg0: Instruction* inst + mov x1, xINST // arg1: uint16_t inst_data + add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf + mov x3, xSELF // arg3: Thread* self + PREFETCH_INST 2 // prefetch next opcode + bl MterpSPutI16 + cbz x0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + /* ------------------------------ */ diff --git a/runtime/interpreter/mterp/out/mterp_mips.S b/runtime/interpreter/mterp/out/mterp_mips.S index fb7d52eed4..1f5bea0873 100644 --- a/runtime/interpreter/mterp/out/mterp_mips.S +++ b/runtime/interpreter/mterp/out/mterp_mips.S @@ -2665,85 +2665,28 @@ artMterpAsmInstructionStart = .L_op_nop .balign 128 .L_op_iget: /* 0x52 */ /* File: mips/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetU32) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - .if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[A] <- v0 - .else - SET_VREG_GOTO(v0, a2, t0) # fp[A] <- v0 - .endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_iget_wide: /* 0x53 */ /* File: mips/op_iget_wide.S */ - /* - * 64-bit instance field get. - * - * for: iget-wide - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field byte offset - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetU64) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - SET_VREG64_GOTO(v0, v1, a2, t0) # fp[A] <- v0/v1 +/* File: mips/op_iget.S */ +/* File: mips/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_iget_object: /* 0x54 */ /* File: mips/op_iget_object.S */ /* File: mips/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetObj) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - .if 1 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[A] <- v0 - .else - SET_VREG_GOTO(v0, a2, t0) # fp[A] <- v0 - .endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -2751,30 +2694,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_boolean: /* 0x55 */ /* File: mips/op_iget_boolean.S */ /* File: mips/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetU8) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - .if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[A] <- v0 - .else - SET_VREG_GOTO(v0, a2, t0) # fp[A] <- v0 - .endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -2782,30 +2704,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_byte: /* 0x56 */ /* File: mips/op_iget_byte.S */ /* File: mips/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetI8) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - .if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[A] <- v0 - .else - SET_VREG_GOTO(v0, a2, t0) # fp[A] <- v0 - .endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -2813,30 +2714,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_char: /* 0x57 */ /* File: mips/op_iget_char.S */ /* File: mips/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetU16) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - .if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[A] <- v0 - .else - SET_VREG_GOTO(v0, a2, t0) # fp[A] <- v0 - .endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -2844,123 +2724,47 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_short: /* 0x58 */ /* File: mips/op_iget_short.S */ /* File: mips/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - JAL(MterpIGetI16) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA4(a2) # a2<- A+ - PREFETCH_INST(2) # load rINST - bnez a3, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - .if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[A] <- v0 - .else - SET_VREG_GOTO(v0, a2, t0) # fp[A] <- v0 - .endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_iput: /* 0x59 */ /* File: mips/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern MterpIPutU32 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - GET_VREG(a2, a2) # a2 <- fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL(MterpIPutU32) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_iput_wide: /* 0x5a */ /* File: mips/op_iput_wide.S */ - /* iput-wide vA, vB, field@CCCC */ - .extern MterpIPutU64 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - EAS2(a2, rFP, a2) # a2 <- &fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL(MterpIPutU64) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/op_iput.S */ +/* File: mips/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_iput_object: /* 0x5b */ /* File: mips/op_iput_object.S */ - /* - * 32-bit instance field put. - * - * for: iput-object, iput-object-volatile - */ - /* op vA, vB, field@CCCC */ - EXPORT_PC() - addu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - JAL(MterpIPutObj) - beqz v0, MterpException - FETCH_ADVANCE_INST(2) # advance rPC, load rINST - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/op_iput.S */ +/* File: mips/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_iput_boolean: /* 0x5c */ /* File: mips/op_iput_boolean.S */ /* File: mips/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern MterpIPutU8 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - GET_VREG(a2, a2) # a2 <- fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL(MterpIPutU8) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -2968,26 +2772,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_byte: /* 0x5d */ /* File: mips/op_iput_byte.S */ /* File: mips/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern MterpIPutI8 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - GET_VREG(a2, a2) # a2 <- fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL(MterpIPutI8) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -2995,26 +2782,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_char: /* 0x5e */ /* File: mips/op_iput_char.S */ /* File: mips/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern MterpIPutU16 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - GET_VREG(a2, a2) # a2 <- fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL(MterpIPutU16) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3022,105 +2792,37 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_short: /* 0x5f */ /* File: mips/op_iput_short.S */ /* File: mips/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern MterpIPutI16 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPB(a1) # a1 <- B - GET_VREG(a1, a1) # a1 <- fp[B], the object pointer - GET_OPA4(a2) # a2 <- A+ - GET_VREG(a2, a2) # a2 <- fp[A] - lw a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST(2) # load rINST - JAL(MterpIPutI16) - bnez v0, MterpPossibleException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sget: /* 0x60 */ /* File: mips/op_sget.S */ - /* - * General SGET handler. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern MterpSGetU32 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetU32) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA(a2) # a2 <- AA - PREFETCH_INST(2) - bnez a3, MterpException # bail out - ADVANCE(2) - GET_INST_OPCODE(t0) # extract opcode from rINST -.if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[AA] <- v0 -.else - SET_VREG_GOTO(v0, a2, t0) # fp[AA] <- v0 -.endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sget_wide: /* 0x61 */ /* File: mips/op_sget_wide.S */ - /* - * 64-bit SGET handler. - */ - /* sget-wide vAA, field@BBBB */ - .extern MterpSGetU64 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetU64) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - bnez a3, MterpException - GET_OPA(a1) # a1 <- AA - FETCH_ADVANCE_INST(2) # advance rPC, load rINST - GET_INST_OPCODE(t0) # extract opcode from rINST - SET_VREG64_GOTO(v0, v1, a1, t0) # vAA/vAA+1 <- v0/v1 +/* File: mips/op_sget.S */ +/* File: mips/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_sget_object: /* 0x62 */ /* File: mips/op_sget_object.S */ /* File: mips/op_sget.S */ - /* - * General SGET handler. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern MterpSGetObj - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetObj) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA(a2) # a2 <- AA - PREFETCH_INST(2) - bnez a3, MterpException # bail out - ADVANCE(2) - GET_INST_OPCODE(t0) # extract opcode from rINST -.if 1 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[AA] <- v0 -.else - SET_VREG_GOTO(v0, a2, t0) # fp[AA] <- v0 -.endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3128,29 +2830,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_boolean: /* 0x63 */ /* File: mips/op_sget_boolean.S */ /* File: mips/op_sget.S */ - /* - * General SGET handler. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern MterpSGetU8 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetU8) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA(a2) # a2 <- AA - PREFETCH_INST(2) - bnez a3, MterpException # bail out - ADVANCE(2) - GET_INST_OPCODE(t0) # extract opcode from rINST -.if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[AA] <- v0 -.else - SET_VREG_GOTO(v0, a2, t0) # fp[AA] <- v0 -.endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3158,29 +2840,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_byte: /* 0x64 */ /* File: mips/op_sget_byte.S */ /* File: mips/op_sget.S */ - /* - * General SGET handler. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern MterpSGetI8 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetI8) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA(a2) # a2 <- AA - PREFETCH_INST(2) - bnez a3, MterpException # bail out - ADVANCE(2) - GET_INST_OPCODE(t0) # extract opcode from rINST -.if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[AA] <- v0 -.else - SET_VREG_GOTO(v0, a2, t0) # fp[AA] <- v0 -.endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3188,29 +2850,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_char: /* 0x65 */ /* File: mips/op_sget_char.S */ /* File: mips/op_sget.S */ - /* - * General SGET handler. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern MterpSGetU16 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetU16) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA(a2) # a2 <- AA - PREFETCH_INST(2) - bnez a3, MterpException # bail out - ADVANCE(2) - GET_INST_OPCODE(t0) # extract opcode from rINST -.if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[AA] <- v0 -.else - SET_VREG_GOTO(v0, a2, t0) # fp[AA] <- v0 -.endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3218,120 +2860,47 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_short: /* 0x66 */ /* File: mips/op_sget_short.S */ /* File: mips/op_sget.S */ - /* - * General SGET handler. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern MterpSGetI16 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - lw a1, OFF_FP_METHOD(rFP) # a1 <- method - move a2, rSELF # a2 <- self - JAL(MterpSGetI16) - lw a3, THREAD_EXCEPTION_OFFSET(rSELF) - GET_OPA(a2) # a2 <- AA - PREFETCH_INST(2) - bnez a3, MterpException # bail out - ADVANCE(2) - GET_INST_OPCODE(t0) # extract opcode from rINST -.if 0 - SET_VREG_OBJECT_GOTO(v0, a2, t0) # fp[AA] <- v0 -.else - SET_VREG_GOTO(v0, a2, t0) # fp[AA] <- v0 -.endif +/* File: mips/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sput: /* 0x67 */ /* File: mips/op_sput.S */ - /* - * General SPUT handler. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - GET_OPA(a3) # a3 <- AA - GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL(MterpSPutU32) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sput_wide: /* 0x68 */ /* File: mips/op_sput_wide.S */ - /* - * 64-bit SPUT handler. - */ - /* sput-wide vAA, field@BBBB */ - .extern MterpSPutU64 - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref CCCC - GET_OPA(a1) # a1 <- AA - EAS2(a1, rFP, a1) # a1 <- &fp[AA] - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL(MterpSPutU64) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/op_sput.S */ +/* File: mips/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_sput_object: /* 0x69 */ /* File: mips/op_sput_object.S */ - /* - * General 32-bit SPUT handler. - * - * for: sput-object, - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - addu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - JAL(MterpSPutObj) - beqz v0, MterpException - FETCH_ADVANCE_INST(2) # advance rPC, load rINST - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/op_sput.S */ +/* File: mips/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_sput_boolean: /* 0x6a */ /* File: mips/op_sput_boolean.S */ /* File: mips/op_sput.S */ - /* - * General SPUT handler. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - GET_OPA(a3) # a3 <- AA - GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL(MterpSPutU8) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3339,24 +2908,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_byte: /* 0x6b */ /* File: mips/op_sput_byte.S */ /* File: mips/op_sput.S */ - /* - * General SPUT handler. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - GET_OPA(a3) # a3 <- AA - GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL(MterpSPutI8) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3364,24 +2918,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_char: /* 0x6c */ /* File: mips/op_sput_char.S */ /* File: mips/op_sput.S */ - /* - * General SPUT handler. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - GET_OPA(a3) # a3 <- AA - GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL(MterpSPutU16) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ @@ -3389,24 +2928,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_short: /* 0x6d */ /* File: mips/op_sput_short.S */ /* File: mips/op_sput.S */ - /* - * General SPUT handler. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - EXPORT_PC() - FETCH(a0, 1) # a0 <- field ref BBBB - GET_OPA(a3) # a3 <- AA - GET_VREG(a1, a3) # a1 <- fp[AA], the object pointer - lw a2, OFF_FP_METHOD(rFP) # a2 <- method - move a3, rSELF # a3 <- self - PREFETCH_INST(2) # load rINST - JAL(MterpSPutI16) - bnez v0, MterpException # bail out - ADVANCE(2) # advance rPC - GET_INST_OPCODE(t0) # extract opcode from rINST - GOTO_OPCODE(t0) # jump to next instruction +/* File: mips/field.S */ +TODO + /* ------------------------------ */ diff --git a/runtime/interpreter/mterp/out/mterp_mips64.S b/runtime/interpreter/mterp/out/mterp_mips64.S index 65616919c9..40a8396f77 100644 --- a/runtime/interpreter/mterp/out/mterp_mips64.S +++ b/runtime/interpreter/mterp/out/mterp_mips64.S @@ -2241,88 +2241,28 @@ artMterpAsmInstructionStart = .L_op_nop .balign 128 .L_op_iget: /* 0x52 */ /* File: mips64/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - .extern MterpIGetU32 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetU32 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[A] <- v0 - .else - SET_VREG v0, a2 # fp[A] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_iget_wide: /* 0x53 */ /* File: mips64/op_iget_wide.S */ - /* - * 64-bit instance field get. - * - * for: iget-wide - */ - .extern MterpIGetU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetU64 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - SET_VREG_WIDE v0, a2 # fp[A] <- v0 - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/op_iget.S */ +/* File: mips64/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_iget_object: /* 0x54 */ /* File: mips64/op_iget_object.S */ /* File: mips64/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - .extern MterpIGetObj - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetObj - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - .if 1 - SET_VREG_OBJECT v0, a2 # fp[A] <- v0 - .else - SET_VREG v0, a2 # fp[A] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2330,31 +2270,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_boolean: /* 0x55 */ /* File: mips64/op_iget_boolean.S */ /* File: mips64/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - .extern MterpIGetU8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetU8 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[A] <- v0 - .else - SET_VREG v0, a2 # fp[A] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2362,31 +2280,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_byte: /* 0x56 */ /* File: mips64/op_iget_byte.S */ /* File: mips64/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - .extern MterpIGetI8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetI8 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[A] <- v0 - .else - SET_VREG v0, a2 # fp[A] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2394,31 +2290,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_char: /* 0x57 */ /* File: mips64/op_iget_char.S */ /* File: mips64/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - .extern MterpIGetU16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetU16 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[A] <- v0 - .else - SET_VREG v0, a2 # fp[A] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2426,119 +2300,47 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iget_short: /* 0x58 */ /* File: mips64/op_iget_short.S */ /* File: mips64/op_iget.S */ - /* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - .extern MterpIGetI16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ld a2, OFF_FP_METHOD(rFP) # a2 <- referrer - move a3, rSELF # a3 <- self - jal MterpIGetI16 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - ext a2, rINST, 8, 4 # a2 <- A - PREFETCH_INST 2 - bnez a3, MterpPossibleException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[A] <- v0 - .else - SET_VREG v0, a2 # fp[A] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_iput: /* 0x59 */ /* File: mips64/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field//CCCC */ - .extern MterpIPutU32 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - GET_VREG a2, a2 # a2 <- fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal MterpIPutU32 - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_iput_wide: /* 0x5a */ /* File: mips64/op_iput_wide.S */ - /* iput-wide vA, vB, field//CCCC */ - .extern MterpIPutU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - dlsa a2, a2, rFP, 2 # a2 <- &fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal MterpIPutU64 - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/op_iput.S */ +/* File: mips64/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_iput_object: /* 0x5b */ /* File: mips64/op_iput_object.S */ - .extern MterpIPutObj - EXPORT_PC - daddu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - jal MterpIPutObj - beqzc v0, MterpException - FETCH_ADVANCE_INST 2 # advance rPC, load rINST - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/op_iput.S */ +/* File: mips64/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_iput_boolean: /* 0x5c */ /* File: mips64/op_iput_boolean.S */ /* File: mips64/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field//CCCC */ - .extern MterpIPutU8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - GET_VREG a2, a2 # a2 <- fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal MterpIPutU8 - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2546,26 +2348,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_byte: /* 0x5d */ /* File: mips64/op_iput_byte.S */ /* File: mips64/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field//CCCC */ - .extern MterpIPutI8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - GET_VREG a2, a2 # a2 <- fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal MterpIPutI8 - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2573,26 +2358,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_char: /* 0x5e */ /* File: mips64/op_iput_char.S */ /* File: mips64/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field//CCCC */ - .extern MterpIPutU16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - GET_VREG a2, a2 # a2 <- fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal MterpIPutU16 - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2600,111 +2368,37 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_iput_short: /* 0x5f */ /* File: mips64/op_iput_short.S */ /* File: mips64/op_iput.S */ - /* - * General 32-bit instance field put. - * - * for: iput, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field//CCCC */ - .extern MterpIPutI16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref CCCC - srl a1, rINST, 12 # a1 <- B - GET_VREG_U a1, a1 # a1 <- fp[B], the object pointer - ext a2, rINST, 8, 4 # a2 <- A - GET_VREG a2, a2 # a2 <- fp[A] - ld a3, OFF_FP_METHOD(rFP) # a3 <- referrer - PREFETCH_INST 2 - jal MterpIPutI16 - bnez v0, MterpPossibleException # bail out - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sget: /* 0x60 */ /* File: mips64/op_sget.S */ - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - .extern MterpSGetU32 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetU32 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a2, rINST, 8 # a2 <- AA - - PREFETCH_INST 2 - bnez a3, MterpException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[AA] <- v0 - .else - SET_VREG v0, a2 # fp[AA] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sget_wide: /* 0x61 */ /* File: mips64/op_sget_wide.S */ - /* - * SGET_WIDE handler wrapper. - * - */ - /* sget-wide vAA, field//BBBB */ - .extern MterpSGetU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetU64 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a4, rINST, 8 # a4 <- AA - bnez a3, MterpException # bail out - FETCH_ADVANCE_INST 2 # advance rPC, load rINST - SET_VREG_WIDE v0, a4 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/op_sget.S */ +/* File: mips64/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_sget_object: /* 0x62 */ /* File: mips64/op_sget_object.S */ /* File: mips64/op_sget.S */ - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - .extern MterpSGetObj - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetObj - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a2, rINST, 8 # a2 <- AA - - PREFETCH_INST 2 - bnez a3, MterpException # bail out - .if 1 - SET_VREG_OBJECT v0, a2 # fp[AA] <- v0 - .else - SET_VREG v0, a2 # fp[AA] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2712,31 +2406,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_boolean: /* 0x63 */ /* File: mips64/op_sget_boolean.S */ /* File: mips64/op_sget.S */ - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - .extern MterpSGetU8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetU8 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a2, rINST, 8 # a2 <- AA - and v0, v0, 0xff - PREFETCH_INST 2 - bnez a3, MterpException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[AA] <- v0 - .else - SET_VREG v0, a2 # fp[AA] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2744,31 +2416,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_byte: /* 0x64 */ /* File: mips64/op_sget_byte.S */ /* File: mips64/op_sget.S */ - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - .extern MterpSGetI8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetI8 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a2, rINST, 8 # a2 <- AA - seb v0, v0 - PREFETCH_INST 2 - bnez a3, MterpException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[AA] <- v0 - .else - SET_VREG v0, a2 # fp[AA] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2776,31 +2426,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_char: /* 0x65 */ /* File: mips64/op_sget_char.S */ /* File: mips64/op_sget.S */ - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - .extern MterpSGetU16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetU16 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a2, rINST, 8 # a2 <- AA - and v0, v0, 0xffff - PREFETCH_INST 2 - bnez a3, MterpException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[AA] <- v0 - .else - SET_VREG v0, a2 # fp[AA] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2808,120 +2436,47 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sget_short: /* 0x66 */ /* File: mips64/op_sget_short.S */ /* File: mips64/op_sget.S */ - /* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field//BBBB */ - .extern MterpSGetI16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - ld a1, OFF_FP_METHOD(rFP) - move a2, rSELF - jal MterpSGetI16 - ld a3, THREAD_EXCEPTION_OFFSET(rSELF) - srl a2, rINST, 8 # a2 <- AA - seh v0, v0 - PREFETCH_INST 2 - bnez a3, MterpException # bail out - .if 0 - SET_VREG_OBJECT v0, a2 # fp[AA] <- v0 - .else - SET_VREG v0, a2 # fp[AA] <- v0 - .endif - ADVANCE 2 - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sput: /* 0x67 */ /* File: mips64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - .extern MterpSPutU32 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a3, rINST, 8 # a3 <- AA - GET_VREG a1, a3 # a1 <- fp[AA] - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal MterpSPutU32 - bnezc v0, MterpException # 0 on success - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ .balign 128 .L_op_sput_wide: /* 0x68 */ /* File: mips64/op_sput_wide.S */ - /* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field//BBBB */ - .extern MterpSPutU64 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a1, rINST, 8 # a2 <- AA - dlsa a1, a1, rFP, 2 - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal MterpSPutU64 - bnezc v0, MterpException # 0 on success, -1 on failure - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/op_sput.S */ +/* File: mips64/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_sput_object: /* 0x69 */ /* File: mips64/op_sput_object.S */ - .extern MterpSPutObj - EXPORT_PC - daddu a0, rFP, OFF_FP_SHADOWFRAME - move a1, rPC - move a2, rINST - move a3, rSELF - jal MterpSPutObj - beqzc v0, MterpException - FETCH_ADVANCE_INST 2 # advance rPC, load rINST - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/op_sput.S */ +/* File: mips64/field.S */ +TODO + + /* ------------------------------ */ .balign 128 .L_op_sput_boolean: /* 0x6a */ /* File: mips64/op_sput_boolean.S */ /* File: mips64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - .extern MterpSPutU8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a3, rINST, 8 # a3 <- AA - GET_VREG a1, a3 # a1 <- fp[AA] - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal MterpSPutU8 - bnezc v0, MterpException # 0 on success - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2929,25 +2484,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_byte: /* 0x6b */ /* File: mips64/op_sput_byte.S */ /* File: mips64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - .extern MterpSPutI8 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a3, rINST, 8 # a3 <- AA - GET_VREG a1, a3 # a1 <- fp[AA] - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal MterpSPutI8 - bnezc v0, MterpException # 0 on success - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2955,25 +2494,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_char: /* 0x6c */ /* File: mips64/op_sput_char.S */ /* File: mips64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - .extern MterpSPutU16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a3, rINST, 8 # a3 <- AA - GET_VREG a1, a3 # a1 <- fp[AA] - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal MterpSPutU16 - bnezc v0, MterpException # 0 on success - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ @@ -2981,25 +2504,9 @@ artMterpAsmInstructionStart = .L_op_nop .L_op_sput_short: /* 0x6d */ /* File: mips64/op_sput_short.S */ /* File: mips64/op_sput.S */ - /* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field//BBBB */ - .extern MterpSPutI16 - EXPORT_PC - lhu a0, 2(rPC) # a0 <- field ref BBBB - srl a3, rINST, 8 # a3 <- AA - GET_VREG a1, a3 # a1 <- fp[AA] - ld a2, OFF_FP_METHOD(rFP) - move a3, rSELF - PREFETCH_INST 2 # Get next inst, but don't advance rPC - jal MterpSPutI16 - bnezc v0, MterpException # 0 on success - ADVANCE 2 # Past exception point - now advance rPC - GET_INST_OPCODE v0 # extract opcode from rINST - GOTO_OPCODE v0 # jump to next instruction +/* File: mips64/field.S */ +TODO + /* ------------------------------ */ diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S index 3f709199b9..32811ff370 100644 --- a/runtime/interpreter/mterp/out/mterp_x86.S +++ b/runtime/interpreter/mterp/out/mterp_x86.S @@ -2120,832 +2120,694 @@ SYMBOL(artMterpAsmInstructionStart) = .L_op_nop .balign 128 .L_op_iget: /* 0x52 */ /* File: x86/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU32 + REFRESH_INST 82 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIGetU32) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <-value - .else - SET_VREG %eax, rINST # fp[A] <-value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_wide: /* 0x53 */ /* File: x86/op_iget_wide.S */ -/* - * 64-bit instance field get. - * - * for: iget-wide - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self +/* File: x86/op_iget.S */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU64 + REFRESH_INST 83 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIGetU64) - mov rSELF, %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - SET_VREG %eax, rINST - SET_VREG_HIGH %edx, rINST - RESTORE_IBASE_FROM_SELF %ecx + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_iget_object: /* 0x54 */ /* File: x86/op_iget_object.S */ /* File: x86/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetObj + REFRESH_INST 84 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIGetObj) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 1 - SET_VREG_OBJECT %eax, rINST # fp[A] <-value - .else - SET_VREG %eax, rINST # fp[A] <-value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_boolean: /* 0x55 */ /* File: x86/op_iget_boolean.S */ /* File: x86/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU8 + REFRESH_INST 85 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIGetU8) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <-value - .else - SET_VREG %eax, rINST # fp[A] <-value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_byte: /* 0x56 */ /* File: x86/op_iget_byte.S */ /* File: x86/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetI8 + REFRESH_INST 86 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIGetI8) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <-value - .else - SET_VREG %eax, rINST # fp[A] <-value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_char: /* 0x57 */ /* File: x86/op_iget_char.S */ /* File: x86/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU16 + REFRESH_INST 87 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIGetU16) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <-value - .else - SET_VREG %eax, rINST # fp[A] <-value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_short: /* 0x58 */ /* File: x86/op_iget_short.S */ /* File: x86/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetI16 + REFRESH_INST 88 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIGetI16) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <-value - .else - SET_VREG %eax, rINST # fp[A] <-value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput: /* 0x59 */ /* File: x86/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU32 - EXPORT_PC - movzwl 2(rPC), %eax # eax<- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG %eax, rINST - movl %eax, OUT_ARG2(%esp) # fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer + REFRESH_INST 89 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIPutU32) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_wide: /* 0x5a */ /* File: x86/op_iput_wide.S */ - /* iput-wide vA, vB, field@CCCC */ +/* File: x86/op_iput.S */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU64 - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl,%ecx # ecx <- BA - sarl $4,%ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $0xf,rINSTbl # rINST <- A - leal VREG_ADDRESS(rINST), %eax - movl %eax, OUT_ARG2(%esp) # &fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer + REFRESH_INST 90 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIPutU64) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_iput_object: /* 0x5b */ /* File: x86/op_iput_object.S */ - EXPORT_PC +/* File: x86/op_iput.S */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIPutObj + REFRESH_INST 91 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data leal OFF_FP_SHADOWFRAME(rFP), %eax - movl %eax, OUT_ARG0(%esp) - movl rPC, OUT_ARG1(%esp) - REFRESH_INST 91 - movl rINST, OUT_ARG2(%esp) + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf movl rSELF, %eax - movl %eax, OUT_ARG3(%esp) + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIPutObj) testb %al, %al - jz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_iput_boolean: /* 0x5c */ /* File: x86/op_iput_boolean.S */ /* File: x86/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU8 - EXPORT_PC - movzwl 2(rPC), %eax # eax<- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG %eax, rINST - movl %eax, OUT_ARG2(%esp) # fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer + REFRESH_INST 92 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIPutU8) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_byte: /* 0x5d */ /* File: x86/op_iput_byte.S */ /* File: x86/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutI8 - EXPORT_PC - movzwl 2(rPC), %eax # eax<- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG %eax, rINST - movl %eax, OUT_ARG2(%esp) # fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer + REFRESH_INST 93 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIPutI8) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_char: /* 0x5e */ /* File: x86/op_iput_char.S */ /* File: x86/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU16 - EXPORT_PC - movzwl 2(rPC), %eax # eax<- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG %eax, rINST - movl %eax, OUT_ARG2(%esp) # fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer + REFRESH_INST 94 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIPutU16) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_short: /* 0x5f */ /* File: x86/op_iput_short.S */ /* File: x86/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutI16 - EXPORT_PC - movzwl 2(rPC), %eax # eax<- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG %eax, rINST - movl %eax, OUT_ARG2(%esp) # fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer + REFRESH_INST 95 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpIPutI16) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget: /* 0x60 */ /* File: x86/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU32 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self + REFRESH_INST 96 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSGetU32) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <- value - .else - SET_VREG %eax, rINST # fp[A] <- value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_wide: /* 0x61 */ /* File: x86/op_sget_wide.S */ -/* - * SGET_WIDE handler wrapper. - * - */ - /* sget-wide vAA, field@BBBB */ +/* File: x86/op_sget.S */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU64 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self + REFRESH_INST 97 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSGetU64) - movl rSELF, %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - SET_VREG %eax, rINST # fp[A]<- low part - SET_VREG_HIGH %edx, rINST # fp[A+1]<- high part - RESTORE_IBASE_FROM_SELF %ecx + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_sget_object: /* 0x62 */ /* File: x86/op_sget_object.S */ /* File: x86/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetObj - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self + REFRESH_INST 98 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSGetObj) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - .if 1 - SET_VREG_OBJECT %eax, rINST # fp[A] <- value - .else - SET_VREG %eax, rINST # fp[A] <- value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_boolean: /* 0x63 */ /* File: x86/op_sget_boolean.S */ /* File: x86/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU8 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self + REFRESH_INST 99 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSGetU8) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <- value - .else - SET_VREG %eax, rINST # fp[A] <- value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_byte: /* 0x64 */ /* File: x86/op_sget_byte.S */ /* File: x86/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetI8 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self + REFRESH_INST 100 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSGetI8) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <- value - .else - SET_VREG %eax, rINST # fp[A] <- value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_char: /* 0x65 */ /* File: x86/op_sget_char.S */ /* File: x86/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU16 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self + REFRESH_INST 101 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSGetU16) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <- value - .else - SET_VREG %eax, rINST # fp[A] <- value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_short: /* 0x66 */ /* File: x86/op_sget_short.S */ /* File: x86/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetI16 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self + REFRESH_INST 102 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSGetI16) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINST # fp[A] <- value - .else - SET_VREG %eax, rINST # fp[A] <- value - .endif + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput: /* 0x67 */ /* File: x86/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU32 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - GET_VREG rINST, rINST - movl rINST, OUT_ARG1(%esp) # fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self + REFRESH_INST 103 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSPutU32) testb %al, %al - jnz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_wide: /* 0x68 */ /* File: x86/op_sput_wide.S */ -/* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field@BBBB */ +/* File: x86/op_sput.S */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU64 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - leal VREG_ADDRESS(rINST), %eax - movl %eax, OUT_ARG1(%esp) # &fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self + REFRESH_INST 104 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSPutU64) testb %al, %al - jnz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_sput_object: /* 0x69 */ /* File: x86/op_sput_object.S */ - EXPORT_PC +/* File: x86/op_sput.S */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutObj + REFRESH_INST 105 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data leal OFF_FP_SHADOWFRAME(rFP), %eax - movl %eax, OUT_ARG0(%esp) - movl rPC, OUT_ARG1(%esp) - REFRESH_INST 105 - movl rINST, OUT_ARG2(%esp) - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSPutObj) testb %al, %al - jz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_sput_boolean: /* 0x6a */ /* File: x86/op_sput_boolean.S */ /* File: x86/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU8 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - GET_VREG rINST, rINST - movl rINST, OUT_ARG1(%esp) # fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self + REFRESH_INST 106 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSPutU8) testb %al, %al - jnz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_byte: /* 0x6b */ /* File: x86/op_sput_byte.S */ /* File: x86/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutI8 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - GET_VREG rINST, rINST - movl rINST, OUT_ARG1(%esp) # fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self + REFRESH_INST 107 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSPutI8) testb %al, %al - jnz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_char: /* 0x6c */ /* File: x86/op_sput_char.S */ /* File: x86/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU16 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - GET_VREG rINST, rINST - movl rINST, OUT_ARG1(%esp) # fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self + REFRESH_INST 108 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSPutU16) testb %al, %al - jnz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_short: /* 0x6d */ /* File: x86/op_sput_short.S */ /* File: x86/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutI16 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - GET_VREG rINST, rINST - movl rINST, OUT_ARG1(%esp) # fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self + REFRESH_INST 109 # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self call SYMBOL(MterpSPutI16) testb %al, %al - jnz MterpException + jz MterpPossibleException RESTORE_IBASE ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_invoke_virtual: /* 0x6e */ diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S index 89d56372af..6d8bb4c7c4 100644 --- a/runtime/interpreter/mterp/out/mterp_x86_64.S +++ b/runtime/interpreter/mterp/out/mterp_x86_64.S @@ -2067,770 +2067,610 @@ SYMBOL(artMterpAsmInstructionStart) = .L_op_nop .balign 128 .L_op_iget: /* 0x52 */ /* File: x86_64/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU32 + REFRESH_INST 82 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIGetU32) - movq rSELF, %rcx - cmpq $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_wide: /* 0x53 */ /* File: x86_64/op_iget_wide.S */ /* File: x86_64/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU64 + REFRESH_INST 83 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIGetU64) - movq rSELF, %rcx - cmpq $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if 1 - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_object: /* 0x54 */ /* File: x86_64/op_iget_object.S */ /* File: x86_64/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetObj + REFRESH_INST 84 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIGetObj) - movq rSELF, %rcx - cmpq $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 1 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_boolean: /* 0x55 */ /* File: x86_64/op_iget_boolean.S */ /* File: x86_64/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU8 + REFRESH_INST 85 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIGetU8) - movq rSELF, %rcx - cmpq $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_byte: /* 0x56 */ /* File: x86_64/op_iget_byte.S */ /* File: x86_64/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetI8 + REFRESH_INST 86 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIGetI8) - movq rSELF, %rcx - cmpq $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_char: /* 0x57 */ /* File: x86_64/op_iget_char.S */ /* File: x86_64/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetU16 + REFRESH_INST 87 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIGetU16) - movq rSELF, %rcx - cmpq $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iget_short: /* 0x58 */ /* File: x86_64/op_iget_short.S */ /* File: x86_64/op_iget.S */ -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIGetI16 + REFRESH_INST 88 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIGetI16) - movq rSELF, %rcx - cmpq $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $0xf, rINSTbl # rINST <- A - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput: /* 0x59 */ /* File: x86_64/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU32 - EXPORT_PC - movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC - movzbq rINSTbl, %rcx # rcx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG OUT_32_ARG2, rINSTq # fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer + REFRESH_INST 89 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIPutU32) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_wide: /* 0x5a */ /* File: x86_64/op_iput_wide.S */ - /* iput-wide vA, vB, field@CCCC */ +/* File: x86_64/op_iput.S */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU64 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movzbq rINSTbl, %rcx # rcx <- BA - sarl $4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $0xf, rINSTbl # rINST <- A - leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer + REFRESH_INST 90 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIPutU64) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_iput_object: /* 0x5b */ /* File: x86_64/op_iput_object.S */ - EXPORT_PC - leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0 - movq rPC, OUT_ARG1 - REFRESH_INST 91 - movl rINST, OUT_32_ARG2 - movq rSELF, OUT_ARG3 +/* File: x86_64/op_iput.S */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpIPutObj + REFRESH_INST 91 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIPutObj) testb %al, %al - jz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_iput_boolean: /* 0x5c */ /* File: x86_64/op_iput_boolean.S */ /* File: x86_64/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU8 - EXPORT_PC - movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC - movzbq rINSTbl, %rcx # rcx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG OUT_32_ARG2, rINSTq # fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer + REFRESH_INST 92 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIPutU8) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_byte: /* 0x5d */ /* File: x86_64/op_iput_byte.S */ /* File: x86_64/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutI8 - EXPORT_PC - movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC - movzbq rINSTbl, %rcx # rcx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG OUT_32_ARG2, rINSTq # fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer + REFRESH_INST 93 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIPutI8) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_char: /* 0x5e */ /* File: x86_64/op_iput_char.S */ /* File: x86_64/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutU16 - EXPORT_PC - movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC - movzbq rINSTbl, %rcx # rcx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG OUT_32_ARG2, rINSTq # fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer + REFRESH_INST 94 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIPutU16) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_iput_short: /* 0x5f */ /* File: x86_64/op_iput_short.S */ /* File: x86_64/op_iput.S */ -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpIPutI16 - EXPORT_PC - movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC - movzbq rINSTbl, %rcx # rcx<- BA - sarl $4, %ecx # ecx<- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $0xf, rINSTbl # rINST<- A - GET_VREG OUT_32_ARG2, rINSTq # fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer + REFRESH_INST 95 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpIPutI16) testb %al, %al - jnz MterpPossibleException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget: /* 0x60 */ /* File: x86_64/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU32 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self + REFRESH_INST 96 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSGetU32) - movq rSELF, %rcx - cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_wide: /* 0x61 */ /* File: x86_64/op_sget_wide.S */ /* File: x86_64/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU64 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self + REFRESH_INST 97 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSGetU64) - movq rSELF, %rcx - cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if 1 - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_object: /* 0x62 */ /* File: x86_64/op_sget_object.S */ /* File: x86_64/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetObj - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self + REFRESH_INST 98 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSGetObj) - movq rSELF, %rcx - cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if 1 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_boolean: /* 0x63 */ /* File: x86_64/op_sget_boolean.S */ /* File: x86_64/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU8 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self + REFRESH_INST 99 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSGetU8) - movq rSELF, %rcx - cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_byte: /* 0x64 */ /* File: x86_64/op_sget_byte.S */ /* File: x86_64/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetI8 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self + REFRESH_INST 100 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSGetI8) - movq rSELF, %rcx - cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_char: /* 0x65 */ /* File: x86_64/op_sget_char.S */ /* File: x86_64/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetU16 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self + REFRESH_INST 101 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSGetU16) - movq rSELF, %rcx - cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sget_short: /* 0x66 */ /* File: x86_64/op_sget_short.S */ /* File: x86_64/op_sget.S */ -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSGetI16 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self + REFRESH_INST 102 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSGetI16) - movq rSELF, %rcx - cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if 0 - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if 0 - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif + testb %al, %al + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput: /* 0x67 */ /* File: x86_64/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU32 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - GET_VREG OUT_32_ARG1, rINSTq # fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self + REFRESH_INST 103 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSPutU32) testb %al, %al - jnz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_wide: /* 0x68 */ /* File: x86_64/op_sput_wide.S */ -/* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field@BBBB */ +/* File: x86_64/op_sput.S */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU64 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - leaq VREG_ADDRESS(rINSTq), OUT_ARG1 # &fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self + REFRESH_INST 104 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSPutU64) testb %al, %al - jnz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_sput_object: /* 0x69 */ /* File: x86_64/op_sput_object.S */ - EXPORT_PC - leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0 - movq rPC, OUT_ARG1 - REFRESH_INST 105 - movq rINSTq, OUT_ARG2 - movq rSELF, OUT_ARG3 +/* File: x86_64/op_sput.S */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern MterpSPutObj + REFRESH_INST 105 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSPutObj) testb %al, %al - jz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + + /* ------------------------------ */ .balign 128 .L_op_sput_boolean: /* 0x6a */ /* File: x86_64/op_sput_boolean.S */ /* File: x86_64/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU8 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - GET_VREG OUT_32_ARG1, rINSTq # fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self + REFRESH_INST 106 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSPutU8) testb %al, %al - jnz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_byte: /* 0x6b */ /* File: x86_64/op_sput_byte.S */ /* File: x86_64/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutI8 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - GET_VREG OUT_32_ARG1, rINSTq # fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self + REFRESH_INST 107 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSPutI8) testb %al, %al - jnz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_char: /* 0x6c */ /* File: x86_64/op_sput_char.S */ /* File: x86_64/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutU16 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - GET_VREG OUT_32_ARG1, rINSTq # fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self + REFRESH_INST 108 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSPutU16) testb %al, %al - jnz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_sput_short: /* 0x6d */ /* File: x86_64/op_sput_short.S */ /* File: x86_64/op_sput.S */ -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ +/* File: x86_64/field.S */ + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ .extern MterpSPutI16 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - GET_VREG OUT_32_ARG1, rINSTq # fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self + REFRESH_INST 109 # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self call SYMBOL(MterpSPutI16) testb %al, %al - jnz MterpException + jz MterpPossibleException ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 + /* ------------------------------ */ .balign 128 .L_op_invoke_virtual: /* 0x6e */ diff --git a/runtime/interpreter/mterp/x86/field.S b/runtime/interpreter/mterp/x86/field.S new file mode 100644 index 0000000000..8432c744ea --- /dev/null +++ b/runtime/interpreter/mterp/x86/field.S @@ -0,0 +1,17 @@ +%default { } + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern $helper + REFRESH_INST ${opnum} # fix rINST to include opcode + movl rPC, OUT_ARG0(%esp) # arg0: Instruction* inst + movl rINST, OUT_ARG1(%esp) # arg1: uint16_t inst_data + leal OFF_FP_SHADOWFRAME(rFP), %eax + movl %eax, OUT_ARG2(%esp) # arg2: ShadowFrame* sf + movl rSELF, %eax + movl %eax, OUT_ARG3(%esp) # arg3: Thread* self + call SYMBOL($helper) + testb %al, %al + jz MterpPossibleException + RESTORE_IBASE + ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 diff --git a/runtime/interpreter/mterp/x86/op_iget.S b/runtime/interpreter/mterp/x86/op_iget.S index 0af1becb24..d85d54c515 100644 --- a/runtime/interpreter/mterp/x86/op_iget.S +++ b/runtime/interpreter/mterp/x86/op_iget.S @@ -1,29 +1,2 @@ %default { "is_object":"0", "helper":"MterpIGetU32"} -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $$4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self - call SYMBOL($helper) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $$0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $$0xf, rINSTbl # rINST <- A - .if $is_object - SET_VREG_OBJECT %eax, rINST # fp[A] <-value - .else - SET_VREG %eax, rINST # fp[A] <-value - .endif - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/field.S" { } diff --git a/runtime/interpreter/mterp/x86/op_iget_wide.S b/runtime/interpreter/mterp/x86/op_iget_wide.S index da27df952b..741a64e4cb 100644 --- a/runtime/interpreter/mterp/x86/op_iget_wide.S +++ b/runtime/interpreter/mterp/x86/op_iget_wide.S @@ -1,25 +1 @@ -/* - * 64-bit instance field get. - * - * for: iget-wide - */ - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx <- BA - sarl $$4, %ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - mov rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self - call SYMBOL(MterpIGetU64) - mov rSELF, %ecx - cmpl $$0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException # bail out - andb $$0xf, rINSTbl # rINST <- A - SET_VREG %eax, rINST - SET_VREG_HIGH %edx, rINST - RESTORE_IBASE_FROM_SELF %ecx - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/op_iget.S" { "helper":"MterpIGetU64" } diff --git a/runtime/interpreter/mterp/x86/op_iput.S b/runtime/interpreter/mterp/x86/op_iput.S index 4c6603a572..3628ffdb56 100644 --- a/runtime/interpreter/mterp/x86/op_iput.S +++ b/runtime/interpreter/mterp/x86/op_iput.S @@ -1,25 +1,2 @@ -%default { "helper":"MterpIPutU32" } -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern $helper - EXPORT_PC - movzwl 2(rPC), %eax # eax<- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl, %ecx # ecx<- BA - sarl $$4, %ecx # ecx<- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $$0xf, rINSTbl # rINST<- A - GET_VREG %eax, rINST - movl %eax, OUT_ARG2(%esp) # fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer - call SYMBOL($helper) - testb %al, %al - jnz MterpPossibleException - RESTORE_IBASE - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%default { "is_object":"0", "helper":"MterpIPutU32" } +%include "x86/field.S" { } diff --git a/runtime/interpreter/mterp/x86/op_iput_object.S b/runtime/interpreter/mterp/x86/op_iput_object.S index 56e026e40a..a124b7ed41 100644 --- a/runtime/interpreter/mterp/x86/op_iput_object.S +++ b/runtime/interpreter/mterp/x86/op_iput_object.S @@ -1,13 +1 @@ - EXPORT_PC - leal OFF_FP_SHADOWFRAME(rFP), %eax - movl %eax, OUT_ARG0(%esp) - movl rPC, OUT_ARG1(%esp) - REFRESH_INST ${opnum} - movl rINST, OUT_ARG2(%esp) - movl rSELF, %eax - movl %eax, OUT_ARG3(%esp) - call SYMBOL(MterpIPutObj) - testb %al, %al - jz MterpException - RESTORE_IBASE - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/op_iput.S" { "is_object":"1", "helper":"MterpIPutObj" } diff --git a/runtime/interpreter/mterp/x86/op_iput_wide.S b/runtime/interpreter/mterp/x86/op_iput_wide.S index ea22b919c3..2820ede182 100644 --- a/runtime/interpreter/mterp/x86/op_iput_wide.S +++ b/runtime/interpreter/mterp/x86/op_iput_wide.S @@ -1,19 +1 @@ - /* iput-wide vA, vB, field@CCCC */ - .extern MterpIPutU64 - EXPORT_PC - movzwl 2(rPC), %eax # eax <- 0000CCCC - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movzbl rINSTbl,%ecx # ecx <- BA - sarl $$4,%ecx # ecx <- B - GET_VREG %ecx, %ecx - movl %ecx, OUT_ARG1(%esp) # the object pointer - andb $$0xf,rINSTbl # rINST <- A - leal VREG_ADDRESS(rINST), %eax - movl %eax, OUT_ARG2(%esp) # &fp[A] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG3(%esp) # referrer - call SYMBOL(MterpIPutU64) - testb %al, %al - jnz MterpPossibleException - RESTORE_IBASE - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/op_iput.S" { "helper":"MterpIPutU64" } diff --git a/runtime/interpreter/mterp/x86/op_sget.S b/runtime/interpreter/mterp/x86/op_sget.S index 66c7b0bac5..ada4e0e26a 100644 --- a/runtime/interpreter/mterp/x86/op_sget.S +++ b/runtime/interpreter/mterp/x86/op_sget.S @@ -1,26 +1,2 @@ %default { "is_object":"0", "helper":"MterpSGetU32" } -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short - */ - /* op vAA, field@BBBB */ - .extern $helper - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self - call SYMBOL($helper) - movl rSELF, %ecx - RESTORE_IBASE_FROM_SELF %ecx - cmpl $$0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - .if $is_object - SET_VREG_OBJECT %eax, rINST # fp[A] <- value - .else - SET_VREG %eax, rINST # fp[A] <- value - .endif - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/field.S" { } diff --git a/runtime/interpreter/mterp/x86/op_sget_wide.S b/runtime/interpreter/mterp/x86/op_sget_wide.S index 994cc3aebb..59232749a2 100644 --- a/runtime/interpreter/mterp/x86/op_sget_wide.S +++ b/runtime/interpreter/mterp/x86/op_sget_wide.S @@ -1,21 +1 @@ -/* - * SGET_WIDE handler wrapper. - * - */ - /* sget-wide vAA, field@BBBB */ - .extern MterpSGetU64 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref CCCC - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG1(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG2(%esp) # self - call SYMBOL(MterpSGetU64) - movl rSELF, %ecx - cmpl $$0, THREAD_EXCEPTION_OFFSET(%ecx) - jnz MterpException - SET_VREG %eax, rINST # fp[A]<- low part - SET_VREG_HIGH %edx, rINST # fp[A+1]<- high part - RESTORE_IBASE_FROM_SELF %ecx - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/op_sget.S" {"helper":"MterpSGetU64"} diff --git a/runtime/interpreter/mterp/x86/op_sput.S b/runtime/interpreter/mterp/x86/op_sput.S index e99e7a7239..2ad68e7683 100644 --- a/runtime/interpreter/mterp/x86/op_sput.S +++ b/runtime/interpreter/mterp/x86/op_sput.S @@ -1,22 +1,2 @@ -%default { "helper":"MterpSPutU32"} -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - .extern $helper - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - GET_VREG rINST, rINST - movl rINST, OUT_ARG1(%esp) # fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self - call SYMBOL($helper) - testb %al, %al - jnz MterpException - RESTORE_IBASE - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%default { "is_object":"0", "helper":"MterpSPutU32"} +%include "x86/field.S" { } diff --git a/runtime/interpreter/mterp/x86/op_sput_object.S b/runtime/interpreter/mterp/x86/op_sput_object.S index 941b07201e..4452dba272 100644 --- a/runtime/interpreter/mterp/x86/op_sput_object.S +++ b/runtime/interpreter/mterp/x86/op_sput_object.S @@ -1,13 +1 @@ - EXPORT_PC - leal OFF_FP_SHADOWFRAME(rFP), %eax - movl %eax, OUT_ARG0(%esp) - movl rPC, OUT_ARG1(%esp) - REFRESH_INST ${opnum} - movl rINST, OUT_ARG2(%esp) - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) - call SYMBOL(MterpSPutObj) - testb %al, %al - jz MterpException - RESTORE_IBASE - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/op_sput.S" {"is_object":"1", "helper":"MterpSPutObj"} diff --git a/runtime/interpreter/mterp/x86/op_sput_wide.S b/runtime/interpreter/mterp/x86/op_sput_wide.S index f58150706e..d79b068f33 100644 --- a/runtime/interpreter/mterp/x86/op_sput_wide.S +++ b/runtime/interpreter/mterp/x86/op_sput_wide.S @@ -1,20 +1 @@ -/* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field@BBBB */ - .extern MterpSPutU64 - EXPORT_PC - movzwl 2(rPC), %eax - movl %eax, OUT_ARG0(%esp) # field ref BBBB - leal VREG_ADDRESS(rINST), %eax - movl %eax, OUT_ARG1(%esp) # &fp[AA] - movl OFF_FP_METHOD(rFP), %eax - movl %eax, OUT_ARG2(%esp) # referrer - movl rSELF, %ecx - movl %ecx, OUT_ARG3(%esp) # self - call SYMBOL(MterpSPutU64) - testb %al, %al - jnz MterpException - RESTORE_IBASE - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86/op_sput.S" {"helper":"MterpSPutU64"} diff --git a/runtime/interpreter/mterp/x86_64/field.S b/runtime/interpreter/mterp/x86_64/field.S new file mode 100644 index 0000000000..f8b0588e1b --- /dev/null +++ b/runtime/interpreter/mterp/x86_64/field.S @@ -0,0 +1,14 @@ +%default { } + /* + * General field read / write (iget-* iput-* sget-* sput-*). + */ + .extern $helper + REFRESH_INST ${opnum} # fix rINST to include opcode + movq rPC, OUT_ARG0 # arg0: Instruction* inst + movl rINST, OUT_32_ARG1 # arg1: uint16_t inst_data + leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG2 # arg2: ShadowFrame* sf + movq rSELF, OUT_ARG3 # arg3: Thread* self + call SYMBOL($helper) + testb %al, %al + jz MterpPossibleException + ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 diff --git a/runtime/interpreter/mterp/x86_64/op_iget.S b/runtime/interpreter/mterp/x86_64/op_iget.S index 5c6cab6acb..4ab7c27c51 100644 --- a/runtime/interpreter/mterp/x86_64/op_iget.S +++ b/runtime/interpreter/mterp/x86_64/op_iget.S @@ -1,28 +1,2 @@ -%default { "is_object":"0", "helper":"MterpIGetU32", "wide":"0"} -/* - * General instance field get. - * - * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short, iget-wide - */ - EXPORT_PC - movzbq rINSTbl, %rcx # rcx <- BA - movzwl 2(rPC), OUT_32_ARG0 # eax <- field ref CCCC - sarl $$4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 - call SYMBOL($helper) - movq rSELF, %rcx - cmpq $$0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException # bail out - andb $$0xf, rINSTbl # rINST <- A - .if $is_object - SET_VREG_OBJECT %eax, rINSTq # fp[A] <-value - .else - .if $wide - SET_WIDE_VREG %rax, rINSTq # fp[A] <-value - .else - SET_VREG %eax, rINSTq # fp[A] <-value - .endif - .endif - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%default { "is_object":"0", "helper":"MterpIGetU32"} +%include "x86_64/field.S" { } diff --git a/runtime/interpreter/mterp/x86_64/op_iget_wide.S b/runtime/interpreter/mterp/x86_64/op_iget_wide.S index d9d174400c..a85a474845 100644 --- a/runtime/interpreter/mterp/x86_64/op_iget_wide.S +++ b/runtime/interpreter/mterp/x86_64/op_iget_wide.S @@ -1 +1 @@ -%include "x86_64/op_iget.S" { "helper":"MterpIGetU64", "wide":"1" } +%include "x86_64/op_iget.S" { "helper":"MterpIGetU64" } diff --git a/runtime/interpreter/mterp/x86_64/op_iput.S b/runtime/interpreter/mterp/x86_64/op_iput.S index 12affdbe84..dad5af664b 100644 --- a/runtime/interpreter/mterp/x86_64/op_iput.S +++ b/runtime/interpreter/mterp/x86_64/op_iput.S @@ -1,20 +1,2 @@ -%default { "helper":"MterpIPutU32"} -/* - * General 32-bit instance field put. - * - * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short - */ - /* op vA, vB, field@CCCC */ - .extern $helper - EXPORT_PC - movzwl 2(rPC), OUT_32_ARG0 # field ref <- 0000CCCC - movzbq rINSTbl, %rcx # rcx<- BA - sarl $$4, %ecx # ecx<- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $$0xf, rINSTbl # rINST<- A - GET_VREG OUT_32_ARG2, rINSTq # fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer - call SYMBOL($helper) - testb %al, %al - jnz MterpPossibleException - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%default { "is_object":"0", "helper":"MterpIPutU32" } +%include "x86_64/field.S" { } diff --git a/runtime/interpreter/mterp/x86_64/op_iput_object.S b/runtime/interpreter/mterp/x86_64/op_iput_object.S index 22648cdde7..202e33fa76 100644 --- a/runtime/interpreter/mterp/x86_64/op_iput_object.S +++ b/runtime/interpreter/mterp/x86_64/op_iput_object.S @@ -1,10 +1 @@ - EXPORT_PC - leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0 - movq rPC, OUT_ARG1 - REFRESH_INST ${opnum} - movl rINST, OUT_32_ARG2 - movq rSELF, OUT_ARG3 - call SYMBOL(MterpIPutObj) - testb %al, %al - jz MterpException - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86_64/op_iput.S" { "is_object":"1", "helper":"MterpIPutObj" } diff --git a/runtime/interpreter/mterp/x86_64/op_iput_wide.S b/runtime/interpreter/mterp/x86_64/op_iput_wide.S index 4f8c47c1e6..db520167d2 100644 --- a/runtime/interpreter/mterp/x86_64/op_iput_wide.S +++ b/runtime/interpreter/mterp/x86_64/op_iput_wide.S @@ -1,14 +1 @@ - /* iput-wide vA, vB, field@CCCC */ - .extern MterpIPutU64 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movzbq rINSTbl, %rcx # rcx <- BA - sarl $$4, %ecx # ecx <- B - GET_VREG OUT_32_ARG1, %rcx # the object pointer - andb $$0xf, rINSTbl # rINST <- A - leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[A] - movq OFF_FP_METHOD(rFP), OUT_ARG3 # referrer - call SYMBOL(MterpIPutU64) - testb %al, %al - jnz MterpPossibleException - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86_64/op_iput.S" { "helper":"MterpIPutU64" } diff --git a/runtime/interpreter/mterp/x86_64/op_sget.S b/runtime/interpreter/mterp/x86_64/op_sget.S index c15ac1e280..21e8e64b8b 100644 --- a/runtime/interpreter/mterp/x86_64/op_sget.S +++ b/runtime/interpreter/mterp/x86_64/op_sget.S @@ -1,26 +1,2 @@ -%default { "is_object":"0", "helper":"MterpSGetU32", "wide":"0" } -/* - * General SGET handler wrapper. - * - * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide - */ - /* op vAA, field@BBBB */ - .extern $helper - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref CCCC - movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer - movq rSELF, OUT_ARG2 # self - call SYMBOL($helper) - movq rSELF, %rcx - cmpl $$0, THREAD_EXCEPTION_OFFSET(%rcx) - jnz MterpException - .if $is_object - SET_VREG_OBJECT %eax, rINSTq # fp[A] <- value - .else - .if $wide - SET_WIDE_VREG %rax, rINSTq # fp[A] <- value - .else - SET_VREG %eax, rINSTq # fp[A] <- value - .endif - .endif - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%default { "is_object":"0", "helper":"MterpSGetU32" } +%include "x86_64/field.S" { } diff --git a/runtime/interpreter/mterp/x86_64/op_sget_wide.S b/runtime/interpreter/mterp/x86_64/op_sget_wide.S index 65ddb8a09c..c53c0773a5 100644 --- a/runtime/interpreter/mterp/x86_64/op_sget_wide.S +++ b/runtime/interpreter/mterp/x86_64/op_sget_wide.S @@ -1 +1 @@ -%include "x86_64/op_sget.S" {"helper":"MterpSGetU64", "wide":"1"} +%include "x86_64/op_sget.S" {"helper":"MterpSGetU64"} diff --git a/runtime/interpreter/mterp/x86_64/op_sput.S b/runtime/interpreter/mterp/x86_64/op_sput.S index 9a33d521b9..7dd24985ff 100644 --- a/runtime/interpreter/mterp/x86_64/op_sput.S +++ b/runtime/interpreter/mterp/x86_64/op_sput.S @@ -1,17 +1,2 @@ -%default { "helper":"MterpSPutU32"} -/* - * General SPUT handler wrapper. - * - * for: sput, sput-boolean, sput-byte, sput-char, sput-short - */ - /* op vAA, field@BBBB */ - .extern $helper - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - GET_VREG OUT_32_ARG1, rINSTq # fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self - call SYMBOL($helper) - testb %al, %al - jnz MterpException - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%default { "is_object":"0", "helper":"MterpSPutU32"} +%include "x86_64/field.S" { } diff --git a/runtime/interpreter/mterp/x86_64/op_sput_object.S b/runtime/interpreter/mterp/x86_64/op_sput_object.S index 8a47074ec3..c2bd07bcc8 100644 --- a/runtime/interpreter/mterp/x86_64/op_sput_object.S +++ b/runtime/interpreter/mterp/x86_64/op_sput_object.S @@ -1,10 +1 @@ - EXPORT_PC - leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG0 - movq rPC, OUT_ARG1 - REFRESH_INST ${opnum} - movq rINSTq, OUT_ARG2 - movq rSELF, OUT_ARG3 - call SYMBOL(MterpSPutObj) - testb %al, %al - jz MterpException - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86_64/op_sput.S" {"is_object":"1", "helper":"MterpSPutObj"} diff --git a/runtime/interpreter/mterp/x86_64/op_sput_wide.S b/runtime/interpreter/mterp/x86_64/op_sput_wide.S index 464d1697ac..7e77072dce 100644 --- a/runtime/interpreter/mterp/x86_64/op_sput_wide.S +++ b/runtime/interpreter/mterp/x86_64/op_sput_wide.S @@ -1,15 +1 @@ -/* - * SPUT_WIDE handler wrapper. - * - */ - /* sput-wide vAA, field@BBBB */ - .extern MterpSPutU64 - EXPORT_PC - movzwq 2(rPC), OUT_ARG0 # field ref BBBB - leaq VREG_ADDRESS(rINSTq), OUT_ARG1 # &fp[AA] - movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer - movq rSELF, OUT_ARG3 # self - call SYMBOL(MterpSPutU64) - testb %al, %al - jnz MterpException - ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 +%include "x86_64/op_sput.S" {"helper":"MterpSPutU64"} diff --git a/runtime/jdwp/jdwp_adb.cc b/runtime/jdwp/jdwp_adb.cc index 481aff91f8..e6043c65de 100644 --- a/runtime/jdwp/jdwp_adb.cc +++ b/runtime/jdwp/jdwp_adb.cc @@ -87,13 +87,13 @@ struct JdwpAdbState : public JdwpNetStateBase { } } - virtual bool Accept() REQUIRES(!state_lock_); + bool Accept() override REQUIRES(!state_lock_); - virtual bool Establish(const JdwpOptions*) { + bool Establish(const JdwpOptions*) override { return false; } - virtual void Shutdown() REQUIRES(!state_lock_) { + void Shutdown() override REQUIRES(!state_lock_) { int control_sock; int local_clientSock; { @@ -116,7 +116,7 @@ struct JdwpAdbState : public JdwpNetStateBase { WakePipe(); } - virtual bool ProcessIncoming() REQUIRES(!state_lock_); + bool ProcessIncoming() override REQUIRES(!state_lock_); private: int ReceiveClientFd() REQUIRES(!state_lock_); diff --git a/runtime/jdwp/jdwp_socket.cc b/runtime/jdwp/jdwp_socket.cc index 673a942517..29fa1603dd 100644 --- a/runtime/jdwp/jdwp_socket.cc +++ b/runtime/jdwp/jdwp_socket.cc @@ -54,10 +54,10 @@ struct JdwpSocketState : public JdwpNetStateBase { remote_port_(0U) { } - virtual bool Accept(); - virtual bool Establish(const JdwpOptions*); - virtual void Shutdown(); - virtual bool ProcessIncoming(); + bool Accept() override; + bool Establish(const JdwpOptions*) override; + void Shutdown() override; + bool ProcessIncoming() override; private: in_addr remote_addr_; diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index 2b2898c195..bcbdc3bece 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -28,6 +28,7 @@ #include "base/stl_util.h" #include "base/systrace.h" #include "base/time_utils.h" +#include "base/utils.h" #include "cha.h" #include "debugger_interface.h" #include "dex/dex_file_loader.h" @@ -53,8 +54,9 @@ namespace art { namespace jit { -static constexpr int kProtData = PROT_READ | PROT_WRITE; static constexpr int kProtCode = PROT_READ | PROT_EXEC; +static constexpr int kProtData = PROT_READ | PROT_WRITE; +static constexpr int kProtProfile = PROT_READ; static constexpr size_t kCodeSizeLogThreshold = 50 * KB; static constexpr size_t kStackMapSizeLogThreshold = 50 * KB; @@ -192,7 +194,7 @@ JitCodeCache* JitCodeCache::Create(size_t initial_capacity, // to profile system server. // NOTE 2: We could just not create the code section at all but we will need to // special case too many cases. - int memmap_flags_prot_code = used_only_for_profile_data ? (kProtCode & ~PROT_EXEC) : kProtCode; + int memmap_flags_prot_code = used_only_for_profile_data ? kProtProfile : kProtCode; std::string error_str; // Map name specific for android_os_Debug.cpp accounting. @@ -528,7 +530,7 @@ static inline void ProcessWeakClass(GcRoot<mirror::Class>* root_ptr, // This does not need a read barrier because this is called by GC. mirror::Class* cls = root_ptr->Read<kWithoutReadBarrier>(); if (cls != nullptr && cls != weak_sentinel) { - DCHECK((cls->IsClass<kDefaultVerifyFlags, kWithoutReadBarrier>())); + DCHECK((cls->IsClass<kDefaultVerifyFlags>())); // Look at the classloader of the class to know if it has been unloaded. // This does not need a read barrier because this is called by GC. mirror::Object* class_loader = @@ -799,8 +801,18 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self, // // For reference, this behavior is caused by this commit: // https://android.googlesource.com/kernel/msm/+/3fbe6bc28a6b9939d0650f2f17eb5216c719950c - FlushInstructionCache(reinterpret_cast<char*>(code_ptr), - reinterpret_cast<char*>(code_ptr + code_size)); + FlushInstructionCache(code_ptr, code_ptr + code_size); + + // Ensure CPU instruction pipelines are flushed for all cores. This is necessary for + // correctness as code may still be in instruction pipelines despite the i-cache flush. It is + // not safe to assume that changing permissions with mprotect (RX->RWX->RX) will cause a TLB + // shootdown (incidentally invalidating the CPU pipelines by sending an IPI to all cores to + // notify them of the TLB invalidation). Some architectures, notably ARM and ARM64, have + // hardware support that broadcasts TLB invalidations and so their kernels have no software + // based TLB shootdown. FlushInstructionPipeline() is a wrapper around the Linux + // membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED) syscall which does the appropriate flushing. + FlushInstructionPipeline(); + DCHECK(!Runtime::Current()->IsAotCompiler()); if (has_should_deoptimize_flag) { method_header->SetHasShouldDeoptimizeFlag(); @@ -858,8 +870,7 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self, FillRootTable(roots_data, roots); { // Flush data cache, as compiled code references literals in it. - FlushDataCache(reinterpret_cast<char*>(roots_data), - reinterpret_cast<char*>(roots_data + data_size)); + FlushDataCache(roots_data, roots_data + data_size); } method_code_map_.Put(code_ptr, method); if (osr) { diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc index d9ef922390..9043f267fb 100644 --- a/runtime/jit/profile_saver.cc +++ b/runtime/jit/profile_saver.cc @@ -274,7 +274,7 @@ class GetClassesVisitor : public ClassVisitor { : profile_boot_class_path_(profile_boot_class_path), out_(out) {} - virtual bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { + bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) { if (klass->IsProxyClass() || klass->IsArrayClass() || klass->IsPrimitive() || diff --git a/runtime/jni/java_vm_ext_test.cc b/runtime/jni/java_vm_ext_test.cc index 4049c6e699..dfe50cf905 100644 --- a/runtime/jni/java_vm_ext_test.cc +++ b/runtime/jni/java_vm_ext_test.cc @@ -27,7 +27,7 @@ namespace art { class JavaVmExtTest : public CommonRuntimeTest { protected: - virtual void SetUp() { + void SetUp() override { CommonRuntimeTest::SetUp(); vm_ = Runtime::Current()->GetJavaVM(); diff --git a/runtime/jni/jni_internal_test.cc b/runtime/jni/jni_internal_test.cc index 3040b905ec..4ad4c14e0b 100644 --- a/runtime/jni/jni_internal_test.cc +++ b/runtime/jni/jni_internal_test.cc @@ -34,7 +34,7 @@ using android::base::StringPrintf; // TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used. class JniInternalTest : public CommonCompilerTest { protected: - virtual void SetUp() { + void SetUp() override { CommonCompilerTest::SetUp(); vm_ = Runtime::Current()->GetJavaVM(); diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 51dc1a4627..d3f89216b9 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -378,7 +378,7 @@ template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> inline bool Class::IsVariableSize() { // Classes, arrays, and strings vary in size, and so the object_size_ field cannot // be used to Get their instance size - return IsClassClass<kVerifyFlags, kReadBarrierOption>() || + return IsClassClass<kVerifyFlags>() || IsArrayClass<kVerifyFlags, kReadBarrierOption>() || IsStringClass(); } @@ -853,10 +853,12 @@ inline uint32_t Class::ComputeClassSize(bool has_embedded_vtable, return size; } -template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> +template<VerifyObjectFlags kVerifyFlags> inline bool Class::IsClassClass() { - ObjPtr<Class> java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> - template GetClass<kVerifyFlags, kReadBarrierOption>(); + // OK to look at from-space copies since java.lang.Class.class is not movable. + // See b/114413743 + ObjPtr<Class> java_lang_Class = GetClass<kVerifyFlags, kWithoutReadBarrier>()-> + template GetClass<kVerifyFlags, kWithoutReadBarrier>(); return this == java_lang_Class; } diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 811ee515d3..4015bd2f1a 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -430,8 +430,7 @@ class MANAGED Class final : public Object { ReadBarrierOption kReadBarrierOption = kWithReadBarrier> bool IsArrayClass() REQUIRES_SHARED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsClassClass() REQUIRES_SHARED(Locks::mutator_lock_); bool IsThrowableClass() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index bd89907ae2..1b03956123 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -137,17 +137,18 @@ inline bool Object::InstanceOf(ObjPtr<Class> klass) { return klass->IsAssignableFrom(GetClass<kVerifyFlags>()); } -template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> +template<VerifyObjectFlags kVerifyFlags> inline bool Object::IsClass() { - constexpr auto kNewFlags = RemoveThisFlags(kVerifyFlags); - Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> - template GetClass<kVerifyFlags, kReadBarrierOption>(); - return GetClass<kNewFlags, kReadBarrierOption>() == java_lang_Class; + // OK to look at from-space copies since java.lang.Class.class is not movable. + // See b/114413743 + ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>(); + ObjPtr<Class> java_lang_Class = klass->template GetClass<kVerifyFlags, kWithoutReadBarrier>(); + return klass == java_lang_Class; } -template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> +template<VerifyObjectFlags kVerifyFlags> inline Class* Object::AsClass() { - DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>())); + DCHECK((IsClass<kVerifyFlags>())); return down_cast<Class*>(this); } @@ -350,8 +351,8 @@ inline size_t Object::SizeOf() { constexpr auto kNewFlags = RemoveThisFlags(kVerifyFlags); if (IsArrayInstance<kVerifyFlags, kRBO>()) { result = AsArray<kNewFlags, kRBO>()->template SizeOf<kNewFlags, kRBO>(); - } else if (IsClass<kNewFlags, kRBO>()) { - result = AsClass<kNewFlags, kRBO>()->template SizeOf<kNewFlags, kRBO>(); + } else if (IsClass<kNewFlags>()) { + result = AsClass<kNewFlags>()->template SizeOf<kNewFlags, kRBO>(); } else if (GetClass<kNewFlags, kRBO>()->IsStringClass()) { result = AsString<kNewFlags, kRBO>()->template SizeOf<kNewFlags>(); } else { @@ -364,7 +365,7 @@ inline size_t Object::SizeOf() { template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> inline int8_t Object::GetFieldByte(MemberOffset field_offset) { Verify<kVerifyFlags>(); - return GetField<int8_t, kIsVolatile>(field_offset); + return GetFieldPrimitive<int8_t, kIsVolatile>(field_offset); } template<VerifyObjectFlags kVerifyFlags> @@ -391,7 +392,7 @@ inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value kIsVolatile); } Verify<kVerifyFlags>(); - SetField<uint8_t, kIsVolatile>(field_offset, new_value); + SetFieldPrimitive<uint8_t, kIsVolatile>(field_offset, new_value); } template<bool kTransactionActive, @@ -407,7 +408,7 @@ inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value) { kIsVolatile); } Verify<kVerifyFlags>(); - SetField<int8_t, kIsVolatile>(field_offset, new_value); + SetFieldPrimitive<int8_t, kIsVolatile>(field_offset, new_value); } template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> @@ -425,13 +426,13 @@ inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_v template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> inline uint16_t Object::GetFieldChar(MemberOffset field_offset) { Verify<kVerifyFlags>(); - return GetField<uint16_t, kIsVolatile>(field_offset); + return GetFieldPrimitive<uint16_t, kIsVolatile>(field_offset); } template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> inline int16_t Object::GetFieldShort(MemberOffset field_offset) { Verify<kVerifyFlags>(); - return GetField<int16_t, kIsVolatile>(field_offset); + return GetFieldPrimitive<int16_t, kIsVolatile>(field_offset); } template<VerifyObjectFlags kVerifyFlags> @@ -457,7 +458,7 @@ inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) kIsVolatile); } Verify<kVerifyFlags>(); - SetField<uint16_t, kIsVolatile>(field_offset, new_value); + SetFieldPrimitive<uint16_t, kIsVolatile>(field_offset, new_value); } template<bool kTransactionActive, @@ -473,7 +474,7 @@ inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) kIsVolatile); } Verify<kVerifyFlags>(); - SetField<int16_t, kIsVolatile>(field_offset, new_value); + SetFieldPrimitive<int16_t, kIsVolatile>(field_offset, new_value); } template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> @@ -501,7 +502,7 @@ inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { kIsVolatile); } Verify<kVerifyFlags>(); - SetField<int32_t, kIsVolatile>(field_offset, new_value); + SetFieldPrimitive<int32_t, kIsVolatile>(field_offset, new_value); } template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> @@ -531,7 +532,7 @@ inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) { kIsVolatile); } Verify<kVerifyFlags>(); - SetField<int64_t, kIsVolatile>(field_offset, new_value); + SetFieldPrimitive<int64_t, kIsVolatile>(field_offset, new_value); } template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> @@ -867,7 +868,7 @@ inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& v // inheritance hierarchy and find reference offsets the hard way. In the static case, just // consider this class. for (ObjPtr<Class> klass = kIsStatic - ? AsClass<kVerifyFlags, kReadBarrierOption>() + ? AsClass<kVerifyFlags>() : GetClass<kVerifyFlags, kReadBarrierOption>(); klass != nullptr; klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) { diff --git a/runtime/mirror/object-readbarrier-inl.h b/runtime/mirror/object-readbarrier-inl.h index cc375bd796..8689e4dadb 100644 --- a/runtime/mirror/object-readbarrier-inl.h +++ b/runtime/mirror/object-readbarrier-inl.h @@ -131,7 +131,7 @@ inline uint32_t Object::GetReadBarrierState() { UNREACHABLE(); } DCHECK(kUseBakerReadBarrier); - LockWord lw(GetField<uint32_t, /*kIsVolatile*/false>(MonitorOffset())); + LockWord lw(GetFieldPrimitive<uint32_t, /*kIsVolatile*/false>(MonitorOffset())); uint32_t rb_state = lw.ReadBarrierState(); DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state; return rb_state; diff --git a/runtime/mirror/object-refvisitor-inl.h b/runtime/mirror/object-refvisitor-inl.h index 39e32bf63c..bd239713c5 100644 --- a/runtime/mirror/object-refvisitor-inl.h +++ b/runtime/mirror/object-refvisitor-inl.h @@ -39,7 +39,7 @@ inline void Object::VisitReferences(const Visitor& visitor, if (LIKELY(class_flags == kClassFlagNormal)) { DCHECK((!klass->IsVariableSize<kVerifyFlags, kReadBarrierOption>())); VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor); - DCHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>())); + DCHECK((!klass->IsClassClass<kVerifyFlags>())); DCHECK(!klass->IsStringClass()); DCHECK(!klass->IsClassLoaderClass()); DCHECK((!klass->IsArrayClass<kVerifyFlags, kReadBarrierOption>())); @@ -47,8 +47,8 @@ inline void Object::VisitReferences(const Visitor& visitor, if ((class_flags & kClassFlagNoReferenceFields) == 0) { DCHECK(!klass->IsStringClass()); if (class_flags == kClassFlagClass) { - DCHECK((klass->IsClassClass<kVerifyFlags, kReadBarrierOption>())); - ObjPtr<Class> as_klass = AsClass<kVerifyNone, kReadBarrierOption>(); + DCHECK((klass->IsClassClass<kVerifyFlags>())); + ObjPtr<Class> as_klass = AsClass<kVerifyNone>(); as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass, visitor); } else if (class_flags == kClassFlagObjectArray) { @@ -69,7 +69,7 @@ inline void Object::VisitReferences(const Visitor& visitor, kReadBarrierOption>(klass, visitor); } } else if (kIsDebugBuild) { - CHECK((!klass->IsClassClass<kVerifyFlags, kReadBarrierOption>())); + CHECK((!klass->IsClassClass<kVerifyFlags>())); CHECK((!klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>())); // String still has instance fields for reflection purposes but these don't exist in // actual string instances. diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index 47aded3f0c..48ce5c1c42 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -169,11 +169,9 @@ class MANAGED LOCKABLE Object { void NotifyAll(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); void Wait(Thread* self, int64_t timeout, int32_t nanos) REQUIRES_SHARED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsClass() REQUIRES_SHARED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> Class* AsClass() REQUIRES_SHARED(Locks::mutator_lock_); template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, @@ -349,11 +347,35 @@ class MANAGED LOCKABLE Object { HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset) REQUIRES_SHARED(Locks::mutator_lock_); + template<typename kType, bool kIsVolatile> + ALWAYS_INLINE void SetFieldPrimitive(MemberOffset field_offset, kType new_value) + REQUIRES_SHARED(Locks::mutator_lock_) { + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + kType* addr = reinterpret_cast<kType*>(raw_addr); + if (kIsVolatile) { + reinterpret_cast<Atomic<kType>*>(addr)->store(new_value, std::memory_order_seq_cst); + } else { + reinterpret_cast<Atomic<kType>*>(addr)->StoreJavaData(new_value); + } + } + + template<typename kType, bool kIsVolatile> + ALWAYS_INLINE kType GetFieldPrimitive(MemberOffset field_offset) + REQUIRES_SHARED(Locks::mutator_lock_) { + const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value(); + const kType* addr = reinterpret_cast<const kType*>(raw_addr); + if (kIsVolatile) { + return reinterpret_cast<const Atomic<kType>*>(addr)->load(std::memory_order_seq_cst); + } else { + return reinterpret_cast<const Atomic<kType>*>(addr)->LoadJavaData(); + } + } + template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false> ALWAYS_INLINE uint8_t GetFieldBoolean(MemberOffset field_offset) REQUIRES_SHARED(Locks::mutator_lock_) { Verify<kVerifyFlags>(); - return GetField<uint8_t, kIsVolatile>(field_offset); + return GetFieldPrimitive<uint8_t, kIsVolatile>(field_offset); } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kIsVolatile = false> @@ -440,7 +462,7 @@ class MANAGED LOCKABLE Object { ALWAYS_INLINE int32_t GetField32(MemberOffset field_offset) REQUIRES_SHARED(Locks::mutator_lock_) { Verify<kVerifyFlags>(); - return GetField<int32_t, kIsVolatile>(field_offset); + return GetFieldPrimitive<int32_t, kIsVolatile>(field_offset); } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> @@ -482,7 +504,7 @@ class MANAGED LOCKABLE Object { ALWAYS_INLINE int64_t GetField64(MemberOffset field_offset) REQUIRES_SHARED(Locks::mutator_lock_) { Verify<kVerifyFlags>(); - return GetField<int64_t, kIsVolatile>(field_offset); + return GetFieldPrimitive<int64_t, kIsVolatile>(field_offset); } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> @@ -683,30 +705,6 @@ class MANAGED LOCKABLE Object { REQUIRES_SHARED(Locks::mutator_lock_); private: - template<typename kSize, bool kIsVolatile> - ALWAYS_INLINE void SetField(MemberOffset field_offset, kSize new_value) - REQUIRES_SHARED(Locks::mutator_lock_) { - uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); - kSize* addr = reinterpret_cast<kSize*>(raw_addr); - if (kIsVolatile) { - reinterpret_cast<Atomic<kSize>*>(addr)->store(new_value, std::memory_order_seq_cst); - } else { - reinterpret_cast<Atomic<kSize>*>(addr)->StoreJavaData(new_value); - } - } - - template<typename kSize, bool kIsVolatile> - ALWAYS_INLINE kSize GetField(MemberOffset field_offset) - REQUIRES_SHARED(Locks::mutator_lock_) { - const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value(); - const kSize* addr = reinterpret_cast<const kSize*>(raw_addr); - if (kIsVolatile) { - return reinterpret_cast<const Atomic<kSize>*>(addr)->load(std::memory_order_seq_cst); - } else { - return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadJavaData(); - } - } - // Get a field with acquire semantics. template<typename kSize> ALWAYS_INLINE kSize GetFieldAcquire(MemberOffset field_offset) diff --git a/runtime/monitor_test.cc b/runtime/monitor_test.cc index c88748ffb8..0b168f86f4 100644 --- a/runtime/monitor_test.cc +++ b/runtime/monitor_test.cc @@ -62,7 +62,7 @@ class CreateTask : public Task { monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis), expected_(expected) {} - void Run(Thread* self) { + void Run(Thread* self) override { { ScopedObjectAccess soa(self); @@ -118,7 +118,7 @@ class CreateTask : public Task { } } - void Finalize() { + void Finalize() override { delete this; } @@ -136,7 +136,7 @@ class UseTask : public Task { monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis), expected_(expected) {} - void Run(Thread* self) { + void Run(Thread* self) override { monitor_test_->barrier_->Wait(self); // Wait for the other thread to set up the monitor. { @@ -158,7 +158,7 @@ class UseTask : public Task { monitor_test_->complete_barrier_->Wait(self); // Wait for test completion. } - void Finalize() { + void Finalize() override { delete this; } @@ -174,7 +174,7 @@ class InterruptTask : public Task { InterruptTask(MonitorTest* monitor_test, uint64_t initial_sleep, uint64_t millis) : monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis) {} - void Run(Thread* self) { + void Run(Thread* self) override { monitor_test_->barrier_->Wait(self); // Wait for the other thread to set up the monitor. { @@ -202,7 +202,7 @@ class InterruptTask : public Task { monitor_test_->complete_barrier_->Wait(self); // Wait for test completion. } - void Finalize() { + void Finalize() override { delete this; } @@ -216,7 +216,7 @@ class WatchdogTask : public Task { public: explicit WatchdogTask(MonitorTest* monitor_test) : monitor_test_(monitor_test) {} - void Run(Thread* self) { + void Run(Thread* self) override { ScopedObjectAccess soa(self); monitor_test_->watchdog_object_.Get()->MonitorEnter(self); // Lock the object. @@ -231,7 +231,7 @@ class WatchdogTask : public Task { } } - void Finalize() { + void Finalize() override { delete this; } @@ -326,14 +326,14 @@ class TryLockTask : public Task { public: explicit TryLockTask(Handle<mirror::Object> obj) : obj_(obj) {} - void Run(Thread* self) { + void Run(Thread* self) override { ScopedObjectAccess soa(self); // Lock is held by other thread, try lock should fail. ObjectTryLock<mirror::Object> lock(self, obj_); EXPECT_FALSE(lock.Acquired()); } - void Finalize() { + void Finalize() override { delete this; } diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc index 39192274ad..e3932df5c0 100644 --- a/runtime/native/dalvik_system_VMStack.cc +++ b/runtime/native/dalvik_system_VMStack.cc @@ -113,7 +113,7 @@ static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass) { : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), class_loader(nullptr) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(class_loader == nullptr); ObjPtr<mirror::Class> c = GetMethod()->GetDeclaringClass(); // c is null for runtime methods. diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 5a5fb16d0c..f5039d1929 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -62,7 +62,7 @@ static bool IsCallerTrusted(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) caller(nullptr) { } - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod *m = GetMethod(); if (m == nullptr) { // Attached native thread. Assume this is *not* boot class path. diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index efdefb1eea..3a974df386 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -1148,7 +1148,7 @@ class RaceGenerateTask : public Task { loaded_oat_file_(nullptr) {} - void Run(Thread* self ATTRIBUTE_UNUSED) { + void Run(Thread* self ATTRIBUTE_UNUSED) override { // Load the dex files, and save a pointer to the loaded oat file, so that // we can verify only one oat file was loaded for the dex location. std::vector<std::unique_ptr<const DexFile>> dex_files; diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 7b92151c66..e882e7370a 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -165,7 +165,7 @@ class InstrumentationStackVisitor : public StackVisitor { CHECK_NE(frame_depth_, kInvalidFrameDepth); } - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { size_t current_frame_depth = GetFrameDepth(); if (current_frame_depth < frame_depth_) { CHECK(GetMethod() != nullptr); diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc index 424ee0681a..00e298ead3 100644 --- a/runtime/reflection_test.cc +++ b/runtime/reflection_test.cc @@ -33,7 +33,7 @@ namespace art { // TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used. class ReflectionTest : public CommonCompilerTest { protected: - virtual void SetUp() { + void SetUp() override { CommonCompilerTest::SetUp(); vm_ = Runtime::Current()->GetJavaVM(); @@ -73,7 +73,7 @@ class ReflectionTest : public CommonCompilerTest { } } - virtual void TearDown() { + void TearDown() override { CleanUpJniEnv(); CommonCompilerTest::TearDown(); } diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc index aaedb23e45..89f312457a 100644 --- a/runtime/runtime_callbacks_test.cc +++ b/runtime/runtime_callbacks_test.cc @@ -458,20 +458,20 @@ class MonitorWaitCallbacksTest : public RuntimeCallbacksTest { ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() }; } - void MonitorContendedLocking(Monitor* mon ATTRIBUTE_UNUSED) + void MonitorContendedLocking(Monitor* mon ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { } - void MonitorContendedLocked(Monitor* mon ATTRIBUTE_UNUSED) + void MonitorContendedLocked(Monitor* mon ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { } - void ObjectWaitStart(Handle<mirror::Object> obj, int64_t millis ATTRIBUTE_UNUSED) + void ObjectWaitStart(Handle<mirror::Object> obj, int64_t millis ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { if (IsInterestingObject(obj.Get())) { saw_wait_start_ = true; } } - void MonitorWaitFinished(Monitor* m, bool timed_out ATTRIBUTE_UNUSED) + void MonitorWaitFinished(Monitor* m, bool timed_out ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { if (IsInterestingObject(m->GetObject())) { saw_wait_finished_ = true; diff --git a/runtime/subtype_check_info_test.cc b/runtime/subtype_check_info_test.cc index e40bca57fe..53230930e6 100644 --- a/runtime/subtype_check_info_test.cc +++ b/runtime/subtype_check_info_test.cc @@ -86,11 +86,11 @@ BitString SetBitStringCharAt(BitString bit_string, size_t i, size_t val) { struct SubtypeCheckInfoTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { android::base::InitLogging(/*argv*/nullptr); } - virtual void TearDown() { + void TearDown() override { } static SubtypeCheckInfo MakeSubtypeCheckInfo(BitString path_to_root = {}, diff --git a/runtime/subtype_check_test.cc b/runtime/subtype_check_test.cc index 666bf812f5..9aa30325c2 100644 --- a/runtime/subtype_check_test.cc +++ b/runtime/subtype_check_test.cc @@ -301,13 +301,13 @@ struct MockScopedLockMutator { struct SubtypeCheckTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { android::base::InitLogging(/*argv*/nullptr); CreateRootedTree(BitString::kCapacity + 2u, BitString::kCapacity + 2u); } - virtual void TearDown() { + void TearDown() override { } void CreateRootedTree(size_t width, size_t height) { diff --git a/runtime/thread.cc b/runtime/thread.cc index 19fe4ea7c5..8a8f53743e 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -2515,7 +2515,7 @@ class FetchStackTraceVisitor : public StackVisitor { saved_frames_(saved_frames), max_saved_frames_(max_saved_frames) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { // We want to skip frames up to and including the exception's constructor. // Note we also skip the frame if it doesn't have a method (namely the callee // save frame) @@ -2603,7 +2603,7 @@ class BuildInternalStackTraceVisitor : public StackVisitor { self_->EndAssertNoThreadSuspension(nullptr); } - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { if (trace_ == nullptr) { return true; // We're probably trying to fillInStackTrace for an OutOfMemoryError. } @@ -3520,7 +3520,7 @@ class ReferenceMapVisitor : public StackVisitor { : StackVisitor(thread, context, StackVisitor::StackWalkKind::kSkipInlinedFrames), visitor_(visitor) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { if (false) { LOG(INFO) << "Visiting stack roots in " << ArtMethod::PrettyMethod(GetMethod()) << StringPrintf("@ PC:%04x", GetDexPc()); diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc index d7842002ee..2600f55695 100644 --- a/runtime/thread_pool_test.cc +++ b/runtime/thread_pool_test.cc @@ -29,7 +29,7 @@ class CountTask : public Task { public: explicit CountTask(AtomicInteger* count) : count_(count), verbose_(false) {} - void Run(Thread* self) { + void Run(Thread* self) override { if (verbose_) { LOG(INFO) << "Running: " << *self; } @@ -39,7 +39,7 @@ class CountTask : public Task { ++*count_; } - void Finalize() { + void Finalize() override { if (verbose_) { LOG(INFO) << "Finalizing: " << *Thread::Current(); } @@ -129,7 +129,7 @@ class TreeTask : public Task { count_(count), depth_(depth) {} - void Run(Thread* self) { + void Run(Thread* self) override { if (depth_ > 1) { thread_pool_->AddTask(self, new TreeTask(thread_pool_, count_, depth_ - 1)); thread_pool_->AddTask(self, new TreeTask(thread_pool_, count_, depth_ - 1)); @@ -138,7 +138,7 @@ class TreeTask : public Task { ++*count_; } - void Finalize() { + void Finalize() override { delete this; } @@ -164,12 +164,12 @@ class PeerTask : public Task { public: PeerTask() {} - void Run(Thread* self) { + void Run(Thread* self) override { ScopedObjectAccess soa(self); CHECK(self->GetPeer() != nullptr); } - void Finalize() { + void Finalize() override { delete this; } }; @@ -178,12 +178,12 @@ class NoPeerTask : public Task { public: NoPeerTask() {} - void Run(Thread* self) { + void Run(Thread* self) override { ScopedObjectAccess soa(self); CHECK(self->GetPeer() == nullptr); } - void Finalize() { + void Finalize() override { delete this; } }; diff --git a/runtime/trace.cc b/runtime/trace.cc index 949fabe7f9..7e48bae581 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -64,7 +64,7 @@ class BuildStackTraceVisitor : public StackVisitor { : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), method_trace_(Trace::AllocStackTrace()) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); // Ignore runtime frames (in particular callee save). if (!m->IsRuntimeMethod()) { diff --git a/test/004-ReferenceMap/stack_walk_refmap_jni.cc b/test/004-ReferenceMap/stack_walk_refmap_jni.cc index 1ce20e2b3d..4c344a3a5f 100644 --- a/test/004-ReferenceMap/stack_walk_refmap_jni.cc +++ b/test/004-ReferenceMap/stack_walk_refmap_jni.cc @@ -37,7 +37,7 @@ struct ReferenceMap2Visitor : public CheckReferenceMapVisitor { explicit ReferenceMap2Visitor(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) : CheckReferenceMapVisitor(thread) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { if (CheckReferenceMapVisitor::VisitFrame()) { return true; } diff --git a/test/004-StackWalk/build b/test/004-StackWalk/build index eeecbfcc40..3de541c75d 100644 --- a/test/004-StackWalk/build +++ b/test/004-StackWalk/build @@ -18,10 +18,8 @@ set -e # This test depends on the exact format of the DEX file. Since dx is deprecated, -# the classes.dex file is packaged as a test input. It was created with: -# -# $ javac -g -Xlint:-options -source 1.7 -target 1.7 -d classes src/Main.java -# $ dx --debug --dex --output=classes.dex classes +# the classes.dex file is packaged as a test input. See src/Main.java file +# to check how it was created. # Wrapper function for javac which for this test does nothing as the # test uses a pre-built DEX file. diff --git a/test/004-StackWalk/classes.dex b/test/004-StackWalk/classes.dex Binary files differindex ad452960c3..61a7277cf9 100644 --- a/test/004-StackWalk/classes.dex +++ b/test/004-StackWalk/classes.dex diff --git a/test/004-StackWalk/src/Main.java b/test/004-StackWalk/src/Main.java index 072b1d0c4d..2a098f7686 100644 --- a/test/004-StackWalk/src/Main.java +++ b/test/004-StackWalk/src/Main.java @@ -1,19 +1,36 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This test depends on the exact format of the DEX file. Since dx is deprecated, +// the classes.dex file is packaged as a test input. It was created with: +// +// $ javac -g -Xlint:-options -source 1.7 -target 1.7 -d classes src/Main.java +// $ dx --debug --dex --output=classes.dex classes + public class Main { public Main() { } - boolean doThrow = false; - int $noinline$f() throws Exception { - g(1); - g(2); - - // This currently defeats inlining of `f`. - if (doThrow) { throw new Error(); } + $noinline$g(1); + $noinline$g(2); return 0; } - void g(int num_calls) { + void $noinline$g(int num_calls) { if (num_calls == 1) { System.out.println("1st call"); } else if (num_calls == 2) { @@ -81,11 +98,14 @@ public class Main { s4 = s18 = s19; s += s4; s += s18; - stackmap(0); - return s; + // Add a branch to workaround ART's large methods without branches heuristic. + if (testStackWalk(0) != 0) { + return s; + } + return s18; } - native int stackmap(int x); + native int testStackWalk(int x); public static void main(String[] args) throws Exception { System.loadLibrary(args[0]); diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc index 89e2e660d9..81c27ec400 100644 --- a/test/004-StackWalk/stack_walk_jni.cc +++ b/test/004-StackWalk/stack_walk_jni.cc @@ -20,7 +20,7 @@ namespace art { -#define CHECK_REGS(...) do { \ +#define CHECK_REGS_ARE_REFERENCES(...) do { \ int t[] = {__VA_ARGS__}; \ int t_size = sizeof(t) / sizeof(*t); \ CheckReferences(t, t_size, GetNativePcOffset()); \ @@ -33,7 +33,7 @@ class TestReferenceMapVisitor : public CheckReferenceMapVisitor { explicit TestReferenceMapVisitor(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) : CheckReferenceMapVisitor(thread) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { if (CheckReferenceMapVisitor::VisitFrame()) { return true; } @@ -43,58 +43,60 @@ class TestReferenceMapVisitor : public CheckReferenceMapVisitor { // Given the method name and the number of times the method has been called, // we know the Dex registers with live reference values. Assert that what we // find is what is expected. - if (m_name == "f") { + if (m_name == "$noinline$f") { if (gJava_StackWalk_refmap_calls == 1) { CHECK_EQ(1U, GetDexPc()); - CHECK_REGS(4); + CHECK_REGS_ARE_REFERENCES(1); } else { CHECK_EQ(gJava_StackWalk_refmap_calls, 2); CHECK_EQ(5U, GetDexPc()); - CHECK_REGS(4); + CHECK_REGS_ARE_REFERENCES(1); } - } else if (m_name == "g") { + found_f_ = true; + } else if (m_name == "$noinline$g") { if (gJava_StackWalk_refmap_calls == 1) { CHECK_EQ(0xcU, GetDexPc()); - CHECK_REGS(0, 2); // Note that v1 is not in the minimal root set + CHECK_REGS_ARE_REFERENCES(0, 2); // Note that v1 is not in the minimal root set } else { CHECK_EQ(gJava_StackWalk_refmap_calls, 2); CHECK_EQ(0xcU, GetDexPc()); - CHECK_REGS(0, 2); + CHECK_REGS_ARE_REFERENCES(0, 2); } + found_g_ = true; } else if (m_name == "shlemiel") { if (gJava_StackWalk_refmap_calls == 1) { CHECK_EQ(0x380U, GetDexPc()); - CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); + CHECK_REGS_ARE_REFERENCES(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); } else { CHECK_EQ(gJava_StackWalk_refmap_calls, 2); CHECK_EQ(0x380U, GetDexPc()); - CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); + CHECK_REGS_ARE_REFERENCES(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); } + found_shlemiel_ = true; } return true; } -}; -extern "C" JNIEXPORT jint JNICALL Java_Main_stackmap(JNIEnv*, jobject, jint count) { - ScopedObjectAccess soa(Thread::Current()); - CHECK_EQ(count, 0); - gJava_StackWalk_refmap_calls++; - - // Visitor - TestReferenceMapVisitor mapper(soa.Self()); - mapper.WalkStack(); + ~TestReferenceMapVisitor() { + } - return count + 1; -} + bool found_f_ = false; + bool found_g_ = false; + bool found_shlemiel_ = false; +}; -extern "C" JNIEXPORT jint JNICALL Java_Main_refmap2(JNIEnv*, jobject, jint count) { +extern "C" JNIEXPORT jint JNICALL Java_Main_testStackWalk(JNIEnv*, jobject, jint count) { ScopedObjectAccess soa(Thread::Current()); + CHECK_EQ(count, 0); gJava_StackWalk_refmap_calls++; // Visitor TestReferenceMapVisitor mapper(soa.Self()); mapper.WalkStack(); + CHECK(mapper.found_f_); + CHECK(mapper.found_g_); + CHECK(mapper.found_shlemiel_); return count + 1; } diff --git a/test/454-get-vreg/get_vreg_jni.cc b/test/454-get-vreg/get_vreg_jni.cc index 5fc5464d5f..eb81f3b6c8 100644 --- a/test/454-get-vreg/get_vreg_jni.cc +++ b/test/454-get-vreg/get_vreg_jni.cc @@ -34,7 +34,7 @@ class TestVisitor : public StackVisitor { this_value_(this_value), found_method_index_(0) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); diff --git a/test/457-regs/regs_jni.cc b/test/457-regs/regs_jni.cc index f867bdf17c..80abb3b406 100644 --- a/test/457-regs/regs_jni.cc +++ b/test/457-regs/regs_jni.cc @@ -32,7 +32,7 @@ class TestVisitor : public StackVisitor { REQUIRES_SHARED(Locks::mutator_lock_) : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); 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 7eb3fe5ae6..ddc86dffa4 100644 --- a/test/461-get-reference-vreg/get_reference_vreg_jni.cc +++ b/test/461-get-reference-vreg/get_reference_vreg_jni.cc @@ -33,7 +33,7 @@ class TestVisitor : public StackVisitor { this_value_(this_value), found_method_index_(0) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); 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 58ffe04fee..905d8e6db5 100644 --- a/test/466-get-live-vreg/get_live_vreg_jni.cc +++ b/test/466-get-live-vreg/get_live_vreg_jni.cc @@ -32,7 +32,7 @@ class TestVisitor : public StackVisitor { TestVisitor(Thread* thread, Context* context) REQUIRES_SHARED(Locks::mutator_lock_) : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); diff --git a/test/543-env-long-ref/env_long_ref.cc b/test/543-env-long-ref/env_long_ref.cc index ce5602f6e1..165f5bf412 100644 --- a/test/543-env-long-ref/env_long_ref.cc +++ b/test/543-env-long-ref/env_long_ref.cc @@ -34,7 +34,7 @@ class TestVisitor : public StackVisitor { found_(false), soa_(soa) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc index faec3c3534..7b88842fcc 100644 --- a/test/570-checker-osr/osr.cc +++ b/test/570-checker-osr/osr.cc @@ -35,7 +35,7 @@ class OsrVisitor : public StackVisitor { in_osr_method_(false), in_interpreter_(false) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); @@ -95,7 +95,7 @@ class ProfilingInfoVisitor : public StackVisitor { : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), method_name_(method_name) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); @@ -129,7 +129,7 @@ class OsrCheckVisitor : public StackVisitor { : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), method_name_(method_name) {} - bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) { + bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java index ff6e335b7f..4097e33564 100644 --- a/test/623-checker-loop-regressions/src/Main.java +++ b/test/623-checker-loop-regressions/src/Main.java @@ -304,6 +304,19 @@ public class Main { } } + /// CHECK-START-ARM: void Main.$noinline$stringToShorts(short[], java.lang.String) loop_optimization (after) + /// CHECK-NOT: VecLoad + + /// CHECK-START-ARM64: void Main.$noinline$stringToShorts(short[], java.lang.String) loop_optimization (after) + /// CHECK-DAG: VecLoad loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: VecStore loop:<<Loop>> outer_loop:none + private static void $noinline$stringToShorts(short[] dest, String src) { + int min = Math.min(dest.length, src.length()); + for (int i = 0; i < min; ++i) { + dest[i] = (short) src.charAt(i); + } + } + // A strange function that does not inline. private static void $noinline$foo(boolean x, int n) { if (n < 0) @@ -684,6 +697,12 @@ public class Main { expectEquals(aa[i], cc.charAt(i)); } + short[] s2s = new short[12]; + $noinline$stringToShorts(s2s, "abcdefghijkl"); + for (int i = 0; i < s2s.length; ++i) { + expectEquals((short) "abcdefghijkl".charAt(i), s2s[i]); + } + envUsesInCond(); short[] dd = new short[23]; diff --git a/test/669-moveable-string-class-equals/expected.txt b/test/669-moveable-string-class-equals/expected.txt deleted file mode 100644 index 6a5618ebc6..0000000000 --- a/test/669-moveable-string-class-equals/expected.txt +++ /dev/null @@ -1 +0,0 @@ -JNI_OnLoad called diff --git a/test/669-moveable-string-class-equals/info.txt b/test/669-moveable-string-class-equals/info.txt deleted file mode 100644 index 1d3202ef46..0000000000 --- a/test/669-moveable-string-class-equals/info.txt +++ /dev/null @@ -1,2 +0,0 @@ -Regression test for String.equals() intrinsic instanceof check -when the String.class is moveable. diff --git a/test/669-moveable-string-class-equals/run b/test/669-moveable-string-class-equals/run deleted file mode 100755 index 7c74d8ca0e..0000000000 --- a/test/669-moveable-string-class-equals/run +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2017 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. - -# Run without image, so that String.class is moveable. -# Reduce heap size to force more frequent GCs. -${RUN} --no-image --runtime-option -Xmx16m "$@" diff --git a/test/669-moveable-string-class-equals/src/Main.java b/test/669-moveable-string-class-equals/src/Main.java deleted file mode 100644 index d182d51a25..0000000000 --- a/test/669-moveable-string-class-equals/src/Main.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -public class Main { - public static void main(String[] args) { - System.loadLibrary(args[0]); - if (!hasJit()) { - // Make the test pass if not using JIT. - return; - } - if (hasImage()) { - throw new Error("The `run` script should prevent this test from running with an image!"); - } - if (!isClassMoveable(String.class)) { - throw new Error("String.class not moveable despite running without image!"); - } - - // Make sure the Main.test() is JIT-compiled and then call it. - ensureJitCompiled(Main.class, "test"); - test(); - } - - public static void test() { - int length = 5; - - // Hide the type of these strings in an Object array, - // so that we treat them as Object for the String.equals() below. - Object[] array = new Object[length]; - for (int i = 0; i != length; ++i) { - array[i] = "V" + i; - } - - // Continually check string equality between a newly allocated String and an - // already allocated String with the same contents while allocating over 128MiB - // memory (with heap size limited to 16MiB), ensuring we run GC and stress the - // instanceof check in the String.equals() implementation. - for (int count = 0; count != 128 * 1024; ++count) { - for (int i = 0; i != length; ++i) { - allocateAtLeast1KiB(); - assertTrue(("V" + i).equals(array[i])); - } - } - } - - public static void allocateAtLeast1KiB() { - // Give GC more work by allocating Object arrays. - memory[allocationIndex] = new Object[1024 / 4]; - ++allocationIndex; - if (allocationIndex == memory.length) { - allocationIndex = 0; - } - } - - public static void assertTrue(boolean value) { - if (!value) { - throw new Error("Assertion failed!"); - } - } - - private native static boolean hasJit(); - private native static boolean hasImage(); - private native static boolean isClassMoveable(Class<?> cls); - private static native void ensureJitCompiled(Class<?> itf, String method_name); - - // We shall retain some allocated memory and release old allocations - // so that the GC has something to do. - public static Object[] memory = new Object[4096]; - public static int allocationIndex = 0; -} diff --git a/test/980-redefine-object/redef_object.cc b/test/980-redefine-object/redef_object.cc index b4d82ad76d..a8393dc1b3 100644 --- a/test/980-redefine-object/redef_object.cc +++ b/test/980-redefine-object/redef_object.cc @@ -80,13 +80,13 @@ static void JNICALL RedefineObjectHook(jvmtiEnv *jvmti_env, public: explicit JvmtiAllocator(jvmtiEnv* jvmti) : jvmti_(jvmti) {} - void* Allocate(size_t size) { + void* Allocate(size_t size) override { unsigned char* res = nullptr; jvmti_->Allocate(size, &res); return res; } - void Free(void* ptr) { + void Free(void* ptr) override { jvmti_->Deallocate(reinterpret_cast<unsigned char*>(ptr)); } diff --git a/test/Android.bp b/test/Android.bp index e2656516ef..4b61463585 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -417,10 +417,11 @@ art_cc_test_library { art_cc_defaults { name: "libtistress-static-defaults", - defaults: ["libtistress-srcs"], - static_libs: art_static_dependencies + [ - "slicer", + defaults: [ + "libtistress-srcs", + "libart_static_defaults", ], + static_libs: ["slicer"], } art_cc_test_library { diff --git a/test/StackWalk2/StackWalk2.java b/test/StackWalk2/StackWalk2.java deleted file mode 100644 index 5e7b22c252..0000000000 --- a/test/StackWalk2/StackWalk2.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class StackWalk2 { - // use v1 for this - - String str = new String(); // use v0 for str in <init> - - int f() { - g(1); // use v0 for 1, v1 for this - g(2); // use v0 for 2, v1 for this - strTest(); // use v1 for this - return 0; - } - - void g(int num_calls) throws RuntimeException { - if (num_calls == 1) { // use v0 for 1, v3 for num_calls - System.logI("1st call"); // use v0 for PrintStream, v1 for "1st call" - refmap2(24); // use v0 for 24, v2 for this - } else if (num_calls == 2) { // use v0 for 2, v3 for num_calls - System.logI("2nd call"); // use v0 for PrintStream, v1 for "2nd call" - refmap2(25); // use v0 for 24, v2 for this - } - throw new RuntimeException(); // use v0 for new RuntimeException - } - - void strTest() { - System.logI(str); // use v1 for PrintStream, v2, v3 for str - str = null; // use v1 for null, v3 for str - str = new String("ya"); // use v2 for "ya", v1 for new String - String s = str; // use v0, v1, v3 - System.logI(str); // use v1 for PrintStream, v2, v3 for str - System.logI(s); // use v1 for PrintStream, v0 for s - s = null; // use v0 - System.logI(s); // use v1 for PrintStream, v0 for s - } - - native int refmap2(int x); - - public static void main(String[] args) { - System.loadLibrary(args[0]); - StackWalk2 st = new StackWalk2(); - st.f(); - } -} diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc index da79164f12..c9b789e169 100644 --- a/test/common/runtime_state.cc +++ b/test/common/runtime_state.cc @@ -292,15 +292,6 @@ extern "C" JNIEXPORT void JNICALL Java_Main_fetchProfiles(JNIEnv*, jclass) { code_cache->GetProfiledMethods(unused_locations, unused_vector); } -extern "C" JNIEXPORT jboolean JNICALL Java_Main_isClassMoveable(JNIEnv*, - jclass, - jclass cls) { - Runtime* runtime = Runtime::Current(); - ScopedObjectAccess soa(Thread::Current()); - ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls); - return runtime->GetHeap()->IsMovableObject(klass); -} - extern "C" JNIEXPORT void JNICALL Java_Main_waitForCompilation(JNIEnv*, jclass) { jit::Jit* jit = Runtime::Current()->GetJit(); if (jit != nullptr) { diff --git a/test/knownfailures.json b/test/knownfailures.json index 6004f25285..768bc793fc 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -697,9 +697,14 @@ "description": ["Tests that depend on input-vdex are not supported with compact dex"] }, { - "tests": "661-oat-writer-layout", + "tests": ["661-oat-writer-layout"], "variant": "interp-ac | interpreter | jit | no-prebuild | no-image | trace | redefine-stress | jvmti-stress", - "description": ["Test is designed to only check --compiler-filter=speed"] + "description": ["Test is designed to only check --optimizing"] + }, + { + "tests": ["004-StackWalk"], + "variant": "interp-ac | interpreter | jit | no-prebuild | no-image | trace | redefine-stress | jvmti-stress | debuggable", + "description": ["Test is designed to only check --optimizing"] }, { "tests": "674-HelloWorld-Dm", diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc index bd320c66cc..e123e9f081 100644 --- a/test/ti-stress/stress.cc +++ b/test/ti-stress/stress.cc @@ -92,7 +92,7 @@ static bool DoExtractClassFromData(jvmtiEnv* env, struct Allocator : public dex::Writer::Allocator { explicit Allocator(jvmtiEnv* jvmti_env) : jvmti_env_(jvmti_env) {} - virtual void* Allocate(size_t size) { + void* Allocate(size_t size) override { unsigned char* out = nullptr; if (JVMTI_ERROR_NONE != jvmti_env_->Allocate(size, &out)) { return nullptr; @@ -100,7 +100,7 @@ static bool DoExtractClassFromData(jvmtiEnv* env, return out; } } - virtual void Free(void* ptr) { + void Free(void* ptr) override { jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(ptr)); } private: diff --git a/tools/ahat/etc/ahat_api.txt b/tools/ahat/etc/ahat_api.txt index 5426f7b866..7aa994a805 100644 --- a/tools/ahat/etc/ahat_api.txt +++ b/tools/ahat/etc/ahat_api.txt @@ -96,6 +96,7 @@ package com.android.ahat.heapdump { method public boolean isArrayInstance(); method public boolean isClassInstance(); method public boolean isClassObj(); + method public boolean isInstanceOfClass(java.lang.String); method public boolean isPlaceHolder(); method public boolean isRoot(); method public boolean isStronglyReachable(); @@ -226,6 +227,7 @@ package com.android.ahat.heapdump { method public int getLineNumber(); method public java.lang.String getMethodName(); method public void getObjects(java.lang.String, java.lang.String, java.util.Collection<com.android.ahat.heapdump.AhatInstance>); + method public void getObjects(java.util.function.Predicate<com.android.ahat.heapdump.AhatInstance>, java.util.function.Consumer<com.android.ahat.heapdump.AhatInstance>); method public java.util.List<com.android.ahat.heapdump.Site.ObjectsInfo> getObjectsInfos(); method public com.android.ahat.heapdump.Site getParent(); method public java.lang.String getSignature(); diff --git a/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java b/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java index 1a8f018bd5..81611b6c72 100644 --- a/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java +++ b/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java @@ -16,6 +16,7 @@ package com.android.ahat; +import com.android.ahat.heapdump.AhatHeap; import com.android.ahat.heapdump.AhatInstance; import com.android.ahat.heapdump.AhatSnapshot; import com.android.ahat.heapdump.Site; @@ -24,6 +25,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Predicate; class ObjectsHandler implements AhatHandler { private static final String OBJECTS_ID = "objects"; @@ -34,32 +36,102 @@ class ObjectsHandler implements AhatHandler { mSnapshot = snapshot; } + /** + * Get the list of instances that match the given site, class, and heap + * filters. This method is public to facilitate testing. + * + * @param site the site to get instances from + * @param className non-null name of the class to restrict instances to. + * @param subclass if true, include instances of subclasses of the named class. + * @param heapName name of the heap to restrict instances to. May be null to + * allow instances on any heap. + * @return list of matching instances + */ + public static List<AhatInstance> getObjects( + Site site, String className, boolean subclass, String heapName) { + Predicate<AhatInstance> predicate = (x) -> { + return (heapName == null || x.getHeap().getName().equals(heapName)) + && (subclass ? x.isInstanceOfClass(className) : className.equals(x.getClassName())); + }; + + List<AhatInstance> insts = new ArrayList<AhatInstance>(); + site.getObjects(predicate, x -> insts.add(x)); + return insts; + } + @Override public void handle(Doc doc, Query query) throws IOException { int id = query.getInt("id", 0); - String className = query.get("class", null); + String className = query.get("class", "java.lang.Object"); String heapName = query.get("heap", null); + boolean subclass = (query.getInt("subclass", 0) != 0); Site site = mSnapshot.getSite(id); - List<AhatInstance> insts = new ArrayList<AhatInstance>(); - site.getObjects(heapName, className, insts); + List<AhatInstance> insts = getObjects(site, className, subclass, heapName); Collections.sort(insts, Sort.defaultInstanceCompare(mSnapshot)); - doc.title("Objects"); + doc.title("Instances"); + + // Write a description of the current settings, with links to adjust the + // settings, such as: + // Site: ROOT - + // Class: android.os.Binder + // Subclasses: excluded (switch to included) + // Heap: any (switch to app, image, zygote) + // Count: 17,424 + doc.descriptions(); + doc.description(DocString.text("Site"), Summarizer.summarize(site)); + doc.description(DocString.text("Class"), DocString.text(className)); + + DocString subclassChoice = DocString.text(subclass ? "included" : "excluded"); + subclassChoice.append(" (switch to "); + subclassChoice.appendLink(query.with("subclass", subclass ? 0 : 1), + DocString.text(subclass ? "excluded" : "included")); + subclassChoice.append(")"); + doc.description(DocString.text("Subclasses"), subclassChoice); + + DocString heapChoice = DocString.text(heapName == null ? "any" : heapName); + heapChoice.append(" (switch to "); + String comma = ""; + for (AhatHeap heap : mSnapshot.getHeaps()) { + if (!heap.getName().equals(heapName)) { + heapChoice.append(comma); + heapChoice.appendLink( + query.with("heap", heap.getName()), + DocString.text(heap.getName())); + comma = ", "; + } + } + if (heapName != null) { + heapChoice.append(comma); + heapChoice.appendLink( + query.with("heap", null), + DocString.text("any")); + } + heapChoice.append(")"); + doc.description(DocString.text("Heap"), heapChoice); + + doc.description(DocString.text("Count"), DocString.format("%,14d", insts.size())); + doc.end(); + doc.println(DocString.text("")); - SizeTable.table(doc, mSnapshot.isDiffed(), - new Column("Heap"), - new Column("Object")); + if (insts.isEmpty()) { + doc.println(DocString.text("(none)")); + } else { + SizeTable.table(doc, mSnapshot.isDiffed(), + new Column("Heap"), + new Column("Object")); - SubsetSelector<AhatInstance> selector = new SubsetSelector(query, OBJECTS_ID, insts); - for (AhatInstance inst : selector.selected()) { - AhatInstance base = inst.getBaseline(); - SizeTable.row(doc, inst.getSize(), base.getSize(), - DocString.text(inst.getHeap().getName()), - Summarizer.summarize(inst)); + SubsetSelector<AhatInstance> selector = new SubsetSelector(query, OBJECTS_ID, insts); + for (AhatInstance inst : selector.selected()) { + AhatInstance base = inst.getBaseline(); + SizeTable.row(doc, inst.getSize(), base.getSize(), + DocString.text(inst.getHeap().getName()), + Summarizer.summarize(inst)); + } + SizeTable.end(doc); + selector.render(doc); } - SizeTable.end(doc); - selector.render(doc); } } diff --git a/tools/ahat/src/main/com/android/ahat/Query.java b/tools/ahat/src/main/com/android/ahat/Query.java index 9c2783c081..5f064cdada 100644 --- a/tools/ahat/src/main/com/android/ahat/Query.java +++ b/tools/ahat/src/main/com/android/ahat/Query.java @@ -79,7 +79,9 @@ class Query { /** * Return a uri suitable for an href target that links to the current * page, except with the named query parameter set to the new value. - * + * <p> + * <code>value</code> may be null to remove the named query parameter. + * <p> * The generated parameters will be sorted alphabetically so it is easier to * test. */ @@ -92,11 +94,13 @@ class Query { params.put(name, value); String and = ""; for (Map.Entry<String, String> entry : params.entrySet()) { - newQuery.append(and); - newQuery.append(entry.getKey()); - newQuery.append('='); - newQuery.append(entry.getValue()); - and = "&"; + if (entry.getValue() != null) { + newQuery.append(and); + newQuery.append(entry.getKey()); + newQuery.append('='); + newQuery.append(entry.getValue()); + and = "&"; + } } return DocString.uri(newQuery.toString()); } diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java index 4c60d8b2c8..0511798cad 100644 --- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java +++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java @@ -107,21 +107,6 @@ public class AhatClassInstance extends AhatInstance { return new ReferenceIterator(); } - /** - * Returns true if this is an instance of a (subclass of a) class with the - * given name. - */ - private boolean isInstanceOfClass(String className) { - AhatClassObj cls = getClassObj(); - while (cls != null) { - if (className.equals(cls.getName())) { - return true; - } - cls = cls.getSuperClassObj(); - } - return false; - } - @Override public String asString(int maxChars) { if (!isInstanceOfClass("java.lang.String")) { return null; diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java index 3d691c7b22..c85a057060 100644 --- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java +++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java @@ -330,6 +330,25 @@ public abstract class AhatInstance implements Diffable<AhatInstance> { } /** + * Returns true if this is an instance of a (subclass of a) class with the + * given name. + * + * @param className the name of the class to check for + * @return true if this is an instance of a (subclass of a) class with the + * given name + */ + public boolean isInstanceOfClass(String className) { + AhatClassObj cls = getClassObj(); + while (cls != null) { + if (className.equals(cls.getName())) { + return true; + } + cls = cls.getSuperClassObj(); + } + return false; + } + + /** * Returns true if the given instance is an array instance. * * @return true if the given instance is an array instance diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Site.java b/tools/ahat/src/main/com/android/ahat/heapdump/Site.java index 46a17296b7..4f0660fb50 100644 --- a/tools/ahat/src/main/com/android/ahat/heapdump/Site.java +++ b/tools/ahat/src/main/com/android/ahat/heapdump/Site.java @@ -23,6 +23,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Predicate; /** * Used to collection information about objects allocated at a particular @@ -259,22 +261,37 @@ public class Site implements Diffable<Site> { * every heap should be collected. * @param className the name of the class the collected objects should * belong to. This may be null to indicate objects of - * every class should be collected. + * every class should be collected. Instances of subclasses + * of this class are not included. * @param objects out parameter. A collection of objects that all * collected objects should be added to. */ public void getObjects(String heapName, String className, Collection<AhatInstance> objects) { + Predicate<AhatInstance> predicate = x -> { + return (heapName == null || x.getHeap().getName().equals(heapName)) + && (className == null || x.getClassName().equals(className)); + }; + getObjects(predicate, x -> objects.add(x)); + } + + /** + * Collects the objects allocated under this site, filtered by the given + * predicate. + * Includes objects allocated in children sites. + * @param predicate limit instances to those satisfying this predicate + * @param consumer consumer of the objects + */ + public void getObjects(Predicate<AhatInstance> predicate, Consumer<AhatInstance> consumer) { for (AhatInstance inst : mObjects) { - if ((heapName == null || inst.getHeap().getName().equals(heapName)) - && (className == null || inst.getClassName().equals(className))) { - objects.add(inst); + if (predicate.test(inst)) { + consumer.accept(inst); } } // Recursively visit children. Recursion should be okay here because the // stack depth is limited by a reasonable amount (128 frames or so). for (Site child : mChildren) { - child.getObjects(heapName, className, objects); + child.getObjects(predicate, consumer); } } diff --git a/tools/ahat/src/test/com/android/ahat/AhatTestSuite.java b/tools/ahat/src/test/com/android/ahat/AhatTestSuite.java index 3aa52b5bb8..abc3cc7561 100644 --- a/tools/ahat/src/test/com/android/ahat/AhatTestSuite.java +++ b/tools/ahat/src/test/com/android/ahat/AhatTestSuite.java @@ -29,6 +29,7 @@ import org.junit.runners.Suite; InstanceTest.class, NativeAllocationTest.class, ObjectHandlerTest.class, + ObjectsHandlerTest.class, OverviewHandlerTest.class, PerformanceTest.class, ProguardMapTest.class, diff --git a/tools/ahat/src/test/com/android/ahat/ObjectsHandlerTest.java b/tools/ahat/src/test/com/android/ahat/ObjectsHandlerTest.java new file mode 100644 index 0000000000..927e017ba9 --- /dev/null +++ b/tools/ahat/src/test/com/android/ahat/ObjectsHandlerTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 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. + */ + +package com.android.ahat; + +import com.android.ahat.heapdump.AhatInstance; +import com.android.ahat.heapdump.AhatSnapshot; +import com.android.ahat.heapdump.Site; +import java.io.IOException; +import java.util.List; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class ObjectsHandlerTest { + @Test + public void getObjects() throws IOException { + TestDump dump = TestDump.getTestDump(); + AhatSnapshot snapshot = dump.getAhatSnapshot(); + + Site root = snapshot.getRootSite(); + + // We expect a single instance of DumpedStuff + List<AhatInstance> dumped = ObjectsHandler.getObjects( + root, "DumpedStuff", /* subclass */ false, /* heapName */ null); + assertEquals(1, dumped.size()); + assertTrue(dumped.get(0).getClassName().equals("DumpedStuff")); + + // We expect no direct instances of SuperDumpedStuff + List<AhatInstance> direct = ObjectsHandler.getObjects( + root, "SuperDumpedStuff", /* subclass */ false, /* heapName */ null); + assertTrue(direct.isEmpty()); + + // We expect one subclass instance of SuperDumpedStuff + List<AhatInstance> subclass = ObjectsHandler.getObjects( + root, "SuperDumpedStuff", /* subclass */ true, /* heapName */ null); + assertEquals(1, subclass.size()); + assertTrue(subclass.get(0).getClassName().equals("DumpedStuff")); + assertEquals(dumped.get(0), subclass.get(0)); + } +} diff --git a/tools/ahat/src/test/com/android/ahat/QueryTest.java b/tools/ahat/src/test/com/android/ahat/QueryTest.java index 5bcf8eafc3..52cf963bd9 100644 --- a/tools/ahat/src/test/com/android/ahat/QueryTest.java +++ b/tools/ahat/src/test/com/android/ahat/QueryTest.java @@ -41,6 +41,7 @@ public class QueryTest { assertEquals("/object?answer=43&foo=bar", query.with("answer", "43").toString()); assertEquals("/object?answer=43&foo=bar", query.with("answer", 43).toString()); assertEquals("/object?answer=42&bar=finally&foo=bar", query.with("bar", "finally").toString()); + assertEquals("/object?answer=42", query.with("foo", null).toString()); } @Test @@ -55,6 +56,7 @@ public class QueryTest { assertEquals("/object?answer=43&foo=sludge", query.with("answer", "43").toString()); assertEquals("/object?answer=42&bar=finally&foo=sludge", query.with("bar", "finally").toString()); + assertEquals("/object?answer=42", query.with("foo", null).toString()); } @Test @@ -66,5 +68,6 @@ public class QueryTest { assertEquals(2, query.getInt("foo", 2)); assertEquals("/object?foo=sludge", query.with("foo", "sludge").toString()); assertEquals("/object?answer=43", query.with("answer", "43").toString()); + assertEquals("/object?", query.with("foo", null).toString()); } } diff --git a/tools/amm/Android.bp b/tools/amm/Android.bp new file mode 100644 index 0000000000..e6f6ff76f0 --- /dev/null +++ b/tools/amm/Android.bp @@ -0,0 +1,25 @@ +// Copyright (C) 2017 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. + +// --- ammtestjni.so ------------- + +cc_library_shared { + name: "libammtestjni", + + srcs: [ + "AmmTest/jni/ammtest.c", + ], + + sdk_version: "current", +} diff --git a/tools/amm/Android.mk b/tools/amm/Android.mk index 47030c5a7a..fa4ca44047 100644 --- a/tools/amm/Android.mk +++ b/tools/amm/Android.mk @@ -14,13 +14,6 @@ LOCAL_PATH := $(call my-dir) -# --- ammtestjni.so ------------- -include $(CLEAR_VARS) -LOCAL_MODULE := libammtestjni -LOCAL_SRC_FILES := $(call all-c-files-under, AmmTest/jni) -LOCAL_SDK_VERSION := current -include $(BUILD_SHARED_LIBRARY) - # --- AmmTest.apk -------------- include $(CLEAR_VARS) LOCAL_PACKAGE_NAME := AmmTest @@ -31,4 +24,3 @@ LOCAL_JNI_SHARED_LIBRARIES := libammtestjni LOCAL_JAVA_RESOURCE_FILES := $(LOCAL_PATH)/AmmTest/aahat.png LOCAL_MANIFEST_FILE := AmmTest/AndroidManifest.xml include $(BUILD_PACKAGE) - diff --git a/tools/art_verifier/Android.bp b/tools/art_verifier/Android.bp index afd52fbcaa..6fff27a61a 100644 --- a/tools/art_verifier/Android.bp +++ b/tools/art_verifier/Android.bp @@ -16,7 +16,10 @@ art_cc_defaults { name: "art_verifier-defaults", - defaults: ["art_defaults"], + defaults: [ + "art_defaults", + "libart_static_defaults", + ], host_supported: true, srcs: [ "art_verifier.cc", @@ -24,11 +27,8 @@ art_cc_defaults { header_libs: [ "art_cmdlineparser_headers", ], - static_libs: art_static_dependencies + [ - "libart", - "libartbase", - "libdexfile", - "libprofile", + static_libs: [ + "libsigchain_dummy", ], target: { android: { diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc index 8f412bf7a6..45c1a330cc 100644 --- a/tools/art_verifier/art_verifier.cc +++ b/tools/art_verifier/art_verifier.cc @@ -137,7 +137,7 @@ struct MethodVerifierArgs : public CmdlineArgs { return kParseOk; } - virtual std::string GetUsage() const { + std::string GetUsage() const override { std::string usage; usage += diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh index 830505124e..b5d39e1781 100755 --- a/tools/buildbot-build.sh +++ b/tools/buildbot-build.sh @@ -68,15 +68,15 @@ if [[ $mode == "host" ]]; then make_command+=" dx-tests" mode_suffix="-host" elif [[ $mode == "target" ]]; then - if [[ -z "$TARGET_PRODUCT" ]]; then - echo 'TARGET_PRODUCT environment variable is empty; did you forget to run `lunch`?' + if [[ -z "${ANDROID_PRODUCT_OUT}" ]]; then + echo 'ANDROID_PRODUCT_OUT environment variable is empty; did you forget to run `lunch`?' exit 1 fi make_command="make $j_arg $extra_args $showcommands build-art-target-tests $common_targets" make_command+=" libjavacrypto-target libnetd_client-target linker toybox toolbox sh" make_command+=" debuggerd su" make_command+=" ${out_dir}/host/linux-x86/bin/adb libstdc++ " - make_command+=" ${out_dir}/target/product/${TARGET_PRODUCT}/system/etc/public.libraries.txt" + make_command+=" ${ANDROID_PRODUCT_OUT#"${ANDROID_BUILD_TOP}/"}/system/etc/public.libraries.txt" if [[ -n "$ART_TEST_CHROOT" ]]; then # These targets are needed for the chroot environment. make_command+=" crash_dump event-log-tags" diff --git a/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java b/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java index 92620760e7..53157a323e 100644 --- a/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java +++ b/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java @@ -33,10 +33,12 @@ import org.apache.commons.cli.ParseException; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -71,9 +73,10 @@ public class Class2Greylist { .hasArgs() .withDescription( "Specify file to write greylist to. Can be specified multiple times. " + - "Format is either just a filename, or \"int:filename\". If an integer is " + - "given, members with a matching maxTargetSdk are written to the file; if " + - "no integer is given, members with no maxTargetSdk are written.") + "Format is either just a filename, or \"int[,int,...]:filename\". If " + + "integers are given, members with matching maxTargetSdk values are " + + "written to the file; if no integer or \"none\" is given, members with " + + "no maxTargetSdk are written.") .create("g")); options.addOption(OptionBuilder .withLongOpt("write-whitelist") @@ -204,15 +207,22 @@ public class Class2Greylist { static Map<Integer, String> readGreylistMap(Status status, String[] argValues) { Map<Integer, String> map = new HashMap<>(); for (String sdkFile : argValues) { - Integer maxTargetSdk = null; + List<Integer> maxTargetSdks = new ArrayList<>(); String filename; int colonPos = sdkFile.indexOf(':'); if (colonPos != -1) { - try { - maxTargetSdk = Integer.valueOf(sdkFile.substring(0, colonPos)); - } catch (NumberFormatException nfe) { - status.error("Not a valid integer: %s from argument value '%s'", - sdkFile.substring(0, colonPos), sdkFile); + String[] targets = sdkFile.substring(0, colonPos).split(","); + for (String target : targets) { + if ("none".equals(target)) { + maxTargetSdks.add(null); + } else { + try { + maxTargetSdks.add(Integer.valueOf(target)); + } catch (NumberFormatException nfe) { + status.error("Not a valid integer: %s from argument value '%s'", + sdkFile.substring(0, colonPos), sdkFile); + } + } } filename = sdkFile.substring(colonPos + 1); if (filename.length() == 0) { @@ -220,13 +230,16 @@ public class Class2Greylist { filename, sdkFile); } } else { - maxTargetSdk = null; + maxTargetSdks.add(null); filename = sdkFile; } - if (map.containsKey(maxTargetSdk)) { - status.error("Multiple output files for maxTargetSdk %s", maxTargetSdk); - } else { - map.put(maxTargetSdk, filename); + for (Integer maxTargetSdk : maxTargetSdks) { + if (map.containsKey(maxTargetSdk)) { + status.error("Multiple output files for maxTargetSdk %s", + maxTargetSdk == null ? "none" : maxTargetSdk); + } else { + map.put(maxTargetSdk, filename); + } } } return map; diff --git a/tools/class2greylist/src/com/android/class2greylist/FileWritingGreylistConsumer.java b/tools/class2greylist/src/com/android/class2greylist/FileWritingGreylistConsumer.java index 9f334677c3..bfd23102b9 100644 --- a/tools/class2greylist/src/com/android/class2greylist/FileWritingGreylistConsumer.java +++ b/tools/class2greylist/src/com/android/class2greylist/FileWritingGreylistConsumer.java @@ -1,5 +1,7 @@ package com.android.class2greylist; +import com.google.common.annotations.VisibleForTesting; + import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -20,11 +22,16 @@ public class FileWritingGreylistConsumer implements GreylistConsumer { return new PrintStream(new FileOutputStream(new File(filename))); } - private static Map<Integer, PrintStream> openFiles( + @VisibleForTesting + public static Map<Integer, PrintStream> openFiles( Map<Integer, String> filenames) throws FileNotFoundException { + Map<String, PrintStream> streamsByName = new HashMap<>(); Map<Integer, PrintStream> streams = new HashMap<>(); for (Map.Entry<Integer, String> entry : filenames.entrySet()) { - streams.put(entry.getKey(), openFile(entry.getValue())); + if (!streamsByName.containsKey(entry.getValue())) { + streamsByName.put(entry.getValue(), openFile(entry.getValue())); + } + streams.put(entry.getKey(), streamsByName.get(entry.getValue())); } return streams; } diff --git a/tools/class2greylist/test/src/com/android/class2greylist/Class2GreylistTest.java b/tools/class2greylist/test/src/com/android/class2greylist/Class2GreylistTest.java index cb75dd30ed..b87a5b1c3f 100644 --- a/tools/class2greylist/test/src/com/android/class2greylist/Class2GreylistTest.java +++ b/tools/class2greylist/test/src/com/android/class2greylist/Class2GreylistTest.java @@ -56,6 +56,31 @@ public class Class2GreylistTest { } @Test + public void testReadGreylistMapNone() throws IOException { + Map<Integer, String> map = Class2Greylist.readGreylistMap(mStatus, + new String[]{"none:noApi"}); + verifyZeroInteractions(mStatus); + assertThat(map).containsExactly(null, "noApi"); + } + + @Test + public void testReadGreylistMapMulti() throws IOException { + Map<Integer, String> map = Class2Greylist.readGreylistMap(mStatus, + new String[]{"1,none:noOr1Api", "3:apiThree"}); + verifyZeroInteractions(mStatus); + assertThat(map).containsExactly(null, "noOr1Api", 1, "noOr1Api", 3, "apiThree"); + } + + @Test + public void testReadGreylistMapMulti2() throws IOException { + Map<Integer, String> map = Class2Greylist.readGreylistMap(mStatus, + new String[]{"1,none,2,3,4:allApi"}); + verifyZeroInteractions(mStatus); + assertThat(map).containsExactly( + null, "allApi", 1, "allApi", 2, "allApi", 3, "allApi", 4, "allApi"); + } + + @Test public void testReadGreylistMapDuplicate() throws IOException { Class2Greylist.readGreylistMap(mStatus, new String[]{"noApi", "1:apiOne", "1:anotherOne"}); diff --git a/tools/class2greylist/test/src/com/android/class2greylist/FileWritingGreylistConsumerTest.java b/tools/class2greylist/test/src/com/android/class2greylist/FileWritingGreylistConsumerTest.java new file mode 100644 index 0000000000..1e1b1df910 --- /dev/null +++ b/tools/class2greylist/test/src/com/android/class2greylist/FileWritingGreylistConsumerTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 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. + */ + +package com.android.class2greylist; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.common.collect.ImmutableMap; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.mockito.Mock; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class FileWritingGreylistConsumerTest { + + @Mock + Status mStatus; + @Rule + public TestName mTestName = new TestName(); + private int mFileNameSeq = 0; + private final List<String> mTempFiles = new ArrayList<>(); + + @Before + public void setup() throws IOException { + System.out.println(String.format("\n============== STARTING TEST: %s ==============\n", + mTestName.getMethodName())); + initMocks(this); + } + + @After + public void removeTempFiles() { + for (String name : mTempFiles) { + new File(name).delete(); + } + } + + private String tempFileName() { + String name = String.format(Locale.US, "/tmp/test-%s-%d", + mTestName.getMethodName(), mFileNameSeq++); + mTempFiles.add(name); + return name; + } + + @Test + public void testSimpleMap() throws FileNotFoundException { + Map<Integer, PrintStream> streams = FileWritingGreylistConsumer.openFiles( + ImmutableMap.of(1, tempFileName(), 2, tempFileName())); + assertThat(streams.keySet()).containsExactly(1, 2); + assertThat(streams.get(1)).isNotNull(); + assertThat(streams.get(2)).isNotNull(); + assertThat(streams.get(2)).isNotSameAs(streams.get(1)); + } + + @Test + public void testCommonMappings() throws FileNotFoundException { + String name = tempFileName(); + Map<Integer, PrintStream> streams = FileWritingGreylistConsumer.openFiles( + ImmutableMap.of(1, name, 2, name)); + assertThat(streams.keySet()).containsExactly(1, 2); + assertThat(streams.get(1)).isNotNull(); + assertThat(streams.get(2)).isSameAs(streams.get(1)); + } +} diff --git a/tools/field-null-percent/check-null-fields.py b/tools/field-null-percent/check-null-fields.py new file mode 100755 index 0000000000..c11d51a1b0 --- /dev/null +++ b/tools/field-null-percent/check-null-fields.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 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. + +""" +Retrieves the counts of how many objects have a particular field null on all running processes. + +Prints a json map from pid -> (log-tag, field-name, null-count, total-count). +""" + + +import adb +import argparse +import concurrent.futures +import itertools +import json +import logging +import os +import os.path +import signal +import subprocess +import time + +def main(): + parser = argparse.ArgumentParser(description="Get counts of null fields from a device.") + parser.add_argument("-S", "--serial", metavar="SERIAL", type=str, + required=False, + default=os.environ.get("ANDROID_SERIAL", None), + help="Android serial to use. Defaults to ANDROID_SERIAL") + parser.add_argument("-p", "--pid", required=False, + default=[], action="append", + help="Specific pids to check. By default checks all running dalvik processes") + has_out = "OUT" in os.environ + def_32 = os.path.join(os.environ.get("OUT", ""), "system", "lib", "libfieldnull.so") + def_64 = os.path.join(os.environ.get("OUT", ""), "system", "lib64", "libfieldnull.so") + has_32 = has_out and os.path.exists(def_32) + has_64 = has_out and os.path.exists(def_64) + def pushable_lib(name): + if os.path.isfile(name): + return name + else: + raise argparse.ArgumentTypeError(name + " is not a file!") + parser.add_argument('--lib32', type=pushable_lib, + required=not has_32, + action='store', + default=def_32, + help="Location of 32 bit agent to push") + parser.add_argument('--lib64', type=pushable_lib, + required=not has_64, + action='store', + default=def_64 if has_64 else None, + help="Location of 64 bit agent to push") + parser.add_argument("fields", nargs="+", + help="fields to check") + + out = parser.parse_args() + + device = adb.device.get_device(out.serial) + print("getting root") + device.root() + + print("Disabling selinux") + device.shell("setenforce 0".split()) + + print("Pushing libraries") + lib32 = device.shell("mktemp".split())[0].strip() + lib64 = device.shell("mktemp".split())[0].strip() + + print(out.lib32 + " -> " + lib32) + device.push(out.lib32, lib32) + + print(out.lib64 + " -> " + lib64) + device.push(out.lib64, lib64) + + cmd32 = "'{}={}'".format(lib32, ','.join(out.fields)) + cmd64 = "'{}={}'".format(lib64, ','.join(out.fields)) + + if len(out.pid) == 0: + print("Getting jdwp pids") + new_env = dict(os.environ) + new_env["ANDROID_SERIAL"] = device.serial + p = subprocess.Popen([device.adb_path, "jdwp"], env=new_env, stdout=subprocess.PIPE) + # ADB jdwp doesn't ever exit so just kill it after 1 second to get a list of pids. + with concurrent.futures.ProcessPoolExecutor() as ppe: + ppe.submit(kill_it, p.pid).result() + out.pid = p.communicate()[0].strip().split() + p.wait() + print(out.pid) + print("Clearing logcat") + device.shell("logcat -c".split()) + final = {} + print("Getting info from every process dumped to logcat") + for p in out.pid: + res = check_single_process(p, device, cmd32, cmd64); + if res is not None: + final[p] = res + device.shell('rm {}'.format(lib32).split()) + device.shell('rm {}'.format(lib64).split()) + print(json.dumps(final, indent=2)) + +def kill_it(p): + time.sleep(1) + os.kill(p, signal.SIGINT) + +def check_single_process(pid, device, bit32, bit64): + try: + # Just try attaching both 32 and 64 bit. Wrong one will fail silently. + device.shell(['am', 'attach-agent', str(pid), bit32]) + device.shell(['am', 'attach-agent', str(pid), bit64]) + time.sleep(0.5) + device.shell('kill -3 {}'.format(pid).split()) + time.sleep(0.5) + out = [] + all_fields = [] + lc_cmd = "logcat -d -b main --pid={} -e '^\\t.*\\t[0-9]*\\t[0-9]*$'".format(pid).split(' ') + for l in device.shell(lc_cmd)[0].strip().split('\n'): + # first 4 are just date and other useless data. + data = l.strip().split()[5:] + if len(data) < 4: + continue + # If we run multiple times many copies of the agent will be attached. Just choose one of any + # copies for each field. + field = data[1] + if field not in all_fields: + out.append((str(data[0]), str(data[1]), int(data[2]), int(data[3]))) + all_fields.append(field) + if len(out) != 0: + print("pid: " + pid + " -> " + str(out)) + return out + else: + return None + except adb.device.ShellError as e: + print("failed on pid " + repr(pid) + " because " + repr(e)) + return None + +if __name__ == '__main__': + main() diff --git a/tools/field-null-percent/fieldnull.cc b/tools/field-null-percent/fieldnull.cc index 86459d238b..1bd122a1b2 100644 --- a/tools/field-null-percent/fieldnull.cc +++ b/tools/field-null-percent/fieldnull.cc @@ -147,7 +147,7 @@ static void VMDeathCb(jvmtiEnv* jvmti, JNIEnv* env ATTRIBUTE_UNUSED) { delete list; } -static void CreateFieldList(jvmtiEnv* jvmti, JNIEnv* env, std::string args) { +static void CreateFieldList(jvmtiEnv* jvmti, JNIEnv* env, const std::string& args) { RequestList* list = nullptr; CHECK_JVMTI(jvmti->Allocate(sizeof(*list), reinterpret_cast<unsigned char**>(&list))); new (list) RequestList { .fields_ = GetRequestedFields(env, args), }; diff --git a/tools/libcore_gcstress_failures.txt b/tools/libcore_gcstress_failures.txt index 965e85c359..fff1c70ad8 100644 --- a/tools/libcore_gcstress_failures.txt +++ b/tools/libcore_gcstress_failures.txt @@ -29,6 +29,7 @@ modes: [device], names: ["libcore.java.lang.StringTest#testFastPathString_wellFormedUtf8Sequence", "org.apache.harmony.tests.java.lang.ref.ReferenceQueueTest#test_remove", + "org.apache.harmony.tests.java.text.DateFormatTest#test_getAvailableLocales", "org.apache.harmony.tests.java.util.TimerTest#testOverdueTaskExecutesImmediately", "org.apache.harmony.tests.java.util.WeakHashMapTest#test_keySet_hasNext", "libcore.java.text.DecimalFormatTest#testCurrencySymbolSpacing", diff --git a/tools/titrace/instruction_decoder.cc b/tools/titrace/instruction_decoder.cc index d8fb713414..7f8b296bc3 100644 --- a/tools/titrace/instruction_decoder.cc +++ b/tools/titrace/instruction_decoder.cc @@ -32,7 +32,7 @@ class ClassInstructionDecoder : public InstructionDecoder { return Bytecode::ToString(op); } - virtual size_t LocationToOffset(size_t j_location) { + size_t LocationToOffset(size_t j_location) override { return j_location; } @@ -474,7 +474,7 @@ class DexInstructionDecoder : public InstructionDecoder { return Bytecode::ToString(op); } - virtual size_t LocationToOffset(size_t j_location) { + size_t LocationToOffset(size_t j_location) override { // dex pc is uint16_t*, but offset needs to be in bytes. return j_location * (sizeof(uint16_t) / sizeof(uint8_t)); } diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc index 4eba10e764..d81f133f67 100644 --- a/tools/veridex/hidden_api_finder.cc +++ b/tools/veridex/hidden_api_finder.cc @@ -178,7 +178,8 @@ void HiddenApiFinder::Dump(std::ostream& os, stats->linking_count = method_locations_.size() + field_locations_.size(); // Dump methods from hidden APIs linked against. - for (const std::pair<std::string, std::vector<MethodReference>>& pair : method_locations_) { + for (const std::pair<const std::string, + std::vector<MethodReference>>& pair : method_locations_) { HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(pair.first); stats->api_counts[api_list]++; os << "#" << ++stats->count << ": Linking " << api_list << " " << pair.first << " use(s):"; @@ -190,7 +191,8 @@ void HiddenApiFinder::Dump(std::ostream& os, } // Dump fields from hidden APIs linked against. - for (const std::pair<std::string, std::vector<MethodReference>>& pair : field_locations_) { + for (const std::pair<const std::string, + std::vector<MethodReference>>& pair : field_locations_) { HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(pair.first); stats->api_counts[api_list]++; os << "#" << ++stats->count << ": Linking " << api_list << " " << pair.first << " use(s):"; |