diff options
author | 2018-10-31 13:56:49 +0000 | |
---|---|---|
committer | 2018-11-01 17:01:31 +0000 | |
commit | c1c3452e465e473df499196b387330a793b89680 (patch) | |
tree | 1b144182126bfc73c5d82d1941e1673826d39343 | |
parent | 3b5062083d3e203d1c72b066150b4fe441588a25 (diff) |
Do not cache RequiresConstructorBarrier() results.
Avoid caching the results. Caching was broken for JIT in the
presence of class unloading; entries for unloaded dex files
were leaked and potentially used erroneously with a newly
loaded dex file.
Test: m test-art-host-gtest
Test: testrunner.py --host
Test: Pixel 2 XL boots.
Test: m test-art-target-gtest
Test: testrunner.py --target
Bug: 118808764
Change-Id: Ic1163601170364e060c2e3009752f543c9bb37b7
-rw-r--r-- | compiler/dex/dex_to_dex_compiler.cc | 4 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 91 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 52 | ||||
-rw-r--r-- | compiler/driver/dex_compilation_unit.cc | 32 | ||||
-rw-r--r-- | compiler/driver/dex_compilation_unit.h | 35 | ||||
-rw-r--r-- | compiler/optimizing/builder.cc | 12 | ||||
-rw-r--r-- | compiler/optimizing/builder.h | 3 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/inliner.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/instruction_builder.cc | 27 | ||||
-rw-r--r-- | compiler/optimizing/instruction_builder.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 2 | ||||
-rw-r--r-- | runtime/handle.h | 5 |
15 files changed, 106 insertions, 166 deletions
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index ad9a30f8d4..fe99eaa51a 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -376,9 +376,7 @@ void DexToDexCompiler::CompilationState::CompileReturnVoid(Instruction* inst, ui DCHECK_EQ(inst->Opcode(), Instruction::RETURN_VOID); if (unit_.IsConstructor()) { // Are we compiling a non clinit constructor which needs a barrier ? - if (!unit_.IsStatic() && - driver_.RequiresConstructorBarrier(Thread::Current(), unit_.GetDexFile(), - unit_.GetClassDefIndex())) { + if (!unit_.IsStatic() && unit_.RequiresConstructorBarrier()) { return; } } diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index df6e8a83e1..8c276bb706 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -254,7 +254,6 @@ CompilerDriver::CompilerDriver( verification_results_(verification_results), compiler_(Compiler::Create(this, compiler_kind)), compiler_kind_(compiler_kind), - requires_constructor_barrier_lock_("constructor barrier lock"), image_classes_(std::move(image_classes)), number_of_soft_verifier_failures_(0), had_hard_verifier_failure_(false), @@ -1580,18 +1579,6 @@ static void CheckAndClearResolveException(Thread* self) self->ClearException(); } -bool CompilerDriver::RequiresConstructorBarrier(const DexFile& dex_file, - uint16_t class_def_idx) const { - ClassAccessor accessor(dex_file, class_def_idx); - // We require a constructor barrier if there are final instance fields. - for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) { - if (field.IsFinal()) { - return true; - } - } - return false; -} - class ResolveClassFieldsAndMethodsVisitor : public CompilationVisitor { public: explicit ResolveClassFieldsAndMethodsVisitor(const ParallelCompilationManager* manager) @@ -1635,57 +1622,42 @@ class ResolveClassFieldsAndMethodsVisitor : public CompilationVisitor { // We want to resolve the methods and fields eagerly. resolve_fields_and_methods = true; } - // If an instance field is final then we need to have a barrier on the return, static final - // fields are assigned within the lock held for class initialization. - bool requires_constructor_barrier = false; - ClassAccessor accessor(dex_file, class_def_index); - // Optionally resolve fields and methods and figure out if we need a constructor barrier. - auto method_visitor = [&](const ClassAccessor::Method& method) - REQUIRES_SHARED(Locks::mutator_lock_) { - if (resolve_fields_and_methods) { + if (resolve_fields_and_methods) { + ClassAccessor accessor(dex_file, class_def_index); + // Optionally resolve fields and methods and figure out if we need a constructor barrier. + auto method_visitor = [&](const ClassAccessor::Method& method) + REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* resolved = class_linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>( method.GetIndex(), dex_cache, class_loader, - /* referrer */ nullptr, + /*referrer=*/ nullptr, method.GetInvokeType(class_def.access_flags_)); if (resolved == nullptr) { CheckAndClearResolveException(soa.Self()); } - } - }; - accessor.VisitFieldsAndMethods( - // static fields - [&](ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) { - if (resolve_fields_and_methods) { + }; + accessor.VisitFieldsAndMethods( + // static fields + [&](ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) { ArtField* resolved = class_linker->ResolveField( - field.GetIndex(), dex_cache, class_loader, /* is_static */ true); + field.GetIndex(), dex_cache, class_loader, /*is_static=*/ true); if (resolved == nullptr) { CheckAndClearResolveException(soa.Self()); } - } - }, - // instance fields - [&](ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) { - if (field.IsFinal()) { - // We require a constructor barrier if there are final instance fields. - requires_constructor_barrier = true; - } - if (resolve_fields_and_methods) { + }, + // instance fields + [&](ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) { ArtField* resolved = class_linker->ResolveField( - field.GetIndex(), dex_cache, class_loader, /* is_static */ false); + field.GetIndex(), dex_cache, class_loader, /*is_static=*/ false); if (resolved == nullptr) { CheckAndClearResolveException(soa.Self()); } - } - }, - /*direct methods*/ method_visitor, - /*virtual methods*/ method_visitor); - manager_->GetCompiler()->SetRequiresConstructorBarrier(self, - &dex_file, - class_def_index, - requires_constructor_barrier); + }, + /*direct_method_visitor=*/ method_visitor, + /*virtual_method_visitor=*/ method_visitor); + } } private: @@ -2832,31 +2804,6 @@ bool CompilerDriver::IsMethodVerifiedWithoutFailures(uint32_t method_idx, return is_system_class; } -void CompilerDriver::SetRequiresConstructorBarrier(Thread* self, - const DexFile* dex_file, - uint16_t class_def_index, - bool requires) { - WriterMutexLock mu(self, requires_constructor_barrier_lock_); - requires_constructor_barrier_.emplace(ClassReference(dex_file, class_def_index), requires); -} - -bool CompilerDriver::RequiresConstructorBarrier(Thread* self, - const DexFile* dex_file, - uint16_t class_def_index) { - ClassReference class_ref(dex_file, class_def_index); - { - ReaderMutexLock mu(self, requires_constructor_barrier_lock_); - auto it = requires_constructor_barrier_.find(class_ref); - if (it != requires_constructor_barrier_.end()) { - return it->second; - } - } - WriterMutexLock mu(self, requires_constructor_barrier_lock_); - const bool requires = RequiresConstructorBarrier(*dex_file, class_def_index); - requires_constructor_barrier_.emplace(class_ref, requires); - return requires; -} - std::string CompilerDriver::GetMemoryUsageString(bool extended) const { std::ostringstream oss; const gc::Heap* const heap = Runtime::Current()->GetHeap(); diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 9a83e55c96..f42e555410 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -151,50 +151,6 @@ class CompilerDriver { void AddCompiledMethod(const MethodReference& method_ref, CompiledMethod* const compiled_method); CompiledMethod* RemoveCompiledMethod(const MethodReference& method_ref); - void SetRequiresConstructorBarrier(Thread* self, - const DexFile* dex_file, - uint16_t class_def_index, - bool requires) - REQUIRES(!requires_constructor_barrier_lock_); - - // Do the <init> methods for this class require a constructor barrier (prior to the return)? - // The answer is "yes", if and only if this class has any instance final fields. - // (This must not be called for any non-<init> methods; the answer would be "no"). - // - // --- - // - // JLS 17.5.1 "Semantics of final fields" mandates that all final fields are frozen at the end - // of the invoked constructor. The constructor barrier is a conservative implementation means of - // enforcing the freezes happen-before the object being constructed is observable by another - // thread. - // - // Note: This question only makes sense for instance constructors; - // static constructors (despite possibly having finals) never need - // a barrier. - // - // JLS 12.4.2 "Detailed Initialization Procedure" approximately describes - // class initialization as: - // - // lock(class.lock) - // class.state = initializing - // unlock(class.lock) - // - // invoke <clinit> - // - // lock(class.lock) - // class.state = initialized - // unlock(class.lock) <-- acts as a release - // - // The last operation in the above example acts as an atomic release - // for any stores in <clinit>, which ends up being stricter - // than what a constructor barrier needs. - // - // See also QuasiAtomic::ThreadFenceForConstructor(). - bool RequiresConstructorBarrier(Thread* self, - const DexFile* dex_file, - uint16_t class_def_index) - REQUIRES(!requires_constructor_barrier_lock_); - // Resolve compiling method's class. Returns null on failure. ObjPtr<mirror::Class> ResolveCompilingMethodsClass(const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, @@ -407,20 +363,12 @@ class CompilerDriver { void FreeThreadPools(); void CheckThreadPools(); - bool RequiresConstructorBarrier(const DexFile& dex_file, uint16_t class_def_idx) const; - const CompilerOptions* const compiler_options_; VerificationResults* const verification_results_; std::unique_ptr<Compiler> compiler_; Compiler::Kind compiler_kind_; - // All class references that require constructor barriers. If the class reference is not in the - // set then the result has not yet been computed. - mutable ReaderWriterMutex requires_constructor_barrier_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - std::map<ClassReference, bool> requires_constructor_barrier_ - GUARDED_BY(requires_constructor_barrier_lock_); - // All class references that this compiler has compiled. Indexed by class defs. using ClassStateTable = AtomicDexRefMap<ClassReference, ClassStatus>; ClassStateTable compiled_classes_; diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc index 654eccdad6..e5a6f0e177 100644 --- a/compiler/driver/dex_compilation_unit.cc +++ b/compiler/driver/dex_compilation_unit.cc @@ -16,10 +16,14 @@ #include "dex_compilation_unit.h" +#include "art_field.h" #include "base/utils.h" +#include "dex/class_accessor-inl.h" #include "dex/code_item_accessors-inl.h" #include "dex/descriptors_names.h" +#include "mirror/class-inl.h" #include "mirror/dex_cache.h" +#include "scoped_thread_state_change-inl.h" namespace art { @@ -53,4 +57,32 @@ const std::string& DexCompilationUnit::GetSymbol() { return symbol_; } +bool DexCompilationUnit::RequiresConstructorBarrier() const { + // Constructor barriers are applicable only for <init> methods. + DCHECK(!IsStatic()); + DCHECK(IsConstructor()); + + // We require a constructor barrier if there are final instance fields. + if (GetCompilingClass().GetReference() != nullptr && !GetCompilingClass().IsNull()) { + // Decoding class data can be slow, so iterate over fields of the compiling class if resolved. + ScopedObjectAccess soa(Thread::Current()); + ObjPtr<mirror::Class> compiling_class = GetCompilingClass().Get(); + for (size_t i = 0, size = compiling_class->NumInstanceFields(); i != size; ++i) { + ArtField* field = compiling_class->GetInstanceField(i); + if (field->IsFinal()) { + return true; + } + } + } else { + // Iterate over field definitions in the class data. + ClassAccessor accessor(*GetDexFile(), GetClassDefIndex()); + for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) { + if (field.IsFinal()) { + return true; + } + } + } + return false; +} + } // namespace art diff --git a/compiler/driver/dex_compilation_unit.h b/compiler/driver/dex_compilation_unit.h index 9d9c218266..757f0e7695 100644 --- a/compiler/driver/dex_compilation_unit.h +++ b/compiler/driver/dex_compilation_unit.h @@ -123,6 +123,41 @@ class DexCompilationUnit : public DeletableArenaObject<kArenaAllocMisc> { return compiling_class_; } + // Does this <init> method require a constructor barrier (prior to the return)? + // The answer is "yes", if and only if the class has any instance final fields. + // (This must not be called for any non-<init> methods; the answer would be "no"). + // + // --- + // + // JLS 17.5.1 "Semantics of final fields" mandates that all final fields are frozen at the end + // of the invoked constructor. The constructor barrier is a conservative implementation means of + // enforcing the freezes happen-before the object being constructed is observable by another + // thread. + // + // Note: This question only makes sense for instance constructors; + // static constructors (despite possibly having finals) never need + // a barrier. + // + // JLS 12.4.2 "Detailed Initialization Procedure" approximately describes + // class initialization as: + // + // lock(class.lock) + // class.state = initializing + // unlock(class.lock) + // + // invoke <clinit> + // + // lock(class.lock) + // class.state = initialized + // unlock(class.lock) <-- acts as a release + // + // The last operation in the above example acts as an atomic release + // for any stores in <clinit>, which ends up being stricter + // than what a constructor barrier needs. + // + // See also QuasiAtomic::ThreadFenceForConstructor(). + bool RequiresConstructorBarrier() const; + private: const Handle<mirror::ClassLoader> class_loader_; diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index a1a5692ef6..64aa1b9358 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -21,6 +21,7 @@ #include "base/bit_vector-inl.h" #include "base/logging.h" #include "block_builder.h" +#include "code_generator.h" #include "data_type-inl.h" #include "dex/verified_method.h" #include "driver/compiler_options.h" @@ -40,7 +41,6 @@ HGraphBuilder::HGraphBuilder(HGraph* graph, const CodeItemDebugInfoAccessor& accessor, const DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* outer_compilation_unit, - CompilerDriver* driver, CodeGenerator* code_generator, OptimizingCompilerStats* compiler_stats, ArrayRef<const uint8_t> interpreter_metadata, @@ -50,7 +50,6 @@ HGraphBuilder::HGraphBuilder(HGraph* graph, code_item_accessor_(accessor), dex_compilation_unit_(dex_compilation_unit), outer_compilation_unit_(outer_compilation_unit), - compiler_driver_(driver), code_generator_(code_generator), compilation_stats_(compiler_stats), interpreter_metadata_(interpreter_metadata), @@ -67,19 +66,18 @@ HGraphBuilder::HGraphBuilder(HGraph* graph, code_item_accessor_(accessor), dex_compilation_unit_(dex_compilation_unit), outer_compilation_unit_(nullptr), - compiler_driver_(nullptr), code_generator_(nullptr), compilation_stats_(nullptr), handles_(handles), return_type_(return_type) {} bool HGraphBuilder::SkipCompilation(size_t number_of_branches) { - if (compiler_driver_ == nullptr) { - // Note that the compiler driver is null when unit testing. + if (code_generator_ == nullptr) { + // Note that the codegen is null when unit testing. return false; } - const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions(); + const CompilerOptions& compiler_options = code_generator_->GetCompilerOptions(); CompilerFilter::Filter compiler_filter = compiler_options.GetCompilerFilter(); if (compiler_filter == CompilerFilter::kEverything) { return false; @@ -131,7 +129,6 @@ GraphAnalysisResult HGraphBuilder::BuildGraph() { return_type_, dex_compilation_unit_, outer_compilation_unit_, - compiler_driver_, code_generator_, interpreter_metadata_, compilation_stats_, @@ -203,7 +200,6 @@ void HGraphBuilder::BuildIntrinsicGraph(ArtMethod* method) { return_type_, dex_compilation_unit_, outer_compilation_unit_, - compiler_driver_, code_generator_, interpreter_metadata_, compilation_stats_, diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 5a1914ce08..6152740324 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -22,7 +22,6 @@ #include "dex/code_item_accessors.h" #include "dex/dex_file-inl.h" #include "dex/dex_file.h" -#include "driver/compiler_driver.h" #include "nodes.h" namespace art { @@ -38,7 +37,6 @@ class HGraphBuilder : public ValueObject { const CodeItemDebugInfoAccessor& accessor, const DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* outer_compilation_unit, - CompilerDriver* driver, CodeGenerator* code_generator, OptimizingCompilerStats* compiler_stats, ArrayRef<const uint8_t> interpreter_metadata, @@ -70,7 +68,6 @@ class HGraphBuilder : public ValueObject { // The compilation unit of the enclosing method being compiled. const DexCompilationUnit* const outer_compilation_unit_; - CompilerDriver* const compiler_driver_; CodeGenerator* const code_generator_; OptimizingCompilerStats* const compilation_stats_; diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 3f560780ce..39966ff8ea 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -59,7 +59,6 @@ static constexpr ReadBarrierOption kCompilerReadBarrierOption = class Assembler; class CodeGenerator; -class CompilerDriver; class CompilerOptions; class StackMapStream; class ParallelMoveResolver; diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index f9e9abbdfd..f56f9cb84f 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -1807,7 +1807,6 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, code_item_accessor, &dex_compilation_unit, &outer_compilation_unit_, - compiler_driver_, codegen_, inline_stats_, resolved_method->GetQuickenedInfo(), diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 5af8796ca0..e9b5b5a93d 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -25,7 +25,6 @@ #include "data_type-inl.h" #include "dex/bytecode_utils.h" #include "dex/dex_instruction-inl.h" -#include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" #include "driver/compiler_options.h" #include "imtable-inl.h" @@ -48,7 +47,6 @@ HInstructionBuilder::HInstructionBuilder(HGraph* graph, DataType::Type return_type, const DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* outer_compilation_unit, - CompilerDriver* compiler_driver, CodeGenerator* code_generator, ArrayRef<const uint8_t> interpreter_metadata, OptimizingCompilerStats* compiler_stats, @@ -62,7 +60,6 @@ HInstructionBuilder::HInstructionBuilder(HGraph* graph, return_type_(return_type), block_builder_(block_builder), ssa_builder_(ssa_builder), - compiler_driver_(compiler_driver), code_generator_(code_generator), dex_compilation_unit_(dex_compilation_unit), outer_compilation_unit_(outer_compilation_unit), @@ -711,20 +708,18 @@ void HInstructionBuilder::Binop_22b(const Instruction& instruction, bool reverse // Does the method being compiled need any constructor barriers being inserted? // (Always 'false' for methods that aren't <init>.) -static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, CompilerDriver* driver) { +static bool RequiresConstructorBarrier(const DexCompilationUnit* cu) { // Can be null in unit tests only. if (UNLIKELY(cu == nullptr)) { return false; } - Thread* self = Thread::Current(); - return cu->IsConstructor() - && !cu->IsStatic() - // RequiresConstructorBarrier must only be queried for <init> methods; - // it's effectively "false" for every other method. - // - // See CompilerDriver::RequiresConstructBarrier for more explanation. - && driver->RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex()); + // Constructor barriers are applicable only for <init> methods. + if (LIKELY(!cu->IsConstructor() || cu->IsStatic())) { + return false; + } + + return cu->RequiresConstructorBarrier(); } // Returns true if `block` has only one successor which starts at the next @@ -770,7 +765,7 @@ void HInstructionBuilder::BuildReturn(const Instruction& instruction, // Only <init> (which is a return-void) could possibly have a constructor fence. // This may insert additional redundant constructor fences from the super constructors. // TODO: remove redundant constructor fences (b/36656456). - if (RequiresConstructorBarrier(dex_compilation_unit_, compiler_driver_)) { + if (RequiresConstructorBarrier(dex_compilation_unit_)) { // Compiling instance constructor. DCHECK_STREQ("<init>", graph_->GetMethodName()); @@ -784,7 +779,7 @@ void HInstructionBuilder::BuildReturn(const Instruction& instruction, } AppendInstruction(new (allocator_) HReturnVoid(dex_pc)); } else { - DCHECK(!RequiresConstructorBarrier(dex_compilation_unit_, compiler_driver_)); + DCHECK(!RequiresConstructorBarrier(dex_compilation_unit_)); HInstruction* value = LoadLocal(instruction.VRegA(), type); AppendInstruction(new (allocator_) HReturn(value, dex_pc)); } @@ -881,8 +876,8 @@ ArtMethod* HInstructionBuilder::ResolveMethod(uint16_t method_idx, InvokeType in // The back-end code generator relies on this check in order to ensure that it will not // attempt to read the dex_cache with a dex_method_index that is not from the correct // dex_file. If we didn't do this check then the dex_method_index will not be updated in the - // builder, which means that the code-generator (and compiler driver during sharpening and - // inliner, maybe) might invoke an incorrect method. + // builder, which means that the code-generator (and sharpening and inliner, maybe) + // might invoke an incorrect method. // TODO: The actual method could still be referenced in the current dex file, so we // could try locating it. // TODO: Remove the dex_file restriction. diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h index 21afd1166a..d701445946 100644 --- a/compiler/optimizing/instruction_builder.h +++ b/compiler/optimizing/instruction_builder.h @@ -34,7 +34,6 @@ class ArenaBitVector; class ArtField; class ArtMethod; class CodeGenerator; -class CompilerDriver; class DexCompilationUnit; class HBasicBlockBuilder; class Instruction; @@ -59,7 +58,6 @@ class HInstructionBuilder : public ValueObject { DataType::Type return_type, const DexCompilationUnit* dex_compilation_unit, const DexCompilationUnit* outer_compilation_unit, - CompilerDriver* compiler_driver, CodeGenerator* code_generator, ArrayRef<const uint8_t> interpreter_metadata, OptimizingCompilerStats* compiler_stats, @@ -307,8 +305,6 @@ class HInstructionBuilder : public ValueObject { HBasicBlockBuilder* const block_builder_; SsaBuilder* const ssa_builder_; - CompilerDriver* const compiler_driver_; - CodeGenerator* const code_generator_; // The compilation unit of the current method being compiled. Note that diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 8245453ab5..5bd1122698 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -24,7 +24,6 @@ namespace art { -class CompilerDriver; class DexFile; // Positive floating-point infinities. diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 6ebe89eae1..21243804fb 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -7402,7 +7402,7 @@ class HMemoryBarrier final : public HExpression<0> { // } // // See also: -// * CompilerDriver::RequiresConstructorBarrier +// * DexCompilationUnit::RequiresConstructorBarrier // * QuasiAtomic::ThreadFenceForConstructor // class HConstructorFence final : public HVariableInputSizeInstruction { diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 38daaaa31c..4f495b6d81 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -870,7 +870,6 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* allocator, code_item_accessor, &dex_compilation_unit, &dex_compilation_unit, - compiler_driver, codegen.get(), compilation_stats_.get(), interpreter_metadata, @@ -991,7 +990,6 @@ CodeGenerator* OptimizingCompiler::TryCompileIntrinsic( CodeItemDebugInfoAccessor(), // Null code item. &dex_compilation_unit, &dex_compilation_unit, - compiler_driver, codegen.get(), compilation_stats_.get(), /* interpreter_metadata */ ArrayRef<const uint8_t>(), diff --git a/runtime/handle.h b/runtime/handle.h index 18e503d1de..b13c43ef34 100644 --- a/runtime/handle.h +++ b/runtime/handle.h @@ -62,8 +62,9 @@ class Handle : public ValueObject { return down_cast<T*>(reference_->AsMirrorPtr()); } - ALWAYS_INLINE bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_) { - return Get() == nullptr; + ALWAYS_INLINE bool IsNull() const { + // It's safe to null-check it without a read barrier. + return reference_->IsNull(); } ALWAYS_INLINE jobject ToJObject() const REQUIRES_SHARED(Locks::mutator_lock_) { |