jni: Add @CriticalNative optimization to speed up JNI transitions
Change-Id: I963059ac3a72dd8e6a867596c356d7062deb6da7
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index 995fa51..3d89146 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -161,6 +161,12 @@
size_t NumArgs() const {
return num_args_;
}
+ // Implicit argument count: 1 for instance functions, 0 for static functions.
+ // (The implicit argument is only relevant to the shorty, i.e.
+ // the 0th arg is not in the shorty if it's implicit).
+ size_t NumImplicitArgs() const {
+ return IsStatic() ? 0 : 1;
+ }
size_t NumLongOrDoubleArgs() const {
return num_long_or_double_args_;
}
@@ -281,6 +287,7 @@
static std::unique_ptr<JniCallingConvention> Create(ArenaAllocator* arena,
bool is_static,
bool is_synchronized,
+ bool is_critical_native,
const char* shorty,
InstructionSet instruction_set);
@@ -288,7 +295,8 @@
// always at the bottom of a frame, but this doesn't work for outgoing
// native args). Includes alignment.
virtual size_t FrameSize() = 0;
- // Size of outgoing arguments, including alignment
+ // Size of outgoing arguments (stack portion), including alignment.
+ // -- Arguments that are passed via registers are excluded from this size.
virtual size_t OutArgSize() = 0;
// Number of references in stack indirect reference table
size_t ReferenceCount() const;
@@ -319,8 +327,11 @@
bool IsCurrentParamAFloatOrDouble();
bool IsCurrentParamADouble();
bool IsCurrentParamALong();
+ bool IsCurrentParamALongOrDouble() {
+ return IsCurrentParamALong() || IsCurrentParamADouble();
+ }
bool IsCurrentParamJniEnv();
- size_t CurrentParamSize();
+ size_t CurrentParamSize() const;
virtual bool IsCurrentParamInRegister() = 0;
virtual bool IsCurrentParamOnStack() = 0;
virtual ManagedRegister CurrentParamRegister() = 0;
@@ -359,18 +370,62 @@
kObjectOrClass = 1
};
+ // TODO: remove this constructor once all are changed to the below one.
JniCallingConvention(bool is_static,
bool is_synchronized,
const char* shorty,
PointerSize frame_pointer_size)
- : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {}
+ : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size),
+ is_critical_native_(false) {}
+
+ JniCallingConvention(bool is_static,
+ bool is_synchronized,
+ bool is_critical_native,
+ const char* shorty,
+ PointerSize frame_pointer_size)
+ : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size),
+ is_critical_native_(is_critical_native) {}
// Number of stack slots for outgoing arguments, above which the handle scope is
// located
virtual size_t NumberOfOutgoingStackArgs() = 0;
protected:
- size_t NumberOfExtraArgumentsForJni();
+ size_t NumberOfExtraArgumentsForJni() const;
+
+ // Does the transition have a StackHandleScope?
+ bool HasHandleScope() const;
+ // Does the transition have a local reference segment state?
+ bool HasLocalReferenceSegmentState() const;
+ // Has a JNIEnv* parameter implicitly?
+ bool HasJniEnv() const;
+ // Has a 'jclass' parameter implicitly?
+ bool HasSelfClass() const;
+
+ // Are there extra JNI arguments (JNIEnv* and maybe jclass)?
+ bool HasExtraArgumentsForJni() const;
+
+ // Returns the position of itr_args_, fixed up by removing the offset of extra JNI arguments.
+ unsigned int GetIteratorPositionWithinShorty() const;
+
+ // Is the current argument (at the iterator) an extra argument for JNI?
+ bool IsCurrentArgExtraForJni() const;
+
+ const bool is_critical_native_;
+
+ private:
+ // Shorthand for switching on the switch value but only IF there are extra JNI arguments.
+ //
+ // Puts the case value into return_value.
+ // * (switch_value == kJniEnv) => case_jni_env
+ // * (switch_value == kObjectOrClass) => case_object_or_class
+ //
+ // Returns false otherwise (or if there are no extra JNI arguments).
+ bool SwitchExtraJniArguments(size_t switch_value,
+ bool case_jni_env,
+ bool case_object_or_class,
+ /* out parameters */
+ bool* return_value) const;
};
} // namespace art