Ensure SIRT isn't accessed via quick callee save frame.
Some tidying of code.
Change-Id: I8fec3e89aa6d2e86789c60a07550db2e92478ca7
# Mac OS complains about unresolved symbols if you don't include this.
LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_host
endif
+ ifneq ($(BUILD_HOST_64bit),)
+ # 64bit Linux complains about unresolved symbols if you don't include this.
+ LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_host
+ endif
include $(BUILD_HOST_EXECUTABLE)
art_gtest_exe := $(HOST_OUT_EXECUTABLES)/$$(LOCAL_MODULE)
ART_HOST_GTEST_EXECUTABLES += $$(art_gtest_exe)
movq %gs:THREAD_SELF_OFFSET, %rdi
movq %rbp, %rsi
call PLT_SYMBOL(artQuickGenericJniTrampoline) // (Thread*, sp)
- test %rax, %rax // check whether error (negative value)
- js 1f
+ test %rax, %rax // Check for error, negative value.
+ js .Lentry_error
// release part of the alloca
addq %rax, %rsp
// get the code pointer
movq 56(%rsp), %xmm7
addq LITERAL(64), %rsp // floating-point done
// native call
- call *%rax // Q: is the stack aligned 16B with or without the return addr?
+ call *%rax // Stack should be aligned 16B without the return addr?
// result sign extension is handled in C code
// prepare for artQuickGenericJniEndTrampoline call
// (Thread*, SP, result, result_f)
movq %rax, %rdx
movq %xmm0, %rcx
call PLT_SYMBOL(artQuickGenericJniEndTrampoline)
- // tear down the alloca already
+
+ // Tear down the alloca.
movq %rbp, %rsp
CFI_DEF_CFA_REGISTER(rsp)
- // Exceptions possible.
+
+ // Pending exceptions possible.
// TODO: use cmpq, needs direct encoding because of gas bug
- movq %gs:THREAD_EXCEPTION_OFFSET, %rbx
- test %rbx, %rbx
- jnz 2f
- // Tear down the callee-save frame
+ movq %gs:THREAD_EXCEPTION_OFFSET, %rcx
+ test %rcx, %rcx
+ jnz .Lexception_in_native
+
+ // Tear down the callee-save frame.
// Load FPRs.
// movq %xmm0, 16(%rsp) // doesn't make sense!!!
movq 24(%rsp), %xmm1 // neither does this!!!
// store into fpr, for when it's a fpr return...
movq %rax, %xmm0
ret
-1:
- // tear down the _whole_ scratch space, assumes SIRT is empty, cookie not valid etc.
+.Lentry_error:
movq %rbp, %rsp
- CFI_DEF_CFA_REGISTER(rsp)
-2: RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
+.Lexception_in_native:
+ CFI_REL_OFFSET(rsp,176)
+ // TODO: the SIRT contains the this pointer which is used by the debugger for exception
+ // delivery.
+ RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
DELIVER_PENDING_EXCEPTION
END_FUNCTION art_quick_generic_jni_trampoline
sirt_number_of_references_++;
}
sirt_->SetNumberOfReferences(sirt_expected_refs_);
-
+ DCHECK_NE(sirt_expected_refs_, 0U);
// Install Sirt.
self->PushSirt(sirt_);
}
// fix up managed-stack things in Thread
self->SetTopOfStack(sp, 0);
+ self->VerifyStack();
+
// start JNI, save the cookie
uint32_t cookie;
if (called->IsSynchronized()) {
} else {
cookie = JniMethodStart(self);
}
- *(sp32-1) = cookie;
+ *(sp32 - 1) = cookie;
// retrieve native code
const void* nativeCode = called->GetNativeMethod();
*code_pointer = reinterpret_cast<uintptr_t>(nativeCode);
// 5K reserved, window_size used.
- return 5*1024 - window_size;
+ return (5 * KB) - window_size;
}
/*
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp);
mirror::ArtMethod* called = *sp;
- uint32_t cookie = *(sp32-1);
+ uint32_t cookie = *(sp32 - 1);
MethodHelper mh(called);
char return_shorty_char = mh.GetShorty()[0];
ComputeGenericJniFrameSize fsc;
fsc.ComputeSirtOffset();
uint32_t offset = fsc.GetFirstSirtEntryOffset();
- jobject tmp = reinterpret_cast<jobject>(reinterpret_cast<uint8_t*>(sp)-offset);
+ jobject tmp = reinterpret_cast<jobject>(reinterpret_cast<uint8_t*>(sp) - offset);
return reinterpret_cast<uint64_t>(JniMethodEndWithReferenceSynchronized(result.l, cookie, tmp,
self));
ComputeGenericJniFrameSize fsc;
fsc.ComputeSirtOffset();
uint32_t offset = fsc.GetFirstSirtEntryOffset();
- jobject tmp = reinterpret_cast<jobject>(reinterpret_cast<uint8_t*>(sp)-offset);
+ jobject tmp = reinterpret_cast<jobject>(reinterpret_cast<uint8_t*>(sp) - offset);
JniMethodEndSynchronized(cookie, tmp, self);
} else {
self->PopManagedStackFragment(fragment);
}
+#ifndef NDEBUG
+size_t ArtMethod::GetSirtOffsetInBytes() {
+ CHECK(IsNative());
+ // TODO: support Sirt access from generic JNI trampoline.
+ CHECK_NE(GetEntryPointFromQuickCompiledCode(), GetQuickGenericJniTrampoline());
+ return kPointerSize;
+}
+#endif
+
bool ArtMethod::IsRegistered() {
void* native_method =
GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), false);
return GetFrameSizeInBytes() - kPointerSize;
}
+#ifndef NDEBUG
+ size_t GetSirtOffsetInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+#else
size_t GetSirtOffsetInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(IsNative());
return kPointerSize;
}
+#endif
bool IsRegistered();
return NULL;
} else if (m->IsNative()) {
if (cur_quick_frame_ != NULL) {
- StackIndirectReferenceTable* sirt =
- reinterpret_cast<StackIndirectReferenceTable*>(
- reinterpret_cast<char*>(cur_quick_frame_) +
- m->GetSirtOffsetInBytes());
- return sirt->GetReference(0);
+ if (m->GetEntryPointFromQuickCompiledCode() == GetQuickGenericJniTrampoline()) {
+ UNIMPLEMENTED(ERROR) << "Failed to determine this object of native method: "
+ << PrettyMethod(m);
+ return nullptr;
+ } else {
+ StackIndirectReferenceTable* sirt =
+ reinterpret_cast<StackIndirectReferenceTable*>(
+ reinterpret_cast<char*>(cur_quick_frame_) +
+ m->GetSirtOffsetInBytes());
+ return sirt->GetReference(0);
+ }
} else {
return cur_shadow_frame_->GetVRegReference(0);
}
} else {
const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
if (code_item == NULL) {
- UNIMPLEMENTED(ERROR) << "Failed to determine this object of abstract or proxy method"
+ UNIMPLEMENTED(ERROR) << "Failed to determine this object of abstract or proxy method: "
<< PrettyMethod(m);
- return NULL;
+ return nullptr;
} else {
uint16_t reg = code_item->registers_size_ - code_item->ins_size_;
return reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kReferenceVReg));
return result;
}
-struct CurrentMethodVisitor : public StackVisitor {
+struct CurrentMethodVisitor FINAL : public StackVisitor {
CurrentMethodVisitor(Thread* thread, Context* context)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: StackVisitor(thread, context), this_object_(nullptr), method_(nullptr), dex_pc_(0) {}
- virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* m = GetMethod();
if (m->IsRuntimeMethod()) {
// Continue if this is a runtime method.