Support unresolved fields in optimizing
Change-Id: I9941fa5fcb6ef0a7a253c7a0b479a44a0210aad4
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 3c6a41d..1b66121 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -413,6 +413,120 @@
InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), nullptr);
}
+void CodeGenerator::CreateUnresolvedFieldLocationSummary(
+ HInstruction* field_access,
+ Primitive::Type field_type,
+ const FieldAccessCallingConvetion& calling_convention) {
+ bool is_instance = field_access->IsUnresolvedInstanceFieldGet()
+ || field_access->IsUnresolvedInstanceFieldSet();
+ bool is_get = field_access->IsUnresolvedInstanceFieldGet()
+ || field_access->IsUnresolvedStaticFieldGet();
+
+ ArenaAllocator* allocator = field_access->GetBlock()->GetGraph()->GetArena();
+ LocationSummary* locations =
+ new (allocator) LocationSummary(field_access, LocationSummary::kCall);
+
+ locations->AddTemp(calling_convention.GetFieldIndexLocation());
+
+ if (is_instance) {
+ // Add the `this` object for instance field accesses.
+ locations->SetInAt(0, calling_convention.GetObjectLocation());
+ }
+
+ // Note that pSetXXStatic/pGetXXStatic always takes/returns an int or int64
+ // regardless of the the type. Because of that we forced to special case
+ // the access to floating point values.
+ if (is_get) {
+ if (Primitive::IsFloatingPointType(field_type)) {
+ // The return value will be stored in regular registers while register
+ // allocator expects it in a floating point register. Allocate a temp for
+ // it and make the transfer at codegen.
+ AddLocationAsTemp(calling_convention.GetReturnLocation(field_type), locations);
+ locations->SetOut(calling_convention.GetFpuLocation(field_type));
+ } else {
+ locations->SetOut(calling_convention.GetReturnLocation(field_type));
+ }
+ } else {
+ size_t set_index = is_instance ? 1 : 0;
+ if (Primitive::IsFloatingPointType(field_type)) {
+ // The set value comes from a float location while the calling convention
+ // expects it in a regular register location. Allocate a temp for it and
+ // make the transfer at codegen.
+ AddLocationAsTemp(calling_convention.GetSetValueLocation(field_type, is_instance), locations);
+ locations->SetInAt(set_index, calling_convention.GetFpuLocation(field_type));
+ } else {
+ locations->SetInAt(set_index,
+ calling_convention.GetSetValueLocation(field_type, is_instance));
+ }
+ }
+}
+
+void CodeGenerator::GenerateUnresolvedFieldAccess(HInstruction* field_access,
+ Primitive::Type field_type,
+ uint32_t field_index,
+ uint32_t dex_pc) {
+ LocationSummary* locations = field_access->GetLocations();
+
+ MoveConstant(locations->GetTemp(0), field_index);
+
+ bool is_instance = field_access->IsUnresolvedInstanceFieldGet()
+ || field_access->IsUnresolvedInstanceFieldSet();
+ bool is_get = field_access->IsUnresolvedInstanceFieldGet()
+ || field_access->IsUnresolvedStaticFieldGet();
+
+ if (!is_get && Primitive::IsFloatingPointType(field_type)) {
+ MoveLocationToTemp(locations->InAt(is_instance ? 1 : 0), *locations, 1, field_type);
+ }
+
+ QuickEntrypointEnum entrypoint = kQuickSet8Static; // Initialize to anything to avoid warnings.
+ switch (field_type) {
+ case Primitive::kPrimBoolean:
+ entrypoint = is_instance
+ ? (is_get ? kQuickGetBooleanInstance : kQuickSet8Instance)
+ : (is_get ? kQuickGetBooleanStatic : kQuickSet8Static);
+ break;
+ case Primitive::kPrimByte:
+ entrypoint = is_instance
+ ? (is_get ? kQuickGetByteInstance : kQuickSet8Instance)
+ : (is_get ? kQuickGetByteStatic : kQuickSet8Static);
+ break;
+ case Primitive::kPrimShort:
+ entrypoint = is_instance
+ ? (is_get ? kQuickGetShortInstance : kQuickSet16Instance)
+ : (is_get ? kQuickGetShortStatic : kQuickSet16Static);
+ break;
+ case Primitive::kPrimChar:
+ entrypoint = is_instance
+ ? (is_get ? kQuickGetCharInstance : kQuickSet16Instance)
+ : (is_get ? kQuickGetCharStatic : kQuickSet16Static);
+ break;
+ case Primitive::kPrimInt:
+ case Primitive::kPrimFloat:
+ entrypoint = is_instance
+ ? (is_get ? kQuickGet32Instance : kQuickSet32Instance)
+ : (is_get ? kQuickGet32Static : kQuickSet32Static);
+ break;
+ case Primitive::kPrimNot:
+ entrypoint = is_instance
+ ? (is_get ? kQuickGetObjInstance : kQuickSetObjInstance)
+ : (is_get ? kQuickGetObjStatic : kQuickSetObjStatic);
+ break;
+ case Primitive::kPrimLong:
+ case Primitive::kPrimDouble:
+ entrypoint = is_instance
+ ? (is_get ? kQuickGet64Instance : kQuickSet64Instance)
+ : (is_get ? kQuickGet64Static : kQuickSet64Static);
+ break;
+ default:
+ LOG(FATAL) << "Invalid type " << field_type;
+ }
+ InvokeRuntime(entrypoint, field_access, dex_pc, nullptr);
+
+ if (is_get && Primitive::IsFloatingPointType(field_type)) {
+ MoveTempToLocation(*locations, 1, locations->Out(), field_type);
+ }
+}
+
void CodeGenerator::BlockIfInRegister(Location location, bool is_out) const {
// The DCHECKS below check that a register is not specified twice in
// the summary. The out location can overlap with an input, so we need