EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
}
-template <typename U, typename V> V convert(U in) {
- DCHECK_LE(sizeof(U), sizeof(V));
- union { U u; V v; } tmp;
- tmp.u = in;
- return tmp.v;
-}
-
void Java_MyClassNatives_stackArgsIntsFirst(JNIEnv* env, jclass klass, jint i1, jint i2, jint i3,
jint i4, jint i5, jint i6, jint i7, jint i8, jint i9,
jint i10, jfloat f1, jfloat f2, jfloat f3, jfloat f4,
EXPECT_EQ(i9, 9);
EXPECT_EQ(i10, 10);
- jint i11 = convert<jfloat, jint>(f1);
+ jint i11 = bit_cast<jfloat, jint>(f1);
EXPECT_EQ(i11, 11);
- jint i12 = convert<jfloat, jint>(f2);
+ jint i12 = bit_cast<jfloat, jint>(f2);
EXPECT_EQ(i12, 12);
- jint i13 = convert<jfloat, jint>(f3);
+ jint i13 = bit_cast<jfloat, jint>(f3);
EXPECT_EQ(i13, 13);
- jint i14 = convert<jfloat, jint>(f4);
+ jint i14 = bit_cast<jfloat, jint>(f4);
EXPECT_EQ(i14, 14);
- jint i15 = convert<jfloat, jint>(f5);
+ jint i15 = bit_cast<jfloat, jint>(f5);
EXPECT_EQ(i15, 15);
- jint i16 = convert<jfloat, jint>(f6);
+ jint i16 = bit_cast<jfloat, jint>(f6);
EXPECT_EQ(i16, 16);
- jint i17 = convert<jfloat, jint>(f7);
+ jint i17 = bit_cast<jfloat, jint>(f7);
EXPECT_EQ(i17, 17);
- jint i18 = convert<jfloat, jint>(f8);
+ jint i18 = bit_cast<jfloat, jint>(f8);
EXPECT_EQ(i18, 18);
- jint i19 = convert<jfloat, jint>(f9);
+ jint i19 = bit_cast<jfloat, jint>(f9);
EXPECT_EQ(i19, 19);
- jint i20 = convert<jfloat, jint>(f10);
+ jint i20 = bit_cast<jfloat, jint>(f10);
EXPECT_EQ(i20, 20);
}
jint i9 = 9;
jint i10 = 10;
- jfloat f1 = convert<jint, jfloat>(11);
- jfloat f2 = convert<jint, jfloat>(12);
- jfloat f3 = convert<jint, jfloat>(13);
- jfloat f4 = convert<jint, jfloat>(14);
- jfloat f5 = convert<jint, jfloat>(15);
- jfloat f6 = convert<jint, jfloat>(16);
- jfloat f7 = convert<jint, jfloat>(17);
- jfloat f8 = convert<jint, jfloat>(18);
- jfloat f9 = convert<jint, jfloat>(19);
- jfloat f10 = convert<jint, jfloat>(20);
+ jfloat f1 = bit_cast<jint, jfloat>(11);
+ jfloat f2 = bit_cast<jint, jfloat>(12);
+ jfloat f3 = bit_cast<jint, jfloat>(13);
+ jfloat f4 = bit_cast<jint, jfloat>(14);
+ jfloat f5 = bit_cast<jint, jfloat>(15);
+ jfloat f6 = bit_cast<jint, jfloat>(16);
+ jfloat f7 = bit_cast<jint, jfloat>(17);
+ jfloat f8 = bit_cast<jint, jfloat>(18);
+ jfloat f9 = bit_cast<jint, jfloat>(19);
+ jfloat f10 = bit_cast<jint, jfloat>(20);
env_->CallStaticVoidMethod(jklass_, jmethod_, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, f1, f2,
f3, f4, f5, f6, f7, f8, f9, f10);
EXPECT_EQ(i9, 9);
EXPECT_EQ(i10, 10);
- jint i11 = convert<jfloat, jint>(f1);
+ jint i11 = bit_cast<jfloat, jint>(f1);
EXPECT_EQ(i11, 11);
- jint i12 = convert<jfloat, jint>(f2);
+ jint i12 = bit_cast<jfloat, jint>(f2);
EXPECT_EQ(i12, 12);
- jint i13 = convert<jfloat, jint>(f3);
+ jint i13 = bit_cast<jfloat, jint>(f3);
EXPECT_EQ(i13, 13);
- jint i14 = convert<jfloat, jint>(f4);
+ jint i14 = bit_cast<jfloat, jint>(f4);
EXPECT_EQ(i14, 14);
- jint i15 = convert<jfloat, jint>(f5);
+ jint i15 = bit_cast<jfloat, jint>(f5);
EXPECT_EQ(i15, 15);
- jint i16 = convert<jfloat, jint>(f6);
+ jint i16 = bit_cast<jfloat, jint>(f6);
EXPECT_EQ(i16, 16);
- jint i17 = convert<jfloat, jint>(f7);
+ jint i17 = bit_cast<jfloat, jint>(f7);
EXPECT_EQ(i17, 17);
- jint i18 = convert<jfloat, jint>(f8);
+ jint i18 = bit_cast<jfloat, jint>(f8);
EXPECT_EQ(i18, 18);
- jint i19 = convert<jfloat, jint>(f9);
+ jint i19 = bit_cast<jfloat, jint>(f9);
EXPECT_EQ(i19, 19);
- jint i20 = convert<jfloat, jint>(f10);
+ jint i20 = bit_cast<jfloat, jint>(f10);
EXPECT_EQ(i20, 20);
}
jint i9 = 9;
jint i10 = 10;
- jfloat f1 = convert<jint, jfloat>(11);
- jfloat f2 = convert<jint, jfloat>(12);
- jfloat f3 = convert<jint, jfloat>(13);
- jfloat f4 = convert<jint, jfloat>(14);
- jfloat f5 = convert<jint, jfloat>(15);
- jfloat f6 = convert<jint, jfloat>(16);
- jfloat f7 = convert<jint, jfloat>(17);
- jfloat f8 = convert<jint, jfloat>(18);
- jfloat f9 = convert<jint, jfloat>(19);
- jfloat f10 = convert<jint, jfloat>(20);
+ jfloat f1 = bit_cast<jint, jfloat>(11);
+ jfloat f2 = bit_cast<jint, jfloat>(12);
+ jfloat f3 = bit_cast<jint, jfloat>(13);
+ jfloat f4 = bit_cast<jint, jfloat>(14);
+ jfloat f5 = bit_cast<jint, jfloat>(15);
+ jfloat f6 = bit_cast<jint, jfloat>(16);
+ jfloat f7 = bit_cast<jint, jfloat>(17);
+ jfloat f8 = bit_cast<jint, jfloat>(18);
+ jfloat f9 = bit_cast<jint, jfloat>(19);
+ jfloat f10 = bit_cast<jint, jfloat>(20);
env_->CallStaticVoidMethod(jklass_, jmethod_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, i1, i2, i3,
i4, i5, i6, i7, i8, i9, i10);
EXPECT_EQ(i9, 9);
EXPECT_EQ(i10, 10);
- jint i11 = convert<jfloat, jint>(f1);
+ jint i11 = bit_cast<jfloat, jint>(f1);
EXPECT_EQ(i11, 11);
- jint i12 = convert<jfloat, jint>(f2);
+ jint i12 = bit_cast<jfloat, jint>(f2);
EXPECT_EQ(i12, 12);
- jint i13 = convert<jfloat, jint>(f3);
+ jint i13 = bit_cast<jfloat, jint>(f3);
EXPECT_EQ(i13, 13);
- jint i14 = convert<jfloat, jint>(f4);
+ jint i14 = bit_cast<jfloat, jint>(f4);
EXPECT_EQ(i14, 14);
- jint i15 = convert<jfloat, jint>(f5);
+ jint i15 = bit_cast<jfloat, jint>(f5);
EXPECT_EQ(i15, 15);
- jint i16 = convert<jfloat, jint>(f6);
+ jint i16 = bit_cast<jfloat, jint>(f6);
EXPECT_EQ(i16, 16);
- jint i17 = convert<jfloat, jint>(f7);
+ jint i17 = bit_cast<jfloat, jint>(f7);
EXPECT_EQ(i17, 17);
- jint i18 = convert<jfloat, jint>(f8);
+ jint i18 = bit_cast<jfloat, jint>(f8);
EXPECT_EQ(i18, 18);
- jint i19 = convert<jfloat, jint>(f9);
+ jint i19 = bit_cast<jfloat, jint>(f9);
EXPECT_EQ(i19, 19);
- jint i20 = convert<jfloat, jint>(f10);
+ jint i20 = bit_cast<jfloat, jint>(f10);
EXPECT_EQ(i20, 20);
}
jint i9 = 9;
jint i10 = 10;
- jfloat f1 = convert<jint, jfloat>(11);
- jfloat f2 = convert<jint, jfloat>(12);
- jfloat f3 = convert<jint, jfloat>(13);
- jfloat f4 = convert<jint, jfloat>(14);
- jfloat f5 = convert<jint, jfloat>(15);
- jfloat f6 = convert<jint, jfloat>(16);
- jfloat f7 = convert<jint, jfloat>(17);
- jfloat f8 = convert<jint, jfloat>(18);
- jfloat f9 = convert<jint, jfloat>(19);
- jfloat f10 = convert<jint, jfloat>(20);
+ jfloat f1 = bit_cast<jint, jfloat>(11);
+ jfloat f2 = bit_cast<jint, jfloat>(12);
+ jfloat f3 = bit_cast<jint, jfloat>(13);
+ jfloat f4 = bit_cast<jint, jfloat>(14);
+ jfloat f5 = bit_cast<jint, jfloat>(15);
+ jfloat f6 = bit_cast<jint, jfloat>(16);
+ jfloat f7 = bit_cast<jint, jfloat>(17);
+ jfloat f8 = bit_cast<jint, jfloat>(18);
+ jfloat f9 = bit_cast<jint, jfloat>(19);
+ jfloat f10 = bit_cast<jint, jfloat>(20);
env_->CallStaticVoidMethod(jklass_, jmethod_, i1, f1, i2, f2, i3, f3, i4, f4, i5, f5, i6, f6, i7,
f7, i8, f8, i9, f9, i10, f10);
case 3: return (5 * GetBytesPerGprSpillLocation(kRuntimeISA));
case 4: return (6 * GetBytesPerGprSpillLocation(kRuntimeISA));
default:
- LOG(FATAL) << "Unexpected GPR index: " << gpr_index;
- return 0;
+ LOG(FATAL) << "Unexpected GPR index: " << gpr_index;
+ return 0;
}
}
#else
return *reinterpret_cast<uintptr_t*>(lr);
}
- QuickArgumentVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static,
- const char* shorty, uint32_t shorty_len)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
- is_static_(is_static), shorty_(shorty), shorty_len_(shorty_len),
- gpr_args_(reinterpret_cast<byte*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset),
- fpr_args_(reinterpret_cast<byte*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset),
- stack_args_(reinterpret_cast<byte*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize
- + StackArgumentStartFromShorty(is_static, shorty, shorty_len)),
- gpr_index_(0), fpr_index_(0), stack_index_(0), cur_type_(Primitive::kPrimVoid),
- is_split_long_or_double_(false) { }
+ QuickArgumentVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static, const char* shorty,
+ uint32_t shorty_len) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
+ is_static_(is_static), shorty_(shorty), shorty_len_(shorty_len),
+ gpr_args_(reinterpret_cast<byte*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset),
+ fpr_args_(reinterpret_cast<byte*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset),
+ stack_args_(reinterpret_cast<byte*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize
+ + StackArgumentStartFromShorty(is_static, shorty, shorty_len)),
+ gpr_index_(0), fpr_index_(0), stack_index_(0), cur_type_(Primitive::kPrimVoid),
+ is_split_long_or_double_(false) {}
virtual ~QuickArgumentVisitor() {}
}
}
+ protected:
const bool is_static_;
const char* const shorty_;
const uint32_t shorty_len_;
+
+ private:
byte* const gpr_args_; // Address of GPR arguments in callee save frame.
byte* const fpr_args_; // Address of FPR arguments in callee save frame.
byte* const stack_args_; // Address of stack arguments in caller's frame.
BuildQuickShadowFrameVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static,
const char* shorty, uint32_t shorty_len, ShadowFrame* sf,
size_t first_arg_reg) :
- QuickArgumentVisitor(sp, is_static, shorty, shorty_len), sf_(sf), cur_reg_(first_arg_reg) {}
+ QuickArgumentVisitor(sp, is_static, shorty, shorty_len), sf_(sf), cur_reg_(first_arg_reg) {}
void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(BuildQuickShadowFrameVisitor);
};
-void BuildQuickShadowFrameVisitor::Visit() {
+void BuildQuickShadowFrameVisitor::Visit() {
Primitive::Type type = GetParamPrimitiveType();
switch (type) {
case Primitive::kPrimLong: // Fall-through.
return 0;
} else {
DCHECK(!method->IsNative()) << PrettyMethod(method);
- const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame");
+ const char* old_cause = self->StartAssertNoThreadSuspension(
+ "Building interpreter shadow frame");
const DexFile::CodeItem* code_item = method->GetCodeItem();
DCHECK(code_item != nullptr) << PrettyMethod(method);
uint16_t num_regs = code_item->registers_size_;
void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
- ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL, // No last shadow coming from quick.
- method, 0, memory));
+ // No last shadow coming from quick.
+ ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, nullptr, method, 0, memory));
size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
uint32_t shorty_len = 0;
const char* shorty = method->GetShorty(&shorty_len);
BuildQuickArgumentVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static,
const char* shorty, uint32_t shorty_len,
ScopedObjectAccessUnchecked* soa, std::vector<jvalue>* args) :
- QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa), args_(args) {}
+ QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa), args_(args) {}
void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
const char* old_cause =
self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
// Register the top of the managed stack, making stack crawlable.
- DCHECK_EQ(sp->AsMirrorPtr(), proxy_method) << PrettyMethod(proxy_method);
+ DCHECK_EQ(sp->AsMirrorPtr(), proxy_method)
+ << PrettyMethod(proxy_method);
self->SetTopOfStack(sp, 0);
DCHECK_EQ(proxy_method->GetFrameSizeInBytes(),
Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes())
// Placing arguments into args vector and remove the receiver.
mirror::ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy();
CHECK(!non_proxy_method->IsStatic()) << PrettyMethod(proxy_method) << " "
- << PrettyMethod(non_proxy_method);
+ << PrettyMethod(non_proxy_method);
std::vector<jvalue> args;
uint32_t shorty_len = 0;
const char* shorty = proxy_method->GetShorty(&shorty_len);
RememberForGcArgumentVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static,
const char* shorty, uint32_t shorty_len,
ScopedObjectAccessUnchecked* soa) :
- QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa) {}
+ QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa) {}
void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
private:
ScopedObjectAccessUnchecked* const soa_;
// References which we must update when exiting in case the GC moved the objects.
- std::vector<std::pair<jobject, StackReference<mirror::Object>*>> references_;
+ std::vector<std::pair<jobject, StackReference<mirror::Object>*> > references_;
+
DISALLOW_COPY_AND_ASSIGN(RememberForGcArgumentVisitor);
};
}
}
-
// Lazily resolve a method for quick. Called by stub code.
extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
mirror::Object* receiver,
is_range = false;
}
dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
-
} else {
invoke_type = kStatic;
dex_file = called->GetDexFile();
return code;
}
-
-
/*
* This class uses a couple of observations to unite the different calling conventions through
* a few constants.
* entry in the HandleScope (nullptr if necessary).
*
*/
-template <class T> class BuildGenericJniFrameStateMachine {
+template<class T> class BuildNativeCallFrameStateMachine {
public:
#if defined(__arm__)
// TODO: These are all dummy values!
static constexpr size_t kRegistersNeededForLong = 2;
static constexpr size_t kRegistersNeededForDouble = 2;
- static constexpr bool kMultiRegistersAligned = false; // x86 not using regs, anyways
+ static constexpr bool kMultiRegistersAligned = false; // x86 not using regs, anyways
static constexpr bool kMultiRegistersWidened = false;
static constexpr bool kAlignLongOnStack = false;
static constexpr bool kAlignDoubleOnStack = false;
#endif
public:
- explicit BuildGenericJniFrameStateMachine(T* delegate) : gpr_index_(kNumNativeGprArgs),
- fpr_index_(kNumNativeFprArgs),
- stack_entries_(0),
- delegate_(delegate) {
+ explicit BuildNativeCallFrameStateMachine(T* delegate)
+ : gpr_index_(kNumNativeGprArgs),
+ fpr_index_(kNumNativeFprArgs),
+ stack_entries_(0),
+ delegate_(delegate) {
// For register alignment, we want to assume that counters (gpr_index_, fpr_index_) are even iff
// the next register is even; counting down is just to make the compiler happy...
CHECK_EQ(kNumNativeGprArgs % 2, 0U);
CHECK_EQ(kNumNativeFprArgs % 2, 0U);
}
- virtual ~BuildGenericJniFrameStateMachine() {}
+ virtual ~BuildNativeCallFrameStateMachine() {}
bool HavePointerGpr() {
return gpr_index_ > 0;
}
- void AdvancePointer(void* val) {
+ void AdvancePointer(const void* val) {
if (HavePointerGpr()) {
gpr_index_--;
PushGpr(reinterpret_cast<uintptr_t>(val));
} else {
- stack_entries_++; // TODO: have a field for pointer length as multiple of 32b
+ stack_entries_++; // TODO: have a field for pointer length as multiple of 32b
PushStack(reinterpret_cast<uintptr_t>(val));
gpr_index_ = 0;
}
}
-
bool HaveHandleScopeGpr() {
return gpr_index_ > 0;
}
}
}
-
bool HaveIntGpr() {
return gpr_index_ > 0;
}
}
}
-
bool HaveLongGpr() {
return gpr_index_ >= kRegistersNeededForLong + (LongGprNeedsPadding() ? 1 : 0);
}
}
}
-
bool HaveFloatFpr() {
return fpr_index_ > 0;
}
- template <typename U, typename V> V convert(U in) {
- CHECK_LE(sizeof(U), sizeof(V));
- union { U u; V v; } tmp;
- tmp.u = in;
- return tmp.v;
- }
-
void AdvanceFloat(float val) {
if (kNativeSoftFloatAbi) {
- AdvanceInt(convert<float, uint32_t>(val));
+ AdvanceInt(bit_cast<float, uint32_t>(val));
} else {
if (HaveFloatFpr()) {
fpr_index_--;
if (kRegistersNeededForDouble == 1) {
if (kMultiRegistersWidened) {
- PushFpr8(convert<double, uint64_t>(val));
+ PushFpr8(bit_cast<double, uint64_t>(val));
} else {
// No widening, just use the bits.
- PushFpr8(convert<float, uint64_t>(val));
+ PushFpr8(bit_cast<float, uint64_t>(val));
}
} else {
PushFpr4(val);
stack_entries_++;
if (kRegistersNeededForDouble == 1 && kMultiRegistersWidened) {
// Need to widen before storing: Note the "double" in the template instantiation.
- PushStack(convert<double, uintptr_t>(val));
+ // Note: We need to jump through those hoops to make the compiler happy.
+ DCHECK_EQ(sizeof(uintptr_t), sizeof(uint64_t));
+ PushStack(static_cast<uintptr_t>(bit_cast<double, uint64_t>(val)));
} else {
- PushStack(convert<float, uintptr_t>(val));
+ PushStack(bit_cast<float, uintptr_t>(val));
}
fpr_index_ = 0;
}
}
}
-
bool HaveDoubleFpr() {
return fpr_index_ >= kRegistersNeededForDouble + (DoubleFprNeedsPadding() ? 1 : 0);
}
T* delegate_; // What Push implementation gets called
};
-class ComputeGenericJniFrameSize FINAL {
+// Computes the sizes of register stacks and call stack area. Handling of references can be extended
+// in subclasses.
+//
+// To handle native pointers, use "L" in the shorty for an object reference, which simulates
+// them with handles.
+class ComputeNativeCallFrameSize {
public:
- ComputeGenericJniFrameSize() : num_handle_scope_references_(0), num_stack_entries_(0) {}
+ ComputeNativeCallFrameSize() : num_stack_entries_(0) {}
+
+ virtual ~ComputeNativeCallFrameSize() {}
uint32_t GetStackSize() {
return num_stack_entries_ * sizeof(uintptr_t);
}
- // WARNING: After this, *sp won't be pointing to the method anymore!
- void ComputeLayout(StackReference<mirror::ArtMethod>** m, bool is_static, const char* shorty,
- uint32_t shorty_len, void* sp, HandleScope** table,
- uint32_t* handle_scope_entries, uintptr_t** start_stack, uintptr_t** start_gpr,
- uint32_t** start_fpr, void** code_return, size_t* overall_size)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ComputeAll(is_static, shorty, shorty_len);
-
- mirror::ArtMethod* method = (*m)->AsMirrorPtr();
-
- uint8_t* sp8 = reinterpret_cast<uint8_t*>(sp);
-
- // First, fix up the layout of the callee-save frame.
- // We have to squeeze in the HandleScope, and relocate the method pointer.
-
- // "Free" the slot for the method.
- sp8 += kPointerSize; // In the callee-save frame we use a full pointer.
-
- // Under the callee saves put handle scope and new method stack reference.
- *handle_scope_entries = num_handle_scope_references_;
-
- size_t handle_scope_size = HandleScope::SizeOf(num_handle_scope_references_);
- size_t scope_and_method = handle_scope_size + sizeof(StackReference<mirror::ArtMethod>);
-
- sp8 -= scope_and_method;
- // Align by kStackAlignment.
- sp8 = reinterpret_cast<uint8_t*>(RoundDown(reinterpret_cast<uintptr_t>(sp8), kStackAlignment));
-
- uint8_t* sp8_table = sp8 + sizeof(StackReference<mirror::ArtMethod>);
- *table = reinterpret_cast<HandleScope*>(sp8_table);
- (*table)->SetNumberOfReferences(num_handle_scope_references_);
-
- // Add a slot for the method pointer, and fill it. Fix the pointer-pointer given to us.
- uint8_t* method_pointer = sp8;
- StackReference<mirror::ArtMethod>* new_method_ref =
- reinterpret_cast<StackReference<mirror::ArtMethod>*>(method_pointer);
- new_method_ref->Assign(method);
- *m = new_method_ref;
-
- // Reference cookie and padding
- sp8 -= 8;
- // Store HandleScope size
- *reinterpret_cast<uint32_t*>(sp8) = static_cast<uint32_t>(handle_scope_size & 0xFFFFFFFF);
-
- // Next comes the native call stack.
+ uint8_t* LayoutCallStack(uint8_t* sp8) {
sp8 -= GetStackSize();
// Align by kStackAlignment.
sp8 = reinterpret_cast<uint8_t*>(RoundDown(reinterpret_cast<uintptr_t>(sp8), kStackAlignment));
- *start_stack = reinterpret_cast<uintptr_t*>(sp8);
+ return sp8;
+ }
- // put fprs and gprs below
+ uint8_t* LayoutCallRegisterStacks(uint8_t* sp8, uintptr_t** start_gpr, uint32_t** start_fpr) {
// Assumption is OK right now, as we have soft-float arm
- size_t fregs = BuildGenericJniFrameStateMachine<ComputeGenericJniFrameSize>::kNumNativeFprArgs;
+ size_t fregs = BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>::kNumNativeFprArgs;
sp8 -= fregs * sizeof(uintptr_t);
*start_fpr = reinterpret_cast<uint32_t*>(sp8);
- size_t iregs = BuildGenericJniFrameStateMachine<ComputeGenericJniFrameSize>::kNumNativeGprArgs;
+ size_t iregs = BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>::kNumNativeGprArgs;
sp8 -= iregs * sizeof(uintptr_t);
*start_gpr = reinterpret_cast<uintptr_t*>(sp8);
+ return sp8;
+ }
- // reserve space for the code pointer
- sp8 -= kPointerSize;
- *code_return = reinterpret_cast<void*>(sp8);
+ uint8_t* LayoutNativeCall(uint8_t* sp8, uintptr_t** start_stack, uintptr_t** start_gpr,
+ uint32_t** start_fpr) {
+ // Native call stack.
+ sp8 = LayoutCallStack(sp8);
+ *start_stack = reinterpret_cast<uintptr_t*>(sp8);
- *overall_size = reinterpret_cast<uint8_t*>(sp) - sp8;
+ // Put fprs and gprs below.
+ sp8 = LayoutCallRegisterStacks(sp8, start_gpr, start_fpr);
- // The new SP is stored at the end of the alloca, so it can be immediately popped
- sp8 = reinterpret_cast<uint8_t*>(sp) - 5 * KB;
- *(reinterpret_cast<uint8_t**>(sp8)) = method_pointer;
+ // Return the new bottom.
+ return sp8;
}
- void ComputeHandleScopeOffset() { } // nothing to do, static right now
+ virtual void WalkHeader(BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {}
- void ComputeAll(bool is_static, const char* shorty, uint32_t shorty_len)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- BuildGenericJniFrameStateMachine<ComputeGenericJniFrameSize> sm(this);
-
- // JNIEnv
- sm.AdvancePointer(nullptr);
+ void Walk(const char* shorty, uint32_t shorty_len) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize> sm(this);
- // Class object or this as first argument
- sm.AdvanceHandleScope(reinterpret_cast<mirror::Object*>(0x12345678));
+ WalkHeader(&sm);
for (uint32_t i = 1; i < shorty_len; ++i) {
Primitive::Type cur_type_ = Primitive::GetType(shorty[i]);
switch (cur_type_) {
case Primitive::kPrimNot:
- sm.AdvanceHandleScope(reinterpret_cast<mirror::Object*>(0x12345678));
+ sm.AdvanceHandleScope(
+ reinterpret_cast<mirror::Object*>(0x12345678));
break;
case Primitive::kPrimBoolean:
// counting is already done in the superclass
}
- uintptr_t PushHandle(mirror::Object* /* ptr */) {
- num_handle_scope_references_++;
+ virtual uintptr_t PushHandle(mirror::Object* /* ptr */) {
return reinterpret_cast<uintptr_t>(nullptr);
}
- private:
- uint32_t num_handle_scope_references_;
+ protected:
uint32_t num_stack_entries_;
};
-// Visits arguments on the stack placing them into a region lower down the stack for the benefit
-// of transitioning into native code.
-class BuildGenericJniFrameVisitor FINAL : public QuickArgumentVisitor {
+class ComputeGenericJniFrameSize FINAL : public ComputeNativeCallFrameSize {
public:
- BuildGenericJniFrameVisitor(StackReference<mirror::ArtMethod>** sp, bool is_static,
- const char* shorty, uint32_t shorty_len, Thread* self) :
- QuickArgumentVisitor(*sp, is_static, shorty, shorty_len), sm_(this) {
- ComputeGenericJniFrameSize fsc;
- fsc.ComputeLayout(sp, is_static, shorty, shorty_len, *sp, &handle_scope_, &handle_scope_expected_refs_,
- &cur_stack_arg_, &cur_gpr_reg_, &cur_fpr_reg_, &code_return_,
- &alloca_used_size_);
- handle_scope_number_of_references_ = 0;
- cur_hs_entry_ = GetFirstHandleScopeEntry();
+ ComputeGenericJniFrameSize() : num_handle_scope_references_(0) {}
+
+ // Lays out the callee-save frame. Assumes that the incorrect frame corresponding to RefsAndArgs
+ // is at *m = sp. Will update to point to the bottom of the save frame.
+ //
+ // Note: assumes ComputeAll() has been run before.
+ void LayoutCalleeSaveFrame(StackReference<mirror::ArtMethod>** m, void* sp, HandleScope** table,
+ uint32_t* handle_scope_entries)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtMethod* method = (*m)->AsMirrorPtr();
- // jni environment is always first argument
- sm_.AdvancePointer(self->GetJniEnv());
+ uint8_t* sp8 = reinterpret_cast<uint8_t*>(sp);
- if (is_static) {
- sm_.AdvanceHandleScope((*sp)->AsMirrorPtr()->GetDeclaringClass());
- }
- }
+ // First, fix up the layout of the callee-save frame.
+ // We have to squeeze in the HandleScope, and relocate the method pointer.
- void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
+ // "Free" the slot for the method.
+ sp8 += kPointerSize; // In the callee-save frame we use a full pointer.
- void FinalizeHandleScope(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Under the callee saves put handle scope and new method stack reference.
+ *handle_scope_entries = num_handle_scope_references_;
- StackReference<mirror::Object>* GetFirstHandleScopeEntry()
+ size_t handle_scope_size = HandleScope::SizeOf(num_handle_scope_references_);
+ size_t scope_and_method = handle_scope_size + sizeof(StackReference<mirror::ArtMethod>);
+
+ sp8 -= scope_and_method;
+ // Align by kStackAlignment.
+ sp8 = reinterpret_cast<uint8_t*>(RoundDown(
+ reinterpret_cast<uintptr_t>(sp8), kStackAlignment));
+
+ uint8_t* sp8_table = sp8 + sizeof(StackReference<mirror::ArtMethod>);
+ *table = reinterpret_cast<HandleScope*>(sp8_table);
+ (*table)->SetNumberOfReferences(num_handle_scope_references_);
+
+ // Add a slot for the method pointer, and fill it. Fix the pointer-pointer given to us.
+ uint8_t* method_pointer = sp8;
+ StackReference<mirror::ArtMethod>* new_method_ref =
+ reinterpret_cast<StackReference<mirror::ArtMethod>*>(method_pointer);
+ new_method_ref->Assign(method);
+ *m = new_method_ref;
+ }
+
+ // Adds space for the cookie. Note: may leave stack unaligned.
+ void LayoutCookie(uint8_t** sp) {
+ // Reference cookie and padding
+ *sp -= 8;
+ }
+
+ // Re-layout the callee-save frame (insert a handle-scope). Then add space for the cookie.
+ // Returns the new bottom. Note: this may be unaligned.
+ uint8_t* LayoutJNISaveFrame(StackReference<mirror::ArtMethod>** m, void* sp, HandleScope** table,
+ uint32_t* handle_scope_entries)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return handle_scope_->GetHandle(0).GetReference();
+ // First, fix up the layout of the callee-save frame.
+ // We have to squeeze in the HandleScope, and relocate the method pointer.
+ LayoutCalleeSaveFrame(m, sp, table, handle_scope_entries);
+
+ // The bottom of the callee-save frame is now where the method is, *m.
+ uint8_t* sp8 = reinterpret_cast<uint8_t*>(*m);
+
+ // Add space for cookie.
+ LayoutCookie(&sp8);
+
+ return sp8;
}
- jobject GetFirstHandleScopeJObject()
+ // WARNING: After this, *sp won't be pointing to the method anymore!
+ uint8_t* ComputeLayout(StackReference<mirror::ArtMethod>** m, bool is_static, const char* shorty,
+ uint32_t shorty_len, HandleScope** table, uint32_t* handle_scope_entries,
+ uintptr_t** start_stack, uintptr_t** start_gpr, uint32_t** start_fpr)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return handle_scope_->GetHandle(0).ToJObject();
+ Walk(shorty, shorty_len);
+
+ // JNI part.
+ uint8_t* sp8 = LayoutJNISaveFrame(m, reinterpret_cast<void*>(*m), table, handle_scope_entries);
+
+ sp8 = LayoutNativeCall(sp8, start_stack, start_gpr, start_fpr);
+
+ // Return the new bottom.
+ return sp8;
+ }
+
+ uintptr_t PushHandle(mirror::Object* /* ptr */) OVERRIDE;
+
+ // Add JNIEnv* and jobj/jclass before the shorty-derived elements.
+ void WalkHeader(BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) OVERRIDE
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ uint32_t num_handle_scope_references_;
+};
+
+uintptr_t ComputeGenericJniFrameSize::PushHandle(mirror::Object* /* ptr */) {
+ num_handle_scope_references_++;
+ return reinterpret_cast<uintptr_t>(nullptr);
+}
+
+void ComputeGenericJniFrameSize::WalkHeader(
+ BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) {
+ // JNIEnv
+ sm->AdvancePointer(nullptr);
+
+ // Class object or this as first argument
+ sm->AdvanceHandleScope(reinterpret_cast<mirror::Object*>(0x12345678));
+}
+
+// Class to push values to three separate regions. Used to fill the native call part. Adheres to
+// the template requirements of BuildGenericJniFrameStateMachine.
+class FillNativeCall {
+ public:
+ FillNativeCall(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args) :
+ cur_gpr_reg_(gpr_regs), cur_fpr_reg_(fpr_regs), cur_stack_arg_(stack_args) {}
+
+ virtual ~FillNativeCall() {}
+
+ void Reset(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args) {
+ cur_gpr_reg_ = gpr_regs;
+ cur_fpr_reg_ = fpr_regs;
+ cur_stack_arg_ = stack_args;
}
void PushGpr(uintptr_t val) {
cur_stack_arg_++;
}
- uintptr_t PushHandle(mirror::Object* ref) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uintptr_t tmp;
- if (ref == nullptr) {
- *cur_hs_entry_ = StackReference<mirror::Object>();
- tmp = reinterpret_cast<uintptr_t>(nullptr);
- } else {
- *cur_hs_entry_ = StackReference<mirror::Object>::FromMirrorPtr(ref);
- tmp = reinterpret_cast<uintptr_t>(cur_hs_entry_);
+ virtual uintptr_t PushHandle(mirror::Object* ref) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ LOG(FATAL) << "(Non-JNI) Native call does not use handles.";
+ return 0U;
+ }
+
+ private:
+ uintptr_t* cur_gpr_reg_;
+ uint32_t* cur_fpr_reg_;
+ uintptr_t* cur_stack_arg_;
+};
+
+// Visits arguments on the stack placing them into a region lower down the stack for the benefit
+// of transitioning into native code.
+class BuildGenericJniFrameVisitor FINAL : public QuickArgumentVisitor {
+ public:
+ BuildGenericJniFrameVisitor(StackReference<mirror::ArtMethod>** sp, bool is_static,
+ const char* shorty, uint32_t shorty_len, Thread* self)
+ : QuickArgumentVisitor(*sp, is_static, shorty, shorty_len),
+ jni_call_(nullptr, nullptr, nullptr, nullptr), sm_(&jni_call_) {
+ ComputeGenericJniFrameSize fsc;
+ uintptr_t* start_gpr_reg;
+ uint32_t* start_fpr_reg;
+ uintptr_t* start_stack_arg;
+ uint32_t handle_scope_entries;
+ bottom_of_used_area_ = fsc.ComputeLayout(sp, is_static, shorty, shorty_len, &handle_scope_,
+ &handle_scope_entries, &start_stack_arg,
+ &start_gpr_reg, &start_fpr_reg);
+
+ handle_scope_->SetNumberOfReferences(handle_scope_entries);
+ jni_call_.Reset(start_gpr_reg, start_fpr_reg, start_stack_arg, handle_scope_);
+
+ // jni environment is always first argument
+ sm_.AdvancePointer(self->GetJniEnv());
+
+ if (is_static) {
+ sm_.AdvanceHandleScope((*sp)->AsMirrorPtr()->GetDeclaringClass());
}
- cur_hs_entry_++;
- handle_scope_number_of_references_++;
- return tmp;
}
- // Size of the part of the alloca that we actually need.
- size_t GetAllocaUsedSize() {
- return alloca_used_size_;
+ void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
+
+ void FinalizeHandleScope(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ StackReference<mirror::Object>* GetFirstHandleScopeEntry()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return handle_scope_->GetHandle(0).GetReference();
+ }
+
+ jobject GetFirstHandleScopeJObject() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return handle_scope_->GetHandle(0).ToJObject();
}
- void* GetCodeReturn() {
- return code_return_;
+ void* GetBottomOfUsedArea() {
+ return bottom_of_used_area_;
}
private:
- uint32_t handle_scope_number_of_references_;
- StackReference<mirror::Object>* cur_hs_entry_;
+ // A class to fill a JNI call. Adds reference/handle-scope management to FillNativeCall.
+ class FillJniCall FINAL : public FillNativeCall {
+ public:
+ FillJniCall(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args,
+ HandleScope* handle_scope) : FillNativeCall(gpr_regs, fpr_regs, stack_args),
+ handle_scope_(handle_scope), cur_entry_(0) {}
+
+ uintptr_t PushHandle(mirror::Object* ref) OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ void Reset(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args, HandleScope* scope) {
+ FillNativeCall::Reset(gpr_regs, fpr_regs, stack_args);
+ handle_scope_ = scope;
+ cur_entry_ = 0U;
+ }
+
+ void ResetRemainingScopeSlots() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ // Initialize padding entries.
+ size_t expected_slots = handle_scope_->NumberOfReferences();
+ while (cur_entry_ < expected_slots) {
+ handle_scope_->GetHandle(cur_entry_++).Assign(nullptr);
+ }
+ DCHECK_NE(cur_entry_, 0U);
+ }
+
+ private:
+ HandleScope* handle_scope_;
+ size_t cur_entry_;
+ };
+
HandleScope* handle_scope_;
- uint32_t handle_scope_expected_refs_;
- uintptr_t* cur_gpr_reg_;
- uint32_t* cur_fpr_reg_;
- uintptr_t* cur_stack_arg_;
- // StackReference<mirror::Object>* top_of_handle_scope_;
- void* code_return_;
- size_t alloca_used_size_;
+ FillJniCall jni_call_;
+ void* bottom_of_used_area_;
- BuildGenericJniFrameStateMachine<BuildGenericJniFrameVisitor> sm_;
+ BuildNativeCallFrameStateMachine<FillJniCall> sm_;
DISALLOW_COPY_AND_ASSIGN(BuildGenericJniFrameVisitor);
};
+uintptr_t BuildGenericJniFrameVisitor::FillJniCall::PushHandle(mirror::Object* ref) {
+ uintptr_t tmp;
+ Handle<mirror::Object> h = handle_scope_->GetHandle(cur_entry_);
+ h.Assign(ref);
+ tmp = reinterpret_cast<uintptr_t>(h.ToJObject());
+ cur_entry_++;
+ return tmp;
+}
+
void BuildGenericJniFrameVisitor::Visit() {
Primitive::Type type = GetParamPrimitiveType();
switch (type) {
}
void BuildGenericJniFrameVisitor::FinalizeHandleScope(Thread* self) {
- // Initialize padding entries.
- while (handle_scope_number_of_references_ < handle_scope_expected_refs_) {
- *cur_hs_entry_ = StackReference<mirror::Object>();
- cur_hs_entry_++;
- handle_scope_number_of_references_++;
- }
- handle_scope_->SetNumberOfReferences(handle_scope_expected_refs_);
- DCHECK_NE(handle_scope_expected_refs_, 0U);
+ // Clear out rest of the scope.
+ jni_call_.ResetRemainingScopeSlots();
// Install HandleScope.
self->PushHandleScope(handle_scope_);
}
* 1) How many bytes of the alloca can be released, if the value is non-negative.
* 2) An error, if the value is negative.
*/
-extern "C" ssize_t artQuickGenericJniTrampoline(Thread* self, StackReference<mirror::ArtMethod>* sp)
+extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self,
+ StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* called = sp->AsMirrorPtr();
DCHECK(called->IsNative()) << PrettyMethod(called, true);
-
- // run the visitor
uint32_t shorty_len = 0;
const char* shorty = called->GetShorty(&shorty_len);
+
+ // Run the visitor.
BuildGenericJniFrameVisitor visitor(&sp, called->IsStatic(), shorty, shorty_len, self);
visitor.VisitArguments();
visitor.FinalizeHandleScope(self);
- // fix up managed-stack things in Thread
+ // Fix up managed-stack things in Thread.
self->SetTopOfStack(sp, 0);
self->VerifyStack();
if (self->IsExceptionPending()) {
self->PopHandleScope();
// A negative value denotes an error.
- return -1;
+ return GetTwoWordFailureValue();
}
} else {
cookie = JniMethodStart(self);
artQuickGenericJniEndJNINonRef(self, cookie, lock);
}
- return -1;
+ return GetTwoWordFailureValue();
}
// Note that the native code pointer will be automatically set by artFindNativeMethod().
}
- // Store the native code pointer in the stack at the right location.
- uintptr_t* code_pointer = reinterpret_cast<uintptr_t*>(visitor.GetCodeReturn());
- *code_pointer = reinterpret_cast<uintptr_t>(nativeCode);
-
- // 5K reserved, window_size + frame pointer used.
- size_t window_size = visitor.GetAllocaUsedSize();
- return (5 * KB) - window_size - kPointerSize;
+ // Return native code addr(lo) and bottom of alloca address(hi).
+ return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(visitor.GetBottomOfUsedArea()),
+ reinterpret_cast<uintptr_t>(nativeCode));
}
/*
* Is called after the native JNI code. Responsible for cleanup (handle scope, saved state) and
* unlocking.
*/
-extern "C" uint64_t artQuickGenericJniEndTrampoline(Thread* self,
- StackReference<mirror::ArtMethod>* sp,
- jvalue result, uint64_t result_f)
+extern "C" uint64_t artQuickGenericJniEndTrampoline(Thread* self, jvalue result, uint64_t result_f)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ StackReference<mirror::ArtMethod>* sp = self->GetManagedStack()->GetTopQuickFrame();
uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp);
mirror::ArtMethod* called = sp->AsMirrorPtr();
uint32_t cookie = *(sp32 - 1);
jobject lock = nullptr;
if (called->IsSynchronized()) {
- HandleScope* table = reinterpret_cast<HandleScope*>(
- reinterpret_cast<uint8_t*>(sp) + sizeof(StackReference<mirror::ArtMethod>));
+ HandleScope* table = reinterpret_cast<HandleScope*>(reinterpret_cast<uint8_t*>(sp)
+ + sizeof(StackReference<mirror::ArtMethod>));
lock = table->GetHandle(0).ToJObject();
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()->GetDexFile();
uint32_t shorty_len;
- const char* shorty =
- dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx), &shorty_len);
+ const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx), &shorty_len);
{
// Remember the args in case a GC happens in FindMethodFromCode.
ScopedObjectAccessUnchecked soa(self->GetJniEnv());
const void* code = method->GetEntryPointFromQuickCompiledCode();
// When we return, the caller will branch to this address, so it had better not be 0!
- DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method) << " location: "
- << method->GetDexFile()->GetLocation();
+ DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method)
+ << " location: "
+ << method->GetDexFile()->GetLocation();
return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code),
reinterpret_cast<uintptr_t>(method));
EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kSuper, true);
#undef EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL
-
// See comments in runtime_support_asm.S
-extern "C" TwoWordReturn artInvokeInterfaceTrampolineWithAccessCheck(uint32_t method_idx,
- mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
- Thread* self,
- StackReference<mirror::ArtMethod>* sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kInterface, true>(method_idx, this_object, caller_method, self, sp);
+extern "C" TwoWordReturn artInvokeInterfaceTrampolineWithAccessCheck(
+ uint32_t method_idx, mirror::Object* this_object,
+ mirror::ArtMethod* caller_method, Thread* self,
+ StackReference<mirror::ArtMethod>* sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return artInvokeCommon<kInterface, true>(method_idx, this_object,
+ caller_method, self, sp);
}
-
-extern "C" TwoWordReturn artInvokeDirectTrampolineWithAccessCheck(uint32_t method_idx,
- mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
- Thread* self,
- StackReference<mirror::ArtMethod>* sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kDirect, true>(method_idx, this_object, caller_method, self, sp);
+extern "C" TwoWordReturn artInvokeDirectTrampolineWithAccessCheck(
+ uint32_t method_idx, mirror::Object* this_object,
+ mirror::ArtMethod* caller_method, Thread* self,
+ StackReference<mirror::ArtMethod>* sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return artInvokeCommon<kDirect, true>(method_idx, this_object, caller_method,
+ self, sp);
}
-extern "C" TwoWordReturn artInvokeStaticTrampolineWithAccessCheck(uint32_t method_idx,
- mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
- Thread* self,
- StackReference<mirror::ArtMethod>* sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kStatic, true>(method_idx, this_object, caller_method, self, sp);
+extern "C" TwoWordReturn artInvokeStaticTrampolineWithAccessCheck(
+ uint32_t method_idx, mirror::Object* this_object,
+ mirror::ArtMethod* caller_method, Thread* self,
+ StackReference<mirror::ArtMethod>* sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return artInvokeCommon<kStatic, true>(method_idx, this_object, caller_method,
+ self, sp);
}
-extern "C" TwoWordReturn artInvokeSuperTrampolineWithAccessCheck(uint32_t method_idx,
- mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
- Thread* self,
- StackReference<mirror::ArtMethod>* sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kSuper, true>(method_idx, this_object, caller_method, self, sp);
+extern "C" TwoWordReturn artInvokeSuperTrampolineWithAccessCheck(
+ uint32_t method_idx, mirror::Object* this_object,
+ mirror::ArtMethod* caller_method, Thread* self,
+ StackReference<mirror::ArtMethod>* sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return artInvokeCommon<kSuper, true>(method_idx, this_object, caller_method,
+ self, sp);
}
-extern "C" TwoWordReturn artInvokeVirtualTrampolineWithAccessCheck(uint32_t method_idx,
- mirror::Object* this_object,
- mirror::ArtMethod* caller_method,
- Thread* self,
- StackReference<mirror::ArtMethod>* sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return artInvokeCommon<kVirtual, true>(method_idx, this_object, caller_method, self, sp);
+extern "C" TwoWordReturn artInvokeVirtualTrampolineWithAccessCheck(
+ uint32_t method_idx, mirror::Object* this_object,
+ mirror::ArtMethod* caller_method, Thread* self,
+ StackReference<mirror::ArtMethod>* sp)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return artInvokeCommon<kVirtual, true>(method_idx, this_object, caller_method,
+ self, sp);
}
// Determine target of interface dispatch. This object is known non-null.
dex_method_idx = instr->VRegB_3rc();
}
- const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()->GetDexFile();
+ const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()
+ ->GetDexFile();
uint32_t shorty_len;
- const char* shorty =
- dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx), &shorty_len);
+ const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx),
+ &shorty_len);
{
// Remember the args in case a GC happens in FindMethodFromCode.
ScopedObjectAccessUnchecked soa(self->GetJniEnv());
const void* code = method->GetEntryPointFromQuickCompiledCode();
// When we return, the caller will branch to this address, so it had better not be 0!
- DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method) << " location: "
- << method->GetDexFile()->GetLocation();
+ DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method)
+ << " location: " << method->GetDexFile()->GetLocation();
return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code),
reinterpret_cast<uintptr_t>(method));