Fix illegal field access bug to pass 075.
Change-Id: I33b4e2066d7ad17053e4556f80ca49f93093f78d
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index abafb3a..50ed471 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2366,15 +2366,6 @@
}
-void MethodCompiler::PrintUnresolvedFieldWarning(int32_t field_idx) {
- DexFile::FieldId const& field_id = dex_file_->GetFieldId(field_idx);
-
- LOG(WARNING) << "unable to resolve static field " << field_idx << " ("
- << dex_file_->GetFieldName(field_id) << ") in "
- << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
-}
-
-
void MethodCompiler::EmitInsn_IGet(uint32_t dex_pc,
Instruction const* insn,
JType field_jty) {
@@ -2384,17 +2375,18 @@
uint32_t reg_idx = dec_insn.vB;
uint32_t field_idx = dec_insn.vC;
- Field* field = dex_cache_->GetResolvedField(field_idx);
-
llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
EmitGuard_NullPointerException(dex_pc, object_addr);
llvm::Value* field_value;
- if (field == NULL) {
- PrintUnresolvedFieldWarning(field_idx);
+ int field_offset;
+ bool is_volatile;
+ bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
+ field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
+ if (!is_fast_path) {
llvm::Function* runtime_func;
if (field_jty == kObject) {
@@ -2417,15 +2409,18 @@
EmitGuard_ExceptionLandingPad(dex_pc);
} else {
+ DCHECK_GE(field_offset, 0);
+
llvm::PointerType* field_type =
irb_.getJType(field_jty, kField)->getPointerTo();
- llvm::ConstantInt* field_offset =
- irb_.getPtrEquivInt(field->GetOffset().Int32Value());
+ llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
llvm::Value* field_addr =
- irb_.CreatePtrDisp(object_addr, field_offset, field_type);
+ irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+ // TODO: Check is_volatile. We need to generate atomic load instruction
+ // when is_volatile is true.
field_value = irb_.CreateLoad(field_addr);
}
@@ -2444,17 +2439,18 @@
uint32_t reg_idx = dec_insn.vB;
uint32_t field_idx = dec_insn.vC;
- Field* field = dex_cache_->GetResolvedField(field_idx);
-
llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
EmitGuard_NullPointerException(dex_pc, object_addr);
llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
- if (field == NULL) {
- PrintUnresolvedFieldWarning(field_idx);
+ int field_offset;
+ bool is_volatile;
+ bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
+ field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
+ if (!is_fast_path) {
llvm::Function* runtime_func;
if (field_jty == kObject) {
@@ -2477,15 +2473,18 @@
EmitGuard_ExceptionLandingPad(dex_pc);
} else {
+ DCHECK_GE(field_offset, 0);
+
llvm::PointerType* field_type =
irb_.getJType(field_jty, kField)->getPointerTo();
- llvm::Value* field_offset =
- irb_.getPtrEquivInt(field->GetOffset().Int32Value());
+ llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
llvm::Value* field_addr =
- irb_.CreatePtrDisp(object_addr, field_offset, field_type);
+ irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+ // TODO: Check is_volatile. We need to generate atomic store instruction
+ // when is_volatile is true.
irb_.CreateStore(new_value, field_addr);
}
@@ -2493,82 +2492,6 @@
}
-Field* MethodCompiler::ResolveField(uint32_t field_idx) {
- Thread* thread = Thread::Current();
-
- // Save the exception state
- Throwable* old_exception = NULL;
- if (thread->IsExceptionPending()) {
- old_exception = thread->GetException();
- thread->ClearException();
- }
-
- // Resolve the fields through the class linker
- Field* field = class_linker_->ResolveField(*dex_file_, field_idx,
- dex_cache_, class_loader_,
- /* is_static= */ true);
-
- if (field == NULL) {
- // Ignore the exception raised during the field resolution
- thread->ClearException();
- }
-
- // Restore the exception state
- if (old_exception != NULL) {
- thread->SetException(old_exception);
- }
-
- return field;
-}
-
-
-Field* MethodCompiler::
-FindFieldAndDeclaringTypeIdx(uint32_t field_idx,
- uint32_t &resolved_type_idx) {
-
- // Resolve the field through the class linker
- Field* field = ResolveField(field_idx);
- if (field == NULL) {
- return NULL;
- }
-
- DexFile::FieldId const& field_id = dex_file_->GetFieldId(field_idx);
-
- // Search for the type_idx of the declaring class
- uint16_t type_idx = field_id.class_idx_;
- Class* klass = dex_cache_->GetResolvedTypes()->Get(type_idx);
-
- // Test: Is referring_class equal to declaring_class?
-
- // If true, then return the type_idx; otherwise, this field must be declared
- // in super class or interfaces, we have to search for declaring class.
-
- if (field->GetDeclaringClass() == klass) {
- resolved_type_idx = type_idx;
- return field;
- }
-
- // Search for the type_idx of the super class or interfaces
- std::string desc(FieldHelper(field).GetDeclaringClassDescriptor());
-
- DexFile::StringId const* string_id = dex_file_->FindStringId(desc);
-
- if (string_id == NULL) {
- return NULL;
- }
-
- DexFile::TypeId const* type_id =
- dex_file_->FindTypeId(dex_file_->GetIndexForStringId(*string_id));
-
- if (type_id == NULL) {
- return NULL;
- }
-
- resolved_type_idx = dex_file_->GetIndexForTypeId(*type_id);
- return field;
-}
-
-
llvm::Value* MethodCompiler::EmitLoadStaticStorage(uint32_t dex_pc,
uint32_t type_idx) {
llvm::BasicBlock* block_load_static =
@@ -2629,13 +2552,20 @@
DecodedInstruction dec_insn(insn);
- uint32_t declaring_type_idx = DexFile::kDexNoIndex;
+ uint32_t field_idx = dec_insn.vB;
- Field* field = FindFieldAndDeclaringTypeIdx(dec_insn.vB, declaring_type_idx);
+ int field_offset;
+ int ssb_index;
+ bool is_referrers_class;
+ bool is_volatile;
+
+ bool is_fast_path = compiler_->ComputeStaticFieldInfo(
+ field_idx, oat_compilation_unit_, field_offset, ssb_index,
+ is_referrers_class, is_volatile, false);
llvm::Value* static_field_value;
- if (field == NULL) {
+ if (!is_fast_path) {
llvm::Function* runtime_func;
if (field_jty == kObject) {
@@ -2658,16 +2588,37 @@
EmitGuard_ExceptionLandingPad(dex_pc);
} else {
- llvm::Value* static_storage_addr =
- EmitLoadStaticStorage(dex_pc, declaring_type_idx);
+ DCHECK_GE(field_offset, 0);
- llvm::Value* static_field_offset_value =
- irb_.getPtrEquivInt(field->GetOffset().Int32Value());
+ llvm::Value* static_storage_addr = NULL;
+
+ if (is_referrers_class) {
+ // Fast path, static storage base is this method's class
+ llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+ llvm::Constant* declaring_class_offset_value =
+ irb_.getPtrEquivInt(Method::DeclaringClassOffset().Int32Value());
+
+ llvm::Value* static_storage_field_addr =
+ irb_.CreatePtrDisp(method_object_addr, declaring_class_offset_value,
+ irb_.getJObjectTy()->getPointerTo());
+
+ static_storage_addr = irb_.CreateLoad(static_storage_field_addr);
+ } else {
+ // Medium path, static storage base in a different class which
+ // requires checks that the other class is initialized
+ DCHECK_GE(ssb_index, 0);
+ static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
+ }
+
+ llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
llvm::Value* static_field_addr =
irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
irb_.getJType(field_jty, kField)->getPointerTo());
+ // TODO: Check is_volatile. We need to generate atomic load instruction
+ // when is_volatile is true.
static_field_value = irb_.CreateLoad(static_field_addr);
}
@@ -2683,13 +2634,20 @@
DecodedInstruction dec_insn(insn);
- uint32_t declaring_type_idx = DexFile::kDexNoIndex;
-
- Field* field = FindFieldAndDeclaringTypeIdx(dec_insn.vB, declaring_type_idx);
+ uint32_t field_idx = dec_insn.vB;
llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
- if (field == NULL) {
+ int field_offset;
+ int ssb_index;
+ bool is_referrers_class;
+ bool is_volatile;
+
+ bool is_fast_path = compiler_->ComputeStaticFieldInfo(
+ field_idx, oat_compilation_unit_, field_offset, ssb_index,
+ is_referrers_class, is_volatile, true);
+
+ if (!is_fast_path) {
llvm::Function* runtime_func;
if (field_jty == kObject) {
@@ -2712,16 +2670,37 @@
EmitGuard_ExceptionLandingPad(dex_pc);
} else {
- llvm::Value* static_storage_addr =
- EmitLoadStaticStorage(dex_pc, declaring_type_idx);
+ DCHECK_GE(field_offset, 0);
- llvm::Value* static_field_offset_value =
- irb_.getPtrEquivInt(field->GetOffset().Int32Value());
+ llvm::Value* static_storage_addr = NULL;
+
+ if (is_referrers_class) {
+ // Fast path, static storage base is this method's class
+ llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+ llvm::Constant* declaring_class_offset_value =
+ irb_.getPtrEquivInt(Method::DeclaringClassOffset().Int32Value());
+
+ llvm::Value* static_storage_field_addr =
+ irb_.CreatePtrDisp(method_object_addr, declaring_class_offset_value,
+ irb_.getJObjectTy()->getPointerTo());
+
+ static_storage_addr = irb_.CreateLoad(static_storage_field_addr);
+ } else {
+ // Medium path, static storage base in a different class which
+ // requires checks that the other class is initialized
+ DCHECK_GE(ssb_index, 0);
+ static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
+ }
+
+ llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
llvm::Value* static_field_addr =
irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
irb_.getJType(field_jty, kField)->getPointerTo());
+ // TODO: Check is_volatile. We need to generate atomic store instruction
+ // when is_volatile is true.
irb_.CreateStore(new_value, static_field_addr);
}
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 7b374af..efe8486 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -369,15 +369,6 @@
RegCategory GetInferredRegCategory(uint32_t dex_pc, uint16_t reg);
- Field* ResolveField(uint32_t field_idx);
-
- Field* FindFieldAndDeclaringTypeIdx(uint32_t field_idx,
- uint32_t &resolved_type_idx);
-
-
- // Diagnostics helper function
- void PrintUnresolvedFieldWarning(int32_t field_idx);
-
// Basic block helper functions
llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);