thread.cc revision 7dc5166ea740359d381097a7ab382c1dd404055f
18d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes/* 28d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * Copyright (C) 2011 The Android Open Source Project 38d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 48d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 58d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * you may not use this file except in compliance with the License. 68d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * You may obtain a copy of the License at 78d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 88d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 98d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 108d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * Unless required by applicable law or agreed to in writing, software 118d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 128d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * See the License for the specific language governing permissions and 148d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * limitations under the License. 158d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes */ 16b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 17578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 18b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 198d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes#include <dynamic_annotations.h> 20b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <pthread.h> 212acf36d8cfeb5ddb293904148aa70f25ef6d8845Elliott Hughes#include <signal.h> 22b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <sys/mman.h> 23dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom#include <sys/resource.h> 24dbf05b722af99ba2fd2f4c4fc7eb6c3e9880e5d1Brian Carlstrom#include <sys/time.h> 25a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 26b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <algorithm> 27dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes#include <bitset> 28eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes#include <cerrno> 29a09576416788b916095739e43a16917e7948f3a4Elliott Hughes#include <iostream> 30b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <list> 31b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h" 33a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "class_linker.h" 34df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom#include "class_loader.h" 35408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers#include "heap.h" 36c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h" 378e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes#include "monitor.h" 3857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers#include "oat/runtime/context.h" 39a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "object.h" 406d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 419a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson#include "reflection.h" 42578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h" 435433072f589b61413e042eddf76e8190a048f71dbuzbee#include "runtime_support.h" 44726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes#include "ScopedLocalRef.h" 45aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#include "scoped_jni_thread_state.h" 46f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien#include "shadow_frame.h" 4730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers#include "space.h" 4868e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#include "stack.h" 4968e76526e98432625464022cb26f66b9ef6f5af4Elliott Hughes#include "stack_indirect_reference_table.h" 508daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h" 51a09576416788b916095739e43a16917e7948f3a4Elliott Hughes#include "utils.h" 52776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#include "verifier/gc_map.h" 53b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 54b557353b22c728eecbd1c68593b482622c7782a8Carl Shapironamespace art { 55b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 56b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiropthread_key_t Thread::pthread_key_self_; 57b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 58462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughesstatic Class* gThreadGroup = NULL; 598e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughesstatic Class* gThreadLock = NULL; 60038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_daemon = NULL; 61038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_group = NULL; 62038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_lock = NULL; 63038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_name = NULL; 64038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_priority = NULL; 6529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughesstatic Field* gThread_uncaughtHandler = NULL; 66038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_vmData = NULL; 67462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughesstatic Field* gThreadGroup_mMain = NULL; 68462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughesstatic Field* gThreadGroup_mSystem = NULL; 69038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThreadGroup_name = NULL; 708e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughesstatic Field* gThreadLock_thread = NULL; 71038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Method* gThread_run = NULL; 7229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughesstatic Method* gThreadGroup_removeThread = NULL; 7329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughesstatic Method* gUncaughtExceptionHandler_uncaughtException = NULL; 74038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes 757dc5166ea740359d381097a7ab382c1dd404055fElliott Hughesstatic const char* kThreadNameDuringStartup = "<native thread without managed peer>"; 767dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes 775d76c435082332ef79a22962386fa92a0870e378Ian Rogersvoid Thread::InitCardTable() { 78b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes card_table_ = Runtime::Current()->GetHeap()->GetCardTable()->GetBiasedBegin(); 795d76c435082332ef79a22962386fa92a0870e378Ian Rogers} 805d76c435082332ef79a22962386fa92a0870e378Ian Rogers 8199250ba6a2cc72b8894dffa77c1fca5570087e3cElliott Hughes#if !defined(__APPLE__) 823ea0f42467790809fcfc9fc861605d465808090fElliott Hughesstatic void UnimplementedEntryPoint() { 833ea0f42467790809fcfc9fc861605d465808090fElliott Hughes UNIMPLEMENTED(FATAL); 843ea0f42467790809fcfc9fc861605d465808090fElliott Hughes} 8599250ba6a2cc72b8894dffa77c1fca5570087e3cElliott Hughes#endif 863ea0f42467790809fcfc9fc861605d465808090fElliott Hughes 873ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid Thread::InitFunctionPointers() { 8899250ba6a2cc72b8894dffa77c1fca5570087e3cElliott Hughes#if !defined(__APPLE__) // The Mac GCC is too old to accept this code. 893ea0f42467790809fcfc9fc861605d465808090fElliott Hughes // Insert a placeholder so we can easily tell if we call an unimplemented entry point. 903ea0f42467790809fcfc9fc861605d465808090fElliott Hughes uintptr_t* begin = reinterpret_cast<uintptr_t*>(&entrypoints_); 913ea0f42467790809fcfc9fc861605d465808090fElliott Hughes uintptr_t* end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(begin) + sizeof(entrypoints_)); 923ea0f42467790809fcfc9fc861605d465808090fElliott Hughes for (uintptr_t* it = begin; it != end; ++it) { 933ea0f42467790809fcfc9fc861605d465808090fElliott Hughes *it = reinterpret_cast<uintptr_t>(UnimplementedEntryPoint); 943ea0f42467790809fcfc9fc861605d465808090fElliott Hughes } 9599250ba6a2cc72b8894dffa77c1fca5570087e3cElliott Hughes#endif 9657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers InitEntryPoints(&entrypoints_); 97c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes} 98c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes 99c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughesvoid Thread::SetDebuggerUpdatesEnabled(bool enabled) { 100c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes LOG(INFO) << "Turning debugger updates " << (enabled ? "on" : "off") << " for " << *this; 101776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 10257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers ChangeDebuggerEntryPoint(&entrypoints_, enabled); 103776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#else 104776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers UNIMPLEMENTED(FATAL); 105776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 1063ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee} 1073ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee 108caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Thread::InitTid() { 109caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom tid_ = ::art::GetTid(); 110caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom} 111caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom 112caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstromvoid Thread::InitAfterFork() { 113caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom InitTid(); 1147dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes 1153147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes#if defined(__BIONIC__) 1163147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes // Work around a bionic bug. 1173147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes struct bionic_pthread_internal_t { 1183147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes void* next; 1193147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes void** pref; 1203147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes pthread_attr_t attr; 1213147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes pid_t kernel_id; 1223147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes // et cetera. we just need 'kernel_id' so we can stop here. 1233147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes }; 1247dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes bionic_pthread_internal_t* self = reinterpret_cast<bionic_pthread_internal_t*>(pthread_self()); 1257dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes if (self->kernel_id == tid_) { 1267dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes // TODO: if you see this logging, you can remove this code! 1277dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes LOG(INFO) << "*** this tree doesn't have the bionic pthread kernel_id bug"; 1287dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes } 1297dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes self->kernel_id = tid_; 1303147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes#endif 131caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom} 132caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom 13378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromvoid* Thread::CreateCallback(void* arg) { 13493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Thread* self = reinterpret_cast<Thread*>(arg); 135462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes self->Init(); 13693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 13793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Wait until it's safe to start running code. (There may have been a suspend-all 13893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // in progress while we were starting up.) 139462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes Runtime* runtime = Runtime::Current(); 14093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes runtime->GetThreadList()->WaitForGo(); 14193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 14247179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes { 14334e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes CHECK_EQ(self->GetState(), kRunnable); 144899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes SirtRef<String> thread_name(self->GetThreadName()); 145899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes self->SetThreadName(thread_name->ToModifiedUtf8().c_str()); 14647179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes } 14747179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes 148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes Dbg::PostThreadStart(self); 14993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 15093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Invoke the 'run' method of our java.lang.Thread. 15193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes CHECK(self->peer_ != NULL); 15293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Object* receiver = self->peer_; 153038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Method* m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(gThread_run); 15493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes m->Invoke(self, receiver, NULL, NULL); 15593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 15693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Detach. 15793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes runtime->GetThreadList()->Unregister(); 15893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 159b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return NULL; 160b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 161b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 162ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic void SetVmData(Object* managed_thread, Thread* native_thread) { 163038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_vmData->SetInt(managed_thread, reinterpret_cast<uintptr_t>(native_thread)); 16493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes} 16593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 166761928d24e4e7ed7776b52243eaf9095ad35f448Elliott HughesThread* Thread::FromManagedThread(Object* thread_peer) { 167761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes return reinterpret_cast<Thread*>(static_cast<uintptr_t>(gThread_vmData->GetInt(thread_peer))); 168761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes} 169761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes 17001158d7a57c8321370667a6045220237d16e0da8Elliott HughesThread* Thread::FromManagedThread(JNIEnv* env, jobject java_thread) { 171761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes return FromManagedThread(Decode<Object*>(env, java_thread)); 17201158d7a57c8321370667a6045220237d16e0da8Elliott Hughes} 17301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes 174ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic size_t FixStackSize(size_t stack_size) { 1757502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes // A stack size of zero means "use the default". 176d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (stack_size == 0) { 177d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes stack_size = Runtime::Current()->GetDefaultStackSize(); 178d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 17961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 1806414a97a3c6dc101ae8ebc9480114d0c327e8e8dBrian Carlstrom // Dalvik used the bionic pthread default stack size for native threads, 1816414a97a3c6dc101ae8ebc9480114d0c327e8e8dBrian Carlstrom // so include that here to support apps that expect large native stacks. 1826414a97a3c6dc101ae8ebc9480114d0c327e8e8dBrian Carlstrom stack_size += 1 * MB; 1836414a97a3c6dc101ae8ebc9480114d0c327e8e8dBrian Carlstrom 1846414a97a3c6dc101ae8ebc9480114d0c327e8e8dBrian Carlstrom 1857502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes // It's not possible to request a stack smaller than the system-defined PTHREAD_STACK_MIN. 1867502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes if (stack_size < PTHREAD_STACK_MIN) { 1877502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes stack_size = PTHREAD_STACK_MIN; 1887502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes } 1897502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes 1907502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes // It's likely that callers are trying to ensure they have at least a certain amount of 1917502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes // stack space, so we should add our reserved space on top of what they requested, rather 1927502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes // than implicitly take it away from them. 1937502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes stack_size += Thread::kStackOverflowReservedBytes; 1947502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes 1957502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes // Some systems require the stack size to be a multiple of the system page size, so round up. 1967502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes stack_size = RoundUp(stack_size, kPageSize); 1977502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes 1987502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes return stack_size; 1997502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes} 2007502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes 201d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughesstatic void SigAltStack(stack_t* new_stack, stack_t* old_stack) { 202d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes if (sigaltstack(new_stack, old_stack) == -1) { 203d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes PLOG(FATAL) << "sigaltstack failed"; 204d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes } 205d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes} 206d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes 207d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughesstatic void SetUpAlternateSignalStack() { 208d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes // Create and set an alternate signal stack. 209d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes stack_t ss; 210d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes ss.ss_sp = new uint8_t[SIGSTKSZ]; 211d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes ss.ss_size = SIGSTKSZ; 212d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes ss.ss_flags = 0; 213d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes CHECK(ss.ss_sp != NULL); 214d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes SigAltStack(&ss, NULL); 215d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes 216d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes // Double-check that it worked. 217d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes ss.ss_sp = NULL; 218d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes SigAltStack(NULL, &ss); 219d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes VLOG(threads) << "Alternate signal stack is " << PrettySize(ss.ss_size) << " at " << ss.ss_sp; 220d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes} 221d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes 222d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughesstatic void TearDownAlternateSignalStack() { 223d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes // Get the pointer so we can free the memory. 224d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes stack_t ss; 225d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes SigAltStack(NULL, &ss); 226d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes uint8_t* allocated_signal_stack = reinterpret_cast<uint8_t*>(ss.ss_sp); 227d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes 228d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes // Tell the kernel to stop using it. 229d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes ss.ss_sp = NULL; 230d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes ss.ss_flags = SS_DISABLE; 2314c5231d2cd83536584f7f1063d0afffa124fcec4Elliott Hughes ss.ss_size = SIGSTKSZ; // Avoid ENOMEM failure with Mac OS' buggy libc. 232d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes SigAltStack(&ss, NULL); 233d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes 234d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes // Free it. 235d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes delete[] allocated_signal_stack; 236d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes} 237d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes 2387502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughesvoid Thread::Create(Object* peer, size_t stack_size) { 2397502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes CHECK(peer != NULL); 2407502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes 2417502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes stack_size = FixStackSize(stack_size); 2427502e2a419f84808518cf212b3d7145c7b959c76Elliott Hughes 24393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Thread* native_thread = new Thread; 24493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes native_thread->peer_ = peer; 24593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 24693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Thread.start is synchronized, so we know that vmData is 0, 24793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // and know that we're not racing to assign it. 24893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes SetVmData(peer, native_thread); 24961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 25047179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes { 25134e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes ScopedThreadStateChange tsc(Thread::Current(), kVmWait); 25247179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes pthread_t new_pthread; 25347179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes pthread_attr_t attr; 25447179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread"); 25547179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED), "PTHREAD_CREATE_DETACHED"); 25647179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size); 25747179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes CHECK_PTHREAD_CALL(pthread_create, (&new_pthread, &attr, Thread::CreateCallback, native_thread), "new thread"); 25847179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread"); 25947179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes } 26061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 26193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Let the child know when it's safe to start running. 26293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Runtime::Current()->GetThreadList()->SignalGo(native_thread); 26393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes} 26461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 265462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughesvoid Thread::Init() { 266462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes // This function does all the initialization that must be run by the native thread it applies to. 267462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes // (When we create a new thread from managed code, we allocate the Thread* in Thread::Create so 268462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes // we can handshake with the corresponding native thread when it's ready.) Check this native 269462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes // thread hasn't been through here already... 270cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes CHECK(Thread::Current() == NULL); 271cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes 272d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes SetUpAlternateSignalStack(); 27393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes InitCpu(); 27493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes InitFunctionPointers(); 2755d76c435082332ef79a22962386fa92a0870e378Ian Rogers InitCardTable(); 27661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 277462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes Runtime* runtime = Runtime::Current(); 278462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes CHECK(runtime != NULL); 279462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes 280462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes thin_lock_id_ = runtime->GetThreadList()->AllocThreadId(); 281be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes 282caabb1b77b4a55eb1bb45ebcd3071c9ea01dd3cfBrian Carlstrom InitTid(); 28393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes InitStackHwm(); 284dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes 2853147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, this), "attach"); 286a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes 28793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes jni_env_ = new JNIEnvExt(this, runtime->GetJavaVM()); 2885fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 2897a3aeb4d7580164c6a6905c63b96823b77ff5a64Elliott Hughes runtime->GetThreadList()->Register(); 29093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes} 29193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 292462c94449720e0dc6b93d7138d835d345ccf67aeElliott HughesThread* Thread::Attach(const char* thread_name, bool as_daemon, Object* thread_group) { 293cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes Thread* self = new Thread; 294462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes self->Init(); 2955fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 29634e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes self->SetState(kNative); 297726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes 298cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes // If we're the main thread, ClassLinker won't be created until after we're attached, 299cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes // so that thread needs a two-stage attach. Regular threads don't need this hack. 300d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes // In the compiler, all threads need this hack, because no-one's going to be getting 301d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes // a native peer! 302d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes if (self->thin_lock_id_ != ThreadList::kMainId && !Runtime::Current()->IsCompiler()) { 303462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes self->CreatePeer(thread_name, as_daemon, thread_group); 30406e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes } else { 30506e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes // These aren't necessary, but they improve diagnostics for unit tests & command-line tools. 30622869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes if (thread_name != NULL) { 30722869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes self->name_->assign(thread_name); 30822869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes ::art::SetThreadName(thread_name); 30922869a9026a08b544eca4cefd67386d347e30d2cElliott Hughes } 31036e0a955e48e9357bff1eab783e493107ebfff62Ian Rogers } 311cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes 312cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes self->GetJniEnv()->locals.AssertEmpty(); 3135fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes return self; 3145fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes} 3155fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 316462c94449720e0dc6b93d7138d835d345ccf67aeElliott HughesObject* Thread::GetMainThreadGroup() { 3170045a290e6b79a274250e3112880c04bde437d4aIan Rogers if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(gThreadGroup, true, true)) { 318462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes return NULL; 319462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes } 320462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes return gThreadGroup_mMain->GetObject(NULL); 321d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes} 322d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 323462c94449720e0dc6b93d7138d835d345ccf67aeElliott HughesObject* Thread::GetSystemThreadGroup() { 3240045a290e6b79a274250e3112880c04bde437d4aIan Rogers if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(gThreadGroup, true, true)) { 325462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes return NULL; 326462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes } 327462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes return gThreadGroup_mSystem->GetObject(NULL); 328462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes} 329462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes 330462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughesvoid Thread::CreatePeer(const char* name, bool as_daemon, Object* thread_group) { 3319a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson CHECK(Runtime::Current()->IsStarted()); 3325fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes JNIEnv* env = jni_env_; 3335fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 334462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes if (thread_group == NULL) { 335462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes thread_group = Thread::GetMainThreadGroup(); 336462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes } 337462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes ScopedLocalRef<jobject> java_thread_group(env, AddLocalReference<jobject>(env, thread_group)); 338726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes ScopedLocalRef<jobject> thread_name(env, env->NewStringUTF(name)); 3398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes jint thread_priority = GetNativePriority(); 3405fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes jboolean thread_is_daemon = as_daemon; 3415fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 342726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Thread")); 3435d4bdc29737a693027daaf6ed3f0792368eb4baeIan Rogers ScopedLocalRef<jobject> peer(env, env->AllocObject(c.get())); 344726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes peer_ = DecodeJObject(peer.get()); 3455d4bdc29737a693027daaf6ed3f0792368eb4baeIan Rogers if (peer_ == NULL) { 3465d4bdc29737a693027daaf6ed3f0792368eb4baeIan Rogers CHECK(IsExceptionPending()); 3475d4bdc29737a693027daaf6ed3f0792368eb4baeIan Rogers return; 3485d4bdc29737a693027daaf6ed3f0792368eb4baeIan Rogers } 3495d4bdc29737a693027daaf6ed3f0792368eb4baeIan Rogers jmethodID mid = env->GetMethodID(c.get(), "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V"); 350462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes env->CallNonvirtualVoidMethod(peer.get(), c.get(), mid, java_thread_group.get(), thread_name.get(), thread_priority, thread_is_daemon); 3519a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson CHECK(!IsExceptionPending()) << " " << PrettyTypeOf(GetException()); 3527a3aeb4d7580164c6a6905c63b96823b77ff5a64Elliott Hughes SetVmData(peer_, Thread::Current()); 353d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 354899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes SirtRef<String> peer_thread_name(GetThreadName()); 35500fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom if (peer_thread_name.get() == NULL) { 35600fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom // The Thread constructor should have set the Thread.name to a 35700fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom // non-null value. However, because we can run without code 35800fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom // available (in the compiler, in tests), we manually assign the 35900fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom // fields the constructor should have set. 36000fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom gThread_daemon->SetBoolean(peer_, thread_is_daemon); 361462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes gThread_group->SetObject(peer_, thread_group); 36200fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom gThread_name->SetObject(peer_, Decode<Object*>(env, thread_name.get())); 36300fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom gThread_priority->SetInt(peer_, thread_priority); 364899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes peer_thread_name.reset(GetThreadName()); 36500fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom } 36600fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom // thread_name may have been null, so don't trust this to be non-null 36700fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom if (peer_thread_name.get() != NULL) { 368899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes SetThreadName(peer_thread_name->ToModifiedUtf8().c_str()); 36900fae585c6e4a37b964c77f557fbf84f11e2d930Brian Carlstrom } 370726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes 371726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes // Pre-allocate an OutOfMemoryError for the double-OOME case. 372726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes ThrowNewException("Ljava/lang/OutOfMemoryError;", 373726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes "OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available"); 374726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes ScopedLocalRef<jthrowable> exception(env, env->ExceptionOccurred()); 375726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes env->ExceptionClear(); 376726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes pre_allocated_OutOfMemoryError_ = Decode<Throwable*>(env, exception.get()); 37761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 37861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 379899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughesvoid Thread::SetThreadName(const char* name) { 380899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes name_->assign(name); 381899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes ::art::SetThreadName(name); 382899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes Dbg::DdmSendThreadNotification(this, CHUNK_TYPE("THNM")); 383899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes} 384899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes 385be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughesvoid Thread::InitStackHwm() { 386e188419b971936086a188843378375f5ced13724Elliott Hughes void* stack_base; 387e188419b971936086a188843378375f5ced13724Elliott Hughes size_t stack_size; 388e188419b971936086a188843378375f5ced13724Elliott Hughes GetThreadStack(stack_base, stack_size); 38936ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes 39036ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes // TODO: include this in the thread dumps; potentially useful in SIGQUIT output? 391e188419b971936086a188843378375f5ced13724Elliott Hughes VLOG(threads) << StringPrintf("Native stack is at %p (%s)", stack_base, PrettySize(stack_size).c_str()); 392e188419b971936086a188843378375f5ced13724Elliott Hughes 393e188419b971936086a188843378375f5ced13724Elliott Hughes stack_begin_ = reinterpret_cast<byte*>(stack_base); 394e188419b971936086a188843378375f5ced13724Elliott Hughes stack_size_ = stack_size; 39536ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes 396932746a4f22951abcba7b7c4c94c27b1bf164272Ian Rogers if (stack_size_ <= kStackOverflowReservedBytes) { 3973d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Attempt to attach a thread with a too-small stack (" << stack_size_ << " bytes)"; 398be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes } 399449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes 400e188419b971936086a188843378375f5ced13724Elliott Hughes // TODO: move this into the Linux GetThreadStack implementation. 401e188419b971936086a188843378375f5ced13724Elliott Hughes#if !defined(__APPLE__) 40236ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes // If we're the main thread, check whether we were run with an unlimited stack. In that case, 40336ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes // glibc will have reported a 2GB stack for our 32-bit process, and our stack overflow detection 40436ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes // will be broken because we'll die long before we get close to 2GB. 40536ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes if (thin_lock_id_ == 1) { 40636ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes rlimit stack_limit; 40736ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) { 40836ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes PLOG(FATAL) << "getrlimit(RLIMIT_STACK) failed"; 40936ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes } 41036ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes if (stack_limit.rlim_cur == RLIM_INFINITY) { 41136ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes // Find the default stack size for new threads... 41236ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes pthread_attr_t default_attributes; 41336ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes size_t default_stack_size; 41436ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_init, (&default_attributes), "default stack size query"); 41536ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_getstacksize, (&default_attributes, &default_stack_size), 41636ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes "default stack size query"); 41736ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_destroy, (&default_attributes), "default stack size query"); 41836ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes 41936ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes // ...and use that as our limit. 42036ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes size_t old_stack_size = stack_size_; 42136ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes stack_size_ = default_stack_size; 42236ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes stack_begin_ += (old_stack_size - stack_size_); 423faf4ba01738400f418b45c4323aa9e8e6b6ba2a0Elliott Hughes VLOG(threads) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ")" 424faf4ba01738400f418b45c4323aa9e8e6b6ba2a0Elliott Hughes << " to " << PrettySize(stack_size_) 425faf4ba01738400f418b45c4323aa9e8e6b6ba2a0Elliott Hughes << " with base " << reinterpret_cast<void*>(stack_begin_); 42636ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes } 42736ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes } 428e188419b971936086a188843378375f5ced13724Elliott Hughes#endif 42936ecb789775eb5bd284ce5dd35d2e31e42354f24Elliott Hughes 430932746a4f22951abcba7b7c4c94c27b1bf164272Ian Rogers // Set stack_end_ to the bottom of the stack saving space of stack overflows 431932746a4f22951abcba7b7c4c94c27b1bf164272Ian Rogers ResetDefaultStackEnd(); 432449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes 433449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes // Sanity check. 434449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes int stack_variable; 435398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes CHECK_GT(&stack_variable, reinterpret_cast<void*>(stack_end_)); 436be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes} 437be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes 438899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughesvoid Thread::Dump(std::ostream& os, bool full) const { 439899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes if (full) { 440899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes DumpState(os); 441899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes DumpStack(os); 442899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes } else { 443899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes os << "Thread["; 444899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes if (GetThinLockId() != 0) { 445899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes // If we're in kStarting, we won't have a thin lock id or tid yet. 446899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes os << GetThinLockId() 447899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes << ",tid=" << GetTid() << ','; 448899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes } 449899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes os << GetState() 450899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes << ",Thread*=" << this 451ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes << ",peer=" << peer_ 452899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes << ",\"" << *name_ << "\"" 453899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes << "]"; 454e0918556e7551de638870dcad3f2023f94f85a50Elliott Hughes } 455d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes} 456d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 457899e789bd4741c0172268f7838ce8ab220a5f916Elliott HughesString* Thread::GetThreadName() const { 458fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes return (peer_ != NULL) ? reinterpret_cast<String*>(gThread_name->GetObject(peer_)) : NULL; 459fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes} 460fc86162ce2a3467acb690e18cc8bd9b3daafc606Elliott Hughes 461ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesvoid Thread::GetThreadName(std::string& name) const { 462ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes name.assign(*name_); 463ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes} 464ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes 465d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Thread::DumpState(std::ostream& os) const { 466d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes std::string group_name; 467d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes int priority; 468d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes bool is_daemon = false; 469d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 470d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (peer_ != NULL) { 471038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes priority = gThread_priority->GetInt(peer_); 472038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes is_daemon = gThread_daemon->GetBoolean(peer_); 473d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 474a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Object* thread_group = GetThreadGroup(); 475d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (thread_group != NULL) { 476038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes String* group_name_string = reinterpret_cast<String*>(gThreadGroup_name->GetObject(thread_group)); 477d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes group_name = (group_name_string != NULL) ? group_name_string->ToModifiedUtf8() : "<null>"; 478d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 479d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } else { 480d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes priority = GetNativePriority(); 481dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes } 482d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 483d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int policy; 484d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes sched_param sp; 4853147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes CHECK_PTHREAD_CALL(pthread_getschedparam, (pthread_self(), &policy, &sp), __FUNCTION__); 486d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 4871bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes std::string scheduler_group_name(GetSchedulerGroupName(GetTid())); 4881bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes if (scheduler_group_name.empty()) { 4891bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes scheduler_group_name = "default"; 490d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 491d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 492899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes os << '"' << *name_ << '"'; 493d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (is_daemon) { 494d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " daemon"; 495d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 496d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " prio=" << priority 497dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes << " tid=" << GetThinLockId() 49893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes << " " << GetState() << "\n"; 499d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 500d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " | group=\"" << group_name << "\"" 5018d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes << " sCount=" << suspend_count_ 502234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes << " dsCount=" << debug_suspend_count_ 503dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes << " obj=" << reinterpret_cast<void*>(peer_) 504d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " self=" << reinterpret_cast<const void*>(this) << "\n"; 505d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " | sysTid=" << GetTid() 506d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " nice=" << getpriority(PRIO_PROCESS, GetTid()) 507d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " sched=" << policy << "/" << sp.sched_priority 5081bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes << " cgrp=" << scheduler_group_name 5093147a2347d4fd775d51ec0a558955332beb9d1feElliott Hughes << " handle=" << pthread_self() << "\n"; 510d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 511d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // Grab the scheduler stats for this thread. 512d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::string scheduler_stats; 5138a31b50daf530a28c8ce2be8d758c737cb32897bElliott Hughes if (ReadFileToString(StringPrintf("/proc/self/task/%d/schedstat", GetTid()), &scheduler_stats)) { 514d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes scheduler_stats.resize(scheduler_stats.size() - 1); // Lose the trailing '\n'. 515d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } else { 516d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes scheduler_stats = "0 0 0"; 517d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 518d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 519d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int utime = 0; 520d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int stime = 0; 521d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int task_cpu = 0; 522bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes GetTaskStats(GetTid(), utime, stime, task_cpu); 523d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 524d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " | schedstat=( " << scheduler_stats << " )" 525d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " utm=" << utime 526d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " stm=" << stime 527d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " core=" << task_cpu 528d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " HZ=" << sysconf(_SC_CLK_TCK) << "\n"; 5295b17d08be8f9508ead25891c4d3e707f9dddfbc5Elliott Hughes 5305b17d08be8f9508ead25891c4d3e707f9dddfbc5Elliott Hughes os << " | stackSize=" << PrettySize(stack_size_) 5315b17d08be8f9508ead25891c4d3e707f9dddfbc5Elliott Hughes << " stack=" << reinterpret_cast<void*>(stack_begin_) << "-" << reinterpret_cast<void*>(stack_end_) << "\n"; 532a09576416788b916095739e43a16917e7948f3a4Elliott Hughes} 533a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 534ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#if !defined(ART_USE_LLVM_COMPILER) 535b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogersvoid Thread::PushNativeToManagedRecord(NativeToManagedRecord* record) { 536b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers Method **sp = top_of_managed_stack_.GetSP(); 537b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers#ifndef NDEBUG 538b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers if (sp != NULL) { 539b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers Method* m = *sp; 540b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes Runtime::Current()->GetHeap()->VerifyObject(m); 541b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers DCHECK((m == NULL) || m->IsMethod()); 542b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers } 543b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers#endif 544b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers record->last_top_of_managed_stack_ = reinterpret_cast<void*>(sp); 545b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers record->last_top_of_managed_stack_pc_ = top_of_managed_stack_pc_; 546b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers record->link_ = native_to_managed_record_; 547b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers native_to_managed_record_ = record; 548b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers top_of_managed_stack_.SetSP(NULL); 549b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers} 550ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#else 551ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYavoid Thread::PushNativeToManagedRecord(NativeToManagedRecord*) { 552ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa LOG(FATAL) << "Called non-LLVM method with LLVM"; 553ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa} 554ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#endif 555b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers 556ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#if !defined(ART_USE_LLVM_COMPILER) 557b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogersvoid Thread::PopNativeToManagedRecord(const NativeToManagedRecord& record) { 558b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers native_to_managed_record_ = record.link_; 559b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(record.last_top_of_managed_stack_)); 560b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers top_of_managed_stack_pc_ = record.last_top_of_managed_stack_pc_; 561b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers} 562ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#else 563ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYavoid Thread::PopNativeToManagedRecord(const NativeToManagedRecord&) { 564ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa LOG(FATAL) << "Called non-LLVM method with LLVM"; 565ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa} 566ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#endif 567b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers 568d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesstruct StackDumpVisitor : public Thread::StackVisitor { 5698e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes StackDumpVisitor(std::ostream& os, const Thread* thread) 57028ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers : last_method(NULL), last_line_number(0), repetition_count(0), os(os), thread(thread), 57128ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers frame_count(0) { 572d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 573d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 574bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual ~StackDumpVisitor() { 575e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes if (frame_count == 0) { 576e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes os << " (no managed stack frames)\n"; 577e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes } 578d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 579d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 580530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes bool VisitFrame(const Frame& frame, uintptr_t pc) { 5819086572fa809d1a19d886b467e4da3ce42016982Ian Rogers if (!frame.HasMethod()) { 582530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 5839086572fa809d1a19d886b467e4da3ce42016982Ian Rogers } 58428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers const int kMaxRepetition = 3; 585d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes Method* m = frame.GetMethod(); 586d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes Class* c = m->GetDeclaringClass(); 5878e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 588b861dc0077342d5a1d2dd9cade3f6990620778ecIan Rogers const DexCache* dex_cache = c->GetDexCache(); 589b861dc0077342d5a1d2dd9cade3f6990620778ecIan Rogers int line_number = -1; 590b861dc0077342d5a1d2dd9cade3f6990620778ecIan Rogers if (dex_cache != NULL) { // be tolerant of bad input 591b861dc0077342d5a1d2dd9cade3f6990620778ecIan Rogers const DexFile& dex_file = class_linker->FindDexFile(dex_cache); 592b861dc0077342d5a1d2dd9cade3f6990620778ecIan Rogers line_number = dex_file.GetLineNumFromPC(m, m->ToDexPC(pc)); 593b861dc0077342d5a1d2dd9cade3f6990620778ecIan Rogers } 59428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (line_number == last_line_number && last_method == m) { 59528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers repetition_count++; 596d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } else { 59728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (repetition_count >= kMaxRepetition) { 59828ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers os << " ... repeated " << (repetition_count - kMaxRepetition) << " times\n"; 59928ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 60028ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers repetition_count = 0; 60128ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers last_line_number = line_number; 60228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers last_method = m; 60328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 60428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (repetition_count < kMaxRepetition) { 60528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers os << " at " << PrettyMethod(m, false); 60628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (m->IsNative()) { 60728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers os << "(Native method)"; 60828ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } else { 6096d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers mh.ChangeMethod(m); 6106d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers const char* source_file(mh.GetDeclaringClassSourceFile()); 6116d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers os << "(" << (source_file != NULL ? source_file : "unavailable") 61228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers << ":" << line_number << ")"; 61328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 61428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers os << "\n"; 615d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 6168e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 6178e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes if (frame_count++ == 0) { 6188e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes Monitor::DescribeWait(os, thread); 6198e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes } 620530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 621d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 6226d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper mh; 62328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers Method* last_method; 62428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers int last_line_number; 62528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers int repetition_count; 626d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes std::ostream& os; 6278e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes const Thread* thread; 6288e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes int frame_count; 629d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes}; 630d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 631d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Thread::DumpStack(std::ostream& os) const { 632ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes // If we're currently in native code, dump that stack before dumping the managed stack. 63334e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes if (GetState() == kNative || GetState() == kVmWait) { 634e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes DumpKernelStack(os); 635ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes DumpNativeStack(os); 636ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes } 6378e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes StackDumpVisitor dumper(os, this); 638d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes WalkStack(&dumper); 639e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes} 640e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 641e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes#if !defined(__APPLE__) 642beb3240889846c0c196c8b14cc8d595458f25ed4Elliott Hughesvoid Thread::DumpKernelStack(std::ostream& os) const { 643e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes std::string kernel_stack_filename(StringPrintf("/proc/self/task/%d/stack", GetTid())); 644e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes std::string kernel_stack; 645e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes if (!ReadFileToString(kernel_stack_filename, &kernel_stack)) { 646e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes os << " (couldn't read " << kernel_stack_filename << ")"; 647e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes } 648e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes 649e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes std::vector<std::string> kernel_stack_frames; 650e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes Split(kernel_stack, '\n', kernel_stack_frames); 651e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes // We skip the last stack frame because it's always equivalent to "[<ffffffff>] 0xffffffff", 652e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes // which looking at the source appears to be the kernel's way of saying "that's all, folks!". 653e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes kernel_stack_frames.pop_back(); 654e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes for (size_t i = 0; i < kernel_stack_frames.size(); ++i) { 655e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes os << " kernel: " << kernel_stack_frames[i] << "\n"; 656e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes } 657e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes} 658beb3240889846c0c196c8b14cc8d595458f25ed4Elliott Hughes#else 659beb3240889846c0c196c8b14cc8d595458f25ed4Elliott Hughes// TODO: can we get the kernel stack on Mac OS? 660beb3240889846c0c196c8b14cc8d595458f25ed4Elliott Hughesvoid Thread::DumpKernelStack(std::ostream&) const {} 661beb3240889846c0c196c8b14cc8d595458f25ed4Elliott Hughes#endif 662e85d2e924953f1a13b7152edba1c13853e6f3a86Elliott Hughes 66334e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughesvoid Thread::SetStateWithoutSuspendCheck(ThreadState new_state) { 664a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes volatile void* raw = reinterpret_cast<volatile void*>(&state_); 665a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw); 666a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes android_atomic_release_store(new_state, addr); 667a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes} 668a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes 66934e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott HughesThreadState Thread::SetState(ThreadState new_state) { 67034e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes ThreadState old_state = state_; 6718d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes if (old_state == new_state) { 6728d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes return old_state; 6738d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 6748d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 6758d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes volatile void* raw = reinterpret_cast<volatile void*>(&state_); 6768d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw); 6778d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 67834e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes if (new_state == kRunnable) { 6798d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes /* 68034e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes * Change our status to kRunnable. The transition requires 68181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes * that we check for pending suspension, because the runtime considers 6828d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * us to be "asleep" in all other states, and another thread could 6838d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * be performing a GC now. 6848d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 6858d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * The order of operations is very significant here. One way to 6868d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * do this wrong is: 6878d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 6888d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * GCing thread Our thread (in kNative) 6898d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * ------------ ---------------------- 6908d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * check suspend count (== 0) 6918d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * SuspendAllThreads() 6928d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * grab suspend-count lock 6938d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * increment all suspend counts 6948d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * release suspend-count lock 6958d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * check thread state (== kNative) 6968d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * all are suspended, begin GC 6978d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * set state to kRunnable 6988d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * (continue executing) 6998d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7008d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * We can correct this by grabbing the suspend-count lock and 7018d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * performing both of our operations (check suspend count, set 7028d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * state) while holding it, now we need to grab a mutex on every 7038d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * transition to kRunnable. 7048d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7058d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * What we do instead is change the order of operations so that 7068d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * the transition to kRunnable happens first. If we then detect 7078d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * that the suspend count is nonzero, we switch to kSuspended. 7088d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7098d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * Appropriate compiler and memory barriers are required to ensure 7108d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * that the operations are observed in the expected order. 7118d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7128d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * This does create a small window of opportunity where a GC in 7138d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * progress could observe what appears to be a running thread (if 7148d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * it happens to look between when we set to kRunnable and when we 7158d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * switch to kSuspended). At worst this only affects assertions 7168d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * and thread logging. (We could work around it with some sort 7178d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * of intermediate "pre-running" state that is generally treated 7188d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * as equivalent to running, but that doesn't seem worthwhile.) 7198d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7208d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * We can also solve this by combining the "status" and "suspend 7218d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * count" fields into a single 32-bit value. This trades the 7228d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * store/load barrier on transition to kRunnable for an atomic RMW 7238d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * op on all transitions and all suspend count updates (also, all 7248d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * accesses to status or the thread count require bit-fiddling). 7258d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * It also eliminates the brief transition through kRunnable when 7268d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * the thread is supposed to be suspended. This is possibly faster 7278d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * on SMP and slightly more correct, but less convenient. 7288d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes */ 7298d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes android_atomic_acquire_store(new_state, addr); 73006e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes ANNOTATE_IGNORE_READS_BEGIN(); 73106e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes int suspend_count = suspend_count_; 73206e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes ANNOTATE_IGNORE_READS_END(); 73306e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes if (suspend_count != 0) { 7348d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes Runtime::Current()->GetThreadList()->FullSuspendCheck(this); 7358d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 7368d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } else { 7378d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes /* 73834e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes * Not changing to kRunnable. No additional work required. 7398d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7408d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * We use a releasing store to ensure that, if we were runnable, 7418d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * any updates we previously made to objects on the managed heap 7428d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * will be observed before the state change. 7438d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes */ 7448d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes android_atomic_release_store(new_state, addr); 7458d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 7468d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 7478d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes return old_state; 7488d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes} 7498d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 750761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool Thread::IsSuspended() { 75106e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes ANNOTATE_IGNORE_READS_BEGIN(); 75206e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes int suspend_count = suspend_count_; 75306e3ad4a651c2c58dba5e865cd06d2f98462bf1dElliott Hughes ANNOTATE_IGNORE_READS_END(); 75434e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes return suspend_count != 0 && GetState() != kRunnable; 755761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes} 756761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes 757ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughesstatic void ReportThreadSuspendTimeout(Thread* waiting_thread) { 758ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes Runtime* runtime = Runtime::Current(); 759ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes std::ostringstream ss; 760ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes ss << "Thread suspend timeout waiting for thread " << *waiting_thread << "\n"; 761ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes runtime->DumpLockHolders(ss); 762ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes ss << "\n"; 763ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes runtime->GetThreadList()->DumpLocked(ss); 764ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes LOG(FATAL) << ss.str(); 765ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes} 766ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes 7678d768a954b101a9532f980253ac46be2c53aba11Elliott Hughesvoid Thread::WaitUntilSuspended() { 76821a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes static const useconds_t kTimeoutUs = 30 * 1000000; // 30s. 76921a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes 77021a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes useconds_t total_delay = 0; 7718d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes useconds_t delay = 0; 77234e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes while (GetState() == kRunnable) { 77321a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes if (total_delay >= kTimeoutUs) { 774ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes ReportThreadSuspendTimeout(this); 77521a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes } 7768d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes useconds_t new_delay = delay * 2; 7778d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_GE(new_delay, delay); 7788d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes delay = new_delay; 7798d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes if (delay == 0) { 7808d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes sched_yield(); 7818d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes delay = 10000; 7828d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } else { 7838d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes usleep(delay); 78421a5bf2dc8c9cb3fbe5a30a88d1149c328e3aacaElliott Hughes total_delay += delay; 7858d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 7868d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 7878d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes} 7888d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 789be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughesvoid Thread::ThreadExitCallback(void* arg) { 790be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes Thread* self = reinterpret_cast<Thread*>(arg); 791be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes LOG(FATAL) << "Native thread exited without calling DetachCurrentThread: " << *self; 792b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 793b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 794be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughesvoid Thread::Startup() { 795b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Allocate a TLS slot. 7968d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_key_create, (&Thread::pthread_key_self_, Thread::ThreadExitCallback), "self key"); 797b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 798b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Double-check the TLS slot allocation. 799b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (pthread_getspecific(pthread_key_self_) != NULL) { 8003d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Newly-created pthread TLS slot is not NULL"; 801b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 802038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes} 803038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes 8048e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes// TODO: make more accessible? 805ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic Class* FindClassOrDie(ClassLinker* class_linker, const char* descriptor) { 8068e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes Class* c = class_linker->FindSystemClass(descriptor); 8078e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes CHECK(c != NULL) << descriptor; 8088e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes return c; 8098e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes} 8108e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 8118e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes// TODO: make more accessible? 812ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic Field* FindFieldOrDie(Class* c, const char* name, const char* descriptor) { 8136b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom Field* f = c->FindDeclaredInstanceField(name, descriptor); 8146b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << descriptor; 8158e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes return f; 8168e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes} 8178e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 8188e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes// TODO: make more accessible? 819ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic Method* FindMethodOrDie(Class* c, const char* name, const char* signature) { 8208e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes Method* m = c->FindVirtualMethod(name, signature); 8218e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes CHECK(m != NULL) << PrettyClass(c) << " " << name << " " << signature; 8228e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes return m; 8238e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes} 8248e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 825462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes// TODO: make more accessible? 826ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic Field* FindStaticFieldOrDie(Class* c, const char* name, const char* descriptor) { 827462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes Field* f = c->FindDeclaredStaticField(name, descriptor); 828462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << descriptor; 829462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes return f; 830462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes} 831462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes 832038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Thread::FinishStartup() { 8339a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson CHECK(Runtime::Current()->IsStarted()); 834b82b6878fb000d4731063b1bf15c39ff7c50b61fBrian Carlstrom Thread* self = Thread::Current(); 835b82b6878fb000d4731063b1bf15c39ff7c50b61fBrian Carlstrom 836b82b6878fb000d4731063b1bf15c39ff7c50b61fBrian Carlstrom // Need to be kRunnable for FindClass 83734e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes ScopedThreadStateChange tsc(self, kRunnable); 838b82b6878fb000d4731063b1bf15c39ff7c50b61fBrian Carlstrom 839038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // Now the ClassLinker is ready, we can find the various Class*, Field*, and Method*s we need. 840038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 8418e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 8428e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes Class* Thread_class = FindClassOrDie(class_linker, "Ljava/lang/Thread;"); 8438e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes Class* UncaughtExceptionHandler_class = FindClassOrDie(class_linker, "Ljava/lang/Thread$UncaughtExceptionHandler;"); 844462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes gThreadGroup = FindClassOrDie(class_linker, "Ljava/lang/ThreadGroup;"); 8458e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes gThreadLock = FindClassOrDie(class_linker, "Ljava/lang/ThreadLock;"); 8468e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 8476b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThread_daemon = FindFieldOrDie(Thread_class, "daemon", "Z"); 8486b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThread_group = FindFieldOrDie(Thread_class, "group", "Ljava/lang/ThreadGroup;"); 8496b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThread_lock = FindFieldOrDie(Thread_class, "lock", "Ljava/lang/ThreadLock;"); 8506b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThread_name = FindFieldOrDie(Thread_class, "name", "Ljava/lang/String;"); 8516b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThread_priority = FindFieldOrDie(Thread_class, "priority", "I"); 8526b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThread_uncaughtHandler = FindFieldOrDie(Thread_class, "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;"); 8536b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThread_vmData = FindFieldOrDie(Thread_class, "vmData", "I"); 854462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes gThreadGroup_name = FindFieldOrDie(gThreadGroup, "name", "Ljava/lang/String;"); 855462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes gThreadGroup_mMain = FindStaticFieldOrDie(gThreadGroup, "mMain", "Ljava/lang/ThreadGroup;"); 856462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes gThreadGroup_mSystem = FindStaticFieldOrDie(gThreadGroup, "mSystem", "Ljava/lang/ThreadGroup;"); 8576b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom gThreadLock_thread = FindFieldOrDie(gThreadLock, "thread", "Ljava/lang/Thread;"); 8588e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 8598e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes gThread_run = FindMethodOrDie(Thread_class, "run", "()V"); 860462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes gThreadGroup_removeThread = FindMethodOrDie(gThreadGroup, "removeThread", "(Ljava/lang/Thread;)V"); 8618e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes gUncaughtExceptionHandler_uncaughtException = FindMethodOrDie(UncaughtExceptionHandler_class, 8628e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"); 86301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes 86401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // Finish attaching the main thread. 865462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes Thread::Current()->CreatePeer("main", false, Thread::GetMainThreadGroup()); 8669a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson 8679a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson InitBoxingMethods(); 8689a6bae896a2f003d7216603bf29771d105c10ca4Jesse Wilson class_linker->RunRootClinits(); 869b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 870b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 871c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Thread::Shutdown() { 8728d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_key_delete, (Thread::pthread_key_self_), "self key"); 873c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 874c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 8758e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughesuint32_t Thread::LockOwnerFromThreadLock(Object* thread_lock) { 8768e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes if (thread_lock == NULL || thread_lock->GetClass() != gThreadLock) { 8778e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes return ThreadList::kInvalidId; 8788e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes } 8798e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes Object* managed_thread = gThreadLock_thread->GetObject(thread_lock); 8808e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes if (managed_thread == NULL) { 8818e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes return ThreadList::kInvalidId; 8828e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes } 8838e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes uintptr_t vmData = static_cast<uintptr_t>(gThread_vmData->GetInt(managed_thread)); 8848e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes Thread* thread = reinterpret_cast<Thread*>(vmData); 8858e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes if (thread == NULL) { 8868e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes return ThreadList::kInvalidId; 8878e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes } 8888e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes return thread->GetThinLockId(); 8898e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes} 8908e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes 891dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesThread::Thread() 89247179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes : thin_lock_id_(0), 89347179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes tid_(0), 89447179f76e3f03fe3eb21dfb081d50733ca316371Elliott Hughes peer_(NULL), 8958e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes top_of_managed_stack_(), 8968e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes top_of_managed_stack_pc_(0), 897e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes wait_mutex_(new Mutex("a thread wait mutex")), 898e62934d85fbc2d935afdad57eeade39ecbd7440aElliott Hughes wait_cond_(new ConditionVariable("a thread wait condition variable")), 8998daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes wait_monitor_(NULL), 9008daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes interrupted_(false), 901dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes wait_next_(NULL), 9028e4aac52962d54cb4be2078b9cd95685e067133aElliott Hughes monitor_enter_object_(NULL), 903dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes card_table_(0), 9048daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes stack_end_(NULL), 905dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes native_to_managed_record_(NULL), 906dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes top_sirt_(NULL), 907f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien top_shadow_frame_(NULL), 908dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes jni_env_(NULL), 90934e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes state_(kNative), 910dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes self_(NULL), 911dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes runtime_(NULL), 912dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes exception_(NULL), 913dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes suspend_count_(0), 914234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes debug_suspend_count_(0), 91585d1545e985ac689db4bad7849880e843707c862Elliott Hughes class_loader_override_(NULL), 916418dfe7849f45535b5388a91bd7a16cfc20a612bElliott Hughes long_jump_context_(NULL), 917726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes throwing_OutOfMemoryError_(false), 918475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes pre_allocated_OutOfMemoryError_(NULL), 919e343b76af81a005ef64f5e75a555389fd9147dabjeffhao debug_invoke_req_(new DebugInvokeReq), 920899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes trace_stack_(new std::vector<TraceStackFrame>), 9217dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes name_(new std::string(kThreadNameDuringStartup)) { 922f5a7a476e7ea63e094ff0f011dccc170607e6f6bElliott Hughes CHECK_EQ((sizeof(Thread) % 4), 0U) << sizeof(Thread); 923ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes memset(&held_mutexes_[0], 0, sizeof(held_mutexes_)); 924dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes} 925dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes 9267dc5166ea740359d381097a7ab382c1dd404055fElliott Hughesbool Thread::IsStillStarting() const { 9277dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes // You might think you can check whether the state is kStarting, but for much of thread startup, 9287dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes // the thread might also be in kVmWait. 9297dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes // You might think you can check whether the peer is NULL, but the peer is actually created and 9307dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes // assigned fairly early on, and needs to be. 9317dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes // It turns out that the last thing to change is the thread name; that's a good proxy for "has 9327dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes // this thread _ever_ entered kRunnable". 9337dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes return (*name_ == kThreadNameDuringStartup); 9347dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes} 9357dc5166ea740359d381097a7ab382c1dd404055fElliott Hughes 936ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic void MonitorExitVisitor(const Object* object, void*) { 93702b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes Object* entered_monitor = const_cast<Object*>(object); 938ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughes LOG(WARNING) << "Calling MonitorExit on object " << object << " (" << PrettyTypeOf(object) << ")" 939ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughes << " left locked by native thread " << *Thread::Current() << " which is detaching"; 9405f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes entered_monitor->MonitorExit(Thread::Current()); 94102b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes} 94202b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 943c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughesvoid Thread::Destroy() { 94402b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes // On thread detach, all monitors entered with JNI MonitorEnter are automatically exited. 94593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes if (jni_env_ != NULL) { 94693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes jni_env_->monitors.VisitRoots(MonitorExitVisitor, NULL); 94793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes } 94802b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 94929f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (peer_ != NULL) { 950c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes Thread* self = this; 95129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes 952534da072d3db3beecbd74e5aa23d630d73695f2cElliott Hughes // We may need to call user-supplied managed code. 95334e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes SetState(kRunnable); 954534da072d3db3beecbd74e5aa23d630d73695f2cElliott Hughes 955534da072d3db3beecbd74e5aa23d630d73695f2cElliott Hughes HandleUncaughtExceptions(); 956534da072d3db3beecbd74e5aa23d630d73695f2cElliott Hughes RemoveFromThreadGroup(); 957534da072d3db3beecbd74e5aa23d630d73695f2cElliott Hughes 95829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // this.vmData = 0; 95993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes SetVmData(peer_, NULL); 96002b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 961c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes Dbg::PostThreadDeath(self); 96202b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 96329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // Thread.join() is implemented as an Object.wait() on the Thread.lock 96429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // object. Signal anyone who is waiting. 965038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Object* lock = gThread_lock->GetObject(peer_); 966038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // (This conditional is only needed for tests, where Thread.lock won't have been set.) 9675f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes if (lock != NULL) { 9685f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes lock->MonitorEnter(self); 9695f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes lock->NotifyAll(); 9705f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes lock->MonitorExit(self); 9715f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes } 9725f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes } 973c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes} 97402b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 975c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott HughesThread::~Thread() { 976c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes delete jni_env_; 97702b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes jni_env_ = NULL; 97802b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 97934e069606d6f1698cd3c33b39e72b79ae27e1c7bElliott Hughes SetState(kTerminated); 98085d1545e985ac689db4bad7849880e843707c862Elliott Hughes 98185d1545e985ac689db4bad7849880e843707c862Elliott Hughes delete wait_cond_; 98285d1545e985ac689db4bad7849880e843707c862Elliott Hughes delete wait_mutex_; 98385d1545e985ac689db4bad7849880e843707c862Elliott Hughes 984776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 98585d1545e985ac689db4bad7849880e843707c862Elliott Hughes delete long_jump_context_; 986776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 987475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 988475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes delete debug_invoke_req_; 989e343b76af81a005ef64f5e75a555389fd9147dabjeffhao delete trace_stack_; 990899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes delete name_; 991d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes 992d8af1592a97f7447ecf93f85098cb36340ab0fe2Elliott Hughes TearDownAlternateSignalStack(); 993c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 994c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 995accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughesvoid Thread::HandleUncaughtExceptions() { 996accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes if (!IsExceptionPending()) { 997accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes return; 998accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes } 999accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 1000accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes // Get and clear the exception. 1001accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes Object* exception = GetException(); 1002accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes ClearException(); 1003accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 1004accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes // If the thread has its own handler, use that. 1005accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes Object* handler = gThread_uncaughtHandler->GetObject(peer_); 1006accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes if (handler == NULL) { 1007accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes // Otherwise use the thread group's default handler. 1008a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes handler = GetThreadGroup(); 1009accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes } 1010accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 1011accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes // Call the handler. 1012accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes Method* m = handler->GetClass()->FindVirtualMethodForVirtualOrInterface(gUncaughtExceptionHandler_uncaughtException); 101377405796564c6c1353807cda18b28678a719bd68Elliott Hughes JValue args[2]; 1014f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes args[0].SetL(peer_); 1015f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes args[1].SetL(exception); 101677405796564c6c1353807cda18b28678a719bd68Elliott Hughes m->Invoke(this, handler, args, NULL); 1017accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 1018accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes // If the handler threw, clear that exception too. 1019accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes ClearException(); 1020accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes} 10214514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom 1022a215526d5c789cbef0f81a1f9aba22541a841ccaElliott HughesObject* Thread::GetThreadGroup() const { 1023a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return gThread_group->GetObject(peer_); 1024a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes} 1025a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 10264514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstromvoid Thread::RemoveFromThreadGroup() { 10274514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom // this.group.removeThread(this); 10284514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom // group can be null if we're in the compiler or a test. 1029a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Object* group = GetThreadGroup(); 10304514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom if (group != NULL) { 10314514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom Method* m = group->GetClass()->FindVirtualMethodForVirtualOrInterface(gThreadGroup_removeThread); 103277405796564c6c1353807cda18b28678a719bd68Elliott Hughes JValue args[1]; 1033f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes args[0].SetL(peer_); 103477405796564c6c1353807cda18b28678a719bd68Elliott Hughes m->Invoke(this, group, args, NULL); 10354514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom } 10364514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom} 1037accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 1038408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogerssize_t Thread::NumSirtReferences() { 1039a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t count = 0; 104040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) { 1041a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers count += cur->NumberOfReferences(); 1042a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 1043a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return count; 1044a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 1045a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 104628f1a147d77ec772db98bed890b50a9ddcff2365TDYasize_t Thread::NumShadowFrameReferences() { 104728f1a147d77ec772db98bed890b50a9ddcff2365TDYa size_t count = 0; 104828f1a147d77ec772db98bed890b50a9ddcff2365TDYa for (ShadowFrame* cur = top_shadow_frame_; cur; cur = cur->GetLink()) { 104928f1a147d77ec772db98bed890b50a9ddcff2365TDYa count += cur->NumberOfReferences(); 105028f1a147d77ec772db98bed890b50a9ddcff2365TDYa } 105128f1a147d77ec772db98bed890b50a9ddcff2365TDYa return count; 105228f1a147d77ec772db98bed890b50a9ddcff2365TDYa} 105328f1a147d77ec772db98bed890b50a9ddcff2365TDYa 1054408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogersbool Thread::SirtContains(jobject obj) { 1055408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object** sirt_entry = reinterpret_cast<Object**>(obj); 105640381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) { 105740381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom if (cur->Contains(sirt_entry)) { 1058a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return true; 1059a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 1060a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 1061a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return false; 1062a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 1063a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 106428f1a147d77ec772db98bed890b50a9ddcff2365TDYabool Thread::ShadowFrameContains(jobject obj) { 106528f1a147d77ec772db98bed890b50a9ddcff2365TDYa Object** shadow_frame_entry = reinterpret_cast<Object**>(obj); 106628f1a147d77ec772db98bed890b50a9ddcff2365TDYa for (ShadowFrame* cur = top_shadow_frame_; cur; cur = cur->GetLink()) { 106728f1a147d77ec772db98bed890b50a9ddcff2365TDYa if (cur->Contains(shadow_frame_entry)) { 106828f1a147d77ec772db98bed890b50a9ddcff2365TDYa return true; 106928f1a147d77ec772db98bed890b50a9ddcff2365TDYa } 107028f1a147d77ec772db98bed890b50a9ddcff2365TDYa } 107128f1a147d77ec772db98bed890b50a9ddcff2365TDYa return false; 107228f1a147d77ec772db98bed890b50a9ddcff2365TDYa} 107328f1a147d77ec772db98bed890b50a9ddcff2365TDYa 107428f1a147d77ec772db98bed890b50a9ddcff2365TDYabool Thread::StackReferencesContain(jobject obj) { 107528f1a147d77ec772db98bed890b50a9ddcff2365TDYa return SirtContains(obj) || ShadowFrameContains(obj); 107628f1a147d77ec772db98bed890b50a9ddcff2365TDYa} 107728f1a147d77ec772db98bed890b50a9ddcff2365TDYa 10788dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liaovoid Thread::SirtVisitRoots(Heap::RootVisitor* visitor, void* arg) { 107940381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->GetLink()) { 10808dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao size_t num_refs = cur->NumberOfReferences(); 10818dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao for (size_t j = 0; j < num_refs; j++) { 108240381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom Object* object = cur->GetReference(j); 10835e73f9c8990819054f8e0a60061ee8beff1e024aBrian Carlstrom if (object != NULL) { 10845e73f9c8990819054f8e0a60061ee8beff1e024aBrian Carlstrom visitor(object, arg); 10855e73f9c8990819054f8e0a60061ee8beff1e024aBrian Carlstrom } 10868dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao } 10878dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao } 10888dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao} 10898dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao 1090f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chienvoid Thread::ShadowFrameVisitRoots(Heap::RootVisitor* visitor, void* arg) { 1091f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien for (ShadowFrame* cur = top_shadow_frame_; cur; cur = cur->GetLink()) { 1092f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien size_t num_refs = cur->NumberOfReferences(); 1093f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien for (size_t j = 0; j < num_refs; j++) { 1094f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien Object* object = cur->GetReference(j); 1095f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien if (object != NULL) { 1096f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien visitor(object, arg); 1097f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien } 1098f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien } 1099f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien } 1100f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien} 1101f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien 1102408f79aeb676251ba35667a64e86c20638d7cb0bIan RogersObject* Thread::DecodeJObject(jobject obj) { 11030cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers DCHECK(CanAccessDirectReferences()); 1104408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (obj == NULL) { 1105408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 1106408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1107408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRef ref = reinterpret_cast<IndirectRef>(obj); 1108408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRefKind kind = GetIndirectRefKind(ref); 1109408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object* result; 1110408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers switch (kind) { 1111408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kLocal: 1112408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 111369f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes IndirectReferenceTable& locals = jni_env_->locals; 1114cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes result = const_cast<Object*>(locals.Get(ref)); 1115408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 1116408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1117408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kGlobal: 1118408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 1119408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 1120408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& globals = vm->globals; 1121408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->globals_lock); 1122cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes result = const_cast<Object*>(globals.Get(ref)); 1123408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 1124408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1125408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kWeakGlobal: 1126408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 1127408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 1128408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& weak_globals = vm->weak_globals; 1129408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->weak_globals_lock); 1130cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes result = const_cast<Object*>(weak_globals.Get(ref)); 1131408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == kClearedJniWeakGlobal) { 1132408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // This is a special case where it's okay to return NULL. 1133408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 1134408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1135408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 1136408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1137408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kSirtOrInvalid: 1138408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers default: 1139408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // TODO: make stack indirect reference table lookup more efficient 1140408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Check if this is a local reference in the SIRT 114128f1a147d77ec772db98bed890b50a9ddcff2365TDYa if (StackReferencesContain(obj)) { 11420cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers result = *reinterpret_cast<Object**>(obj); // Read from SIRT 1143c2dc62d1c9241dfe880a81698713c314b13aa63fElliott Hughes } else if (Runtime::Current()->GetJavaVM()->work_around_app_jni_bugs) { 1144408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Assume an invalid local reference is actually a direct pointer. 1145408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = reinterpret_cast<Object*>(obj); 1146408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } else { 1147a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes result = kInvalidIndirectRefObject; 1148408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1149408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1150408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 1151408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == NULL) { 1152a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes LOG(ERROR) << "JNI ERROR (app bug): use of deleted " << kind << ": " << obj; 1153a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes JniAbort(NULL); 1154a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 1155a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (result != kInvalidIndirectRefObject) { 1156b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes Runtime::Current()->GetHeap()->VerifyObject(result); 1157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1158408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1159408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return result; 1160408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers} 1161408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 11629b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liaoclass CountStackDepthVisitor : public Thread::StackVisitor { 11639b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public: 116429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes CountStackDepthVisitor() : depth_(0), skip_depth_(0), skipping_(true) {} 1165d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 11661bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes bool VisitFrame(const Frame& frame, uintptr_t /*pc*/) { 116729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // We want to skip frames up to and including the exception's constructor. 11689086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // Note we also skip the frame if it doesn't have a method (namely the callee 11699086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // save frame) 11705167c97a4f672ba821453418e3943988fabbfc43Ian Rogers if (skipping_ && frame.HasMethod() && 11715167c97a4f672ba821453418e3943988fabbfc43Ian Rogers !Throwable::GetJavaLangThrowable()->IsAssignableFrom(frame.GetMethod()->GetDeclaringClass())) { 117229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes skipping_ = false; 117329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 117429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (!skipping_) { 11756b0870dfaaa2e69a900ad7ed88e4e1d3697445aaIan Rogers if (frame.HasMethod()) { // ignore callee save frames 11766b0870dfaaa2e69a900ad7ed88e4e1d3697445aaIan Rogers ++depth_; 11776b0870dfaaa2e69a900ad7ed88e4e1d3697445aaIan Rogers } 117829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } else { 117929f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes ++skip_depth_; 118029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 1181530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 11829b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11839b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 11849b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao int GetDepth() const { 1185aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers return depth_; 11869b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11879b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 118829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes int GetSkipDepth() const { 118929f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes return skip_depth_; 119029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 119129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes 11929b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao private: 1193aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers uint32_t depth_; 119429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes uint32_t skip_depth_; 119529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes bool skipping_; 11969b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao}; 11979b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1198aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogersclass BuildInternalStackTraceVisitor : public Thread::StackVisitor { 11999b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public: 1200283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers explicit BuildInternalStackTraceVisitor(int skip_depth) 1201726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes : skip_depth_(skip_depth), count_(0), pc_trace_(NULL), method_trace_(NULL), local_ref_(NULL) { 1202283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers } 1203283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers 1204283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers bool Init(int depth, ScopedJniThreadState& ts) { 1205aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Allocate method trace with an extra slot that will hold the PC trace 120601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes method_trace_ = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(depth + 1); 1207726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes if (method_trace_ == NULL) { 1208283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers return false; 1209726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes } 1210aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Register a local reference as IntArray::Alloc may trigger GC 1211aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers local_ref_ = AddLocalReference<jobject>(ts.Env(), method_trace_); 1212aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers pc_trace_ = IntArray::Alloc(depth); 1213726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes if (pc_trace_ == NULL) { 1214283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers return false; 1215726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes } 1216aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#ifdef MOVING_GARBAGE_COLLECTOR 1217aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Re-read after potential GC 1218267364429db05d964c0922a8b4e49591c00bdc35Brian Carlstrom method_trace_ = Decode<ObjectArray<Object>*>(ts.Env(), local_ref_); 1219aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#endif 1220aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Save PC trace in last element of method trace, also places it into the 1221aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // object graph. 1222aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method_trace_->Set(depth, pc_trace_); 1223283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers return true; 12249b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 12259b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1226aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers virtual ~BuildInternalStackTraceVisitor() {} 12279b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1228530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes bool VisitFrame(const Frame& frame, uintptr_t pc) { 1229726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes if (method_trace_ == NULL || pc_trace_ == NULL) { 1230530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; // We're probably trying to fillInStackTrace for an OutOfMemoryError. 1231726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes } 123229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (skip_depth_ > 0) { 123329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes skip_depth_--; 1234530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 123529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 12366b0870dfaaa2e69a900ad7ed88e4e1d3697445aaIan Rogers if (!frame.HasMethod()) { 1237530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; // ignore callee save frames 12386b0870dfaaa2e69a900ad7ed88e4e1d3697445aaIan Rogers } 1239aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method_trace_->Set(count_, frame.GetMethod()); 1240bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers pc_trace_->Set(count_, pc); 1241aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ++count_; 1242530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 12439b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 12449b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1245aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers jobject GetInternalStackTrace() const { 1246aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers return local_ref_; 12479b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 12489b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 12499b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao private: 125029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // How many more frames to skip. 125129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes int32_t skip_depth_; 1252aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Current position down stack trace 1253aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers uint32_t count_; 1254aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Array of return PC values 1255aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers IntArray* pc_trace_; 1256aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // An array of the methods on the stack, the last entry is a reference to the 1257aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // PC trace 1258aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ObjectArray<Object>* method_trace_; 1259aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Local indirect reference table entry for method trace 1260aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers jobject local_ref_; 12619b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao}; 12629b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1263776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 1264a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes// TODO: remove this. 1265ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic uintptr_t ManglePc(uintptr_t pc) { 1266a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes // Move the PC back 2 bytes as a call will frequently terminate the 1267a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes // decoding of a particular instruction and we want to make sure we 1268a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes // get the Dex PC of the instruction with the call and not the 1269a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes // instruction following. 1270a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes if (pc > 0) { pc -= 2; } 1271a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes return pc; 1272a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes} 1273776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 1274a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes 1275a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes// TODO: remove this. 1276ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic uintptr_t DemanglePc(uintptr_t pc) { 1277a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes // Revert mangling for the case where we need the PC to return to the upcall 12789a8a8889418e09bf2d4ae3f683fbb40a71c3c8f4Ian Rogers if (pc > 0) { pc += 2; } 12799a8a8889418e09bf2d4ae3f683fbb40a71c3c8f4Ian Rogers return pc; 1280a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes} 1281f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers 1282f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chienvoid Thread::PushShadowFrame(ShadowFrame* frame) { 1283f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien frame->SetLink(top_shadow_frame_); 1284f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien top_shadow_frame_ = frame; 1285f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien} 1286f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien 1287f7ad17e108b9357d7c94c6218a8521140a667f3dLogan ChienShadowFrame* Thread::PopShadowFrame() { 1288f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien CHECK(top_shadow_frame_ != NULL); 1289f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien ShadowFrame* frame = top_shadow_frame_; 1290f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien top_shadow_frame_ = frame->GetLink(); 1291f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien return frame; 1292f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien} 1293f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien 129440381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstromvoid Thread::PushSirt(StackIndirectReferenceTable* sirt) { 129540381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom sirt->SetLink(top_sirt_); 129640381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom top_sirt_ = sirt; 129740381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom} 129840381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom 129940381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian CarlstromStackIndirectReferenceTable* Thread::PopSirt() { 130040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom CHECK(top_sirt_ != NULL); 130140381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom StackIndirectReferenceTable* sirt = top_sirt_; 130240381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom top_sirt_ = top_sirt_->GetLink(); 130340381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom return sirt; 130440381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom} 130540381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom 13069b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa#if !defined(ART_USE_LLVM_COMPILER) // LLVM use ShadowFrame 13079b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa 1308530fa005e2944d3b12712f80d974f0e753f568efElliott Hughesvoid Thread::WalkStack(StackVisitor* visitor, bool include_upcalls) const { 1309d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes Frame frame = GetTopOfStack(); 1310a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes uintptr_t pc = ManglePc(top_of_managed_stack_pc_); 1311a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao uint32_t trace_stack_depth = 0; 13129b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao // TODO: enable this CHECK after native_to_managed_record_ is initialized during startup. 13139b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao // CHECK(native_to_managed_record_ != NULL); 13149b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao NativeToManagedRecord* record = native_to_managed_record_; 131557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers bool method_tracing_active = Runtime::Current()->IsMethodTracingActive(); 1316530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes while (frame.GetSP() != NULL) { 1317530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes for ( ; frame.GetMethod() != NULL; frame.Next()) { 1318f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom frame.GetMethod()->AssertPcIsWithinCode(pc); 1319530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes bool should_continue = visitor->VisitFrame(frame, pc); 132057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(!should_continue)) { 1321530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return; 1322530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } 132357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers uintptr_t return_pc = frame.GetReturnPC(); 132457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (LIKELY(!method_tracing_active)) { 132557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers pc = ManglePc(return_pc); 132657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 13270791adc2249366c50684935a4c42ba5e58bc3746jeffhao // While profiling, the return pc is restored from the side stack, except when walking 13280791adc2249366c50684935a4c42ba5e58bc3746jeffhao // the stack for an exception where the side stack will be unwound in VisitFrame. 13290791adc2249366c50684935a4c42ba5e58bc3746jeffhao if (IsTraceExitPc(return_pc) && !include_upcalls) { 1330a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao TraceStackFrame trace_frame = GetTraceStackFrame(trace_stack_depth++); 133126c0a1a376d8cd639fe6b16594fcb55a723450c0jeffhao CHECK(trace_frame.method_ == frame.GetMethod()); 1332a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao pc = ManglePc(trace_frame.return_pc_); 133357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 133457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers pc = ManglePc(return_pc); 1335a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 1336a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 13379b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 1338530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes if (include_upcalls) { 1339530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes bool should_continue = visitor->VisitFrame(frame, pc); 1340530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes if (!should_continue) { 1341530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return; 1342530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } 1343530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } 13449b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao if (record == NULL) { 1345530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return; 13469b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 1347bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // last_tos should return Frame instead of sp? 1348ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers frame.SetSP(reinterpret_cast<Method**>(record->last_top_of_managed_stack_)); 1349a43cb5e8fb29989dbb986b9b91a68cda150aa3c8Elliott Hughes pc = ManglePc(record->last_top_of_managed_stack_pc_); 1350bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers record = record->link_; 1351bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 1352bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 1353bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 13549b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa#else // defined(ART_USE_LLVM_COMPILER) // LLVM uses ShadowFrame 13559b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa 13569b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYavoid Thread::WalkStack(StackVisitor* visitor, bool /*include_upcalls*/) const { 13579b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa for (ShadowFrame* cur = top_shadow_frame_; cur; cur = cur->GetLink()) { 13589b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa Frame frame; 13599b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa frame.SetSP(reinterpret_cast<Method**>(reinterpret_cast<byte*>(cur) + 13609b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa ShadowFrame::MethodOffset())); 1361c8dc101f8e89feb588de3326bd9be0b84228ca2aTDYa bool should_continue = visitor->VisitFrame(frame, cur->GetDexPC()); 13629b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa if (!should_continue) { 13639b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa return; 13649b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa } 13659b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa } 13669b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa} 13679b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa 13689b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa/* 13699b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | | 13709b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | | 13719b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | | 13729b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 13739b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 13749b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 13759b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 13769b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | Method* | 13779b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 13789b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | <-- top_shadow_frame_ (ShadowFrame*) 13799b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * / +------------------------+ 13809b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * ->| . | 13819b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * . | . | 13829b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * . | . | 13839b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * /+------------------------+ 13849b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * / | . | 13859b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * / | . | 13869b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * --- | | . | 13879b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | | | . | 13889b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | | Method* | <-- frame.GetSP() (Method**) 13899b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * ShadowFrame \ | . | 13909b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | ->| . | <-- cur (ShadowFrame*) 13919b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * --- /+------------------------+ 13929b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * / | . | 13939b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * / | . | 13949b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * --- | | . | 13959b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | cur->GetLink() | | . | 13969b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | | Method* | 13979b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * ShadowFrame \ | . | 13989b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | ->| . | 13999b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * --- +------------------------+ 14009b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 14019b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 14029b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * | . | 14039b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa * +========================+ 14049b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa */ 14059b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa 14069b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa#endif 14079b2ba2ee9fafe46a08473657a2387fd20ab49a35TDYa 140801158d7a57c8321370667a6045220237d16e0da8Elliott Hughesjobject Thread::CreateInternalStackTrace(JNIEnv* env) const { 1409aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Compute depth of stack 14109b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao CountStackDepthVisitor count_visitor; 14119b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao WalkStack(&count_visitor); 14129b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao int32_t depth = count_visitor.GetDepth(); 141329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes int32_t skip_depth = count_visitor.GetSkipDepth(); 14144417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 1415aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Transition into runnable state to work on Object*/Array* 141601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes ScopedJniThreadState ts(env); 1417aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 1418aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Build internal stack trace 141977f74c1455bd8d29deb8a9367cea35deb930ed10Ian Rogers BuildInternalStackTraceVisitor build_trace_visitor(skip_depth); 142077f74c1455bd8d29deb8a9367cea35deb930ed10Ian Rogers if (!build_trace_visitor.Init(depth, ts)) { 1421283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers return NULL; // Allocation failed 1422283ed0d9db3084d0fee46d47cd73bf84bd0cfc16Ian Rogers } 1423267364429db05d964c0922a8b4e49591c00bdc35Brian Carlstrom WalkStack(&build_trace_visitor); 1424267364429db05d964c0922a8b4e49591c00bdc35Brian Carlstrom return build_trace_visitor.GetInternalStackTrace(); 1425aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers} 1426aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 142701158d7a57c8321370667a6045220237d16e0da8Elliott HughesjobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, jobject internal, 142801158d7a57c8321370667a6045220237d16e0da8Elliott Hughes jobjectArray output_array, int* stack_depth) { 1429aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Transition into runnable state to work on Object*/Array* 1430aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ScopedJniThreadState ts(env); 1431aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Decode the internal stack trace into the depth, method trace and PC trace 1432aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ObjectArray<Object>* method_trace = 1433aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers down_cast<ObjectArray<Object>*>(Decode<Object*>(ts.Env(), internal)); 14349074b99bfbd5419e340f138a018b673ce71f77e8Ian Rogers int32_t depth = method_trace->GetLength() - 1; 1435aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); 1436aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 1437aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 1438aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 143901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes jobjectArray result; 144001158d7a57c8321370667a6045220237d16e0da8Elliott Hughes ObjectArray<StackTraceElement>* java_traces; 144101158d7a57c8321370667a6045220237d16e0da8Elliott Hughes if (output_array != NULL) { 144201158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // Reuse the array we were given. 144301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes result = output_array; 144401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes java_traces = reinterpret_cast<ObjectArray<StackTraceElement>*>(Decode<Array*>(env, 144501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes output_array)); 144601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // ...adjusting the number of frames we'll write to not exceed the array length. 144701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes depth = std::min(depth, java_traces->GetLength()); 144801158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } else { 144901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // Create java_trace array and place in local reference table 145001158d7a57c8321370667a6045220237d16e0da8Elliott Hughes java_traces = class_linker->AllocStackTraceElementArray(depth); 145130646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes if (java_traces == NULL) { 145230646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes return NULL; 145330646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes } 145401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes result = AddLocalReference<jobjectArray>(ts.Env(), java_traces); 145501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } 145601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes 145701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes if (stack_depth != NULL) { 145801158d7a57c8321370667a6045220237d16e0da8Elliott Hughes *stack_depth = depth; 145901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } 146055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 14616d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper mh; 14629b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao for (int32_t i = 0; i < depth; ++i) { 1463aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Prepare parameters for StackTraceElement(String cls, String method, String file, int line) 1464aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers Method* method = down_cast<Method*>(method_trace->Get(i)); 14656d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers mh.ChangeMethod(method); 1466aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers uint32_t native_pc = pc_trace->Get(i); 14676d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers int32_t line_number = mh.GetLineNumFromNativePC(native_pc); 1468aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Allocate element, potentially triggering GC 146940381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom // TODO: reuse class_name_object via Class::name_? 1470486013193c94b4321414c28ce9251911e14a0599Ian Rogers const char* descriptor = mh.GetDeclaringClassDescriptor(); 1471486013193c94b4321414c28ce9251911e14a0599Ian Rogers CHECK(descriptor != NULL); 1472486013193c94b4321414c28ce9251911e14a0599Ian Rogers std::string class_name(PrettyDescriptor(descriptor)); 147340381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom SirtRef<String> class_name_object(String::AllocFromModifiedUtf8(class_name.c_str())); 147440381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom if (class_name_object.get() == NULL) { 147540381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom return NULL; 147640381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom } 1477486013193c94b4321414c28ce9251911e14a0599Ian Rogers const char* method_name = mh.GetName(); 1478486013193c94b4321414c28ce9251911e14a0599Ian Rogers CHECK(method_name != NULL); 1479486013193c94b4321414c28ce9251911e14a0599Ian Rogers SirtRef<String> method_name_object(String::AllocFromModifiedUtf8(method_name)); 14806d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (method_name_object.get() == NULL) { 14816d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers return NULL; 14826d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } 1483486013193c94b4321414c28ce9251911e14a0599Ian Rogers const char* source_file = mh.GetDeclaringClassSourceFile(); 1484486013193c94b4321414c28ce9251911e14a0599Ian Rogers SirtRef<String> source_name_object(String::AllocFromModifiedUtf8(source_file)); 148540381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom StackTraceElement* obj = StackTraceElement::Alloc(class_name_object.get(), 14866d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers method_name_object.get(), 14876d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers source_name_object.get(), 148840381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom line_number); 148930646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes if (obj == NULL) { 149030646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes return NULL; 149130646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes } 1492aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#ifdef MOVING_GARBAGE_COLLECTOR 1493aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Re-read after potential GC 1494aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers java_traces = Decode<ObjectArray<Object>*>(ts.Env(), result); 1495aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method_trace = down_cast<ObjectArray<Object>*>(Decode<Object*>(ts.Env(), internal)); 1496aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); 1497aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#endif 149855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao java_traces->Set(i, obj); 149955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao } 1500aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers return result; 150155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao} 150255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 15035cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughesvoid Thread::ThrowNewExceptionF(const char* exception_class_descriptor, const char* fmt, ...) { 1504a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_list args; 1505a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_start(args, fmt); 15064a2b41793d18d402286ae37e9de4fd392bc75a08Elliott Hughes ThrowNewExceptionV(exception_class_descriptor, fmt, args); 1507a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_end(args); 15084a2b41793d18d402286ae37e9de4fd392bc75a08Elliott Hughes} 15094a2b41793d18d402286ae37e9de4fd392bc75a08Elliott Hughes 15104a2b41793d18d402286ae37e9de4fd392bc75a08Elliott Hughesvoid Thread::ThrowNewExceptionV(const char* exception_class_descriptor, const char* fmt, va_list ap) { 15114a2b41793d18d402286ae37e9de4fd392bc75a08Elliott Hughes std::string msg; 15124a2b41793d18d402286ae37e9de4fd392bc75a08Elliott Hughes StringAppendV(&msg, fmt, ap); 15135cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes ThrowNewException(exception_class_descriptor, msg.c_str()); 15145cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes} 151537f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes 15165cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughesvoid Thread::ThrowNewException(const char* exception_class_descriptor, const char* msg) { 1517e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception". 15180cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers CHECK_EQ('L', exception_class_descriptor[0]); 1519e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes std::string descriptor(exception_class_descriptor + 1); 15200cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers CHECK_EQ(';', descriptor[descriptor.length() - 1]); 1521e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes descriptor.erase(descriptor.length() - 1); 1522e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes 1523e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes JNIEnv* env = GetJniEnv(); 1524726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes ScopedLocalRef<jclass> exception_class(env, env->FindClass(descriptor.c_str())); 152530646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes if (exception_class.get() == NULL) { 152630646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes LOG(ERROR) << "Couldn't throw new " << descriptor << " because JNI FindClass failed: " 152730646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes << PrettyTypeOf(GetException()); 152830646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes CHECK(IsExceptionPending()); 152930646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes return; 153030646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes } 1531ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom if (!Runtime::Current()->IsStarted()) { 1532ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom // Something is trying to throw an exception without a started 1533ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom // runtime, which is the common case in the compiler. We won't be 1534ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom // able to invoke the constructor of the exception, so use 1535ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom // AllocObject which will not invoke a constructor. 1536ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom ScopedLocalRef<jthrowable> exception( 1537ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom env, reinterpret_cast<jthrowable>(env->AllocObject(exception_class.get()))); 1538ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom if (exception.get() != NULL) { 1539ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom ScopedJniThreadState ts(env); 1540ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom Throwable* t = reinterpret_cast<Throwable*>(ts.Self()->DecodeJObject(exception.get())); 154102fbef0e356ca43b2032044f870d59de4a4ae92aIan Rogers t->SetDetailMessage(String::AllocFromModifiedUtf8(msg)); 1542ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom ts.Self()->SetException(t); 1543ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom } else { 1544ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom LOG(ERROR) << "Couldn't throw new " << descriptor << " because JNI AllocObject failed: " 1545ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom << PrettyTypeOf(GetException()); 1546ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom CHECK(IsExceptionPending()); 1547ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom } 1548ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom return; 1549ebd1fd233c8e14f50844f15109ccd50b27079722Brian Carlstrom } 1550726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes int rc = env->ThrowNew(exception_class.get(), msg); 155130646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes if (rc != JNI_OK) { 155230646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes LOG(ERROR) << "Couldn't throw new " << descriptor << " because JNI ThrowNew failed: " 155330646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes << PrettyTypeOf(GetException()); 155430646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes CHECK(IsExceptionPending()); 155530646836b4a1c6e5e80ddaea246cf9669eaa0628Elliott Hughes } 1556a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes} 1557a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 15582ced6a534157d5d963693346904389c19775d2daElliott Hughesvoid Thread::ThrowOutOfMemoryError(const char* msg) { 15592ced6a534157d5d963693346904389c19775d2daElliott Hughes LOG(ERROR) << StringPrintf("Throwing OutOfMemoryError \"%s\"%s", 15602ced6a534157d5d963693346904389c19775d2daElliott Hughes msg, (throwing_OutOfMemoryError_ ? " (recursive case)" : "")); 1561726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes if (!throwing_OutOfMemoryError_) { 1562726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes throwing_OutOfMemoryError_ = true; 1563accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes ThrowNewException("Ljava/lang/OutOfMemoryError;", NULL); 1564418dfe7849f45535b5388a91bd7a16cfc20a612bElliott Hughes } else { 1565726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes SetException(pre_allocated_OutOfMemoryError_); 1566418dfe7849f45535b5388a91bd7a16cfc20a612bElliott Hughes } 1567726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes throwing_OutOfMemoryError_ = false; 156879082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes} 156979082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes 1570accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 1571498508c1187dc07d3eae5476784cde20f5224d93Elliott HughesThread* Thread::CurrentFromGdb() { 1572accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes return Thread::Current(); 1573accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes} 1574accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 1575accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughesvoid Thread::DumpFromGdb() const { 15766b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom std::ostringstream ss; 15776b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom Dump(ss); 1578955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string str(ss.str()); 15796b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom // log to stderr for debugging command line processes 15806b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom std::cerr << str; 15816b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom#ifdef HAVE_ANDROID_OS 15826b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom // log to logcat for debugging frameworks processes 15836b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom LOG(INFO) << str; 15846b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom#endif 1585accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes} 1586accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 158798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughesstruct EntryPointInfo { 158898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes uint32_t offset; 158998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes const char* name; 159098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes}; 159198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes#define ENTRY_POINT_INFO(x) { ENTRYPOINT_OFFSET(x), #x } 159298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughesstatic const EntryPointInfo gThreadEntryPointInfo[] = { 159398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pAllocArrayFromCode), 159498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pAllocArrayFromCodeWithAccessCheck), 159598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pAllocObjectFromCode), 159698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pAllocObjectFromCodeWithAccessCheck), 159798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCheckAndAllocArrayFromCode), 159898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCheckAndAllocArrayFromCodeWithAccessCheck), 159998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInstanceofNonTrivialFromCode), 160098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCanPutArrayElementFromCode), 160198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCheckCastFromCode), 160298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pDebugMe), 160398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pUpdateDebuggerFromCode), 160498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInitializeStaticStorage), 160598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInitializeTypeAndVerifyAccessFromCode), 160698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInitializeTypeFromCode), 160798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pResolveStringFromCode), 160898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pSet32Instance), 160998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pSet32Static), 161098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pSet64Instance), 161198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pSet64Static), 161298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pSetObjInstance), 161398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pSetObjStatic), 161498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pGet32Instance), 161598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pGet32Static), 161698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pGet64Instance), 161798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pGet64Static), 161898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pGetObjInstance), 161998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pGetObjStatic), 162098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pHandleFillArrayDataFromCode), 162198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pDecodeJObjectInThread), 162298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pFindNativeMethod), 162398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pLockObjectFromCode), 162498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pUnlockObjectFromCode), 162598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCmpgDouble), 162698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCmpgFloat), 162798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCmplDouble), 162898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCmplFloat), 162998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pDadd), 163098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pDdiv), 163198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pDmul), 163298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pDsub), 163398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pF2d), 163498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pFmod), 163598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pI2d), 163698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pL2d), 163798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pD2f), 163898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pFadd), 163998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pFdiv), 164098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pFmodf), 164198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pFmul), 164298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pFsub), 164398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pI2f), 164498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pL2f), 164598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pD2iz), 164698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pF2iz), 164798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pIdivmod), 164898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pD2l), 164998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pF2l), 165098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pLdiv), 165198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pLdivmod), 165298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pLmul), 165398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pShlLong), 165498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pShrLong), 165598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pUshrLong), 165698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pIndexOf), 165798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pMemcmp16), 165898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pStringCompareTo), 165998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pMemcpy), 166098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pUnresolvedDirectMethodTrampolineFromCode), 166198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInvokeDirectTrampolineWithAccessCheck), 166298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInvokeInterfaceTrampoline), 166398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInvokeInterfaceTrampolineWithAccessCheck), 166498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInvokeStaticTrampolineWithAccessCheck), 166598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInvokeSuperTrampolineWithAccessCheck), 166698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pInvokeVirtualTrampolineWithAccessCheck), 166798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pCheckSuspendFromCode), 166898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pTestSuspendFromCode), 166998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pDeliverException), 167098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pThrowAbstractMethodErrorFromCode), 167198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pThrowArrayBoundsFromCode), 167298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pThrowDivZeroFromCode), 167398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pThrowNoSuchMethodFromCode), 167498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pThrowNullPointerFromCode), 167598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pThrowStackOverflowFromCode), 167698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes ENTRY_POINT_INFO(pThrowVerificationErrorFromCode), 167798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes}; 167898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes#undef ENTRY_POINT_INFO 167998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes 168028fa76d17d741238da86dbdb47f721ae97c9eac8Elliott Hughesvoid Thread::DumpThreadOffset(std::ostream& os, uint32_t offset, size_t size_of_pointers) { 168128fa76d17d741238da86dbdb47f721ae97c9eac8Elliott Hughes CHECK_EQ(size_of_pointers, 4U); // TODO: support 64-bit targets. 168298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes 168398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes#define DO_THREAD_OFFSET(x) if (offset == static_cast<uint32_t>(OFFSETOF_VOLATILE_MEMBER(Thread, x))) { os << # x; return; } 168498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(card_table_); 168598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(exception_); 168698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(jni_env_); 168798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(self_); 168898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(stack_end_); 168998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(state_); 169098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(suspend_count_); 169198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(thin_lock_id_); 169298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(top_of_managed_stack_); 169398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(top_of_managed_stack_pc_); 169498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes DO_THREAD_OFFSET(top_sirt_); 169528fa76d17d741238da86dbdb47f721ae97c9eac8Elliott Hughes#undef DO_THREAD_OFFSET 169698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes 169798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes size_t entry_point_count = arraysize(gThreadEntryPointInfo); 169898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes CHECK_EQ(entry_point_count * size_of_pointers, sizeof(EntryPoints)); 169998e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes uint32_t expected_offset = OFFSETOF_MEMBER(Thread, entrypoints_); 170098e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes for (size_t i = 0; i < entry_point_count; ++i) { 170198e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes CHECK_EQ(gThreadEntryPointInfo[i].offset, expected_offset); 170298e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes expected_offset += size_of_pointers; 170398e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes if (gThreadEntryPointInfo[i].offset == offset) { 170498e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes os << gThreadEntryPointInfo[i].name; 170598e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes return; 170698e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes } 170798e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes } 170898e2017cac7ca554602480fcefabbbe630a4a39bElliott Hughes os << offset; 170928fa76d17d741238da86dbdb47f721ae97c9eac8Elliott Hughes} 171028fa76d17d741238da86dbdb47f721ae97c9eac8Elliott Hughes 1711bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersclass CatchBlockStackVisitor : public Thread::StackVisitor { 1712bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers public: 1713bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers CatchBlockStackVisitor(Class* to_find, Context* ljc) 171457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers : to_find_(to_find), long_jump_context_(ljc), native_method_count_(0), 171557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers method_tracing_active_(Runtime::Current()->IsMethodTracingActive()) { 171667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#ifndef NDEBUG 171767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_pc_ = 0xEBADC0DE; 171867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_frame_.SetSP(reinterpret_cast<Method**>(0xEBADF00D)); 171967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#endif 172067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 1721bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1722530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes bool VisitFrame(const Frame& fr, uintptr_t pc) { 1723530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes Method* method = fr.GetMethod(); 1724530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes if (method == NULL) { 1725530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes // This is the upcall, we remember the frame and last_pc so that we may 1726530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes // long jump to them 1727530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes handler_pc_ = DemanglePc(pc); 1728530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes handler_frame_ = fr; 172957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return false; // End stack walk. 1730530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } 1731530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes uint32_t dex_pc = DexFile::kDexNoIndex; 173257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (method->IsRuntimeMethod()) { 1733530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes // ignore callee save method 173457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers DCHECK(method->IsCalleeSaveMethod()); 1735530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } else if (method->IsNative()) { 1736530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes native_method_count_++; 1737530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } else { 17380791adc2249366c50684935a4c42ba5e58bc3746jeffhao // Unwind stack when an exception occurs during method tracing 173957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(method_tracing_active_)) { 1740776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 174157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (IsTraceExitPc(DemanglePc(pc))) { 1742530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes pc = ManglePc(TraceMethodUnwindFromCode(Thread::Current())); 1743530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } 1744776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#else 1745776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers UNIMPLEMENTED(FATAL); 1746776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 1747bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 1748530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes dex_pc = method->ToDexPC(pc); 1749530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes } 1750530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes if (dex_pc != DexFile::kDexNoIndex) { 1751530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes uint32_t found_dex_pc = method->FindCatchBlock(to_find_, dex_pc); 1752530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes if (found_dex_pc != DexFile::kDexNoIndex) { 1753530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes handler_pc_ = method->ToNativePC(found_dex_pc); 1754530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes handler_frame_ = fr; 175557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return false; // End stack walk. 1756bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 17571a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 1758776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 1759530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes // Caller may be handler, fill in callee saves in context 1760530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes long_jump_context_->FillCalleeSaves(fr); 1761776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 176257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return true; // Continue stack walk. 17631a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 17641a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 1765bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // The type of the exception catch block to find 1766bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Class* to_find_; 1767bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Frame with found handler or last frame if no handler found 1768bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Frame handler_frame_; 176967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // PC to branch to for the handler 177067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers uintptr_t handler_pc_; 1771bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Context that will be the target of the long jump 1772bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Context* long_jump_context_; 177367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // Number of native methods passed in crawl (equates to number of SIRTs to pop) 177467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers uint32_t native_method_count_; 177557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // Is method tracing active? 177657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers const bool method_tracing_active_; 1777bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers}; 1778bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1779ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogersvoid Thread::DeliverException() { 1780776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 178128ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers const bool kDebugExceptionDelivery = false; 1782d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Throwable* exception = GetException(); // Get exception from thread 1783ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers CHECK(exception != NULL); 178428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers // Don't leave exception visible while we try to find the handler, which may cause class 1785d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // resolution. 178628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers ClearException(); 178728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (kDebugExceptionDelivery) { 1788a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers String* msg = exception->GetDetailMessage(); 1789a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers std::string str_msg(msg != NULL ? msg->ToModifiedUtf8() : ""); 1790a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers DumpStack(LOG(INFO) << "Delivering exception: " << PrettyTypeOf(exception) 1791a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers << ": " << str_msg << std::endl); 179228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 1793bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1794bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Context* long_jump_context = GetLongJumpContext(); 1795bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers CatchBlockStackVisitor catch_finder(exception->GetClass(), long_jump_context); 1796530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes WalkStack(&catch_finder, true); 1797bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1798d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Method** sp; 1799d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes uintptr_t throw_native_pc; 1800d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Method* throw_method = GetCurrentMethod(&throw_native_pc, &sp); 1801d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes uintptr_t catch_native_pc = catch_finder.handler_pc_; 1802d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Method* catch_method = catch_finder.handler_frame_.GetMethod(); 1803d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Dbg::PostException(sp, throw_method, throw_native_pc, catch_method, catch_native_pc, exception); 1804d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 180528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (kDebugExceptionDelivery) { 1806d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (catch_method == NULL) { 180728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers LOG(INFO) << "Handler is upcall"; 180828ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } else { 180928ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 181028ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers const DexFile& dex_file = 1811d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes class_linker->FindDexFile(catch_method->GetDeclaringClass()->GetDexCache()); 1812d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes int line_number = dex_file.GetLineNumFromPC(catch_method, 1813d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes catch_method->ToDexPC(catch_finder.handler_pc_)); 1814d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes LOG(INFO) << "Handler: " << PrettyMethod(catch_method) << " (line: " << line_number << ")"; 181528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 181628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 181728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers SetException(exception); 18189a8a8889418e09bf2d4ae3f683fbb40a71c3c8f4Ian Rogers CHECK_NE(catch_native_pc, 0u); 1819d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes long_jump_context->SetSP(reinterpret_cast<uintptr_t>(catch_finder.handler_frame_.GetSP())); 18209a8a8889418e09bf2d4ae3f683fbb40a71c3c8f4Ian Rogers long_jump_context->SetPC(catch_native_pc); 18219c750f9b6283f62b3e6a93c0c6b2838abde5000eElliott Hughes long_jump_context->SmashCallerSaves(); 1822bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers long_jump_context->DoLongJump(); 1823776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 18249a8a8889418e09bf2d4ae3f683fbb40a71c3c8f4Ian Rogers LOG(FATAL) << "UNREACHABLE"; 1825bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 1826bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1827bdb0391258abc54bf77c676e36847d28a783bfe5Ian RogersContext* Thread::GetLongJumpContext() { 182885d1545e985ac689db4bad7849880e843707c862Elliott Hughes Context* result = long_jump_context_; 1829776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 1830bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers if (result == NULL) { 1831bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers result = Context::Create(); 183285d1545e985ac689db4bad7849880e843707c862Elliott Hughes long_jump_context_ = result; 18331a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 1834776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 1835bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers return result; 18361a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 18371a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 1838ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#if !defined(ART_USE_LLVM_COMPILER) 1839d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott HughesMethod* Thread::GetCurrentMethod(uintptr_t* pc, Method*** sp) const { 1840d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Frame f = top_of_managed_stack_; 1841d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Method* m = f.GetMethod(); 18428be2d40d42223b515de12629216151a558895969Elliott Hughes uintptr_t native_pc = top_of_managed_stack_pc_; 18438be2d40d42223b515de12629216151a558895969Elliott Hughes 18449fd66f5bb6a514147a53d57b419d18ecc7937122Elliott Hughes // We use JNI internally for exception throwing, so it's possible to arrive 18459fd66f5bb6a514147a53d57b419d18ecc7937122Elliott Hughes // here via a "FromCode" function, in which case there's a synthetic 18469fd66f5bb6a514147a53d57b419d18ecc7937122Elliott Hughes // callee-save method at the top of the stack. These shouldn't be user-visible, 18479fd66f5bb6a514147a53d57b419d18ecc7937122Elliott Hughes // so if we find one, skip it and return the compiled method underneath. 184833dc7717cd16592bcc825350bea6305be9eb2ea1jeffhao if (m != NULL && m->IsCalleeSaveMethod()) { 18498be2d40d42223b515de12629216151a558895969Elliott Hughes native_pc = f.GetReturnPC(); 18509fd66f5bb6a514147a53d57b419d18ecc7937122Elliott Hughes f.Next(); 18519fd66f5bb6a514147a53d57b419d18ecc7937122Elliott Hughes m = f.GetMethod(); 18529fd66f5bb6a514147a53d57b419d18ecc7937122Elliott Hughes } 1853d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (pc != NULL) { 18548be2d40d42223b515de12629216151a558895969Elliott Hughes *pc = (m != NULL) ? ManglePc(native_pc) : 0; 185533dc7717cd16592bcc825350bea6305be9eb2ea1jeffhao } 1856d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (sp != NULL) { 1857d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes *sp = f.GetSP(); 1858d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 1859d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes return m; 186033dc7717cd16592bcc825350bea6305be9eb2ea1jeffhao} 1861ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#else 1862ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYaMethod* Thread::GetCurrentMethod(uintptr_t*, Method***) const { 1863ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa ShadowFrame* frame = top_shadow_frame_; 186420efe54063f2740d16f01190b280cdba384c869bTDYa if (frame == NULL) { 186520efe54063f2740d16f01190b280cdba384c869bTDYa return NULL; 1866ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa } 1867ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa return frame->GetMethod(); 1868ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa} 1869ee0d3fb2fbd736484fe8c3177a4e965ea86d1c65TDYa#endif 187033dc7717cd16592bcc825350bea6305be9eb2ea1jeffhao 18715f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesbool Thread::HoldsLock(Object* object) { 18725f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes if (object == NULL) { 18735f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes return false; 18745f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes } 187524a3c2e9924e8765c4a9b4d383cb8f3b922f9c9fBrian Carlstrom return object->GetThinLockId() == thin_lock_id_; 18765f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes} 18775f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 1878038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesbool Thread::IsDaemon() { 1879038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes return gThread_daemon->GetBoolean(peer_); 1880038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes} 1881038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes 1882776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#if !defined(ART_USE_LLVM_COMPILER) 1883d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogersclass ReferenceMapVisitor : public Thread::StackVisitor { 1884d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers public: 1885d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers ReferenceMapVisitor(Context* context, Heap::RootVisitor* root_visitor, void* arg) : 1886d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers context_(context), root_visitor_(root_visitor), arg_(arg) { 1887d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 1888d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers 1889530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes bool VisitFrame(const Frame& frame, uintptr_t pc) { 1890d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers Method* m = frame.GetMethod(); 18916a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom if (false) { 1892250455229aa0cc07bbd18174efe510bd52631a99jeffhao LOG(INFO) << "Visiting stack roots in " << PrettyMethod(m) 18930dd7ddaa36a2cf37490dc166ebc21818364130a7Brian Carlstrom << StringPrintf("@ PC:%04x", m->ToDexPC(pc)); 18946a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom } 1895d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Process register map (which native and callee save methods don't have) 18963891c775503b1113a918180d9ecdaa79e92c69c6Ian Rogers if (!m->IsNative() && !m->IsCalleeSaveMethod() && !m->IsProxyMethod()) { 1897e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom CHECK(m->GetGcMap() != NULL) << PrettyMethod(m); 1898e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom CHECK_NE(0U, m->GetGcMapLength()) << PrettyMethod(m); 1899e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom verifier::PcToReferenceMap map(m->GetGcMap(), m->GetGcMapLength()); 1900d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers const uint8_t* reg_bitmap = map.FindBitMap(m->ToDexPC(pc)); 1901d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers CHECK(reg_bitmap != NULL); 190268fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes const VmapTable vmap_table(m->GetVmapTableRaw()); 190311d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); 19046d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers DCHECK(code_item != NULL); // can't be NULL or how would we compile its instructions? 19056d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers uint32_t core_spills = m->GetCoreSpillMask(); 19066d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers uint32_t fp_spills = m->GetFpSpillMask(); 19076d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers size_t frame_size = m->GetFrameSizeInBytes(); 19080dd7ddaa36a2cf37490dc166ebc21818364130a7Brian Carlstrom // For all dex registers in the bitmap 19096d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers size_t num_regs = std::min(map.RegWidth() * 8, 19106d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers static_cast<size_t>(code_item->registers_size_)); 19110dd7ddaa36a2cf37490dc166ebc21818364130a7Brian Carlstrom for (size_t reg = 0; reg < num_regs; ++reg) { 1912d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Does this register hold a reference? 1913d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers if (TestBitmap(reg, reg_bitmap)) { 191468fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes uint32_t vmap_offset; 1915d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers Object* ref; 191668fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes if (vmap_table.IsInContext(reg, vmap_offset)) { 1917d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Compute the register we need to load from the context 1918d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers uint32_t spill_mask = m->GetCoreSpillMask(); 19190dd7ddaa36a2cf37490dc166ebc21818364130a7Brian Carlstrom CHECK_LT(vmap_offset, static_cast<uint32_t>(__builtin_popcount(spill_mask))); 1920f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers uint32_t matches = 0; 1921f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers uint32_t spill_shifts = 0; 1922f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers while (matches != (vmap_offset + 1)) { 19230dd7ddaa36a2cf37490dc166ebc21818364130a7Brian Carlstrom DCHECK_NE(spill_mask, 0u); 1924f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers matches += spill_mask & 1; // Add 1 if the low bit is set 1925f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers spill_mask >>= 1; 1926f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers spill_shifts++; 1927d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 1928f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers spill_shifts--; // wind back one as we want the last match 1929f57c47c29cd3388d1d78008a71c4e18f2217b70cIan Rogers ref = reinterpret_cast<Object*>(context_->GetGPR(spill_shifts)); 1930d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } else { 19316d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers ref = reinterpret_cast<Object*>(frame.GetVReg(code_item, core_spills, fp_spills, 19326d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers frame_size, reg)); 1933d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 19344f894e385e8ac018f078be75fea0a45696626b15Shih-wei Liao if (ref != NULL) { 19354f894e385e8ac018f078be75fea0a45696626b15Shih-wei Liao root_visitor_(ref, arg_); 19364f894e385e8ac018f078be75fea0a45696626b15Shih-wei Liao } 1937d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 1938d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 1939d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 1940d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers context_->FillCalleeSaves(frame); 1941530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 1942d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 1943d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers 1944d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers private: 1945d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers bool TestBitmap(int reg, const uint8_t* reg_vector) { 1946d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0; 1947d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers } 1948d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers 1949d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Context used to build up picture of callee saves 1950d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers Context* context_; 1951d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Call-back when we visit a root 1952d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers Heap::RootVisitor* root_visitor_; 1953d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Argument to call-back 1954d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers void* arg_; 1955d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers}; 1956776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#endif 1957d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers 1958d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogersvoid Thread::VisitRoots(Heap::RootVisitor* visitor, void* arg) { 1959d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (exception_ != NULL) { 1960d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes visitor(exception_, arg); 1961d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 1962d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (peer_ != NULL) { 1963d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes visitor(peer_, arg); 1964d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 1965726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes if (pre_allocated_OutOfMemoryError_ != NULL) { 1966726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes visitor(pre_allocated_OutOfMemoryError_, arg); 1967726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes } 196840381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom if (class_loader_override_ != NULL) { 196940381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom visitor(class_loader_override_, arg); 197040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom } 1971410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes jni_env_->locals.VisitRoots(visitor, arg); 1972410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes jni_env_->monitors.VisitRoots(visitor, arg); 19738dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao 19748dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao SirtVisitRoots(visitor, arg); 1975f7ad17e108b9357d7c94c6218a8521140a667f3dLogan Chien ShadowFrameVisitRoots(visitor, arg); 19768dfc9d551a9603eb8bc8463621b7bc73c3035169Shih-wei Liao 1977540a5b768bf5f76bd71ebf66612fb2298899480fTDYa#if !defined(ART_USE_LLVM_COMPILER) 1978d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Cheat and steal the long jump context. Assume that we are not doing a GC during exception 1979d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // delivery. 1980d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers Context* context = GetLongJumpContext(); 1981d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers // Visit roots on this thread's stack 1982d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers ReferenceMapVisitor mapper(context, visitor, arg); 1983d6b1f6190c8ec42facb08aca34b093244774b318Ian Rogers WalkStack(&mapper); 1984540a5b768bf5f76bd71ebf66612fb2298899480fTDYa#endif 1985410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes} 1986410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 1987250455229aa0cc07bbd18174efe510bd52631a99jeffhao#if VERIFY_OBJECT_ENABLED 1988ab7b9dcbfc4264a0bc4889c3e463ff88a67f6a30Elliott Hughesstatic void VerifyObject(const Object* obj, void*) { 1989250455229aa0cc07bbd18174efe510bd52631a99jeffhao Runtime::Current()->GetHeap()->VerifyObject(obj); 1990250455229aa0cc07bbd18174efe510bd52631a99jeffhao} 1991250455229aa0cc07bbd18174efe510bd52631a99jeffhao 1992250455229aa0cc07bbd18174efe510bd52631a99jeffhaovoid Thread::VerifyStack() { 1993540a5b768bf5f76bd71ebf66612fb2298899480fTDYa#if !defined(ART_USE_LLVM_COMPILER) 1994e66ac79b90a12b01b9d67ee9f7f586e638e67fabjeffhao UniquePtr<Context> context(Context::Create()); 1995e66ac79b90a12b01b9d67ee9f7f586e638e67fabjeffhao ReferenceMapVisitor mapper(context.get(), VerifyObject, NULL); 1996250455229aa0cc07bbd18174efe510bd52631a99jeffhao WalkStack(&mapper); 1997540a5b768bf5f76bd71ebf66612fb2298899480fTDYa#endif 1998250455229aa0cc07bbd18174efe510bd52631a99jeffhao} 1999250455229aa0cc07bbd18174efe510bd52631a99jeffhao#endif 2000250455229aa0cc07bbd18174efe510bd52631a99jeffhao 2001330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread) { 2002899e789bd4741c0172268f7838ce8ab220a5f916Elliott Hughes thread.Dump(os, false); 2003330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes return os; 2004330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes} 2005330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 2006a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughesvoid Thread::CheckSafeToLockOrUnlock(MutexRank rank, bool is_locking) { 200717057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes if (this == NULL) { 200817057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes CHECK(Runtime::Current()->IsShuttingDown()); 200917057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes return; 201017057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes } 2011ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes if (is_locking) { 2012ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes if (held_mutexes_[rank] == 0) { 2013ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes bool bad_mutexes_held = false; 2014ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes for (int i = kMaxMutexRank; i > rank; --i) { 2015ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes if (held_mutexes_[i] != 0) { 2016ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes LOG(ERROR) << "holding " << static_cast<MutexRank>(i) << " while " << (is_locking ? "locking" : "unlocking") << " " << rank; 2017ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes bad_mutexes_held = true; 2018ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes } 2019ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes } 2020b5db3bb5b17f2bb42f3c62408938f4bf939f8a39Elliott Hughes CHECK(!bad_mutexes_held) << rank; 2021ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes } 2022ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes ++held_mutexes_[rank]; 2023ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes } else { 2024b5db3bb5b17f2bb42f3c62408938f4bf939f8a39Elliott Hughes CHECK_GT(held_mutexes_[rank], 0U) << rank; 2025ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes --held_mutexes_[rank]; 2026ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes } 2027ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes} 2028ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes 2029a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughesvoid Thread::CheckSafeToWait(MutexRank rank) { 203017057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes if (this == NULL) { 203117057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes CHECK(Runtime::Current()->IsShuttingDown()); 203217057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes return; 203317057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes } 2034a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes bool bad_mutexes_held = false; 2035a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes for (int i = kMaxMutexRank; i >= 0; --i) { 2036a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes if (i != rank && held_mutexes_[i] != 0) { 2037a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes LOG(ERROR) << "holding " << static_cast<MutexRank>(i) << " while doing condition variable wait on " << rank; 2038a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes bad_mutexes_held = true; 2039a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes } 2040a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes } 2041a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes if (held_mutexes_[rank] == 0) { 2042a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes LOG(ERROR) << "*not* holding " << rank << " while doing condition variable wait on it"; 2043a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes bad_mutexes_held = true; 2044a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes } 2045a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes CHECK(!bad_mutexes_held); 2046a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes} 2047a4060e5fe4729fa30bde965efc35779690478fa4Elliott Hughes 20488daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} // namespace art 2049