Generating stub code for registering a jni function at runtime.

On ARM and x86. Added a unit test.

Change-Id: I6b1ee09ad18295108f406ce21d73555796ecbba6
diff --git a/src/stub_x86.cc b/src/stub_x86.cc
new file mode 100644
index 0000000..bddfc6c
--- /dev/null
+++ b/src/stub_x86.cc
@@ -0,0 +1,47 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "assembler_x86.h"
+#include "jni_internal.h"
+#include "object.h"
+
+#define __ assembler->
+
+namespace art {
+namespace x86 {
+
+ByteArray* CreateJniStub() {
+  UniquePtr<X86Assembler> assembler( static_cast<X86Assembler*>(Assembler::Create(kX86)) );
+
+  // Pad stack to ensure 16-byte alignment
+  __ pushl(Immediate(0));
+  __ pushl(Immediate(0));
+  __ pushl(Immediate(0));
+  __ fs()->movl(ECX, Address::Absolute(Thread::SelfOffset()));
+  __ pushl(ECX);  // Thread*
+
+  __ Call(reinterpret_cast<int32_t>(&FindNativeMethod), X86ManagedRegister::FromCpuRegister(ECX));
+
+  __ addl(ESP, Immediate(16));
+
+  Label no_native_code_found;  // forward declaration
+  __ cmpl(EAX, Immediate(0));
+  __ j(kEqual, &no_native_code_found);
+
+  __ jmp(EAX);  // Tail call into native code
+
+  __ Bind(&no_native_code_found);
+  __ ret(); // return to caller to handle exception
+
+  assembler->EmitSlowPaths();
+
+  size_t cs = assembler->CodeSize();
+  ByteArray* jni_stub = ByteArray::Alloc(cs);
+  CHECK(jni_stub != NULL);
+  MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
+  assembler->FinalizeInstructions(code);
+
+  return jni_stub;
+}
+
+} // namespace x86
+} // namespace art