Support floats and doubles in fields.
Change-Id: I19832106633405403f0461b3fe13b268abe39db3
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 64fb764..fc7333f 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -64,10 +64,6 @@
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 @@
}
}
-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 @@
parameter_index++;
}
}
- return true;
}
template<typename T>
@@ -195,9 +190,7 @@
}
}
- 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 @@
}
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 @@
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 @@
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 030f45b..09c9a51 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -93,10 +93,7 @@
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<typename T>
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 fef7f0e..a031ce3 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1826,10 +1826,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << field_type;
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ SRegister value = locations->InAt(1).As<SRegister>();
+ __ StoreSToOffset(value, obj, offset);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ DRegister value = FromLowSToD(locations->InAt(1).AsFpuRegisterPairLow<SRegister>());
+ __ StoreDToOffset(value, obj, offset);
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << field_type;
UNREACHABLE();
@@ -1887,10 +1895,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ SRegister out = locations->Out().As<SRegister>();
+ __ LoadSFromOffset(out, obj, offset);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ DRegister out = FromLowSToD(locations->Out().AsFpuRegisterPairLow<SRegister>());
+ __ LoadDFromOffset(out, obj, offset);
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
@@ -2424,10 +2440,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ SRegister out = locations->Out().As<SRegister>();
+ __ LoadSFromOffset(out, cls, offset);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ DRegister out = FromLowSToD(locations->Out().AsFpuRegisterPairLow<SRegister>());
+ __ LoadDFromOffset(out, cls, offset);
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
@@ -2486,10 +2510,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << field_type;
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ SRegister value = locations->InAt(1).As<SRegister>();
+ __ StoreSToOffset(value, cls, offset);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ DRegister value = FromLowSToD(locations->InAt(1).AsFpuRegisterPairLow<SRegister>());
+ __ 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 127ddbe..54a12fd 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1844,10 +1844,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << field_type;
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ XmmRegister value = locations->InAt(1).As<XmmRegister>();
+ __ movss(Address(obj, offset), value);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister value = locations->InAt(1).As<XmmRegister>();
+ __ movsd(Address(obj, offset), value);
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << field_type;
UNREACHABLE();
@@ -1917,10 +1925,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ XmmRegister out = locations->Out().As<XmmRegister>();
+ __ movss(out, Address(obj, offset));
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister out = locations->Out().As<XmmRegister>();
+ __ movsd(out, Address(obj, offset));
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
@@ -2508,10 +2524,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ XmmRegister out = locations->Out().As<XmmRegister>();
+ __ movss(out, Address(cls, offset));
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister out = locations->Out().As<XmmRegister>();
+ __ movsd(out, Address(cls, offset));
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
@@ -2583,10 +2607,18 @@
break;
}
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Unimplemented register type " << field_type;
- UNREACHABLE();
+ case Primitive::kPrimFloat: {
+ XmmRegister value = locations->InAt(1).As<XmmRegister>();
+ __ movss(Address(cls, offset), value);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister value = locations->InAt(1).As<XmmRegister>();
+ __ 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 8c0842c..9237cc3 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1692,25 +1692,27 @@
void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
LocationSummary* locations = instruction->GetLocations();
CpuRegister obj = locations->InAt(0).As<CpuRegister>();
- CpuRegister value = locations->InAt(1).As<CpuRegister>();
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<CpuRegister>();
__ movb(Address(obj, offset), value);
break;
}
case Primitive::kPrimShort:
case Primitive::kPrimChar: {
+ CpuRegister value = locations->InAt(1).As<CpuRegister>();
__ movw(Address(obj, offset), value);
break;
}
case Primitive::kPrimInt:
case Primitive::kPrimNot: {
+ CpuRegister value = locations->InAt(1).As<CpuRegister>();
__ movl(Address(obj, offset), value);
if (field_type == Primitive::kPrimNot) {
CpuRegister temp = locations->GetTemp(0).As<CpuRegister>();
@@ -1721,14 +1723,23 @@
}
case Primitive::kPrimLong: {
+ CpuRegister value = locations->InAt(1).As<CpuRegister>();
__ 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<XmmRegister>();
+ __ movss(Address(obj, offset), value);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister value = locations->InAt(1).As<XmmRegister>();
+ __ movsd(Address(obj, offset), value);
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << field_type;
UNREACHABLE();
@@ -1745,45 +1756,58 @@
void InstructionCodeGeneratorX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
LocationSummary* locations = instruction->GetLocations();
CpuRegister obj = locations->InAt(0).As<CpuRegister>();
- CpuRegister out = locations->Out().As<CpuRegister>();
size_t offset = instruction->GetFieldOffset().SizeValue();
switch (instruction->GetType()) {
case Primitive::kPrimBoolean: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movzxb(out, Address(obj, offset));
break;
}
case Primitive::kPrimByte: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movsxb(out, Address(obj, offset));
break;
}
case Primitive::kPrimShort: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movsxw(out, Address(obj, offset));
break;
}
case Primitive::kPrimChar: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movzxw(out, Address(obj, offset));
break;
}
case Primitive::kPrimInt:
case Primitive::kPrimNot: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movl(out, Address(obj, offset));
break;
}
case Primitive::kPrimLong: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ 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<XmmRegister>();
+ __ movss(out, Address(obj, offset));
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister out = locations->Out().As<XmmRegister>();
+ __ movsd(out, Address(obj, offset));
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
@@ -2460,45 +2484,58 @@
void InstructionCodeGeneratorX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
LocationSummary* locations = instruction->GetLocations();
CpuRegister cls = locations->InAt(0).As<CpuRegister>();
- CpuRegister out = locations->Out().As<CpuRegister>();
size_t offset = instruction->GetFieldOffset().SizeValue();
switch (instruction->GetType()) {
case Primitive::kPrimBoolean: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movzxb(out, Address(cls, offset));
break;
}
case Primitive::kPrimByte: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movsxb(out, Address(cls, offset));
break;
}
case Primitive::kPrimShort: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movsxw(out, Address(cls, offset));
break;
}
case Primitive::kPrimChar: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movzxw(out, Address(cls, offset));
break;
}
case Primitive::kPrimInt:
case Primitive::kPrimNot: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ movl(out, Address(cls, offset));
break;
}
case Primitive::kPrimLong: {
+ CpuRegister out = locations->Out().As<CpuRegister>();
__ 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<XmmRegister>();
+ __ movss(out, Address(cls, offset));
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister out = locations->Out().As<XmmRegister>();
+ __ movsd(out, Address(cls, offset));
+ break;
+ }
+
case Primitive::kPrimVoid:
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
@@ -2522,25 +2559,27 @@
void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
LocationSummary* locations = instruction->GetLocations();
CpuRegister cls = locations->InAt(0).As<CpuRegister>();
- CpuRegister value = locations->InAt(1).As<CpuRegister>();
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<CpuRegister>();
__ movb(Address(cls, offset), value);
break;
}
case Primitive::kPrimShort:
case Primitive::kPrimChar: {
+ CpuRegister value = locations->InAt(1).As<CpuRegister>();
__ movw(Address(cls, offset), value);
break;
}
case Primitive::kPrimInt:
case Primitive::kPrimNot: {
+ CpuRegister value = locations->InAt(1).As<CpuRegister>();
__ movl(Address(cls, offset), value);
if (field_type == Primitive::kPrimNot) {
CpuRegister temp = locations->GetTemp(0).As<CpuRegister>();
@@ -2551,14 +2590,23 @@
}
case Primitive::kPrimLong: {
+ CpuRegister value = locations->InAt(1).As<CpuRegister>();
__ 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<XmmRegister>();
+ __ movss(Address(cls, offset), value);
+ break;
+ }
+
+ case Primitive::kPrimDouble: {
+ XmmRegister value = locations->InAt(1).As<XmmRegister>();
+ __ 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 3e94e42..768a784 100644
--- a/test/406-fields/src/Main.java
+++ b/test/406-fields/src/Main.java
@@ -30,6 +30,8 @@
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 @@
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 @@
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 9c5cf13..3403772 100644
--- a/test/414-static-fields/src/Main.java
+++ b/test/414-static-fields/src/Main.java
@@ -59,6 +59,8 @@
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 @@
sJ = longValue;
sS = 68;
sObject = o;
+ sF = 2.3f;
+ sD = 5.3;
assertEquals(true, sZ);
assertEquals(-2, sB);
@@ -78,6 +82,8 @@
assertEquals(longValue, sJ);
assertEquals(68, sS);
assertEquals(o, sObject);
+ assertEquals(2.3f, sF);
+ assertEquals(5.3, sD);
}
static boolean sZ;