Generic JNI implementation for x86_64

Starting implementation for generic JNI on x86_64. Frames are of
large static size (>4K) right now, should be compacted later. Passes
the whole of jni_compiler_test.

Change-Id: I88ac3e13a534afe7568d62a1ef97cb766e8260e4
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 3bdc95e..bca72b8 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -204,19 +204,31 @@
     } else {
       // No code? You must mean to go into the interpreter.
       // Or the generic JNI...
-      const void* method_code = method->IsNative() ? GetQuickGenericJniTrampoline()
-                                                   : (kUsePortableCompiler
-                                                        ? GetPortableToInterpreterBridge()
-                                                        : GetQuickToInterpreterBridge());
-      OatFile::OatMethod oat_method = CreateOatMethod(method_code,
-                                                      kStackAlignment,
-                                                      0,
-                                                      0,
-                                                      nullptr,
-                                                      nullptr,
-                                                      nullptr);
-      oat_method.LinkMethod(method);
-      method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
+      if (!method->IsNative()) {
+        const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
+                                                       : GetQuickToInterpreterBridge();
+        OatFile::OatMethod oat_method = CreateOatMethod(method_code,
+                                                        kStackAlignment,
+                                                        0,
+                                                        0,
+                                                        nullptr,
+                                                        nullptr,
+                                                        nullptr);
+        oat_method.LinkMethod(method);
+        method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
+      } else {
+        const void* method_code = GetQuickGenericJniTrampoline();
+        mirror::ArtMethod* callee_save_method = runtime_->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
+        OatFile::OatMethod oat_method = CreateOatMethod(method_code,
+                                                        callee_save_method->GetFrameSizeInBytes(),
+                                                        callee_save_method->GetCoreSpillMask(),
+                                                        callee_save_method->GetFpSpillMask(),
+                                                        nullptr,
+                                                        nullptr,
+                                                        nullptr);
+        oat_method.LinkMethod(method);
+        method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
+      }
     }
     // Create bridges to transition between different kinds of compiled bridge.
     if (method->GetEntryPointFromPortableCompiledCode() == nullptr) {
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index f48cf6c..a9fbc64 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -328,7 +328,9 @@
   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
   gJava_MyClassNatives_fooIOO_calls++;
   ScopedObjectAccess soa(Thread::Current());
-  EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
+  size_t null_args = (y == nullptr ? 1 : 0) + (z == nullptr ? 1 : 0);
+  EXPECT_TRUE(3U == Thread::Current()->NumStackReferences() ||
+              (3U - null_args) == Thread::Current()->NumStackReferences());
   switch (x) {
     case 1:
       return y;
@@ -434,7 +436,9 @@
   EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
   gJava_MyClassNatives_fooSIOO_calls++;
   ScopedObjectAccess soa(Thread::Current());
-  EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
+  size_t null_args = (y == nullptr ? 1 : 0) + (z == nullptr ? 1 : 0);
+  EXPECT_TRUE(3U == Thread::Current()->NumStackReferences() ||
+              (3U - null_args) == Thread::Current()->NumStackReferences());
   switch (x) {
     case 1:
       return y;
@@ -487,7 +491,9 @@
   EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
   gJava_MyClassNatives_fooSSIOO_calls++;
   ScopedObjectAccess soa(Thread::Current());
-  EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
+  size_t null_args = (y == nullptr ? 1 : 0) + (z == nullptr ? 1 : 0);
+  EXPECT_TRUE(3U == Thread::Current()->NumStackReferences() ||
+              (3U - null_args) == Thread::Current()->NumStackReferences());
   switch (x) {
     case 1:
       return y;
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index 5d5eaf2..ac962af 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -106,7 +106,7 @@
 }
 
 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
-  size_t start_of_sirt = SirtLinkOffset().Int32Value() +  kPointerSize;
+  size_t start_of_sirt = SirtNumRefsOffset().Int32Value() +  kPointerSize;
   size_t references_size = kPointerSize * ReferenceCount();  // size excluding header
   return FrameOffset(start_of_sirt + references_size);
 }
@@ -158,11 +158,11 @@
 // position
 FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
   CHECK(IsCurrentParamAReference());
-  CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
+  CHECK_LT(SirtLinkOffset(), SirtNumRefsOffset());
   // Address of 1st SIRT entry
-  int result = SirtLinkOffset().Int32Value() + kPointerSize;
+  int result = SirtNumRefsOffset().Int32Value() + kPointerSize;
   result += itr_refs_ * kPointerSize;
-  CHECK_GT(result, SirtLinkOffset().Int32Value());
+  CHECK_GT(result, SirtNumRefsOffset().Int32Value());
   return FrameOffset(result);
 }