OSDN Git Service

Support floats and doubles in fields.
authorNicolas Geoffray <ngeoffray@google.com>
Thu, 6 Nov 2014 15:15:31 +0000 (15:15 +0000)
committerNicolas Geoffray <ngeoffray@google.com>
Fri, 7 Nov 2014 13:54:29 +0000 (13:54 +0000)
Change-Id: I19832106633405403f0461b3fe13b268abe39db3

compiler/optimizing/builder.cc
compiler/optimizing/builder.h
compiler/optimizing/code_generator_arm.cc
compiler/optimizing/code_generator_x86.cc
compiler/optimizing/code_generator_x86_64.cc
test/406-fields/src/Main.java
test/414-static-fields/src/Main.java

index 64fb764..fc7333f 100644 (file)
@@ -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<typename T>
@@ -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);
 
index 030f45b..09c9a51 100644 (file)
@@ -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<typename T>
   void Unop_12x(const Instruction& instruction, Primitive::Type type);
index fef7f0e..a031ce3 100644 (file)
@@ -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<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 @@ 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<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 @@ 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<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 @@ 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<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();
index 127ddbe..54a12fd 100644 (file)
@@ -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<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 @@ 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<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 @@ 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<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 @@ 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<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();
index 8c0842c..9237cc3 100644 (file)
@@ -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>();
-  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 @@ void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* in
     }
 
     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 LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instructio
 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 LocationsBuilderX86_64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
 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 LocationsBuilderX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
 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 @@ void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instru
     }
 
     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();
index 3e94e42..768a784 100644 (file)
@@ -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 {
index 9c5cf13..3403772 100644 (file)
@@ -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;