diff options
author | 2015-09-17 14:15:12 +0100 | |
---|---|---|
committer | 2015-10-02 02:25:25 +0100 | |
commit | 07380a2d6cb9feee02facc81f699eed5cb670cd5 (patch) | |
tree | 95667e028ef49ad15e6a0d4ce38074573d414dd4 /compiler/optimizing | |
parent | e460d1df1f789c7c8bb97024a8efbd713ac175e9 (diff) |
Enable compilation of members with access check failures.
Change-Id: I0de73099b53612072c3e6f1235c22f96339fe440
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/builder.cc | 35 | ||||
-rw-r--r-- | compiler/optimizing/builder.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 10 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler_stats.h | 2 |
4 files changed, 36 insertions, 15 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 7ef79ec111..ebbfb14190 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -1305,6 +1305,23 @@ bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const { return outer_class.Get() == cls.Get(); } +void HGraphBuilder::BuildUnresolvedStaticFieldAccess(const Instruction& instruction, + uint32_t dex_pc, + bool is_put, + Primitive::Type field_type) { + uint32_t source_or_dest_reg = instruction.VRegA_21c(); + uint16_t field_index = instruction.VRegB_21c(); + + if (is_put) { + HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); + current_block_->AddInstruction( + new (arena_) HUnresolvedStaticFieldSet(value, field_type, field_index, dex_pc)); + } else { + current_block_->AddInstruction( + new (arena_) HUnresolvedStaticFieldGet(field_type, field_index, dex_pc)); + UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc); + } +} bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put) { @@ -1324,18 +1341,11 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, if (resolved_field == nullptr) { MaybeRecordStat(MethodCompilationStat::kUnresolvedField); Primitive::Type field_type = GetFieldAccessType(*dex_file_, field_index); - if (is_put) { - HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); - current_block_->AddInstruction( - new (arena_) HUnresolvedStaticFieldSet(value, field_type, field_index, dex_pc)); - } else { - current_block_->AddInstruction( - new (arena_) HUnresolvedStaticFieldGet(field_type, field_index, dex_pc)); - UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc); - } + BuildUnresolvedStaticFieldAccess(instruction, dex_pc, is_put, field_type); return true; } + Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile(); Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle( outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file))); @@ -1350,6 +1360,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, // The compiler driver cannot currently understand multiple dex caches involved. Just bailout. return false; } else { + // TODO: This is rather expensive. Perf it and cache the results if needed. std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField( outer_dex_cache.Get(), GetCompilingClass(), @@ -1358,7 +1369,9 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, &storage_index); bool can_easily_access = is_put ? pair.second : pair.first; if (!can_easily_access) { - return false; + MaybeRecordStat(MethodCompilationStat::kUnresolvedFieldNotAFastAccess); + BuildUnresolvedStaticFieldAccess(instruction, dex_pc, is_put, field_type); + return true; } } @@ -1379,8 +1392,6 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, cls = new (arena_) HClinitCheck(constant, dex_pc); current_block_->AddInstruction(cls); } - - Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); if (is_put) { // We need to keep the class alive before loading the value. Temporaries temps(graph_); diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 4c8e3d0442..b2dc24169e 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -187,6 +187,10 @@ class HGraphBuilder : public ValueObject { // Builds an instance field access node and returns whether the instruction is supported. bool BuildInstanceFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put); + void BuildUnresolvedStaticFieldAccess(const Instruction& instruction, + uint32_t dex_pc, + bool is_put, + Primitive::Type field_type); // Builds a static field access node and returns whether the instruction is supported. bool BuildStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put); diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index dbfbd96e39..3e982dca23 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -829,8 +829,12 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite return compiled_method; } -static bool HasOnlyUnresolvedFailures(const VerifiedMethod* verified_method) { - uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS; +static bool CanHandleVerificationFailure(const VerifiedMethod* verified_method) { + // For access errors the compiler will use the unresolved helpers (e.g. HInvokeUnresolved). + uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS + | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS + | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD + | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD; return (verified_method->GetEncounteredVerificationFailures() & (~unresolved_mask)) == 0; } @@ -847,7 +851,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx); DCHECK(!verified_method->HasRuntimeThrow()); if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file) - || HasOnlyUnresolvedFailures(verified_method)) { + || CanHandleVerificationFailure(verified_method)) { method = TryCompile(code_item, access_flags, invoke_type, class_def_idx, method_idx, jclass_loader, dex_file, dex_cache); } else { diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h index f1d29700d9..df45c8e890 100644 --- a/compiler/optimizing/optimizing_compiler_stats.h +++ b/compiler/optimizing/optimizing_compiler_stats.h @@ -35,6 +35,7 @@ enum MethodCompilationStat { kInstructionSimplificationsArch, kUnresolvedMethod, kUnresolvedField, + kUnresolvedFieldNotAFastAccess, kNotCompiledBranchOutsideMethodCode, kNotCompiledCannotBuildSSA, kNotCompiledCantAccesType, @@ -105,6 +106,7 @@ class OptimizingCompilerStats { case kInstructionSimplificationsArch: return "kInstructionSimplificationsArch"; case kUnresolvedMethod : return "kUnresolvedMethod"; case kUnresolvedField : return "kUnresolvedField"; + case kUnresolvedFieldNotAFastAccess : return "kUnresolvedFieldNotAFastAccess"; case kNotCompiledBranchOutsideMethodCode: return "kNotCompiledBranchOutsideMethodCode"; case kNotCompiledCannotBuildSSA : return "kNotCompiledCannotBuildSSA"; case kNotCompiledCantAccesType : return "kNotCompiledCantAccesType"; |