summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Calin Juravle <calin@google.com> 2015-09-17 14:15:12 +0100
committer Calin Juravle <calin@google.com> 2015-10-02 02:25:25 +0100
commit07380a2d6cb9feee02facc81f699eed5cb670cd5 (patch)
tree95667e028ef49ad15e6a0d4ce38074573d414dd4 /compiler/optimizing
parente460d1df1f789c7c8bb97024a8efbd713ac175e9 (diff)
Enable compilation of members with access check failures.
Change-Id: I0de73099b53612072c3e6f1235c22f96339fe440
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/builder.cc35
-rw-r--r--compiler/optimizing/builder.h4
-rw-r--r--compiler/optimizing/optimizing_compiler.cc10
-rw-r--r--compiler/optimizing/optimizing_compiler_stats.h2
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";