Support for cross compilation.
Refactor architecture specific files into arm and x86 name spaces. Make
assemblers and calling conventions use the factory pattern and an
instruction set specifier.
Change-Id: I20cd7aecacc1ae3d418221d98bbe1d69be9162a7
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index fec11da..bb1e965 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -1,5 +1,4 @@
// Copyright 2011 Google Inc. All Rights Reserved.
-// Author: irogers@google.com (Ian Rogers)
#include "jni_compiler.h"
@@ -8,14 +7,28 @@
#include "assembler.h"
#include "calling_convention.h"
+#include "constants.h"
#include "jni_internal.h"
#include "macros.h"
#include "managed_register.h"
#include "logging.h"
#include "thread.h"
+#include "UniquePtr.h"
namespace art {
+JniCompiler::JniCompiler(InstructionSet insns) {
+ if (insns == kThumb2) {
+ // currently only ARM code generation is supported
+ instruction_set_ = kArm;
+ } else {
+ instruction_set_ = insns;
+ }
+}
+
+JniCompiler::~JniCompiler() {}
+
+// Return value helper for jobject return types
static Object* DecodeJObjectInThread(Thread* thread, jobject obj) {
return thread->DecodeJObject(obj);
}
@@ -25,125 +38,140 @@
// registers, a reference to the method object is supplied as part of this
// convention.
//
-void JniCompiler::Compile(Assembler* jni_asm, Method* native_method) {
+void JniCompiler::Compile(Method* native_method) {
CHECK(native_method->IsNative());
- JniCallingConvention jni_conv(native_method);
- ManagedRuntimeCallingConvention mr_conv(native_method);
+
+ // Calling conventions used to iterate over parameters to method
+ UniquePtr<JniCallingConvention> jni_conv(
+ JniCallingConvention::Create(native_method, instruction_set_));
+ UniquePtr<ManagedRuntimeCallingConvention> mr_conv(
+ ManagedRuntimeCallingConvention::Create(native_method, instruction_set_));
+
+ // Assembler that holds generated instructions
+ UniquePtr<Assembler> jni_asm(Assembler::Create(instruction_set_));
+#define __ jni_asm->
+
+ // Offsets into data structures
+ // TODO: if cross compiling these offsets are for the host not the target
+ const Offset functions(OFFSETOF_MEMBER(JNIEnvExt, functions));
+ const Offset monitor_enter(OFFSETOF_MEMBER(JNINativeInterface, MonitorEnter));
+ const Offset monitor_exit(OFFSETOF_MEMBER(JNINativeInterface, MonitorExit));
+
+ // Cache of IsStatic as we call it often enough
const bool is_static = native_method->IsStatic();
- static Offset functions(OFFSETOF_MEMBER(JNIEnvExt, functions));
- static Offset monitor_enter(OFFSETOF_MEMBER(JNINativeInterface, MonitorEnter));
- static Offset monitor_exit(OFFSETOF_MEMBER(JNINativeInterface, MonitorExit));
+
// 1. Build the frame
- const size_t frame_size(jni_conv.FrameSize());
- const std::vector<ManagedRegister>& spill_regs = jni_conv.RegsToSpillPreCall();
- jni_asm->BuildFrame(frame_size, mr_conv.MethodRegister(), spill_regs);
+ const size_t frame_size(jni_conv->FrameSize());
+ const std::vector<ManagedRegister>& spill_regs = jni_conv->RegsToSpillPreCall();
+ __ BuildFrame(frame_size, mr_conv->MethodRegister(), spill_regs);
// 2. Save callee save registers that aren't callee save in the native code
// TODO: implement computing the difference of the callee saves
// and saving
// 3. Set up the StackIndirectReferenceTable
- mr_conv.ResetIterator(FrameOffset(frame_size));
- jni_conv.ResetIterator(FrameOffset(0));
- jni_asm->StoreImmediateToFrame(jni_conv.SirtNumRefsOffset(),
- jni_conv.ReferenceCount(),
- mr_conv.InterproceduralScratchRegister());
- jni_asm->CopyRawPtrFromThread(jni_conv.SirtLinkOffset(),
- Thread::TopSirtOffset(),
- mr_conv.InterproceduralScratchRegister());
- jni_asm->StoreStackOffsetToThread(Thread::TopSirtOffset(),
- jni_conv.SirtOffset(),
- mr_conv.InterproceduralScratchRegister());
+ mr_conv->ResetIterator(FrameOffset(frame_size));
+ jni_conv->ResetIterator(FrameOffset(0));
+ __ StoreImmediateToFrame(jni_conv->SirtNumRefsOffset(),
+ jni_conv->ReferenceCount(),
+ mr_conv->InterproceduralScratchRegister());
+ __ CopyRawPtrFromThread(jni_conv->SirtLinkOffset(),
+ Thread::TopSirtOffset(),
+ mr_conv->InterproceduralScratchRegister());
+ __ StoreStackOffsetToThread(Thread::TopSirtOffset(),
+ jni_conv->SirtOffset(),
+ mr_conv->InterproceduralScratchRegister());
// 4. Place incoming reference arguments into SIRT
- jni_conv.Next(); // Skip JNIEnv*
+ jni_conv->Next(); // Skip JNIEnv*
// 4.5. Create Class argument for static methods out of passed method
if (is_static) {
- FrameOffset sirt_offset = jni_conv.CurrentParamSirtEntryOffset();
+ FrameOffset sirt_offset = jni_conv->CurrentParamSirtEntryOffset();
// Check sirt offset is within frame
CHECK_LT(sirt_offset.Uint32Value(), frame_size);
- jni_asm->LoadRef(jni_conv.InterproceduralScratchRegister(),
- mr_conv.MethodRegister(), Method::DeclaringClassOffset());
- jni_asm->VerifyObject(jni_conv.InterproceduralScratchRegister(), false);
- jni_asm->StoreRef(sirt_offset, jni_conv.InterproceduralScratchRegister());
- jni_conv.Next(); // in SIRT so move to next argument
+ __ LoadRef(jni_conv->InterproceduralScratchRegister(),
+ mr_conv->MethodRegister(), Method::DeclaringClassOffset());
+ __ VerifyObject(jni_conv->InterproceduralScratchRegister(), false);
+ __ StoreRef(sirt_offset, jni_conv->InterproceduralScratchRegister());
+ jni_conv->Next(); // in SIRT so move to next argument
}
- while (mr_conv.HasNext()) {
- CHECK(jni_conv.HasNext());
- bool ref_param = jni_conv.IsCurrentParamAReference();
- CHECK(!ref_param || mr_conv.IsCurrentParamAReference());
+ while (mr_conv->HasNext()) {
+ CHECK(jni_conv->HasNext());
+ bool ref_param = jni_conv->IsCurrentParamAReference();
+ CHECK(!ref_param || mr_conv->IsCurrentParamAReference());
// References need placing in SIRT and the entry value passing
if (ref_param) {
// Compute SIRT entry, note null is placed in the SIRT but its boxed value
// must be NULL
- FrameOffset sirt_offset = jni_conv.CurrentParamSirtEntryOffset();
+ FrameOffset sirt_offset = jni_conv->CurrentParamSirtEntryOffset();
// Check SIRT offset is within frame
CHECK_LT(sirt_offset.Uint32Value(), frame_size);
- bool input_in_reg = mr_conv.IsCurrentParamInRegister();
- bool input_on_stack = mr_conv.IsCurrentParamOnStack();
+ bool input_in_reg = mr_conv->IsCurrentParamInRegister();
+ bool input_on_stack = mr_conv->IsCurrentParamOnStack();
CHECK(input_in_reg || input_on_stack);
if (input_in_reg) {
- ManagedRegister in_reg = mr_conv.CurrentParamRegister();
- jni_asm->VerifyObject(in_reg, mr_conv.IsCurrentArgPossiblyNull());
- jni_asm->StoreRef(sirt_offset, in_reg);
+ ManagedRegister in_reg = mr_conv->CurrentParamRegister();
+ __ VerifyObject(in_reg, mr_conv->IsCurrentArgPossiblyNull());
+ __ StoreRef(sirt_offset, in_reg);
} else if (input_on_stack) {
- FrameOffset in_off = mr_conv.CurrentParamStackOffset();
- jni_asm->VerifyObject(in_off, mr_conv.IsCurrentArgPossiblyNull());
- jni_asm->CopyRef(sirt_offset, in_off,
- mr_conv.InterproceduralScratchRegister());
+ FrameOffset in_off = mr_conv->CurrentParamStackOffset();
+ __ VerifyObject(in_off, mr_conv->IsCurrentArgPossiblyNull());
+ __ CopyRef(sirt_offset, in_off,
+ mr_conv->InterproceduralScratchRegister());
}
}
- mr_conv.Next();
- jni_conv.Next();
+ mr_conv->Next();
+ jni_conv->Next();
}
// 5. Transition from being in managed to native code
// TODO: ensure the transition to native follow a store fence.
- jni_asm->StoreStackPointerToThread(Thread::TopOfManagedStackOffset());
- jni_asm->StoreImmediateToThread(Thread::StateOffset(), Thread::kNative,
- mr_conv.InterproceduralScratchRegister());
+ __ StoreStackPointerToThread(Thread::TopOfManagedStackOffset());
+ __ StoreImmediateToThread(Thread::StateOffset(), Thread::kNative,
+ mr_conv->InterproceduralScratchRegister());
// 6. Move frame down to allow space for out going args. Do for as short a
// time as possible to aid profiling..
- const size_t out_arg_size = jni_conv.OutArgSize();
- jni_asm->IncreaseFrameSize(out_arg_size);
+ const size_t out_arg_size = jni_conv->OutArgSize();
+ __ IncreaseFrameSize(out_arg_size);
// 7. Acquire lock for synchronized methods.
if (native_method->IsSynchronized()) {
// TODO: preserve incoming arguments in registers
- mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
- jni_conv.Next(); // Skip JNIEnv*
+ mr_conv->ResetIterator(FrameOffset(frame_size+out_arg_size));
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
+ jni_conv->Next(); // Skip JNIEnv*
// Get SIRT entry for 1st argument
if (is_static) {
- FrameOffset sirt_offset = jni_conv.CurrentParamSirtEntryOffset();
- if (jni_conv.IsCurrentParamOnStack()) {
- FrameOffset out_off = jni_conv.CurrentParamStackOffset();
- jni_asm->CreateSirtEntry(out_off, sirt_offset,
- mr_conv.InterproceduralScratchRegister(),
- false);
+ FrameOffset sirt_offset = jni_conv->CurrentParamSirtEntryOffset();
+ if (jni_conv->IsCurrentParamOnStack()) {
+ FrameOffset out_off = jni_conv->CurrentParamStackOffset();
+ __ CreateSirtEntry(out_off, sirt_offset,
+ mr_conv->InterproceduralScratchRegister(),
+ false);
} else {
- ManagedRegister out_reg = jni_conv.CurrentParamRegister();
- jni_asm->CreateSirtEntry(out_reg, sirt_offset,
- ManagedRegister::NoRegister(), false);
+ ManagedRegister out_reg = jni_conv->CurrentParamRegister();
+ __ CreateSirtEntry(out_reg, sirt_offset,
+ ManagedRegister::NoRegister(), false);
}
} else {
- CopyParameter(jni_asm, &mr_conv, &jni_conv, frame_size, out_arg_size);
+ CopyParameter(jni_asm.get(), mr_conv.get(), jni_conv.get(), frame_size,
+ out_arg_size);
}
// Generate JNIEnv* in place and leave a copy in jni_fns_register
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
ManagedRegister jni_fns_register =
- jni_conv.InterproceduralScratchRegister();
- jni_asm->LoadRawPtrFromThread(jni_fns_register, Thread::JniEnvOffset());
- SetNativeParameter(jni_asm, &jni_conv, jni_fns_register);
+ jni_conv->InterproceduralScratchRegister();
+ __ LoadRawPtrFromThread(jni_fns_register, Thread::JniEnvOffset());
+ SetNativeParameter(jni_asm.get(), jni_conv.get(), jni_fns_register);
// Call JNIEnv->MonitorEnter(object)
- jni_asm->LoadRawPtr(jni_fns_register, jni_fns_register, functions);
- jni_asm->Call(jni_fns_register, monitor_enter,
- jni_conv.InterproceduralScratchRegister());
- jni_asm->FillFromSpillArea(spill_regs, out_arg_size);
- jni_asm->ExceptionPoll(jni_conv.InterproceduralScratchRegister());
+ __ LoadRawPtr(jni_fns_register, jni_fns_register, functions);
+ __ Call(jni_fns_register, monitor_enter,
+ jni_conv->InterproceduralScratchRegister());
+ __ FillFromSpillArea(spill_regs, out_arg_size);
+ __ ExceptionPoll(jni_conv->InterproceduralScratchRegister());
}
// 8. Iterate over arguments placing values from managed calling convention in
@@ -152,192 +180,198 @@
// NULL (which must be encoded as NULL).
// NB. we do this prior to materializing the JNIEnv* and static's jclass to
// give as many free registers for the shuffle as possible
- mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
+ mr_conv->ResetIterator(FrameOffset(frame_size+out_arg_size));
uint32_t args_count = 0;
- while (mr_conv.HasNext()) {
+ while (mr_conv->HasNext()) {
args_count++;
- mr_conv.Next();
+ mr_conv->Next();
}
// Do a backward pass over arguments, so that the generated code will be "mov
// R2, R3; mov R1, R2" instead of "mov R1, R2; mov R2, R3."
// TODO: A reverse iterator to improve readability.
for (uint32_t i = 0; i < args_count; ++i) {
- mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
- jni_conv.Next(); // Skip JNIEnv*
+ mr_conv->ResetIterator(FrameOffset(frame_size + out_arg_size));
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
+ jni_conv->Next(); // Skip JNIEnv*
if (is_static) {
- jni_conv.Next(); // Skip Class for now
+ jni_conv->Next(); // Skip Class for now
}
for (uint32_t j = 0; j < args_count - i - 1; ++j) {
- mr_conv.Next();
- jni_conv.Next();
+ mr_conv->Next();
+ jni_conv->Next();
}
- CopyParameter(jni_asm, &mr_conv, &jni_conv, frame_size, out_arg_size);
+ CopyParameter(jni_asm.get(), mr_conv.get(), jni_conv.get(), frame_size,
+ out_arg_size);
}
if (is_static) {
// Create argument for Class
- mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
- jni_conv.Next(); // Skip JNIEnv*
- FrameOffset sirt_offset = jni_conv.CurrentParamSirtEntryOffset();
- if (jni_conv.IsCurrentParamOnStack()) {
- FrameOffset out_off = jni_conv.CurrentParamStackOffset();
- jni_asm->CreateSirtEntry(out_off, sirt_offset,
- mr_conv.InterproceduralScratchRegister(),
- false);
+ mr_conv->ResetIterator(FrameOffset(frame_size+out_arg_size));
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
+ jni_conv->Next(); // Skip JNIEnv*
+ FrameOffset sirt_offset = jni_conv->CurrentParamSirtEntryOffset();
+ if (jni_conv->IsCurrentParamOnStack()) {
+ FrameOffset out_off = jni_conv->CurrentParamStackOffset();
+ __ CreateSirtEntry(out_off, sirt_offset,
+ mr_conv->InterproceduralScratchRegister(),
+ false);
} else {
- ManagedRegister out_reg = jni_conv.CurrentParamRegister();
- jni_asm->CreateSirtEntry(out_reg, sirt_offset,
- ManagedRegister::NoRegister(), false);
+ ManagedRegister out_reg = jni_conv->CurrentParamRegister();
+ __ CreateSirtEntry(out_reg, sirt_offset,
+ ManagedRegister::NoRegister(), false);
}
}
// 9. Create 1st argument, the JNI environment ptr
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
- if (jni_conv.IsCurrentParamInRegister()) {
- jni_asm->LoadRawPtrFromThread(jni_conv.CurrentParamRegister(),
- Thread::JniEnvOffset());
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
+ if (jni_conv->IsCurrentParamInRegister()) {
+ __ LoadRawPtrFromThread(jni_conv->CurrentParamRegister(),
+ Thread::JniEnvOffset());
} else {
- jni_asm->CopyRawPtrFromThread(jni_conv.CurrentParamStackOffset(),
- Thread::JniEnvOffset(),
- jni_conv.InterproceduralScratchRegister());
+ __ CopyRawPtrFromThread(jni_conv->CurrentParamStackOffset(),
+ Thread::JniEnvOffset(),
+ jni_conv->InterproceduralScratchRegister());
}
// 10. Plant call to native code associated with method
- if (!jni_conv.IsOutArgRegister(mr_conv.MethodRegister())) {
+ if (!jni_conv->IsOutArgRegister(mr_conv->MethodRegister())) {
// Method register shouldn't have been crushed by setting up outgoing
// arguments
- jni_asm->Call(mr_conv.MethodRegister(), Method::NativeMethodOffset(),
- mr_conv.InterproceduralScratchRegister());
+ __ Call(mr_conv->MethodRegister(), Method::NativeMethodOffset(),
+ mr_conv->InterproceduralScratchRegister());
} else {
- jni_asm->Call(jni_conv.MethodStackOffset(), Method::NativeMethodOffset(),
- mr_conv.InterproceduralScratchRegister());
+ __ Call(jni_conv->MethodStackOffset(), Method::NativeMethodOffset(),
+ mr_conv->InterproceduralScratchRegister());
}
// 11. Release lock for synchronized methods.
if (native_method->IsSynchronized()) {
- mr_conv.ResetIterator(FrameOffset(frame_size+out_arg_size));
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
- jni_conv.Next(); // Skip JNIEnv*
+ mr_conv->ResetIterator(FrameOffset(frame_size+out_arg_size));
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
+ jni_conv->Next(); // Skip JNIEnv*
// Save return value
- FrameOffset return_save_location = jni_conv.ReturnValueSaveLocation();
- if (jni_conv.SizeOfReturnValue() != 0) {
- FrameOffset return_save_location = jni_conv.ReturnValueSaveLocation();
+ FrameOffset return_save_location = jni_conv->ReturnValueSaveLocation();
+ if (jni_conv->SizeOfReturnValue() != 0) {
+ FrameOffset return_save_location = jni_conv->ReturnValueSaveLocation();
CHECK_LT(return_save_location.Uint32Value(), frame_size+out_arg_size);
- jni_asm->Store(return_save_location, jni_conv.ReturnRegister(),
- jni_conv.SizeOfReturnValue());
+ __ Store(return_save_location, jni_conv->ReturnRegister(),
+ jni_conv->SizeOfReturnValue());
}
// Get SIRT entry for 1st argument
if (is_static) {
- FrameOffset sirt_offset = jni_conv.CurrentParamSirtEntryOffset();
- if (jni_conv.IsCurrentParamOnStack()) {
- FrameOffset out_off = jni_conv.CurrentParamStackOffset();
- jni_asm->CreateSirtEntry(out_off, sirt_offset,
- mr_conv.InterproceduralScratchRegister(),
- false);
+ FrameOffset sirt_offset = jni_conv->CurrentParamSirtEntryOffset();
+ if (jni_conv->IsCurrentParamOnStack()) {
+ FrameOffset out_off = jni_conv->CurrentParamStackOffset();
+ __ CreateSirtEntry(out_off, sirt_offset,
+ mr_conv->InterproceduralScratchRegister(),
+ false);
} else {
- ManagedRegister out_reg = jni_conv.CurrentParamRegister();
- jni_asm->CreateSirtEntry(out_reg, sirt_offset,
- ManagedRegister::NoRegister(), false);
+ ManagedRegister out_reg = jni_conv->CurrentParamRegister();
+ __ CreateSirtEntry(out_reg, sirt_offset,
+ ManagedRegister::NoRegister(), false);
}
} else {
- CopyParameter(jni_asm, &mr_conv, &jni_conv, frame_size, out_arg_size);
+ CopyParameter(jni_asm.get(), mr_conv.get(), jni_conv.get(), frame_size,
+ out_arg_size);
}
// Generate JNIEnv* in place and leave a copy in jni_env_register
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
ManagedRegister jni_env_register =
- jni_conv.InterproceduralScratchRegister();
- jni_asm->LoadRawPtrFromThread(jni_env_register, Thread::JniEnvOffset());
- SetNativeParameter(jni_asm, &jni_conv, jni_env_register);
+ jni_conv->InterproceduralScratchRegister();
+ __ LoadRawPtrFromThread(jni_env_register, Thread::JniEnvOffset());
+ SetNativeParameter(jni_asm.get(), jni_conv.get(), jni_env_register);
// Call JNIEnv->MonitorExit(object)
- jni_asm->LoadRawPtr(jni_env_register, jni_env_register, functions);
- jni_asm->Call(jni_env_register, monitor_exit,
- jni_conv.InterproceduralScratchRegister());
+ __ LoadRawPtr(jni_env_register, jni_env_register, functions);
+ __ Call(jni_env_register, monitor_exit,
+ jni_conv->InterproceduralScratchRegister());
// Reload return value
- if (jni_conv.SizeOfReturnValue() != 0) {
- jni_asm->Load(jni_conv.ReturnRegister(), return_save_location,
- jni_conv.SizeOfReturnValue());
+ if (jni_conv->SizeOfReturnValue() != 0) {
+ __ Load(jni_conv->ReturnRegister(), return_save_location,
+ jni_conv->SizeOfReturnValue());
}
}
// 12. Release outgoing argument area
- jni_asm->DecreaseFrameSize(out_arg_size);
- mr_conv.ResetIterator(FrameOffset(frame_size));
- jni_conv.ResetIterator(FrameOffset(0));
+ __ DecreaseFrameSize(out_arg_size);
+ mr_conv->ResetIterator(FrameOffset(frame_size));
+ jni_conv->ResetIterator(FrameOffset(0));
// 13. Transition from being in native to managed code, possibly entering a
// safepoint
- CHECK(!jni_conv.InterproceduralScratchRegister()
- .Equals(jni_conv.ReturnRegister())); // don't clobber result
+ CHECK(!jni_conv->InterproceduralScratchRegister()
+ .Equals(jni_conv->ReturnRegister())); // don't clobber result
// Location to preserve result on slow path, ensuring its within the frame
- FrameOffset return_save_location = jni_conv.ReturnValueSaveLocation();
+ FrameOffset return_save_location = jni_conv->ReturnValueSaveLocation();
CHECK(return_save_location.Uint32Value() < frame_size ||
- jni_conv.SizeOfReturnValue() == 0);
- jni_asm->SuspendPoll(jni_conv.InterproceduralScratchRegister(),
- jni_conv.ReturnRegister(), return_save_location,
- jni_conv.SizeOfReturnValue());
- jni_asm->ExceptionPoll(jni_conv.InterproceduralScratchRegister());
- jni_asm->StoreImmediateToThread(Thread::StateOffset(), Thread::kRunnable,
- jni_conv.InterproceduralScratchRegister());
+ jni_conv->SizeOfReturnValue() == 0);
+ __ SuspendPoll(jni_conv->InterproceduralScratchRegister(),
+ jni_conv->ReturnRegister(), return_save_location,
+ jni_conv->SizeOfReturnValue());
+ __ ExceptionPoll(jni_conv->InterproceduralScratchRegister());
+ __ StoreImmediateToThread(Thread::StateOffset(), Thread::kRunnable,
+ jni_conv->InterproceduralScratchRegister());
// 14. Place result in correct register possibly loading from indirect
// reference table
- if (jni_conv.IsReturnAReference()) {
- jni_asm->IncreaseFrameSize(out_arg_size);
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
+ if (jni_conv->IsReturnAReference()) {
+ __ IncreaseFrameSize(out_arg_size);
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
- jni_conv.Next(); // Skip Thread* argument
+ jni_conv->Next(); // Skip Thread* argument
// Pass result as arg2
- SetNativeParameter(jni_asm, &jni_conv, jni_conv.ReturnRegister());
+ SetNativeParameter(jni_asm.get(), jni_conv.get(),
+ jni_conv->ReturnRegister());
// Pass Thread*
- jni_conv.ResetIterator(FrameOffset(out_arg_size));
- if (jni_conv.IsCurrentParamInRegister()) {
- jni_asm->GetCurrentThread(jni_conv.CurrentParamRegister());
+ jni_conv->ResetIterator(FrameOffset(out_arg_size));
+ if (jni_conv->IsCurrentParamInRegister()) {
+ __ GetCurrentThread(jni_conv->CurrentParamRegister());
} else {
- jni_asm->GetCurrentThread(jni_conv.CurrentParamStackOffset(),
- jni_conv.InterproceduralScratchRegister());
+ __ GetCurrentThread(jni_conv->CurrentParamStackOffset(),
+ jni_conv->InterproceduralScratchRegister());
}
- jni_asm->Call(reinterpret_cast<uintptr_t>(DecodeJObjectInThread),
- jni_conv.InterproceduralScratchRegister());
+ __ Call(reinterpret_cast<uintptr_t>(DecodeJObjectInThread),
+ jni_conv->InterproceduralScratchRegister());
- jni_asm->DecreaseFrameSize(out_arg_size);
- jni_conv.ResetIterator(FrameOffset(0));
+ __ DecreaseFrameSize(out_arg_size);
+ jni_conv->ResetIterator(FrameOffset(0));
}
- jni_asm->Move(mr_conv.ReturnRegister(), jni_conv.ReturnRegister());
+ __ Move(mr_conv->ReturnRegister(), jni_conv->ReturnRegister());
// 15. Remove SIRT from thread
- jni_asm->CopyRawPtrToThread(Thread::TopSirtOffset(), jni_conv.SirtLinkOffset(),
- jni_conv.InterproceduralScratchRegister());
+ __ CopyRawPtrToThread(Thread::TopSirtOffset(), jni_conv->SirtLinkOffset(),
+ jni_conv->InterproceduralScratchRegister());
// 16. Remove activation
- jni_asm->RemoveFrame(frame_size, spill_regs);
+ __ RemoveFrame(frame_size, spill_regs);
// 17. Finalize code generation
- jni_asm->EmitSlowPaths();
- size_t cs = jni_asm->CodeSize();
+ __ EmitSlowPaths();
+ size_t cs = __ CodeSize();
ByteArray* managed_code = ByteArray::Alloc(cs);
CHECK(managed_code != NULL);
MemoryRegion code(managed_code->GetData(), managed_code->GetLength());
- jni_asm->FinalizeInstructions(code);
- native_method->SetCode(managed_code, jni_asm->GetInstructionSet());
+ __ FinalizeInstructions(code);
+ native_method->SetCode(managed_code, instruction_set_);
native_method->SetFrameSizeInBytes(frame_size);
- native_method->SetReturnPcOffsetInBytes(jni_conv.ReturnPcOffset());
+ native_method->SetReturnPcOffsetInBytes(jni_conv->ReturnPcOffset());
+#undef __
}
-void JniCompiler::SetNativeParameter(Assembler *jni_asm,
- JniCallingConvention *jni_conv,
+void JniCompiler::SetNativeParameter(Assembler* jni_asm,
+ JniCallingConvention* jni_conv,
ManagedRegister in_reg) {
+#define __ jni_asm->
if (jni_conv->IsCurrentParamOnStack()) {
FrameOffset dest = jni_conv->CurrentParamStackOffset();
- jni_asm->StoreRawPtr(dest, in_reg);
+ __ StoreRawPtr(dest, in_reg);
} else {
if (!jni_conv->CurrentParamRegister().Equals(in_reg)) {
- jni_asm->Move(jni_conv->CurrentParamRegister(), in_reg);
+ __ Move(jni_conv->CurrentParamRegister(), in_reg);
}
}
+#undef __
}
// Copy a single parameter from the managed to the JNI calling convention
@@ -345,6 +379,7 @@
ManagedRuntimeCallingConvention* mr_conv,
JniCallingConvention* jni_conv,
size_t frame_size, size_t out_arg_size) {
+
bool input_in_reg = mr_conv->IsCurrentParamInRegister();
bool output_in_reg = jni_conv->IsCurrentParamInRegister();
FrameOffset sirt_offset(0);
@@ -368,15 +403,16 @@
// Check SIRT offset is within frame.
CHECK_LT(sirt_offset.Uint32Value(), (frame_size+out_arg_size));
}
+#define __ jni_asm->
if (input_in_reg && output_in_reg) {
ManagedRegister in_reg = mr_conv->CurrentParamRegister();
ManagedRegister out_reg = jni_conv->CurrentParamRegister();
if (ref_param) {
- jni_asm->CreateSirtEntry(out_reg, sirt_offset, in_reg, null_allowed);
+ __ CreateSirtEntry(out_reg, sirt_offset, in_reg, null_allowed);
} else {
if (!mr_conv->IsCurrentParamOnStack()) {
// regular non-straddling move
- jni_asm->Move(out_reg, in_reg);
+ __ Move(out_reg, in_reg);
} else {
UNIMPLEMENTED(FATAL); // we currently don't expect to see this case
}
@@ -384,15 +420,15 @@
} else if (!input_in_reg && !output_in_reg) {
FrameOffset out_off = jni_conv->CurrentParamStackOffset();
if (ref_param) {
- jni_asm->CreateSirtEntry(out_off, sirt_offset,
- mr_conv->InterproceduralScratchRegister(),
- null_allowed);
+ __ CreateSirtEntry(out_off, sirt_offset,
+ mr_conv->InterproceduralScratchRegister(),
+ null_allowed);
} else {
FrameOffset in_off = mr_conv->CurrentParamStackOffset();
size_t param_size = mr_conv->CurrentParamSize();
CHECK_EQ(param_size, jni_conv->CurrentParamSize());
- jni_asm->Copy(out_off, in_off, mr_conv->InterproceduralScratchRegister(),
- param_size);
+ __ Copy(out_off, in_off, mr_conv->InterproceduralScratchRegister(),
+ param_size);
}
} else if (!input_in_reg && output_in_reg) {
FrameOffset in_off = mr_conv->CurrentParamStackOffset();
@@ -400,12 +436,12 @@
// Check that incoming stack arguments are above the current stack frame.
CHECK_GT(in_off.Uint32Value(), frame_size);
if (ref_param) {
- jni_asm->CreateSirtEntry(out_reg, sirt_offset,
- ManagedRegister::NoRegister(), null_allowed);
+ __ CreateSirtEntry(out_reg, sirt_offset,
+ ManagedRegister::NoRegister(), null_allowed);
} else {
unsigned int param_size = mr_conv->CurrentParamSize();
CHECK_EQ(param_size, jni_conv->CurrentParamSize());
- jni_asm->Load(out_reg, in_off, param_size);
+ __ Load(out_reg, in_off, param_size);
}
} else {
CHECK(input_in_reg && !output_in_reg);
@@ -415,28 +451,25 @@
CHECK_LT(out_off.Uint32Value(), frame_size);
if (ref_param) {
// TODO: recycle value in in_reg rather than reload from SIRT
- jni_asm->CreateSirtEntry(out_off, sirt_offset,
- mr_conv->InterproceduralScratchRegister(),
- null_allowed);
+ __ CreateSirtEntry(out_off, sirt_offset,
+ mr_conv->InterproceduralScratchRegister(),
+ null_allowed);
} else {
size_t param_size = mr_conv->CurrentParamSize();
CHECK_EQ(param_size, jni_conv->CurrentParamSize());
if (!mr_conv->IsCurrentParamOnStack()) {
// regular non-straddling store
- jni_asm->Store(out_off, in_reg, param_size);
+ __ Store(out_off, in_reg, param_size);
} else {
// store where input straddles registers and stack
CHECK_EQ(param_size, 8u);
FrameOffset in_off = mr_conv->CurrentParamStackOffset();
- jni_asm->StoreSpanning(out_off, in_reg, in_off,
- mr_conv->InterproceduralScratchRegister());
+ __ StoreSpanning(out_off, in_reg, in_off,
+ mr_conv->InterproceduralScratchRegister());
}
}
}
+#undef __
}
-JniCompiler::JniCompiler() {}
-
-JniCompiler::~JniCompiler() {}
-
} // namespace art