x86_64: JNI compiler

Passed all tests from jni_compiler_test and art/test on host with jni_copiler.
Incoming argument spill is enabled, entry_spills refactored. Now each entry spill
contains data type size (4 or 8) and offset which should be used for spill.
Assembler REX support implemented in opcodes used in JNI compiler.
Please note, JNI compiler is not enabled by default yet (see compiler_driver.cc:1875).

Change-Id: I5fd19cca72122b197aec07c3708b1e80c324be44
Signed-off-by: Dmitry Petrochenko <dmitry.petrochenko@intel.com>
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index f2b7fd9..fe3d1cd 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -60,23 +60,35 @@
     itr_args_ = 0;
     itr_refs_ = 0;
     itr_longs_and_doubles_ = 0;
+    itr_float_and_doubles_ = 0;
   }
 
   virtual ~CallingConvention() {}
 
  protected:
   CallingConvention(bool is_static, bool is_synchronized, const char* shorty)
-      : displacement_(0), is_static_(is_static), is_synchronized_(is_synchronized),
+      : displacement_(0), kSirtPointerSize(sizeof(StackReference<mirror::Object>)), is_static_(is_static), is_synchronized_(is_synchronized),
         shorty_(shorty) {
     num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1;
     num_ref_args_ = is_static ? 0 : 1;  // The implicit this pointer.
+    num_float_or_double_args_ = 0;
     num_long_or_double_args_ = 0;
     for (size_t i = 1; i < strlen(shorty); i++) {
       char ch = shorty_[i];
-      if (ch == 'L') {
+      switch (ch) {
+      case 'L':
         num_ref_args_++;
-      } else if ((ch == 'D') || (ch == 'J')) {
+        break;
+      case 'J':
         num_long_or_double_args_++;
+        break;
+      case 'D':
+        num_long_or_double_args_++;
+        num_float_or_double_args_++;
+        break;
+      case 'F':
+        num_float_or_double_args_++;
+        break;
       }
     }
   }
@@ -97,6 +109,16 @@
     char ch = shorty_[param];
     return (ch == 'J' || ch == 'D');
   }
+  bool IsParamAFloatOrDouble(unsigned int param) const {
+    DCHECK_LT(param, NumArgs());
+    if (IsStatic()) {
+      param++;  // 0th argument must skip return value at start of the shorty
+    } else if (param == 0) {
+      return false;  // this argument
+    }
+    char ch = shorty_[param];
+    return (ch == 'F' || ch == 'D');
+  }
   bool IsParamAReference(unsigned int param) const {
     DCHECK_LT(param, NumArgs());
     if (IsStatic()) {
@@ -112,6 +134,9 @@
   size_t NumLongOrDoubleArgs() const {
     return num_long_or_double_args_;
   }
+  size_t NumFloatOrDoubleArgs() const {
+    return num_float_or_double_args_;
+  }
   size_t NumReferenceArgs() const {
     return num_ref_args_;
   }
@@ -141,8 +166,11 @@
   unsigned int itr_args_;
   // Number of longs and doubles seen along argument list
   unsigned int itr_longs_and_doubles_;
+  // Number of float and doubles seen along argument list
+  unsigned int itr_float_and_doubles_;
   // Space for frames below this on the stack
   FrameOffset displacement_;
+  size_t kSirtPointerSize;
 
  private:
   const bool is_static_;
@@ -150,6 +178,7 @@
   std::string shorty_;
   size_t num_args_;
   size_t num_ref_args_;
+  size_t num_float_or_double_args_;
   size_t num_long_or_double_args_;
 };
 
@@ -174,6 +203,7 @@
   bool HasNext();
   void Next();
   bool IsCurrentParamAReference();
+  bool IsCurrentParamAFloatOrDouble();
   bool IsCurrentArgExplicit();  // ie a non-implict argument such as this
   bool IsCurrentArgPossiblyNull();
   size_t CurrentParamSize();
@@ -185,7 +215,7 @@
   virtual ~ManagedRuntimeCallingConvention() {}
 
   // Registers to spill to caller's out registers on entry.
-  virtual const std::vector<ManagedRegister>& EntrySpills() = 0;
+  virtual const ManagedRegisterEntrySpills& EntrySpills() = 0;
 
  protected:
   ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
@@ -241,6 +271,7 @@
   bool HasNext();
   virtual void Next();
   bool IsCurrentParamAReference();
+  bool IsCurrentParamAFloatOrDouble();
   size_t CurrentParamSize();
   virtual bool IsCurrentParamInRegister() = 0;
   virtual bool IsCurrentParamOnStack() = 0;
@@ -255,13 +286,21 @@
     return FrameOffset(displacement_.Int32Value() +
                        kPointerSize);  // above Method*
   }
+
+  FrameOffset SirtLinkOffset() const {
+    return FrameOffset(SirtOffset().Int32Value() +
+                       StackIndirectReferenceTable::LinkOffset());
+  }
+
   FrameOffset SirtNumRefsOffset() const {
     return FrameOffset(SirtOffset().Int32Value() +
                        StackIndirectReferenceTable::NumberOfReferencesOffset());
   }
-  FrameOffset SirtLinkOffset() const {
-    return FrameOffset(SirtOffset().Int32Value() +
-                       StackIndirectReferenceTable::LinkOffset());
+
+  FrameOffset SirtReferencesOffset() const {
+    // The StackIndirectReferenceTable::number_of_references_ type is uint32_t
+    return FrameOffset(SirtNumRefsOffset().Int32Value() +
+                       sizeof(uint32_t));
   }
 
   virtual ~JniCallingConvention() {}