size_t SizeOfReturnValue() const {
size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[0])); if (result >= 1 && result < 4) {
result = 4;
} return result;
}
// Register that holds result of this method invocation. virtual ManagedRegister ReturnRegister() const = 0;
// Iterator interface
// Place iterator at start of arguments. The displacement is applied to // frame offset methods to account for frames which may be on the stack // below the one being iterated over. virtualvoid ResetIterator(FrameOffset displacement) {
displacement_ = displacement;
itr_slots_ = 0;
itr_args_ = 0;
itr_refs_ = 0;
itr_longs_and_doubles_ = 0;
itr_float_and_doubles_ = 0;
}
bool IsStatic() const { return is_static_;
} bool IsSynchronized() const { return is_synchronized_;
} bool IsParamALongOrDouble(unsignedint param) const {
DCHECK_LT(param, NumArgs()); if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
} elseif (param == 0) { returnfalse; // this argument
} char ch = shorty_[param]; return (ch == 'J' || ch == 'D');
} bool IsParamAFloatOrDouble(unsignedint param) const {
DCHECK_LT(param, NumArgs()); if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
} elseif (param == 0) { returnfalse; // this argument
} char ch = shorty_[param]; return (ch == 'F' || ch == 'D');
} bool IsParamADouble(unsignedint param) const {
DCHECK_LT(param, NumArgs()); if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
} elseif (param == 0) { returnfalse; // this argument
} return shorty_[param] == 'D';
} bool IsParamALong(unsignedint param) const {
DCHECK_LT(param, NumArgs()); if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
} elseif (param == 0) { returnfalse; // this argument
} return shorty_[param] == 'J';
} bool IsParamAReference(unsignedint param) const {
DCHECK_LT(param, NumArgs()); if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
} elseif (param == 0) { returntrue; // this argument
} return shorty_[param] == 'L';
}
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_;
}
size_t NumFloatOrDoubleArgs() const { return num_float_or_double_args_;
}
size_t NumReferenceArgs() const { return num_ref_args_;
}
size_t ParamSize(size_t param, size_t reference_size) const {
DCHECK_LT(param, NumArgs()); if (IsStatic()) {
param++; // 0th argument must skip return value at start of the shorty
} elseif (param == 0) { return reference_size; // this argument
}
Primitive::Type type = Primitive::GetType(shorty_[param]); if (type == Primitive::kPrimNot) { return reference_size;
}
size_t result = Primitive::ComponentSize(type); if (result >= 1 && result < 4) {
result = 4;
} return result;
}
std::string_view GetShorty() const { return shorty_;
} // The slot number for current calling_convention argument. // Note that each slot is 32-bit. When the current argument is bigger // than 32 bits, return the first slot number for this argument. unsignedint itr_slots_; // The number of references iterated past. unsignedint itr_refs_; // The argument number along argument list for current argument. unsignedint itr_args_; // Number of longs and doubles seen along argument list. unsignedint itr_longs_and_doubles_; // Number of float and doubles seen along argument list. unsignedint itr_float_and_doubles_; // Space for frames below this on the stack.
FrameOffset displacement_; // The size of a pointer. const PointerSize frame_pointer_size_;
// Offset of Method within the managed frame.
FrameOffset MethodStackOffset() { return FrameOffset(0u);
}
// Register that holds the incoming method argument virtual ManagedRegister MethodRegister() = 0;
// Register that is used to pass frame size for method exit hook call. This // shouldn't be the same as the return register since method exit hook also expects // return values in the return register. virtual ManagedRegister ArgumentRegisterForMethodExitHook() = 0;
// Abstraction for JNI calling conventions // | { Incoming stack args } | <-- Prior SP // | { Return address } | // | { Callee saves } | ([1]) // | { Return value spill } | (live on return slow paths) // | { Local Ref. Table State } | // | { Stack Indirect Ref. Table | // | num. refs./link } | (here to prior SP is frame size) // | { Method* } | <-- Anchor SP written to thread // | { Outgoing stack args } | <-- SP at point of call // | Native frame | // // [1] We must save all callee saves here to enable any exception throws to restore // callee saves for frames above this one. class JniCallingConvention : public CallingConvention { public: static std::unique_ptr<JniCallingConvention> Create(ArenaAllocator* allocator, bool is_static, bool is_synchronized, bool is_fast_native, bool is_critical_native,
std::string_view shorty,
InstructionSet instruction_set);
// Size of frame excluding space for outgoing args (its assumed Method* is // always at the bottom of a frame, but this doesn't work for outgoing // native args). Includes alignment. virtual size_t FrameSize() const = 0; // Size of outgoing frame, i.e. stack arguments, @CriticalNative return PC if needed, alignment. // -- Arguments that are passed via registers are excluded from this size. virtual size_t OutFrameSize() const = 0; // Number of references in stack indirect reference table
size_t ReferenceCount() const; // Register that holds result if it is integer. virtual ManagedRegister IntReturnRegister() const = 0; // Whether the compiler needs to ensure zero-/sign-extension of a small result type virtualbool RequiresSmallResultTypeExtension() const = 0;
// Callee save registers to spill prior to native code (which may clobber) virtual ArrayRef<const ManagedRegister> CalleeSaveRegisters() const = 0;
// Subset of core callee save registers that can be used for arbitrary purposes after // constructing the JNI transition frame. These should be both managed and native callee-saves. // These should not include special purpose registers such as thread register. // JNI compiler currently requires at least 4 callee save scratch registers, except for x86 // where we have only 3 such registers but all args are passed on stack, so the method register // is never clobbered by argument moves and does not need to be preserved elsewhere. virtual ArrayRef<const ManagedRegister> CalleeSaveScratchRegisters() const = 0;
// Subset of core argument registers that can be used for arbitrary purposes after // calling the native function. These should exclude the return register(s). virtual ArrayRef<const ManagedRegister> ArgumentScratchRegisters() const = 0;
// Does the transition have a method pointer in the stack frame? bool SpillsMethod() const { // Exclude method pointer for @CriticalNative methods for optimization speed. return !IsCriticalNative();
}
// Locking argument register, used to pass the synchronization object for calls // to `JniLockObject()` and `JniUnlockObject()`. virtual ManagedRegister LockingArgumentRegister() const = 0;
// Hidden argument register, used to pass the method pointer for @CriticalNative call. virtual ManagedRegister HiddenArgumentRegister() const = 0;
// Whether to use tail call (used only for @CriticalNative). virtualbool UseTailCall() const = 0;
// Whether the return type is small. Used for RequiresSmallResultTypeExtension() // on architectures that require the sign/zero extension. bool HasSmallReturnType() const {
Primitive::Type return_type = GetReturnType(); return return_type == Primitive::kPrimByte ||
return_type == Primitive::kPrimShort ||
return_type == Primitive::kPrimBoolean ||
return_type == Primitive::kPrimChar;
}
// Does the transition have a local reference segment state? bool HasLocalReferenceSegmentState() const { // Exclude local reference segment states for @CriticalNative methods for optimization speed. return !IsCriticalNative();
}
// Are there extra JNI arguments (JNIEnv* and maybe jclass)? bool HasExtraArgumentsForJni() const { // @CriticalNative jni implementations exclude both JNIEnv* and the jclass/jobject parameters. return !IsCriticalNative();
}
// Has a JNIEnv* parameter implicitly? bool HasJniEnv() const { // Exclude "JNIEnv*" parameter for @CriticalNative methods. return HasExtraArgumentsForJni();
}
// Has a 'jclass' parameter implicitly? bool HasSelfClass() const;
// Returns the position of itr_args_, fixed up by removing the offset of extra JNI arguments.
size_t GetIteratorPositionWithinShorty() const;
// Is the current argument (at the iterator) an extra argument for JNI? bool IsCurrentArgExtraForJni() const;
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;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.