diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/Android.bp | 1 | ||||
| -rw-r--r-- | compiler/dex/dex_to_dex_decompiler.cc | 208 | ||||
| -rw-r--r-- | compiler/dex/dex_to_dex_decompiler.h | 39 | ||||
| -rw-r--r-- | compiler/dex/dex_to_dex_decompiler_test.cc | 4 | ||||
| -rw-r--r-- | compiler/dex/verification_results.cc | 7 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 82 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver_test.cc | 2 | ||||
| -rw-r--r-- | compiler/driver/compiler_options.h | 22 | ||||
| -rw-r--r-- | compiler/oat_test.cc | 2 | ||||
| -rw-r--r-- | compiler/oat_writer.cc | 31 | ||||
| -rw-r--r-- | compiler/optimizing/graph_checker.cc | 3 |
11 files changed, 56 insertions, 345 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp index dec8b577d8..6ef866a3c6 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -28,7 +28,6 @@ art_cc_defaults { "compiled_method.cc", "debug/elf_debug_writer.cc", "dex/dex_to_dex_compiler.cc", - "dex/dex_to_dex_decompiler.cc", "dex/inline_method_analyser.cc", "dex/verified_method.cc", "dex/verification_results.cc", diff --git a/compiler/dex/dex_to_dex_decompiler.cc b/compiler/dex/dex_to_dex_decompiler.cc deleted file mode 100644 index 85d5784c7a..0000000000 --- a/compiler/dex/dex_to_dex_decompiler.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "dex_to_dex_decompiler.h" - -#include "base/logging.h" -#include "base/mutex.h" -#include "dex_file-inl.h" -#include "dex_instruction-inl.h" -#include "bytecode_utils.h" - -namespace art { -namespace optimizer { - -class DexDecompiler { - public: - DexDecompiler(const DexFile::CodeItem& code_item, - const ArrayRef<const uint8_t>& quickened_info, - bool decompile_return_instruction) - : code_item_(code_item), - quickened_info_ptr_(quickened_info.data()), - quickened_info_end_(quickened_info.data() + quickened_info.size()), - decompile_return_instruction_(decompile_return_instruction) {} - - bool Decompile(); - - private: - void DecompileInstanceFieldAccess(Instruction* inst, - uint32_t dex_pc, - Instruction::Code new_opcode) { - uint16_t index = GetIndexAt(dex_pc); - inst->SetOpcode(new_opcode); - inst->SetVRegC_22c(index); - } - - void DecompileInvokeVirtual(Instruction* inst, - uint32_t dex_pc, - Instruction::Code new_opcode, - bool is_range) { - uint16_t index = GetIndexAt(dex_pc); - inst->SetOpcode(new_opcode); - if (is_range) { - inst->SetVRegB_3rc(index); - } else { - inst->SetVRegB_35c(index); - } - } - - void DecompileNop(Instruction* inst, uint32_t dex_pc) { - if (quickened_info_ptr_ == quickened_info_end_) { - return; - } - const uint8_t* temporary_pointer = quickened_info_ptr_; - uint32_t quickened_pc = DecodeUnsignedLeb128(&temporary_pointer); - if (quickened_pc != dex_pc) { - return; - } - uint16_t reference_index = GetIndexAt(dex_pc); - uint16_t type_index = GetIndexAt(dex_pc); - inst->SetOpcode(Instruction::CHECK_CAST); - inst->SetVRegA_21c(reference_index); - inst->SetVRegB_21c(type_index); - } - - uint16_t GetIndexAt(uint32_t dex_pc) { - // Note that as a side effect, DecodeUnsignedLeb128 update the given pointer - // to the new position in the buffer. - DCHECK_LT(quickened_info_ptr_, quickened_info_end_); - uint32_t quickened_pc = DecodeUnsignedLeb128(&quickened_info_ptr_); - DCHECK_LT(quickened_info_ptr_, quickened_info_end_); - uint16_t index = DecodeUnsignedLeb128(&quickened_info_ptr_); - DCHECK_LE(quickened_info_ptr_, quickened_info_end_); - DCHECK_EQ(quickened_pc, dex_pc); - return index; - } - - const DexFile::CodeItem& code_item_; - const uint8_t* quickened_info_ptr_; - const uint8_t* const quickened_info_end_; - const bool decompile_return_instruction_; - - DISALLOW_COPY_AND_ASSIGN(DexDecompiler); -}; - -bool DexDecompiler::Decompile() { - // We need to iterate over the code item, and not over the quickening data, - // because the RETURN_VOID quickening is not encoded in the quickening data. Because - // unquickening is a rare need and not performance sensitive, it is not worth the - // added storage to also add the RETURN_VOID quickening in the quickened data. - for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) { - uint32_t dex_pc = it.CurrentDexPc(); - Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction()); - - switch (inst->Opcode()) { - case Instruction::RETURN_VOID_NO_BARRIER: - if (decompile_return_instruction_) { - inst->SetOpcode(Instruction::RETURN_VOID); - } - break; - - case Instruction::NOP: - DecompileNop(inst, dex_pc); - break; - - case Instruction::IGET_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET); - break; - - case Instruction::IGET_WIDE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_WIDE); - break; - - case Instruction::IGET_OBJECT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_OBJECT); - break; - - case Instruction::IGET_BOOLEAN_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BOOLEAN); - break; - - case Instruction::IGET_BYTE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BYTE); - break; - - case Instruction::IGET_CHAR_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_CHAR); - break; - - case Instruction::IGET_SHORT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_SHORT); - break; - - case Instruction::IPUT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT); - break; - - case Instruction::IPUT_BOOLEAN_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BOOLEAN); - break; - - case Instruction::IPUT_BYTE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BYTE); - break; - - case Instruction::IPUT_CHAR_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_CHAR); - break; - - case Instruction::IPUT_SHORT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_SHORT); - break; - - case Instruction::IPUT_WIDE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_WIDE); - break; - - case Instruction::IPUT_OBJECT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_OBJECT); - break; - - case Instruction::INVOKE_VIRTUAL_QUICK: - DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL, false); - break; - - case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: - DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL_RANGE, true); - break; - - default: - break; - } - } - - if (quickened_info_ptr_ != quickened_info_end_) { - LOG(FATAL) << "Failed to use all values in quickening info." - << " Actual: " << std::hex << quickened_info_ptr_ - << " Expected: " << quickened_info_end_; - return false; - } - - return true; -} - -bool ArtDecompileDEX(const DexFile::CodeItem& code_item, - const ArrayRef<const uint8_t>& quickened_info, - bool decompile_return_instruction) { - if (quickened_info.size() == 0 && !decompile_return_instruction) { - return true; - } - DexDecompiler decompiler(code_item, quickened_info, decompile_return_instruction); - return decompiler.Decompile(); -} - -} // namespace optimizer -} // namespace art diff --git a/compiler/dex/dex_to_dex_decompiler.h b/compiler/dex/dex_to_dex_decompiler.h deleted file mode 100644 index b5d5b91915..0000000000 --- a/compiler/dex/dex_to_dex_decompiler.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_COMPILER_DEX_DEX_TO_DEX_DECOMPILER_H_ -#define ART_COMPILER_DEX_DEX_TO_DEX_DECOMPILER_H_ - -#include "base/array_ref.h" -#include "dex_file.h" - -namespace art { -namespace optimizer { - -// "Decompile", that is unquicken, the code item provided, given the -// associated quickening data. -// TODO: code_item isn't really a const element, but changing it -// to non-const has too many repercussions on the code base. We make it -// consistent with DexToDexCompiler, but we should really change it to -// DexFile::CodeItem*. -bool ArtDecompileDEX(const DexFile::CodeItem& code_item, - const ArrayRef<const uint8_t>& quickened_data, - bool decompile_return_instruction); - -} // namespace optimizer -} // namespace art - -#endif // ART_COMPILER_DEX_DEX_TO_DEX_DECOMPILER_H_ diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc index 9a8d27cd03..e486e2e6ec 100644 --- a/compiler/dex/dex_to_dex_decompiler_test.cc +++ b/compiler/dex/dex_to_dex_decompiler_test.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "dex/dex_to_dex_decompiler.h" +#include "dex_to_dex_decompiler.h" #include "class_linker.h" #include "compiler/common_compiler_test.h" @@ -38,7 +38,7 @@ class DexToDexDecompilerTest : public CommonCompilerTest { TimingLogger timings("CompilerDriverTest::CompileAll", false, false); TimingLogger::ScopedTiming t(__FUNCTION__, &timings); compiler_options_->boot_image_ = false; - compiler_options_->SetCompilerFilter(CompilerFilter::kInterpretOnly); + compiler_options_->SetCompilerFilter(CompilerFilter::kQuicken); compiler_driver_->CompileAll(class_loader, GetDexFiles(class_loader), /* verifier_deps */ nullptr, diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index 00a7d44bac..3f0df3b2c8 100644 --- a/compiler/dex/verification_results.cc +++ b/compiler/dex/verification_results.cc @@ -104,11 +104,12 @@ void VerificationResults::CreateVerifiedMethodFor(MethodReference ref) { // This method should only be called for classes verified at compile time, // which have no verifier error, nor has methods that we know will throw // at runtime. - AtomicMap::InsertResult result = atomic_verified_methods_.Insert( + atomic_verified_methods_.Insert( ref, /*expected*/ nullptr, new VerifiedMethod(/* encountered_error_types */ 0, /* has_runtime_throw */ false)); - DCHECK_EQ(result, AtomicMap::kInsertResultSuccess); + // We don't check the result of `Insert` as we could insert twice for the same + // MethodReference in the presence of duplicate methods. } void VerificationResults::AddRejectedClass(ClassReference ref) { @@ -126,7 +127,7 @@ bool VerificationResults::IsClassRejected(ClassReference ref) { bool VerificationResults::IsCandidateForCompilation(MethodReference&, const uint32_t access_flags) { - if (!compiler_options_->IsBytecodeCompilationEnabled()) { + if (!compiler_options_->IsAotCompilationEnabled()) { return false; } // Don't compile class initializers unless kEverything. diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index f77b3ddfe0..fbfa087cfd 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -45,7 +45,6 @@ #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "dex/dex_to_dex_compiler.h" -#include "dex/dex_to_dex_decompiler.h" #include "dex/verification_results.h" #include "dex/verified_method.h" #include "driver/compiler_options.h" @@ -421,7 +420,7 @@ INTRINSICS_LIST(SETUP_INTRINSICS) // Compile: // 1) Compile all classes and methods enabled for compilation. May fall back to dex-to-dex // compilation. - if (GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (GetCompilerOptions().IsAnyCompilationEnabled()) { Compile(class_loader, dex_files, timings); } if (dump_stats_) { @@ -431,61 +430,6 @@ INTRINSICS_LIST(SETUP_INTRINSICS) FreeThreadPools(); } -// In-place unquicken the given `dex_files` based on `quickening_info`. -static void Unquicken(const std::vector<const DexFile*>& dex_files, - const ArrayRef<const uint8_t>& quickening_info, - bool decompile_return_instruction) { - const uint8_t* quickening_info_ptr = quickening_info.data(); - const uint8_t* const quickening_info_end = quickening_info.data() + quickening_info.size(); - for (const DexFile* dex_file : dex_files) { - for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { - const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); - const uint8_t* class_data = dex_file->GetClassData(class_def); - if (class_data == nullptr) { - continue; - } - ClassDataItemIterator it(*dex_file, class_data); - // Skip fields - while (it.HasNextStaticField()) { - it.Next(); - } - while (it.HasNextInstanceField()) { - it.Next(); - } - - while (it.HasNextDirectMethod()) { - const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); - if (code_item != nullptr) { - uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); - quickening_info_ptr += sizeof(uint32_t); - optimizer::ArtDecompileDEX(*code_item, - ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), - decompile_return_instruction); - quickening_info_ptr += quickening_size; - } - it.Next(); - } - - while (it.HasNextVirtualMethod()) { - const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); - if (code_item != nullptr) { - uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); - quickening_info_ptr += sizeof(uint32_t); - optimizer::ArtDecompileDEX(*code_item, - ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), - decompile_return_instruction); - quickening_info_ptr += quickening_size; - } - it.Next(); - } - DCHECK(!it.HasNext()); - } - } - if (quickening_info_ptr != quickening_info_end) { - LOG(FATAL) << "Failed to use all quickening info"; - } -} - void CompilerDriver::CompileAll(jobject class_loader, const std::vector<const DexFile*>& dex_files, VdexFile* vdex_file, @@ -494,15 +438,12 @@ void CompilerDriver::CompileAll(jobject class_loader, // TODO: we unquicken unconditionnally, as we don't know // if the boot image has changed. How exactly we'll know is under // experimentation. - if (vdex_file->GetQuickeningInfo().size() != 0) { - TimingLogger::ScopedTiming t("Unquicken", timings); - // We do not decompile a RETURN_VOID_NO_BARRIER into a RETURN_VOID, as the quickening - // optimization does not depend on the boot image (the optimization relies on not - // having final fields in a class, which does not change for an app). - Unquicken(dex_files, - vdex_file->GetQuickeningInfo(), - /* decompile_return_instruction */ false); - } + TimingLogger::ScopedTiming t("Unquicken", timings); + // We do not decompile a RETURN_VOID_NO_BARRIER into a RETURN_VOID, as the quickening + // optimization does not depend on the boot image (the optimization relies on not + // having final fields in a class, which does not change for an app). + VdexFile::Unquicken(dex_files, vdex_file->GetQuickeningInfo()); + Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps( new verifier::VerifierDeps(dex_files, vdex_file->GetVerifierDepsData())); } @@ -514,7 +455,7 @@ static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel( const DexFile& dex_file, const DexFile::ClassDef& class_def) REQUIRES_SHARED(Locks::mutator_lock_) { auto* const runtime = Runtime::Current(); - DCHECK(driver.GetCompilerOptions().IsAnyMethodCompilationEnabled()); + DCHECK(driver.GetCompilerOptions().IsQuickeningCompilationEnabled()); const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = runtime->GetClassLinker(); mirror::Class* klass = class_linker->FindClass(self, descriptor, class_loader); @@ -986,7 +927,8 @@ void CompilerDriver::PreCompile(jobject class_loader, LoadImageClasses(timings); VLOG(compiler) << "LoadImageClasses: " << GetMemoryUsageString(false); - if (compiler_options_->IsAnyMethodCompilationEnabled()) { + if (compiler_options_->IsAnyCompilationEnabled()) { + // Resolve eagerly to prepare for compilation. Resolve(class_loader, dex_files, timings); VLOG(compiler) << "Resolve: " << GetMemoryUsageString(false); } @@ -1014,7 +956,7 @@ void CompilerDriver::PreCompile(jobject class_loader, << "situations. Please check the log."; } - if (compiler_options_->IsAnyMethodCompilationEnabled()) { + if (compiler_options_->IsAnyCompilationEnabled()) { if (kIsDebugBuild) { EnsureVerifiedOrVerifyAtRuntime(class_loader, dex_files); } @@ -2017,7 +1959,7 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, return false; } - bool compiler_only_verifies = !GetCompilerOptions().IsAnyMethodCompilationEnabled(); + bool compiler_only_verifies = !GetCompilerOptions().IsAnyCompilationEnabled(); // We successfully validated the dependencies, now update class status // of verified classes. Note that the dependencies also record which classes diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index 42ff1e748a..17854fd61a 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -325,7 +325,7 @@ TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) { class CompilerDriverVerifyTest : public CompilerDriverTest { protected: CompilerFilter::Filter GetCompilerFilter() const OVERRIDE { - return CompilerFilter::kVerifyProfile; + return CompilerFilter::kVerify; } void CheckVerifiedClass(jobject class_loader, const std::string& clazz) const { diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index 2376fbf5f5..957ea99c49 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -84,32 +84,32 @@ class CompilerOptions FINAL { compiler_filter_ = compiler_filter; } - bool VerifyAtRuntime() const { - return compiler_filter_ == CompilerFilter::kVerifyAtRuntime; - } - - bool IsBytecodeCompilationEnabled() const { - return CompilerFilter::IsBytecodeCompilationEnabled(compiler_filter_); + bool IsAotCompilationEnabled() const { + return CompilerFilter::IsAotCompilationEnabled(compiler_filter_); } bool IsJniCompilationEnabled() const { return CompilerFilter::IsJniCompilationEnabled(compiler_filter_); } + bool IsQuickeningCompilationEnabled() const { + return CompilerFilter::IsQuickeningCompilationEnabled(compiler_filter_); + } + bool IsVerificationEnabled() const { return CompilerFilter::IsVerificationEnabled(compiler_filter_); } bool AssumeClassesAreVerified() const { - return compiler_filter_ == CompilerFilter::kVerifyNone; + return compiler_filter_ == CompilerFilter::kAssumeVerified; } - bool VerifyOnlyProfile() const { - return compiler_filter_ == CompilerFilter::kVerifyProfile; + bool VerifyAtRuntime() const { + return compiler_filter_ == CompilerFilter::kExtract; } - bool IsAnyMethodCompilationEnabled() const { - return CompilerFilter::IsAnyMethodCompilationEnabled(compiler_filter_); + bool IsAnyCompilationEnabled() const { + return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_); } size_t GetHugeMethodThreshold() const { diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index ead41240c2..1578c0cd3e 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -519,7 +519,7 @@ TEST_F(OatTest, EmptyTextSection) { if (insn_set == kArm) insn_set = kThumb2; std::string error_msg; std::vector<std::string> compiler_options; - compiler_options.push_back("--compiler-filter=verify-at-runtime"); + compiler_options.push_back("--compiler-filter=extract"); SetupCompiler(compiler_kind, insn_set, compiler_options, /*out*/ &error_msg); jobject class_loader; diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index af60def11e..6b5387ae19 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -1675,7 +1675,7 @@ bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) { if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) { return false; } - if (compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); const uint8_t* class_data = dex_file->GetClassData(class_def); if (class_data != nullptr) { // ie not an empty class, such as a marker interface @@ -1757,7 +1757,7 @@ size_t OatWriter::InitOatClasses(size_t offset) { } size_t OatWriter::InitOatMaps(size_t offset) { - if (!compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { return offset; } { @@ -1813,7 +1813,7 @@ size_t OatWriter::InitOatCode(size_t offset) { } size_t OatWriter::InitOatCodeDexFiles(size_t offset) { - if (!compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { return offset; } InitCodeMethodVisitor code_visitor(this, offset, vdex_quickening_info_offset_); @@ -1982,7 +1982,7 @@ bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) { return false; } - if (compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { WriteQuickeningInfoMethodVisitor visitor(this, vdex_out, start_offset); if (!VisitDexMethods(&visitor)) { PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation(); @@ -2474,11 +2474,28 @@ bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_fil /* verify */ true, /* verify_checksum */ true, &error_msg); - } else { - CHECK(oat_dex_file->source_.IsRawFile()) - << static_cast<size_t>(oat_dex_file->source_.GetType()); + } else if (oat_dex_file->source_.IsRawFile()) { File* raw_file = oat_dex_file->source_.GetRawFile(); dex_file = DexFile::OpenDex(raw_file->Fd(), location, /* verify_checksum */ true, &error_msg); + } else { + // The source data is a vdex file. + CHECK(oat_dex_file->source_.IsRawData()) + << static_cast<size_t>(oat_dex_file->source_.GetType()); + const uint8_t* raw_dex_file = oat_dex_file->source_.GetRawData(); + // Note: The raw data has already been checked to contain the header + // and all the data that the header specifies as the file size. + DCHECK(raw_dex_file != nullptr); + DCHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file->GetLocation())); + const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file); + // Since the source may have had its layout changed, or may be quickened, don't verify it. + dex_file = DexFile::Open(raw_dex_file, + header->file_size_, + location, + oat_dex_file->dex_file_location_checksum_, + nullptr, + /* verify */ false, + /* verify_checksum */ false, + &error_msg); } if (dex_file == nullptr) { LOG(ERROR) << "Failed to open dex file for layout: " << error_msg; diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index 34b52a87b5..12340b416d 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -497,8 +497,7 @@ void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) { "has a null pointer as last input.", invoke->DebugName(), invoke->GetId())); - } - if (!last_input->IsClinitCheck() && !last_input->IsLoadClass()) { + } else if (!last_input->IsClinitCheck() && !last_input->IsLoadClass()) { AddError(StringPrintf("Static invoke %s:%d marked as having an explicit clinit check " "has a last instruction (%s:%d) which is neither a clinit check " "nor a load class instruction.", |