From: Nicolas Geoffray Date: Thu, 6 Nov 2014 15:15:31 +0000 (+0000) Subject: Support floats and doubles in fields. X-Git-Tag: android-x86-7.1-r1~889^2~2668^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=52e832b1278449e62d9eb502d54d5ff18f8606ed;p=android-x86%2Fart.git Support floats and doubles in fields. Change-Id: I19832106633405403f0461b3fe13b268abe39db3 --- diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 64fb76493..fc7333fa2 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -64,10 +64,6 @@ class Temporaries : public ValueObject { size_t index_; }; -static bool IsTypeSupported(Primitive::Type type) { - return type != Primitive::kPrimFloat && type != Primitive::kPrimDouble; -} - void HGraphBuilder::InitializeLocals(uint16_t count) { graph_->SetNumberOfVRegs(count); locals_.SetSize(count); @@ -78,10 +74,10 @@ void HGraphBuilder::InitializeLocals(uint16_t count) { } } -bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { +void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { // dex_compilation_unit_ is null only when unit testing. if (dex_compilation_unit_ == nullptr) { - return true; + return; } graph_->SetNumberOfInVRegs(number_of_parameters); @@ -116,7 +112,6 @@ bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { parameter_index++; } } - return true; } template @@ -195,9 +190,7 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { } } - if (!InitializeParameters(code_item.ins_size_)) { - return nullptr; - } + InitializeParameters(code_item.ins_size_); size_t dex_offset = 0; while (code_ptr < code_end) { @@ -456,9 +449,6 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, } Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); - if (!IsTypeSupported(field_type)) { - return false; - } HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot); current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_offset)); @@ -516,10 +506,6 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, return false; } - if (!IsTypeSupported(field_type)) { - return false; - } - HLoadClass* constant = new (arena_) HLoadClass( storage_index, is_referrers_class, dex_offset); current_block_->AddInstruction(constant); @@ -574,8 +560,6 @@ void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, uint8_t array_reg = instruction.VRegB_23x(); uint8_t index_reg = instruction.VRegC_23x(); - DCHECK(IsTypeSupported(anticipated_type)); - // We need one temporary for the null check, one for the index, and one for the length. Temporaries temps(graph_, 3); diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 030f45b60..09c9a5126 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -93,10 +93,7 @@ class HGraphBuilder : public ValueObject { void UpdateLocal(int register_index, HInstruction* instruction) const; HInstruction* LoadLocal(int register_index, Primitive::Type type) const; void PotentiallyAddSuspendCheck(int32_t target_offset, uint32_t dex_offset); - - // Temporarily returns whether the compiler supports the parameters - // of the method. - bool InitializeParameters(uint16_t number_of_parameters); + void InitializeParameters(uint16_t number_of_parameters); template void Unop_12x(const Instruction& instruction, Primitive::Type type); diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index fef7f0e80..a031ce338 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1826,10 +1826,18 @@ void InstructionCodeGeneratorARM::VisitInstanceFieldSet(HInstanceFieldSet* instr break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << field_type; - UNREACHABLE(); + case Primitive::kPrimFloat: { + SRegister value = locations->InAt(1).As(); + __ StoreSToOffset(value, obj, offset); + break; + } + + case Primitive::kPrimDouble: { + DRegister value = FromLowSToD(locations->InAt(1).AsFpuRegisterPairLow()); + __ StoreDToOffset(value, obj, offset); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); @@ -1887,10 +1895,18 @@ void InstructionCodeGeneratorARM::VisitInstanceFieldGet(HInstanceFieldGet* instr break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << instruction->GetType(); - UNREACHABLE(); + case Primitive::kPrimFloat: { + SRegister out = locations->Out().As(); + __ LoadSFromOffset(out, obj, offset); + break; + } + + case Primitive::kPrimDouble: { + DRegister out = FromLowSToD(locations->Out().AsFpuRegisterPairLow()); + __ LoadDFromOffset(out, obj, offset); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); @@ -2424,10 +2440,18 @@ void InstructionCodeGeneratorARM::VisitStaticFieldGet(HStaticFieldGet* instructi break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << instruction->GetType(); - UNREACHABLE(); + case Primitive::kPrimFloat: { + SRegister out = locations->Out().As(); + __ LoadSFromOffset(out, cls, offset); + break; + } + + case Primitive::kPrimDouble: { + DRegister out = FromLowSToD(locations->Out().AsFpuRegisterPairLow()); + __ LoadDFromOffset(out, cls, offset); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); @@ -2486,10 +2510,18 @@ void InstructionCodeGeneratorARM::VisitStaticFieldSet(HStaticFieldSet* instructi break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << field_type; - UNREACHABLE(); + case Primitive::kPrimFloat: { + SRegister value = locations->InAt(1).As(); + __ StoreSToOffset(value, cls, offset); + break; + } + + case Primitive::kPrimDouble: { + DRegister value = FromLowSToD(locations->InAt(1).AsFpuRegisterPairLow()); + __ StoreDToOffset(value, cls, offset); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 127ddbeab..54a12fdee 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1844,10 +1844,18 @@ void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instr break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << field_type; - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister value = locations->InAt(1).As(); + __ movss(Address(obj, offset), value); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister value = locations->InAt(1).As(); + __ movsd(Address(obj, offset), value); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); @@ -1917,10 +1925,18 @@ void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instr break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << instruction->GetType(); - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister out = locations->Out().As(); + __ movss(out, Address(obj, offset)); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister out = locations->Out().As(); + __ movsd(out, Address(obj, offset)); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); @@ -2508,10 +2524,18 @@ void InstructionCodeGeneratorX86::VisitStaticFieldGet(HStaticFieldGet* instructi break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << instruction->GetType(); - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister out = locations->Out().As(); + __ movss(out, Address(cls, offset)); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister out = locations->Out().As(); + __ movsd(out, Address(cls, offset)); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); @@ -2583,10 +2607,18 @@ void InstructionCodeGeneratorX86::VisitStaticFieldSet(HStaticFieldSet* instructi break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << field_type; - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister value = locations->InAt(1).As(); + __ movss(Address(cls, offset), value); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister value = locations->InAt(1).As(); + __ movsd(Address(cls, offset), value); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 8c0842cb8..9237cc3a4 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1692,25 +1692,27 @@ void LocationsBuilderX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instructio void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) { LocationSummary* locations = instruction->GetLocations(); CpuRegister obj = locations->InAt(0).As(); - CpuRegister value = locations->InAt(1).As(); size_t offset = instruction->GetFieldOffset().SizeValue(); Primitive::Type field_type = instruction->GetFieldType(); switch (field_type) { case Primitive::kPrimBoolean: case Primitive::kPrimByte: { + CpuRegister value = locations->InAt(1).As(); __ movb(Address(obj, offset), value); break; } case Primitive::kPrimShort: case Primitive::kPrimChar: { + CpuRegister value = locations->InAt(1).As(); __ movw(Address(obj, offset), value); break; } case Primitive::kPrimInt: case Primitive::kPrimNot: { + CpuRegister value = locations->InAt(1).As(); __ movl(Address(obj, offset), value); if (field_type == Primitive::kPrimNot) { CpuRegister temp = locations->GetTemp(0).As(); @@ -1721,14 +1723,23 @@ void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* in } case Primitive::kPrimLong: { + CpuRegister value = locations->InAt(1).As(); __ movq(Address(obj, offset), value); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << field_type; - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister value = locations->InAt(1).As(); + __ movss(Address(obj, offset), value); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister value = locations->InAt(1).As(); + __ movsd(Address(obj, offset), value); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); @@ -1745,45 +1756,58 @@ void LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instructio void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) { LocationSummary* locations = instruction->GetLocations(); CpuRegister obj = locations->InAt(0).As(); - CpuRegister out = locations->Out().As(); size_t offset = instruction->GetFieldOffset().SizeValue(); switch (instruction->GetType()) { case Primitive::kPrimBoolean: { + CpuRegister out = locations->Out().As(); __ movzxb(out, Address(obj, offset)); break; } case Primitive::kPrimByte: { + CpuRegister out = locations->Out().As(); __ movsxb(out, Address(obj, offset)); break; } case Primitive::kPrimShort: { + CpuRegister out = locations->Out().As(); __ movsxw(out, Address(obj, offset)); break; } case Primitive::kPrimChar: { + CpuRegister out = locations->Out().As(); __ movzxw(out, Address(obj, offset)); break; } case Primitive::kPrimInt: case Primitive::kPrimNot: { + CpuRegister out = locations->Out().As(); __ movl(out, Address(obj, offset)); break; } case Primitive::kPrimLong: { + CpuRegister out = locations->Out().As(); __ movq(out, Address(obj, offset)); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << instruction->GetType(); - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister out = locations->Out().As(); + __ movss(out, Address(obj, offset)); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister out = locations->Out().As(); + __ movsd(out, Address(obj, offset)); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); @@ -2460,45 +2484,58 @@ void LocationsBuilderX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) { void InstructionCodeGeneratorX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) { LocationSummary* locations = instruction->GetLocations(); CpuRegister cls = locations->InAt(0).As(); - CpuRegister out = locations->Out().As(); size_t offset = instruction->GetFieldOffset().SizeValue(); switch (instruction->GetType()) { case Primitive::kPrimBoolean: { + CpuRegister out = locations->Out().As(); __ movzxb(out, Address(cls, offset)); break; } case Primitive::kPrimByte: { + CpuRegister out = locations->Out().As(); __ movsxb(out, Address(cls, offset)); break; } case Primitive::kPrimShort: { + CpuRegister out = locations->Out().As(); __ movsxw(out, Address(cls, offset)); break; } case Primitive::kPrimChar: { + CpuRegister out = locations->Out().As(); __ movzxw(out, Address(cls, offset)); break; } case Primitive::kPrimInt: case Primitive::kPrimNot: { + CpuRegister out = locations->Out().As(); __ movl(out, Address(cls, offset)); break; } case Primitive::kPrimLong: { + CpuRegister out = locations->Out().As(); __ movq(out, Address(cls, offset)); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << instruction->GetType(); - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister out = locations->Out().As(); + __ movss(out, Address(cls, offset)); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister out = locations->Out().As(); + __ movsd(out, Address(cls, offset)); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); @@ -2522,25 +2559,27 @@ void LocationsBuilderX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) { void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) { LocationSummary* locations = instruction->GetLocations(); CpuRegister cls = locations->InAt(0).As(); - CpuRegister value = locations->InAt(1).As(); size_t offset = instruction->GetFieldOffset().SizeValue(); Primitive::Type field_type = instruction->GetFieldType(); switch (field_type) { case Primitive::kPrimBoolean: case Primitive::kPrimByte: { + CpuRegister value = locations->InAt(1).As(); __ movb(Address(cls, offset), value); break; } case Primitive::kPrimShort: case Primitive::kPrimChar: { + CpuRegister value = locations->InAt(1).As(); __ movw(Address(cls, offset), value); break; } case Primitive::kPrimInt: case Primitive::kPrimNot: { + CpuRegister value = locations->InAt(1).As(); __ movl(Address(cls, offset), value); if (field_type == Primitive::kPrimNot) { CpuRegister temp = locations->GetTemp(0).As(); @@ -2551,14 +2590,23 @@ void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instru } case Primitive::kPrimLong: { + CpuRegister value = locations->InAt(1).As(); __ movq(Address(cls, offset), value); break; } - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << field_type; - UNREACHABLE(); + case Primitive::kPrimFloat: { + XmmRegister value = locations->InAt(1).As(); + __ movss(Address(cls, offset), value); + break; + } + + case Primitive::kPrimDouble: { + XmmRegister value = locations->InAt(1).As(); + __ movsd(Address(cls, offset), value); + break; + } + case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable type " << field_type; UNREACHABLE(); diff --git a/test/406-fields/src/Main.java b/test/406-fields/src/Main.java index 3e94e4294..768a78472 100644 --- a/test/406-fields/src/Main.java +++ b/test/406-fields/src/Main.java @@ -30,6 +30,8 @@ public class Main extends TestCase { assertEquals(0, fields.iI); assertEquals(0, fields.iJ); assertEquals(0, fields.iS); + assertEquals(0.0f, fields.iF); + assertEquals(0.0, fields.iD); assertNull(fields.iObject); long longValue = -1122198787987987987L; @@ -40,6 +42,8 @@ public class Main extends TestCase { fields.iJ = longValue; fields.iS = 68; fields.iObject = fields; + fields.iF = 2.3f; + fields.iD = 5.3; assertEquals(true, fields.iZ); assertEquals(-2, fields.iB); @@ -48,6 +52,8 @@ public class Main extends TestCase { assertEquals(longValue, fields.iJ); assertEquals(68, fields.iS); assertEquals(fields, fields.iObject); + assertEquals(2.3f, fields.iF); + assertEquals(5.3, fields.iD); } static class AllFields { diff --git a/test/414-static-fields/src/Main.java b/test/414-static-fields/src/Main.java index 9c5cf133a..340377262 100644 --- a/test/414-static-fields/src/Main.java +++ b/test/414-static-fields/src/Main.java @@ -59,6 +59,8 @@ public class Main extends TestCase { assertEquals(0, sI); assertEquals(0, sJ); assertEquals(0, sS); + assertEquals(0.0f, sF); + assertEquals(0.0, sD); assertNull(sObject); long longValue = -1122198787987987987L; @@ -70,6 +72,8 @@ public class Main extends TestCase { sJ = longValue; sS = 68; sObject = o; + sF = 2.3f; + sD = 5.3; assertEquals(true, sZ); assertEquals(-2, sB); @@ -78,6 +82,8 @@ public class Main extends TestCase { assertEquals(longValue, sJ); assertEquals(68, sS); assertEquals(o, sObject); + assertEquals(2.3f, sF); + assertEquals(5.3, sD); } static boolean sZ;