thread.cc revision 01158d7a57c8321370667a6045220237d16e0da8
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> 21b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <sys/mman.h> 22a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 23b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <algorithm> 24dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes#include <bitset> 25eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes#include <cerrno> 26a09576416788b916095739e43a16917e7948f3a4Elliott Hughes#include <iostream> 27b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <list> 28b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 29a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "class_linker.h" 30bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers#include "context.h" 31408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers#include "heap.h" 32c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h" 33a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "object.h" 34578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h" 355433072f589b61413e042eddf76e8190a048f71dbuzbee#include "runtime_support.h" 36aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#include "scoped_jni_thread_state.h" 378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "thread_list.h" 38a09576416788b916095739e43a16917e7948f3a4Elliott Hughes#include "utils.h" 39b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 40b557353b22c728eecbd1c68593b482622c7782a8Carl Shapironamespace art { 41b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 42b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiropthread_key_t Thread::pthread_key_self_; 43b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 4429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughesstatic Class* gThrowable = NULL; 45038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_daemon = NULL; 46038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_group = NULL; 47038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_lock = NULL; 48038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_name = NULL; 49038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_priority = NULL; 5029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughesstatic Field* gThread_uncaughtHandler = NULL; 51038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThread_vmData = NULL; 52038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Field* gThreadGroup_name = NULL; 53038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesstatic Method* gThread_run = NULL; 5429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughesstatic Method* gThreadGroup_removeThread = NULL; 5529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughesstatic Method* gUncaughtExceptionHandler_uncaughtException = NULL; 56038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes 574a3164faefd255b1c1e911e7ad7c3d57749caaf6buzbee// Temporary debugging hook for compiler. 58d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid DebugMe(Method* method, uint32_t info) { 5901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes LOG(INFO) << "DebugMe"; 6001158d7a57c8321370667a6045220237d16e0da8Elliott Hughes if (method != NULL) { 6101158d7a57c8321370667a6045220237d16e0da8Elliott Hughes LOG(INFO) << PrettyMethod(method); 6201158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } 6301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes LOG(INFO) << "Info: " << info; 644a3164faefd255b1c1e911e7ad7c3d57749caaf6buzbee} 654a3164faefd255b1c1e911e7ad7c3d57749caaf6buzbee 66bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} // namespace art 67bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 68bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// Called by generated call to throw an exception 6967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogersextern "C" void artDeliverExceptionHelper(art::Throwable* exception, 7067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers art::Thread* thread, 7167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers art::Method** sp) { 72d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes /* 73d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes * exception may be NULL, in which case this routine should 74d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes * throw NPE. NOTE: this is a convenience for generated code, 75d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes * which previously did the null check inline and constructed 76d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes * and threw a NPE if NULL. This routine responsible for setting 77bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers * exception_ in thread and delivering the exception. 78d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes */ 7967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // Place a special frame at the TOS that will save all callee saves 80bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers *sp = thread->CalleeSaveMethod(); 81bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers thread->SetTopOfStack(sp, 0); 8293dd9660955f1c0f068c57199c1945fc51fb84a7Ian Rogers if (exception == NULL) { 8393dd9660955f1c0f068c57199c1945fc51fb84a7Ian Rogers thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception"); 8493dd9660955f1c0f068c57199c1945fc51fb84a7Ian Rogers exception = thread->GetException(); 8593dd9660955f1c0f068c57199c1945fc51fb84a7Ian Rogers } 86bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers thread->DeliverException(exception); 871b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee} 881b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee 899651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers// Called by generated call to throw a NPE exception 909651f425f7413772a7b5352da2b04eb7de7d416fIan Rogersextern "C" void artThrowNullPointerExceptionFromCodeHelper(art::Thread* thread, 919651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers art::Method** sp) { 929651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers // Place a special frame at the TOS that will save all callee saves 939651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers *sp = thread->CalleeSaveMethod(); 949651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->SetTopOfStack(sp, 0); 959651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->ThrowNewException("Ljava/lang/NullPointerException;", "unexpected null reference"); 969651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers art::Throwable* exception = thread->GetException(); 979651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->DeliverException(exception); 989651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers} 999651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers 1009651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers// Called by generated call to throw an arithmetic divide by zero exception 1019651f425f7413772a7b5352da2b04eb7de7d416fIan Rogersextern "C" void artThrowDivZeroFromCodeHelper(art::Thread* thread, 1029651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers art::Method** sp) { 1039651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers // Place a special frame at the TOS that will save all callee saves 1049651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers *sp = thread->CalleeSaveMethod(); 1059651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->SetTopOfStack(sp, 0); 1069651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero"); 1079651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers art::Throwable* exception = thread->GetException(); 1089651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->DeliverException(exception); 1099651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers} 1109651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers 1119651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers// Called by generated call to throw an arithmetic divide by zero exception 1129651f425f7413772a7b5352da2b04eb7de7d416fIan Rogersextern "C" void artThrowArrayBoundsFromCodeHelper(int index, int limit, 1139651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers art::Thread* thread, 1149651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers art::Method** sp) { 1159651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers // Place a special frame at the TOS that will save all callee saves 1169651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers *sp = thread->CalleeSaveMethod(); 1179651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->SetTopOfStack(sp, 0); 1189651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;", 1199651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers "length=%d; index=%d", limit, index); 1209651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers art::Throwable* exception = thread->GetException(); 1219651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers thread->DeliverException(exception); 1229651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers} 1239651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers 124bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersnamespace art { 125bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1261b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee// TODO: placeholder. Helper function to type 127d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott HughesClass* InitializeTypeFromCode(uint32_t type_idx, Method* method) { 1281b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee /* 1291b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee * Should initialize & fix up method->dex_cache_resolved_types_[]. 1301b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee * Returns initialized type. Does not return normally if an exception 1311b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee * is thrown, but instead initiates the catch. Should be similar to 1321b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee * ClassLinker::InitializeStaticStorageFromCode. 1331b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee */ 1341b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee UNIMPLEMENTED(FATAL); 1351b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee return NULL; 1361b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee} 1371b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee 138561227c80077bbb4147f778043f1a836af6b9248buzbee// TODO: placeholder. Helper function to resolve virtual method 139d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ResolveMethodFromCode(Method* method, uint32_t method_idx) { 140561227c80077bbb4147f778043f1a836af6b9248buzbee /* 141561227c80077bbb4147f778043f1a836af6b9248buzbee * Slow-path handler on invoke virtual method path in which 142561227c80077bbb4147f778043f1a836af6b9248buzbee * base method is unresolved at compile-time. Doesn't need to 143561227c80077bbb4147f778043f1a836af6b9248buzbee * return anything - just either ensure that 144561227c80077bbb4147f778043f1a836af6b9248buzbee * method->dex_cache_resolved_methods_(method_idx) != NULL or 145561227c80077bbb4147f778043f1a836af6b9248buzbee * throw and unwind. The caller will restart call sequence 146561227c80077bbb4147f778043f1a836af6b9248buzbee * from the beginning. 147561227c80077bbb4147f778043f1a836af6b9248buzbee */ 148561227c80077bbb4147f778043f1a836af6b9248buzbee} 149561227c80077bbb4147f778043f1a836af6b9248buzbee 1501da522de18ac6e4c2913c3233529e9dd115059f8buzbee// TODO: placeholder. Helper function to alloc array for OP_FILLED_NEW_ARRAY 151d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott HughesArray* CheckAndAllocFromCode(uint32_t type_index, Method* method, int32_t component_count) { 1521da522de18ac6e4c2913c3233529e9dd115059f8buzbee /* 1531da522de18ac6e4c2913c3233529e9dd115059f8buzbee * Just a wrapper around Array::AllocFromCode() that additionally 1541da522de18ac6e4c2913c3233529e9dd115059f8buzbee * throws a runtime exception "bad Filled array req" for 'D' and 'J'. 1551da522de18ac6e4c2913c3233529e9dd115059f8buzbee */ 1561da522de18ac6e4c2913c3233529e9dd115059f8buzbee UNIMPLEMENTED(WARNING) << "Need check that not 'D' or 'J'"; 1571da522de18ac6e4c2913c3233529e9dd115059f8buzbee return Array::AllocFromCode(type_index, method, component_count); 1581da522de18ac6e4c2913c3233529e9dd115059f8buzbee} 1591da522de18ac6e4c2913c3233529e9dd115059f8buzbee 1602a475e7b93d754e0a7525bb5c7059386307ea63abuzbee// TODO: placeholder (throw on failure) 161d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid CheckCastFromCode(const Class* a, const Class* b) { 162c228252eb1bf859c6b976b9493269ea31b3c14c9Brian Carlstrom DCHECK(a->IsClass()); 163c228252eb1bf859c6b976b9493269ea31b3c14c9Brian Carlstrom DCHECK(b->IsClass()); 164c228252eb1bf859c6b976b9493269ea31b3c14c9Brian Carlstrom if (b->IsAssignableFrom(a)) { 165c228252eb1bf859c6b976b9493269ea31b3c14c9Brian Carlstrom return; 166c228252eb1bf859c6b976b9493269ea31b3c14c9Brian Carlstrom } 167c228252eb1bf859c6b976b9493269ea31b3c14c9Brian Carlstrom UNIMPLEMENTED(FATAL); 1682a475e7b93d754e0a7525bb5c7059386307ea63abuzbee} 1692a475e7b93d754e0a7525bb5c7059386307ea63abuzbee 170d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid UnlockObjectFromCode(Thread* thread, Object* obj) { 1718d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes // TODO: throw and unwind if lock not held 1728d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes // TODO: throw and unwind on NPE 1738d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes obj->MonitorExit(thread); 1742a475e7b93d754e0a7525bb5c7059386307ea63abuzbee} 1752a475e7b93d754e0a7525bb5c7059386307ea63abuzbee 176d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid LockObjectFromCode(Thread* thread, Object* obj) { 1778d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes obj->MonitorEnter(thread); 1788d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes // TODO: throw and unwind on failure. 1792a475e7b93d754e0a7525bb5c7059386307ea63abuzbee} 1802a475e7b93d754e0a7525bb5c7059386307ea63abuzbee 181d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid CheckSuspendFromCode(Thread* thread) { 1828d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes Runtime::Current()->GetThreadList()->FullSuspendCheck(thread); 1830d966cff87464544a264efdbfba6c379474d5928buzbee} 1840d966cff87464544a264efdbfba6c379474d5928buzbee 185cefd1878e09fb0fb519a175545a99eb8c4a375b2buzbee// TODO: placeholder 186d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid StackOverflowFromCode(Method* method) { 187fa3baf7998f0af9de067eadf1f3b9a0b45d13349Brian Carlstrom Thread::Current()->SetTopOfStackPC(reinterpret_cast<uintptr_t>(__builtin_return_address(0))); 188161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom Thread::Current()->Dump(std::cerr); 189d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes //NOTE: to save code space, this handler needs to look up its own Thread* 190d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes UNIMPLEMENTED(FATAL) << "Stack overflow: " << PrettyMethod(method); 191cefd1878e09fb0fb519a175545a99eb8c4a375b2buzbee} 192cefd1878e09fb0fb519a175545a99eb8c4a375b2buzbee 1935ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 194d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowNullPointerFromCode() { 195fa3baf7998f0af9de067eadf1f3b9a0b45d13349Brian Carlstrom Thread::Current()->SetTopOfStackPC(reinterpret_cast<uintptr_t>(__builtin_return_address(0))); 196d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes Thread::Current()->Dump(std::cerr); 197d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes //NOTE: to save code space, this handler must look up caller's Method* 198d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes UNIMPLEMENTED(FATAL) << "Null pointer exception"; 1995ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2005ade1d255ef1b5022321ac20493208703b34d2b1buzbee 2015ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 202d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowDivZeroFromCode() { 203d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes UNIMPLEMENTED(FATAL) << "Divide by zero"; 2045ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2055ade1d255ef1b5022321ac20493208703b34d2b1buzbee 2065ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 207d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowArrayBoundsFromCode(int32_t index, int32_t limit) { 208d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes UNIMPLEMENTED(FATAL) << "Bound check exception, idx: " << index << ", limit: " << limit; 2095ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2105ade1d255ef1b5022321ac20493208703b34d2b1buzbee 2115ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 212d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowVerificationErrorFromCode(int32_t src1, int32_t ref) { 2135ade1d255ef1b5022321ac20493208703b34d2b1buzbee UNIMPLEMENTED(FATAL) << "Verification error, src1: " << src1 << 2145ade1d255ef1b5022321ac20493208703b34d2b1buzbee " ref: " << ref; 2155ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2165ade1d255ef1b5022321ac20493208703b34d2b1buzbee 2175ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 218d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowNegArraySizeFromCode(int32_t index) { 2195ade1d255ef1b5022321ac20493208703b34d2b1buzbee UNIMPLEMENTED(FATAL) << "Negative array size: " << index; 2205ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2215ade1d255ef1b5022321ac20493208703b34d2b1buzbee 2225ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 223d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowInternalErrorFromCode(int32_t errnum) { 2245ade1d255ef1b5022321ac20493208703b34d2b1buzbee UNIMPLEMENTED(FATAL) << "Internal error: " << errnum; 2255ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2265ade1d255ef1b5022321ac20493208703b34d2b1buzbee 2275ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 228d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowRuntimeExceptionFromCode(int32_t errnum) { 2295ade1d255ef1b5022321ac20493208703b34d2b1buzbee UNIMPLEMENTED(FATAL) << "Internal error: " << errnum; 2305ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2315ade1d255ef1b5022321ac20493208703b34d2b1buzbee 2325ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: placeholder 233d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid ThrowNoSuchMethodFromCode(int32_t method_idx) { 2345ade1d255ef1b5022321ac20493208703b34d2b1buzbee UNIMPLEMENTED(FATAL) << "No such method, idx: " << method_idx; 2355ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2365ade1d255ef1b5022321ac20493208703b34d2b1buzbee 237bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersvoid ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread) { 238bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers thread->ThrowNewException("Ljava/lang/AbstractMethodError", 239bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers "abstract method \"%s\"", 240bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers PrettyMethod(method).c_str()); 241bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers thread->DeliverException(thread->GetException()); 242bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 243bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 244bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 2455ade1d255ef1b5022321ac20493208703b34d2b1buzbee/* 2465ade1d255ef1b5022321ac20493208703b34d2b1buzbee * Temporary placeholder. Should include run-time checks for size 2475ade1d255ef1b5022321ac20493208703b34d2b1buzbee * of fill data <= size of array. If not, throw arrayOutOfBoundsException. 2485ade1d255ef1b5022321ac20493208703b34d2b1buzbee * As with other new "FromCode" routines, this should return to the caller 2495ade1d255ef1b5022321ac20493208703b34d2b1buzbee * only if no exception has been thrown. 2505ade1d255ef1b5022321ac20493208703b34d2b1buzbee * 2515ade1d255ef1b5022321ac20493208703b34d2b1buzbee * NOTE: When dealing with a raw dex file, the data to be copied uses 2525ade1d255ef1b5022321ac20493208703b34d2b1buzbee * little-endian ordering. Require that oat2dex do any required swapping 2535ade1d255ef1b5022321ac20493208703b34d2b1buzbee * so this routine can get by with a memcpy(). 2545ade1d255ef1b5022321ac20493208703b34d2b1buzbee * 2555ade1d255ef1b5022321ac20493208703b34d2b1buzbee * Format of the data: 2565ade1d255ef1b5022321ac20493208703b34d2b1buzbee * ushort ident = 0x0300 magic value 2575ade1d255ef1b5022321ac20493208703b34d2b1buzbee * ushort width width of each element in the table 2585ade1d255ef1b5022321ac20493208703b34d2b1buzbee * uint size number of elements in the table 2595ade1d255ef1b5022321ac20493208703b34d2b1buzbee * ubyte data[size*width] table of data values (may contain a single-byte 2605ade1d255ef1b5022321ac20493208703b34d2b1buzbee * padding at the end) 2615ade1d255ef1b5022321ac20493208703b34d2b1buzbee */ 262d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid HandleFillArrayDataFromCode(Array* array, const uint16_t* table) { 2635ade1d255ef1b5022321ac20493208703b34d2b1buzbee uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16); 2645ade1d255ef1b5022321ac20493208703b34d2b1buzbee uint32_t size_in_bytes = size * table[1]; 2655ade1d255ef1b5022321ac20493208703b34d2b1buzbee if (static_cast<int32_t>(size) > array->GetLength()) { 2665ade1d255ef1b5022321ac20493208703b34d2b1buzbee ThrowArrayBoundsFromCode(array->GetLength(), size); 2675ade1d255ef1b5022321ac20493208703b34d2b1buzbee } 2685ade1d255ef1b5022321ac20493208703b34d2b1buzbee memcpy((char*)array + art::Array::DataOffset().Int32Value(), 2695ade1d255ef1b5022321ac20493208703b34d2b1buzbee (char*)&table[4], size_in_bytes); 2705ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 2715ade1d255ef1b5022321ac20493208703b34d2b1buzbee 272161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom/* 273161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom * TODO: placeholder for a method that can be called by the 274161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom * invoke-interface trampoline to unwind and handle exception. The 275161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom * trampoline will arrange it so that the caller appears to be the 276161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom * callsite of the failed invoke-interface. See comments in 277161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom * runtime_support.S 278161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom */ 279161928613d3f097108319de60494fab1aab8d48aBrian Carlstromextern "C" void artFailedInvokeInterface() { 280161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom UNIMPLEMENTED(FATAL) << "Unimplemented exception throw"; 281161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom} 282161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 283161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom// See comments in runtime_support.S 284161928613d3f097108319de60494fab1aab8d48aBrian Carlstromextern "C" uint64_t artFindInterfaceMethodInCache(uint32_t method_idx, 285161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom Object* this_object , Method* caller_method) 286161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom{ 287161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom if (this_object == NULL) { 288161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom ThrowNullPointerFromCode(); 289161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom } 290161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 291161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom Method* interface_method = class_linker->ResolveMethod(method_idx, caller_method, false); 292161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom if (interface_method == NULL) { 293161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom UNIMPLEMENTED(FATAL) << "Could not resolve interface method. Throw error and unwind"; 294161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom } 295161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom Method* method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method); 296161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom const void* code = method->GetCode(); 297161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 298161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom uint32_t method_uint = reinterpret_cast<uint32_t>(method); 299161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom uint64_t code_uint = reinterpret_cast<uint32_t>(code); 300161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom uint64_t result = ((code_uint << 32) | method_uint); 301161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom return result; 302161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom} 303161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 3045ade1d255ef1b5022321ac20493208703b34d2b1buzbee// TODO: move to more appropriate location 3055ade1d255ef1b5022321ac20493208703b34d2b1buzbee/* 3065ade1d255ef1b5022321ac20493208703b34d2b1buzbee * Float/double conversion requires clamping to min and max of integer form. If 3075ade1d255ef1b5022321ac20493208703b34d2b1buzbee * target doesn't support this normally, use these. 3085ade1d255ef1b5022321ac20493208703b34d2b1buzbee */ 309d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesint64_t D2L(double d) { 3105ade1d255ef1b5022321ac20493208703b34d2b1buzbee static const double kMaxLong = (double)(int64_t)0x7fffffffffffffffULL; 3115ade1d255ef1b5022321ac20493208703b34d2b1buzbee static const double kMinLong = (double)(int64_t)0x8000000000000000ULL; 3125ade1d255ef1b5022321ac20493208703b34d2b1buzbee if (d >= kMaxLong) 3135ade1d255ef1b5022321ac20493208703b34d2b1buzbee return (int64_t)0x7fffffffffffffffULL; 3145ade1d255ef1b5022321ac20493208703b34d2b1buzbee else if (d <= kMinLong) 3155ade1d255ef1b5022321ac20493208703b34d2b1buzbee return (int64_t)0x8000000000000000ULL; 3165ade1d255ef1b5022321ac20493208703b34d2b1buzbee else if (d != d) // NaN case 3175ade1d255ef1b5022321ac20493208703b34d2b1buzbee return 0; 3185ade1d255ef1b5022321ac20493208703b34d2b1buzbee else 3195ade1d255ef1b5022321ac20493208703b34d2b1buzbee return (int64_t)d; 3205ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 3215ade1d255ef1b5022321ac20493208703b34d2b1buzbee 322d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesint64_t F2L(float f) { 3235ade1d255ef1b5022321ac20493208703b34d2b1buzbee static const float kMaxLong = (float)(int64_t)0x7fffffffffffffffULL; 3245ade1d255ef1b5022321ac20493208703b34d2b1buzbee static const float kMinLong = (float)(int64_t)0x8000000000000000ULL; 3255ade1d255ef1b5022321ac20493208703b34d2b1buzbee if (f >= kMaxLong) 3265ade1d255ef1b5022321ac20493208703b34d2b1buzbee return (int64_t)0x7fffffffffffffffULL; 3275ade1d255ef1b5022321ac20493208703b34d2b1buzbee else if (f <= kMinLong) 3285ade1d255ef1b5022321ac20493208703b34d2b1buzbee return (int64_t)0x8000000000000000ULL; 3295ade1d255ef1b5022321ac20493208703b34d2b1buzbee else if (f != f) // NaN case 3305ade1d255ef1b5022321ac20493208703b34d2b1buzbee return 0; 3315ade1d255ef1b5022321ac20493208703b34d2b1buzbee else 3325ade1d255ef1b5022321ac20493208703b34d2b1buzbee return (int64_t)f; 3335ade1d255ef1b5022321ac20493208703b34d2b1buzbee} 3345ade1d255ef1b5022321ac20493208703b34d2b1buzbee 335161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom// Return value helper for jobject return types 336161928613d3f097108319de60494fab1aab8d48aBrian Carlstromstatic Object* DecodeJObjectInThread(Thread* thread, jobject obj) { 337161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom return thread->DecodeJObject(obj); 338161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom} 339161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 3403ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid Thread::InitFunctionPointers() { 3415433072f589b61413e042eddf76e8190a048f71dbuzbee#if defined(__arm__) 3425433072f589b61413e042eddf76e8190a048f71dbuzbee pShlLong = art_shl_long; 3435433072f589b61413e042eddf76e8190a048f71dbuzbee pShrLong = art_shr_long; 3445433072f589b61413e042eddf76e8190a048f71dbuzbee pUshrLong = art_ushr_long; 3457b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pIdiv = __aeabi_idiv; 3467b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pIdivmod = __aeabi_idivmod; 3477b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pI2f = __aeabi_i2f; 3487b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pF2iz = __aeabi_f2iz; 3497b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pD2f = __aeabi_d2f; 3507b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pF2d = __aeabi_f2d; 3517b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pD2iz = __aeabi_d2iz; 3527b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pL2f = __aeabi_l2f; 3537b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pL2d = __aeabi_l2d; 3547b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFadd = __aeabi_fadd; 3557b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFsub = __aeabi_fsub; 3567b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFdiv = __aeabi_fdiv; 3577b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFmul = __aeabi_fmul; 3587b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFmodf = fmodf; 3597b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDadd = __aeabi_dadd; 3607b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDsub = __aeabi_dsub; 3617b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDdiv = __aeabi_ddiv; 3627b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pDmul = __aeabi_dmul; 3637b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pFmod = fmod; 3647b1b86d68244b0bb4ea3f43505eb45fdd46814d6buzbee pLdivmod = __aeabi_ldivmod; 365439c4fa0db980fb19e4a585723a64a3461e4c278buzbee pLmul = __aeabi_lmul; 3669651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers pThrowNullPointerFromCode = art_throw_null_pointer_exception_from_code; 3679651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code; 3689651f425f7413772a7b5352da2b04eb7de7d416fIan Rogers pThrowDivZeroFromCode = art_throw_div_zero_from_code; 3694a3164faefd255b1c1e911e7ad7c3d57749caaf6buzbee pInvokeInterfaceTrampoline = art_invoke_interface_trampoline; 37067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#endif 37167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers pDeliverException = art_deliver_exception; 372c396efc1baec875160afe34a3e65c46cce2bd72fbuzbee pF2l = F2L; 373c396efc1baec875160afe34a3e65c46cce2bd72fbuzbee pD2l = D2L; 374dfd3d70e58c37b5d56eded3a4469082d8bb26ee0buzbee pAllocFromCode = Array::AllocFromCode; 3751da522de18ac6e4c2913c3233529e9dd115059f8buzbee pCheckAndAllocFromCode = CheckAndAllocFromCode; 3761f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom pAllocObjectFromCode = Class::AllocObjectFromCode; 3773ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee pMemcpy = memcpy; 3781b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee pHandleFillArrayDataFromCode = HandleFillArrayDataFromCode; 379e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pGet32Static = Field::Get32StaticFromCode; 380e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pSet32Static = Field::Set32StaticFromCode; 381e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pGet64Static = Field::Get64StaticFromCode; 382e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pSet64Static = Field::Set64StaticFromCode; 383e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pGetObjStatic = Field::GetObjStaticFromCode; 384e1931749814dbb80c5a756f9842e9c261bb2e8f6buzbee pSetObjStatic = Field::SetObjStaticFromCode; 3851b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee pCanPutArrayElementFromCode = Class::CanPutArrayElementFromCode; 3861b4c85959b3d9a4a33bc2160c46c1bbde67350c7buzbee pInitializeTypeFromCode = InitializeTypeFromCode; 387561227c80077bbb4147f778043f1a836af6b9248buzbee pResolveMethodFromCode = ResolveMethodFromCode; 3881da522de18ac6e4c2913c3233529e9dd115059f8buzbee pInitializeStaticStorage = ClassLinker::InitializeStaticStorageFromCode; 3892a475e7b93d754e0a7525bb5c7059386307ea63abuzbee pInstanceofNonTrivialFromCode = Object::InstanceOf; 3902a475e7b93d754e0a7525bb5c7059386307ea63abuzbee pCheckCastFromCode = CheckCastFromCode; 3912a475e7b93d754e0a7525bb5c7059386307ea63abuzbee pLockObjectFromCode = LockObjectFromCode; 3922a475e7b93d754e0a7525bb5c7059386307ea63abuzbee pUnlockObjectFromCode = UnlockObjectFromCode; 393845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom pFindInstanceFieldFromCode = Field::FindInstanceFieldFromCode; 3940d966cff87464544a264efdbfba6c379474d5928buzbee pCheckSuspendFromCode = CheckSuspendFromCode; 395cefd1878e09fb0fb519a175545a99eb8c4a375b2buzbee pStackOverflowFromCode = StackOverflowFromCode; 3965ade1d255ef1b5022321ac20493208703b34d2b1buzbee pThrowVerificationErrorFromCode = ThrowVerificationErrorFromCode; 3975ade1d255ef1b5022321ac20493208703b34d2b1buzbee pThrowNegArraySizeFromCode = ThrowNegArraySizeFromCode; 3985ade1d255ef1b5022321ac20493208703b34d2b1buzbee pThrowRuntimeExceptionFromCode = ThrowRuntimeExceptionFromCode; 3995ade1d255ef1b5022321ac20493208703b34d2b1buzbee pThrowInternalErrorFromCode = ThrowInternalErrorFromCode; 4005ade1d255ef1b5022321ac20493208703b34d2b1buzbee pThrowNoSuchMethodFromCode = ThrowNoSuchMethodFromCode; 401bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode; 402161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom pFindNativeMethod = FindNativeMethod; 403161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom pDecodeJObjectInThread = DecodeJObjectInThread; 4044a3164faefd255b1c1e911e7ad7c3d57749caaf6buzbee pDebugMe = DebugMe; 4053ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee} 4063ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee 4071a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid Frame::Next() { 40867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers size_t frame_size = GetMethod()->GetFrameSizeInBytes(); 40967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers DCHECK_NE(frame_size, 0u); 41067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers DCHECK_LT(frame_size, 1024u); 4111a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 41267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers frame_size; 4130cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers sp_ = reinterpret_cast<Method**>(next_sp); 41467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers DCHECK(*sp_ == NULL || 41567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (*sp_)->GetClass()->GetDescriptor()->Equals("Ljava/lang/reflect/Method;")); 4161a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 4171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4189086572fa809d1a19d886b467e4da3ce42016982Ian Rogersbool Frame::HasMethod() const { 4199086572fa809d1a19d886b467e4da3ce42016982Ian Rogers return GetMethod() != NULL && (!GetMethod()->IsPhony()); 4209086572fa809d1a19d886b467e4da3ce42016982Ian Rogers} 4219086572fa809d1a19d886b467e4da3ce42016982Ian Rogers 422bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersuintptr_t Frame::GetReturnPC() const { 4231a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* pc_addr = reinterpret_cast<byte*>(sp_) + 424d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetReturnPcOffsetInBytes(); 42555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao return *reinterpret_cast<uintptr_t*>(pc_addr); 4261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 4271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 428bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersuintptr_t Frame::LoadCalleeSave(int num) const { 429bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Callee saves are held at the top of the frame 430bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Method* method = GetMethod(); 431bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers DCHECK(method != NULL); 432bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers size_t frame_size = method->GetFrameSizeInBytes(); 433bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers byte* save_addr = reinterpret_cast<byte*>(sp_) + frame_size - 434bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers ((num + 1) * kPointerSize); 43567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#if defined(__i386__) 43667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers save_addr -= kPointerSize; // account for return address 43767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#endif 438bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers return *reinterpret_cast<uintptr_t*>(save_addr); 439bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 440bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 4410cfe1fb7060576d047f7f894fc0d8b87de84fcabIan RogersMethod* Frame::NextMethod() const { 4421a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 443d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetFrameSizeInBytes(); 4440cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers return *reinterpret_cast<Method**>(next_sp); 4451a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 4461a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 44778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromvoid* Thread::CreateCallback(void* arg) { 44893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Thread* self = reinterpret_cast<Thread*>(arg); 44993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Runtime* runtime = Runtime::Current(); 45093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 45193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes self->Attach(runtime); 45293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 453038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes String* thread_name = reinterpret_cast<String*>(gThread_name->GetObject(self->peer_)); 45493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes if (thread_name != NULL) { 45593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes SetThreadName(thread_name->ToModifiedUtf8().c_str()); 45693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes } 45793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 45893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Wait until it's safe to start running code. (There may have been a suspend-all 45993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // in progress while we were starting up.) 46093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes runtime->GetThreadList()->WaitForGo(); 46193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 46293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // TODO: say "hi" to the debugger. 46393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes //if (gDvm.debuggerConnected) { 46493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // dvmDbgPostThreadStart(self); 46593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes //} 46693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 46793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Invoke the 'run' method of our java.lang.Thread. 46893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes CHECK(self->peer_ != NULL); 46993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Object* receiver = self->peer_; 470038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Method* m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(gThread_run); 47193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes m->Invoke(self, receiver, NULL, NULL); 47293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 47393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Detach. 47493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes runtime->GetThreadList()->Unregister(); 47593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 476b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return NULL; 477b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 478b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 47993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughesvoid SetVmData(Object* managed_thread, Thread* native_thread) { 480038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_vmData->SetInt(managed_thread, reinterpret_cast<uintptr_t>(native_thread)); 48193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes} 48293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 48301158d7a57c8321370667a6045220237d16e0da8Elliott HughesThread* Thread::FromManagedThread(JNIEnv* env, jobject java_thread) { 48401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes Object* thread = Decode<Object*>(env, java_thread); 48501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes return reinterpret_cast<Thread*>(static_cast<uintptr_t>(gThread_vmData->GetInt(thread))); 48601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes} 48701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes 488d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesvoid Thread::Create(Object* peer, size_t stack_size) { 489d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes CHECK(peer != NULL); 490dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes 491d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (stack_size == 0) { 492d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes stack_size = Runtime::Current()->GetDefaultStackSize(); 493d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 49461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 49593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Thread* native_thread = new Thread; 49693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes native_thread->peer_ = peer; 49793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 49893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Thread.start is synchronized, so we know that vmData is 0, 49993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // and know that we're not racing to assign it. 50093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes SetVmData(peer, native_thread); 50161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 50261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro pthread_attr_t attr; 5038d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread"); 5048d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED), "PTHREAD_CREATE_DETACHED"); 5058d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size); 5068d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_create, (&native_thread->pthread_, &attr, Thread::CreateCallback, native_thread), "new thread"); 5078d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread"); 50861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 50993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes // Let the child know when it's safe to start running. 51093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Runtime::Current()->GetThreadList()->SignalGo(native_thread); 51193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes} 51261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 51393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughesvoid Thread::Attach(const Runtime* runtime) { 51493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes InitCpu(); 51593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes InitFunctionPointers(); 51661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 51793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes thin_lock_id_ = Runtime::Current()->GetThreadList()->AllocThreadId(); 518be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes 51993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes tid_ = ::art::GetTid(); 52093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes pthread_ = pthread_self(); 52161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 52293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes InitStackHwm(); 523dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes 5248d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, this), "attach"); 525a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes 52693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes jni_env_ = new JNIEnvExt(this, runtime->GetJavaVM()); 5275fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 52893e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes runtime->GetThreadList()->Register(this); 52993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes} 53093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 53193e74e8d879270071c3aa163f8495ada8d21f42fElliott HughesThread* Thread::Attach(const Runtime* runtime, const char* name, bool as_daemon) { 53293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes Thread* self = new Thread; 53393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes self->Attach(runtime); 53493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 53593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes self->SetState(Thread::kRunnable); 53693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes 53793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes SetThreadName(name); 5385fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 5395fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes // If we're the main thread, ClassLinker won't be created until after we're attached, 5405fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes // so that thread needs a two-stage attach. Regular threads don't need this hack. 5415fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes if (self->thin_lock_id_ != ThreadList::kMainId) { 5425fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes self->CreatePeer(name, as_daemon); 5435fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes } 5445fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 5455fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes return self; 5465fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes} 5475fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 548d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesjobject GetWellKnownThreadGroup(JNIEnv* env, const char* field_name) { 549d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes jclass thread_group_class = env->FindClass("java/lang/ThreadGroup"); 550d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes jfieldID fid = env->GetStaticFieldID(thread_group_class, field_name, "Ljava/lang/ThreadGroup;"); 551d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes jobject thread_group = env->GetStaticObjectField(thread_group_class, fid); 552d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes // This will be null in the compiler (and tests), but never in a running system. 553d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes //CHECK(thread_group != NULL) << "java.lang.ThreadGroup." << field_name << " not initialized"; 554d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes return thread_group; 555d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes} 556d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 5575fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughesvoid Thread::CreatePeer(const char* name, bool as_daemon) { 55801158d7a57c8321370667a6045220237d16e0da8Elliott Hughes Thread* self = Thread::Current(); 55901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes ScopedThreadStateChange tsc(self, Thread::kNative); 5605fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 5615fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes JNIEnv* env = jni_env_; 5625fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 563d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes const char* field_name = (GetThinLockId() == ThreadList::kMainId) ? "mMain" : "mSystem"; 564d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes jobject thread_group = GetWellKnownThreadGroup(env, field_name); 5655fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes jobject thread_name = env->NewStringUTF(name); 5668daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes jint thread_priority = GetNativePriority(); 5675fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes jboolean thread_is_daemon = as_daemon; 5685fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes 5695fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes jclass c = env->FindClass("java/lang/Thread"); 5705fe594f576225dd7d333835e39c448a71ea9b433Elliott Hughes jmethodID mid = env->GetMethodID(c, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V"); 571330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 5728daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes jobject peer = env->NewObject(c, mid, thread_group, thread_name, thread_priority, thread_is_daemon); 57301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes peer_ = DecodeJObject(peer); 57401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes SetVmData(peer_, self); 575d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 576d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes // Because we mostly run without code available (in the compiler, in tests), we 577d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes // manually assign the fields the constructor should have set. 578d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes // TODO: lose this. 57901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes gThread_daemon->SetBoolean(peer_, thread_is_daemon); 58001158d7a57c8321370667a6045220237d16e0da8Elliott Hughes gThread_group->SetObject(peer_, Decode<Object*>(env, thread_group)); 58101158d7a57c8321370667a6045220237d16e0da8Elliott Hughes gThread_name->SetObject(peer_, Decode<Object*>(env, thread_name)); 58201158d7a57c8321370667a6045220237d16e0da8Elliott Hughes gThread_priority->SetInt(peer_, thread_priority); 58361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 58461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 585be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughesvoid Thread::InitStackHwm() { 586be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes pthread_attr_t attributes; 5878d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_getattr_np, (pthread_, &attributes), __FUNCTION__); 588be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes 589be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes void* stack_base; 590be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes size_t stack_size; 5918d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, &stack_base, &stack_size), __FUNCTION__); 592be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes 593be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes if (stack_size <= kStackOverflowReservedBytes) { 594be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes LOG(FATAL) << "attempt to attach a thread with a too-small stack (" << stack_size << " bytes)"; 595be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes } 596449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes 597449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes // stack_base is the "lowest addressable byte" of the stack. 598449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes // Our stacks grow down, so we want stack_end_ to be near there, but reserving enough room 599449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes // to throw a StackOverflowError. 600cefd1878e09fb0fb519a175545a99eb8c4a375b2buzbee stack_end_ = reinterpret_cast<byte*>(stack_base) + kStackOverflowReservedBytes; 601449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes 602449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes // Sanity check. 603449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes int stack_variable; 604449b4bdf90b527ef7a42faaf087494538e62363cElliott Hughes CHECK_GT(&stack_variable, (void*) stack_end_); 605be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes 6068d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__); 607be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes} 608be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes 609a09576416788b916095739e43a16917e7948f3a4Elliott Hughesvoid Thread::Dump(std::ostream& os) const { 610d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes DumpState(os); 611d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes DumpStack(os); 612d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes} 613d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 614d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesstd::string GetSchedulerGroup(pid_t tid) { 615d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // /proc/<pid>/group looks like this: 616d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // 2:devices:/ 617d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // 1:cpuacct,cpu:/ 618d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // We want the third field from the line whose second field contains the "cpu" token. 619d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::string cgroup_file; 620d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes if (!ReadFileToString("/proc/self/cgroup", &cgroup_file)) { 621d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes return ""; 622d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 623d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::vector<std::string> cgroup_lines; 624d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes Split(cgroup_file, '\n', cgroup_lines); 625d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes for (size_t i = 0; i < cgroup_lines.size(); ++i) { 626d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::vector<std::string> cgroup_fields; 627d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes Split(cgroup_lines[i], ':', cgroup_fields); 628d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::vector<std::string> cgroups; 629d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes Split(cgroup_fields[1], ',', cgroups); 630d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes for (size_t i = 0; i < cgroups.size(); ++i) { 631d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes if (cgroups[i] == "cpu") { 632d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes return cgroup_fields[2].substr(1); // Skip the leading slash. 633d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 634d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 635d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 636d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes return ""; 637d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes} 638d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 639d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Thread::DumpState(std::ostream& os) const { 640d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes std::string thread_name("<native thread without managed peer>"); 641d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes std::string group_name; 642d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes int priority; 643d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes bool is_daemon = false; 644d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 645d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (peer_ != NULL) { 646038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes String* thread_name_string = reinterpret_cast<String*>(gThread_name->GetObject(peer_)); 647d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes thread_name = (thread_name_string != NULL) ? thread_name_string->ToModifiedUtf8() : "<null>"; 648038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes priority = gThread_priority->GetInt(peer_); 649038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes is_daemon = gThread_daemon->GetBoolean(peer_); 650d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 651038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Object* thread_group = gThread_group->GetObject(peer_); 652d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (thread_group != NULL) { 653038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes String* group_name_string = reinterpret_cast<String*>(gThreadGroup_name->GetObject(thread_group)); 654d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes group_name = (group_name_string != NULL) ? group_name_string->ToModifiedUtf8() : "<null>"; 655d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 656d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } else { 657d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes // This name may be truncated, but it's the best we can do in the absence of a managed peer. 658dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes std::string stats; 659dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes if (ReadFileToString(StringPrintf("/proc/self/task/%d/stat", GetTid()).c_str(), &stats)) { 660dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes size_t start = stats.find('(') + 1; 661dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes size_t end = stats.find(')') - start; 662dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes thread_name = stats.substr(start, end); 663dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes } 664d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes priority = GetNativePriority(); 665dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes } 666d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 667d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int policy; 668d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes sched_param sp; 6698d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_getschedparam, (pthread_, &policy, &sp), __FUNCTION__); 670d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 671d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::string scheduler_group(GetSchedulerGroup(GetTid())); 672d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes if (scheduler_group.empty()) { 673d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes scheduler_group = "default"; 674d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 675d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 676d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << '"' << thread_name << '"'; 677d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (is_daemon) { 678d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " daemon"; 679d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 680d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " prio=" << priority 681dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes << " tid=" << GetThinLockId() 68293e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes << " " << GetState() << "\n"; 683d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 684d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int debug_suspend_count = 0; // TODO 685d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " | group=\"" << group_name << "\"" 6868d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes << " sCount=" << suspend_count_ 687d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " dsCount=" << debug_suspend_count 688dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes << " obj=" << reinterpret_cast<void*>(peer_) 689d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " self=" << reinterpret_cast<const void*>(this) << "\n"; 690d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " | sysTid=" << GetTid() 691d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " nice=" << getpriority(PRIO_PROCESS, GetTid()) 692d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " sched=" << policy << "/" << sp.sched_priority 693d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " cgrp=" << scheduler_group 694d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " handle=" << GetImpl() << "\n"; 695d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 696d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // Grab the scheduler stats for this thread. 697d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::string scheduler_stats; 698d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes if (ReadFileToString(StringPrintf("/proc/self/task/%d/schedstat", GetTid()).c_str(), &scheduler_stats)) { 699d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes scheduler_stats.resize(scheduler_stats.size() - 1); // Lose the trailing '\n'. 700d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } else { 701d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes scheduler_stats = "0 0 0"; 702d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 703d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 704d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int utime = 0; 705d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int stime = 0; 706d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes int task_cpu = 0; 707d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::string stats; 708d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes if (ReadFileToString(StringPrintf("/proc/self/task/%d/stat", GetTid()).c_str(), &stats)) { 709d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // Skip the command, which may contain spaces. 710d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes stats = stats.substr(stats.find(')') + 2); 711d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes // Extract the three fields we care about. 712d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes std::vector<std::string> fields; 713d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes Split(stats, ' ', fields); 714d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes utime = strtoull(fields[11].c_str(), NULL, 10); 715d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes stime = strtoull(fields[12].c_str(), NULL, 10); 716d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes task_cpu = strtoull(fields[36].c_str(), NULL, 10); 717d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes } 718d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes 719d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes os << " | schedstat=( " << scheduler_stats << " )" 720d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " utm=" << utime 721d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " stm=" << stime 722d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " core=" << task_cpu 723d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughes << " HZ=" << sysconf(_SC_CLK_TCK) << "\n"; 724a09576416788b916095739e43a16917e7948f3a4Elliott Hughes} 725a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 726d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughesstruct StackDumpVisitor : public Thread::StackVisitor { 727d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes StackDumpVisitor(std::ostream& os) : os(os) { 728d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 729d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 730bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual ~StackDumpVisitor() { 731d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 732d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 733bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers void VisitFrame(const Frame& frame, uintptr_t pc) { 7349086572fa809d1a19d886b467e4da3ce42016982Ian Rogers if (!frame.HasMethod()) { 7359086572fa809d1a19d886b467e4da3ce42016982Ian Rogers return; 7369086572fa809d1a19d886b467e4da3ce42016982Ian Rogers } 737d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 738d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 739d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes Method* m = frame.GetMethod(); 740d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes Class* c = m->GetDeclaringClass(); 741d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes const DexFile& dex_file = class_linker->FindDexFile(c->GetDexCache()); 742d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 743d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes os << " at " << PrettyMethod(m, false); 744d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (m->IsNative()) { 745d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes os << "(Native method)"; 746d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } else { 747bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers int line_number = dex_file.GetLineNumFromPC(m, m->ToDexPC(pc)); 748d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes os << "(" << c->GetSourceFile()->ToModifiedUtf8() << ":" << line_number << ")"; 749d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 750d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes os << "\n"; 751d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 752d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 753d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes std::ostream& os; 754d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes}; 755d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 756d92bec457dc6c506c80e9da6b8e0c958266b5cdcElliott Hughesvoid Thread::DumpStack(std::ostream& os) const { 757d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes StackDumpVisitor dumper(os); 758d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes WalkStack(&dumper); 759e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes} 760e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 7618d768a954b101a9532f980253ac46be2c53aba11Elliott HughesThread::State Thread::SetState(Thread::State new_state) { 7628d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes Thread::State old_state = state_; 7638d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes if (old_state == new_state) { 7648d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes return old_state; 7658d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 7668d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 7678d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes volatile void* raw = reinterpret_cast<volatile void*>(&state_); 7688d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw); 7698d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 7708d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes if (new_state == Thread::kRunnable) { 7718d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes /* 7728d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * Change our status to Thread::kRunnable. The transition requires 7738d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * that we check for pending suspension, because the VM considers 7748d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * us to be "asleep" in all other states, and another thread could 7758d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * be performing a GC now. 7768d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7778d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * The order of operations is very significant here. One way to 7788d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * do this wrong is: 7798d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7808d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * GCing thread Our thread (in kNative) 7818d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * ------------ ---------------------- 7828d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * check suspend count (== 0) 7838d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * SuspendAllThreads() 7848d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * grab suspend-count lock 7858d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * increment all suspend counts 7868d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * release suspend-count lock 7878d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * check thread state (== kNative) 7888d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * all are suspended, begin GC 7898d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * set state to kRunnable 7908d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * (continue executing) 7918d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7928d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * We can correct this by grabbing the suspend-count lock and 7938d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * performing both of our operations (check suspend count, set 7948d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * state) while holding it, now we need to grab a mutex on every 7958d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * transition to kRunnable. 7968d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 7978d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * What we do instead is change the order of operations so that 7988d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * the transition to kRunnable happens first. If we then detect 7998d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * that the suspend count is nonzero, we switch to kSuspended. 8008d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 8018d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * Appropriate compiler and memory barriers are required to ensure 8028d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * that the operations are observed in the expected order. 8038d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 8048d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * This does create a small window of opportunity where a GC in 8058d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * progress could observe what appears to be a running thread (if 8068d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * it happens to look between when we set to kRunnable and when we 8078d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * switch to kSuspended). At worst this only affects assertions 8088d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * and thread logging. (We could work around it with some sort 8098d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * of intermediate "pre-running" state that is generally treated 8108d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * as equivalent to running, but that doesn't seem worthwhile.) 8118d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 8128d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * We can also solve this by combining the "status" and "suspend 8138d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * count" fields into a single 32-bit value. This trades the 8148d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * store/load barrier on transition to kRunnable for an atomic RMW 8158d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * op on all transitions and all suspend count updates (also, all 8168d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * accesses to status or the thread count require bit-fiddling). 8178d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * It also eliminates the brief transition through kRunnable when 8188d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * the thread is supposed to be suspended. This is possibly faster 8198d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * on SMP and slightly more correct, but less convenient. 8208d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes */ 8218d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes android_atomic_acquire_store(new_state, addr); 8228d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes if (ANNOTATE_UNPROTECTED_READ(suspend_count_) != 0) { 8238d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes Runtime::Current()->GetThreadList()->FullSuspendCheck(this); 8248d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 8258d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } else { 8268d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes /* 8278d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * Not changing to Thread::kRunnable. No additional work required. 8288d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * 8298d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * We use a releasing store to ensure that, if we were runnable, 8308d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * any updates we previously made to objects on the managed heap 8318d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes * will be observed before the state change. 8328d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes */ 8338d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes android_atomic_release_store(new_state, addr); 8348d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 8358d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 8368d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes return old_state; 8378d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes} 8388d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 8398d768a954b101a9532f980253ac46be2c53aba11Elliott Hughesvoid Thread::WaitUntilSuspended() { 8408d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes // TODO: dalvik dropped the waiting thread's priority after a while. 8418d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes // TODO: dalvik timed out and aborted. 8428d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes useconds_t delay = 0; 8438d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes while (GetState() == Thread::kRunnable) { 8448d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes useconds_t new_delay = delay * 2; 8458d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_GE(new_delay, delay); 8468d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes delay = new_delay; 8478d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes if (delay == 0) { 8488d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes sched_yield(); 8498d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes delay = 10000; 8508d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } else { 8518d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes usleep(delay); 8528d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 8538d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes } 8548d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes} 8558d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes 856be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughesvoid Thread::ThreadExitCallback(void* arg) { 857be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes Thread* self = reinterpret_cast<Thread*>(arg); 858be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes LOG(FATAL) << "Native thread exited without calling DetachCurrentThread: " << *self; 859b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 860b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 861be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughesvoid Thread::Startup() { 862b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Allocate a TLS slot. 8638d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_key_create, (&Thread::pthread_key_self_, Thread::ThreadExitCallback), "self key"); 864b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 865b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Double-check the TLS slot allocation. 866b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (pthread_getspecific(pthread_key_self_) != NULL) { 867be759c63c6bb58b76ac71cad2c5a736bd31f374dElliott Hughes LOG(FATAL) << "newly-created pthread TLS slot is not NULL"; 868b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 869038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes} 870038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes 871038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesvoid Thread::FinishStartup() { 872038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // Now the ClassLinker is ready, we can find the various Class*, Field*, and Method*s we need. 873038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 874038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Class* boolean_class = class_linker->FindPrimitiveClass('Z'); 875038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Class* int_class = class_linker->FindPrimitiveClass('I'); 876038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Class* String_class = class_linker->FindSystemClass("Ljava/lang/String;"); 877038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Class* Thread_class = class_linker->FindSystemClass("Ljava/lang/Thread;"); 878038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Class* ThreadGroup_class = class_linker->FindSystemClass("Ljava/lang/ThreadGroup;"); 879038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Class* ThreadLock_class = class_linker->FindSystemClass("Ljava/lang/ThreadLock;"); 88029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes Class* UncaughtExceptionHandler_class = class_linker->FindSystemClass("Ljava/lang/Thread$UncaughtExceptionHandler;"); 88129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes gThrowable = class_linker->FindSystemClass("Ljava/lang/Throwable;"); 882038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_daemon = Thread_class->FindDeclaredInstanceField("daemon", boolean_class); 883038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_group = Thread_class->FindDeclaredInstanceField("group", ThreadGroup_class); 884038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_lock = Thread_class->FindDeclaredInstanceField("lock", ThreadLock_class); 885038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_name = Thread_class->FindDeclaredInstanceField("name", String_class); 886038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_priority = Thread_class->FindDeclaredInstanceField("priority", int_class); 887038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_run = Thread_class->FindVirtualMethod("run", "()V"); 88829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes gThread_uncaughtHandler = Thread_class->FindDeclaredInstanceField("uncaughtHandler", UncaughtExceptionHandler_class); 889038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThread_vmData = Thread_class->FindDeclaredInstanceField("vmData", int_class); 890038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes gThreadGroup_name = ThreadGroup_class->FindDeclaredInstanceField("name", String_class); 89129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes gThreadGroup_removeThread = ThreadGroup_class->FindVirtualMethod("removeThread", "(Ljava/lang/Thread;)V"); 89229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes gUncaughtExceptionHandler_uncaughtException = 89329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes UncaughtExceptionHandler_class->FindVirtualMethod("uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"); 89401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes 89501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // Finish attaching the main thread. 89601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes Thread::Current()->CreatePeer("main", false); 897b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 898b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 899c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Thread::Shutdown() { 9008d768a954b101a9532f980253ac46be2c53aba11Elliott Hughes CHECK_PTHREAD_CALL(pthread_key_delete, (Thread::pthread_key_self_), "self key"); 901c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 902c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 903dcc247493fd8fb243e335c3ec08e5e625896a47cElliott HughesThread::Thread() 90402b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes : peer_(NULL), 90585d1545e985ac689db4bad7849880e843707c862Elliott Hughes wait_mutex_(new Mutex("Thread wait mutex")), 90685d1545e985ac689db4bad7849880e843707c862Elliott Hughes wait_cond_(new ConditionVariable("Thread wait condition variable")), 9078daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes wait_monitor_(NULL), 9088daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes interrupted_(false), 909dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes wait_next_(NULL), 910dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes card_table_(0), 9118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes stack_end_(NULL), 912dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes top_of_managed_stack_(), 913dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes top_of_managed_stack_pc_(0), 914dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes native_to_managed_record_(NULL), 915dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes top_sirt_(NULL), 916dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes jni_env_(NULL), 91793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes state_(Thread::kUnknown), 918dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes self_(NULL), 919dc33ad5db2dc6ed9b76d5219888626a604debbe1Elliott Hughes runtime_(NULL), 920dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes exception_(NULL), 921dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes suspend_count_(0), 92285d1545e985ac689db4bad7849880e843707c862Elliott Hughes class_loader_override_(NULL), 92385d1545e985ac689db4bad7849880e843707c862Elliott Hughes long_jump_context_(NULL) { 924dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes} 925dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes 92602b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughesvoid MonitorExitVisitor(const Object* object, void*) { 92702b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes Object* entered_monitor = const_cast<Object*>(object); 9285f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes entered_monitor->MonitorExit(Thread::Current()); 92902b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes} 93002b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 931c1674ed06662420213441ff2b818f2f71f9098dcElliott HughesThread::~Thread() { 93202b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes // On thread detach, all monitors entered with JNI MonitorEnter are automatically exited. 93393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes if (jni_env_ != NULL) { 93493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes jni_env_->monitors.VisitRoots(MonitorExitVisitor, NULL); 93593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes } 93602b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 93729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (peer_ != NULL) { 93829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes Object* group = gThread_group->GetObject(peer_); 93929f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes 94029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // Handle any pending exception. 94129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (IsExceptionPending()) { 94229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // Get and clear the exception. 94329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes Object* exception = GetException(); 94429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes ClearException(); 94529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes 94629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // If the thread has its own handler, use that. 94729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes Object* handler = gThread_uncaughtHandler->GetObject(peer_); 94829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (handler == NULL) { 94929f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // Otherwise use the thread group's default handler. 95029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes handler = group; 95129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 95202b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 95329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // Call the handler. 95429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes Method* m = handler->GetClass()->FindVirtualMethodForVirtualOrInterface(gUncaughtExceptionHandler_uncaughtException); 95529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes Object* args[2]; 95629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes args[0] = peer_; 95729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes args[1] = exception; 95829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes m->Invoke(this, handler, reinterpret_cast<byte*>(&args), NULL); 95902b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 96029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // If the handler threw, clear that exception too. 96129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes ClearException(); 96229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 96329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes 96429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // this.group.removeThread(this); 965081be7fcd72490937e188e9ef56e72df06b7b006Elliott Hughes // group can be null if we're in the compiler or a test. 966081be7fcd72490937e188e9ef56e72df06b7b006Elliott Hughes if (group != NULL) { 967081be7fcd72490937e188e9ef56e72df06b7b006Elliott Hughes Method* m = group->GetClass()->FindVirtualMethodForVirtualOrInterface(gThreadGroup_removeThread); 968081be7fcd72490937e188e9ef56e72df06b7b006Elliott Hughes Object* args = peer_; 969081be7fcd72490937e188e9ef56e72df06b7b006Elliott Hughes m->Invoke(this, group, reinterpret_cast<byte*>(&args), NULL); 970081be7fcd72490937e188e9ef56e72df06b7b006Elliott Hughes } 97129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes 97229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // this.vmData = 0; 97393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes SetVmData(peer_, NULL); 97402b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 97529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // TODO: say "bye" to the debugger. 97629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes //if (gDvm.debuggerConnected) { 97729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // dvmDbgPostThreadDeath(self); 97829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes //} 97902b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 98029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // Thread.join() is implemented as an Object.wait() on the Thread.lock 98129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // object. Signal anyone who is waiting. 9825f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes Thread* self = Thread::Current(); 983038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes Object* lock = gThread_lock->GetObject(peer_); 984038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes // (This conditional is only needed for tests, where Thread.lock won't have been set.) 9855f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes if (lock != NULL) { 9865f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes lock->MonitorEnter(self); 9875f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes lock->NotifyAll(); 9885f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes lock->MonitorExit(self); 9895f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes } 9905f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes } 99102b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 992c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes delete jni_env_; 99302b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes jni_env_ = NULL; 99402b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes 99502b48d1dae0c3adc01ef6668226fb648fb52990aElliott Hughes SetState(Thread::kTerminated); 99685d1545e985ac689db4bad7849880e843707c862Elliott Hughes 99785d1545e985ac689db4bad7849880e843707c862Elliott Hughes delete wait_cond_; 99885d1545e985ac689db4bad7849880e843707c862Elliott Hughes delete wait_mutex_; 99985d1545e985ac689db4bad7849880e843707c862Elliott Hughes 100085d1545e985ac689db4bad7849880e843707c862Elliott Hughes delete long_jump_context_; 1001c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 1002c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 1003408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogerssize_t Thread::NumSirtReferences() { 1004a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t count = 0; 1005408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) { 1006a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers count += cur->NumberOfReferences(); 1007a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 1008a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return count; 1009a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 1010a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 1011408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogersbool Thread::SirtContains(jobject obj) { 1012408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object** sirt_entry = reinterpret_cast<Object**>(obj); 1013408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) { 1014a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t num_refs = cur->NumberOfReferences(); 1015408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // A SIRT should always have a jobject/jclass as a native method is passed 1016408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // in a this pointer or a class 1017408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers DCHECK_GT(num_refs, 0u); 10182f0ce9d60a4a9371c63a32a3764320fb02341acbShih-wei Liao if ((&cur->References()[0] <= sirt_entry) && 10192f0ce9d60a4a9371c63a32a3764320fb02341acbShih-wei Liao (sirt_entry <= (&cur->References()[num_refs - 1]))) { 1020a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return true; 1021a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 1022a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 1023a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return false; 1024a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 1025a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 102667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogersvoid Thread::PopSirt() { 102767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers CHECK(top_sirt_ != NULL); 102867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers top_sirt_ = top_sirt_->Link(); 102967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers} 103067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers 1031408f79aeb676251ba35667a64e86c20638d7cb0bIan RogersObject* Thread::DecodeJObject(jobject obj) { 10320cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers DCHECK(CanAccessDirectReferences()); 1033408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (obj == NULL) { 1034408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 1035408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1036408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRef ref = reinterpret_cast<IndirectRef>(obj); 1037408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRefKind kind = GetIndirectRefKind(ref); 1038408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object* result; 1039408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers switch (kind) { 1040408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kLocal: 1041408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 104269f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes IndirectReferenceTable& locals = jni_env_->locals; 1043cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes result = const_cast<Object*>(locals.Get(ref)); 1044408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 1045408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1046408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kGlobal: 1047408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 1048408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 1049408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& globals = vm->globals; 1050408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->globals_lock); 1051cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes result = const_cast<Object*>(globals.Get(ref)); 1052408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 1053408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1054408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kWeakGlobal: 1055408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 1056408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 1057408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& weak_globals = vm->weak_globals; 1058408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->weak_globals_lock); 1059cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes result = const_cast<Object*>(weak_globals.Get(ref)); 1060408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == kClearedJniWeakGlobal) { 1061408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // This is a special case where it's okay to return NULL. 1062408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 1063408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1064408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 1065408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1066408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kSirtOrInvalid: 1067408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers default: 1068408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // TODO: make stack indirect reference table lookup more efficient 1069408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Check if this is a local reference in the SIRT 1070408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (SirtContains(obj)) { 10710cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers result = *reinterpret_cast<Object**>(obj); // Read from SIRT 1072c5bfa8f49d8548d7c685a99b411311ef56bedffaElliott Hughes } else if (jni_env_->work_around_app_jni_bugs) { 1073408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Assume an invalid local reference is actually a direct pointer. 1074408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = reinterpret_cast<Object*>(obj); 1075408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } else { 1076a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes result = kInvalidIndirectRefObject; 1077408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1078408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1079408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 1080408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == NULL) { 1081a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes LOG(ERROR) << "JNI ERROR (app bug): use of deleted " << kind << ": " << obj; 1082a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes JniAbort(NULL); 1083a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 1084a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (result != kInvalidIndirectRefObject) { 1085a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes Heap::VerifyObject(result); 1086a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1087408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 1088408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return result; 1089408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers} 1090408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 10919b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liaoclass CountStackDepthVisitor : public Thread::StackVisitor { 10929b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public: 109329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes CountStackDepthVisitor() : depth_(0), skip_depth_(0), skipping_(true) {} 1094d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes 109529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes virtual void VisitFrame(const Frame& frame, uintptr_t pc) { 109629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // We want to skip frames up to and including the exception's constructor. 10979086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // Note we also skip the frame if it doesn't have a method (namely the callee 10989086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // save frame) 109925c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom DCHECK(gThrowable != NULL); 11009086572fa809d1a19d886b467e4da3ce42016982Ian Rogers if (skipping_ && frame.HasMethod() && !gThrowable->IsAssignableFrom(frame.GetMethod()->GetDeclaringClass())) { 110129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes skipping_ = false; 110229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 110329f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (!skipping_) { 110429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes ++depth_; 110529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } else { 110629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes ++skip_depth_; 110729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 11089b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11099b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 11109b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao int GetDepth() const { 1111aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers return depth_; 11129b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11139b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 111429f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes int GetSkipDepth() const { 111529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes return skip_depth_; 111629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 111729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes 11189b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao private: 1119aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers uint32_t depth_; 112029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes uint32_t skip_depth_; 112129f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes bool skipping_; 11229b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao}; 11239b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1124aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogersclass BuildInternalStackTraceVisitor : public Thread::StackVisitor { 11259b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao public: 112629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes explicit BuildInternalStackTraceVisitor(int depth, int skip_depth, ScopedJniThreadState& ts) 112729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes : skip_depth_(skip_depth), count_(0) { 1128aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Allocate method trace with an extra slot that will hold the PC trace 112901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes method_trace_ = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(depth + 1); 1130aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Register a local reference as IntArray::Alloc may trigger GC 1131aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers local_ref_ = AddLocalReference<jobject>(ts.Env(), method_trace_); 1132aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers pc_trace_ = IntArray::Alloc(depth); 1133aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#ifdef MOVING_GARBAGE_COLLECTOR 1134aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Re-read after potential GC 1135aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method_trace = Decode<ObjectArray<Object>*>(ts.Env(), local_ref_); 1136aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#endif 1137aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Save PC trace in last element of method trace, also places it into the 1138aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // object graph. 1139aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method_trace_->Set(depth, pc_trace_); 11409b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11419b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1142aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers virtual ~BuildInternalStackTraceVisitor() {} 11439b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1144bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual void VisitFrame(const Frame& frame, uintptr_t pc) { 114529f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes if (skip_depth_ > 0) { 114629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes skip_depth_--; 114729f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes return; 114829f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes } 1149aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method_trace_->Set(count_, frame.GetMethod()); 1150bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers pc_trace_->Set(count_, pc); 1151aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ++count_; 11529b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11539b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1154aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers jobject GetInternalStackTrace() const { 1155aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers return local_ref_; 11569b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11579b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 11589b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao private: 115929f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes // How many more frames to skip. 116029f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes int32_t skip_depth_; 1161aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Current position down stack trace 1162aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers uint32_t count_; 1163aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Array of return PC values 1164aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers IntArray* pc_trace_; 1165aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // An array of the methods on the stack, the last entry is a reference to the 1166aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // PC trace 1167aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ObjectArray<Object>* method_trace_; 1168aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Local indirect reference table entry for method trace 1169aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers jobject local_ref_; 11709b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao}; 11719b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao 1172aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogersvoid Thread::WalkStack(StackVisitor* visitor) const { 1173d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes Frame frame = GetTopOfStack(); 1174bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers uintptr_t pc = top_of_managed_stack_pc_; 11759b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao // TODO: enable this CHECK after native_to_managed_record_ is initialized during startup. 11769b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao // CHECK(native_to_managed_record_ != NULL); 11779b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao NativeToManagedRecord* record = native_to_managed_record_; 11784417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 1179bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers while (frame.GetSP() != 0) { 11809b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao for ( ; frame.GetMethod() != 0; frame.Next()) { 1181bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers DCHECK(frame.GetMethod()->IsWithinCode(pc)); 1182bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers visitor->VisitFrame(frame, pc); 1183bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers pc = frame.GetReturnPC(); 11849b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 11859b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao if (record == NULL) { 11869b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao break; 11879b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao } 1188bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // last_tos should return Frame instead of sp? 1189bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers frame.SetSP(reinterpret_cast<art::Method**>(record->last_top_of_managed_stack_)); 1190bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers pc = record->last_top_of_managed_stack_pc_; 1191bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers record = record->link_; 1192bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 1193bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 1194bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 119567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogersvoid Thread::WalkStackUntilUpCall(StackVisitor* visitor, bool include_upcall) const { 1196bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Frame frame = GetTopOfStack(); 1197bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers uintptr_t pc = top_of_managed_stack_pc_; 1198bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1199bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers if (frame.GetSP() != 0) { 1200bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers for ( ; frame.GetMethod() != 0; frame.Next()) { 120167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers DCHECK(frame.GetMethod()->IsWithinCode(pc)); 1202bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers visitor->VisitFrame(frame, pc); 1203bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers pc = frame.GetReturnPC(); 1204bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 120567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers if (include_upcall) { 120667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers visitor->VisitFrame(frame, pc); 120767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 120855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao } 120955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao} 121055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 121101158d7a57c8321370667a6045220237d16e0da8Elliott Hughesjobject Thread::CreateInternalStackTrace(JNIEnv* env) const { 1212aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Compute depth of stack 12139b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao CountStackDepthVisitor count_visitor; 12149b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao WalkStack(&count_visitor); 12159b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao int32_t depth = count_visitor.GetDepth(); 121629f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes int32_t skip_depth = count_visitor.GetSkipDepth(); 12174417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 1218aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Transition into runnable state to work on Object*/Array* 121901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes ScopedJniThreadState ts(env); 1220aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 1221aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Build internal stack trace 122229f2742a478e4f5bd2ec7473410c5e5e7134a6f2Elliott Hughes BuildInternalStackTraceVisitor build_trace_visitor(depth, skip_depth, ts); 12239b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao WalkStack(&build_trace_visitor); 12244417536522fd2a9d8215d8672331984769c9520bShih-wei Liao 1225aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers return build_trace_visitor.GetInternalStackTrace(); 1226aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers} 1227aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 122801158d7a57c8321370667a6045220237d16e0da8Elliott HughesjobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, jobject internal, 122901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes jobjectArray output_array, int* stack_depth) { 1230aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Transition into runnable state to work on Object*/Array* 1231aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ScopedJniThreadState ts(env); 1232aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 1233aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Decode the internal stack trace into the depth, method trace and PC trace 1234aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ObjectArray<Object>* method_trace = 1235aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers down_cast<ObjectArray<Object>*>(Decode<Object*>(ts.Env(), internal)); 1236aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers int32_t depth = method_trace->GetLength()-1; 1237aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); 1238aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 1239aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 1240aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers 124101158d7a57c8321370667a6045220237d16e0da8Elliott Hughes jobjectArray result; 124201158d7a57c8321370667a6045220237d16e0da8Elliott Hughes ObjectArray<StackTraceElement>* java_traces; 124301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes if (output_array != NULL) { 124401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // Reuse the array we were given. 124501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes result = output_array; 124601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes java_traces = reinterpret_cast<ObjectArray<StackTraceElement>*>(Decode<Array*>(env, 124701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes output_array)); 124801158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // ...adjusting the number of frames we'll write to not exceed the array length. 124901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes depth = std::min(depth, java_traces->GetLength()); 125001158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } else { 125101158d7a57c8321370667a6045220237d16e0da8Elliott Hughes // Create java_trace array and place in local reference table 125201158d7a57c8321370667a6045220237d16e0da8Elliott Hughes java_traces = class_linker->AllocStackTraceElementArray(depth); 125301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes result = AddLocalReference<jobjectArray>(ts.Env(), java_traces); 125401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } 125501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes 125601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes if (stack_depth != NULL) { 125701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes *stack_depth = depth; 125801158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } 125955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 12609b576b4ed1dbe035952f3106d8f4b6993125ed6fShih-wei Liao for (int32_t i = 0; i < depth; ++i) { 1261aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Prepare parameters for StackTraceElement(String cls, String method, String file, int line) 1262aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers Method* method = down_cast<Method*>(method_trace->Get(i)); 1263aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers uint32_t native_pc = pc_trace->Get(i); 1264aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers Class* klass = method->GetDeclaringClass(); 126555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao const DexFile& dex_file = class_linker->FindDexFile(klass->GetDexCache()); 126638933579b15c74baa09b8713ee8bf715529d05ebElliott Hughes std::string class_name(PrettyDescriptor(klass->GetDescriptor())); 126755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 1268aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Allocate element, potentially triggering GC 126955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao StackTraceElement* obj = 127038933579b15c74baa09b8713ee8bf715529d05ebElliott Hughes StackTraceElement::Alloc(String::AllocFromModifiedUtf8(class_name.c_str()), 12714417536522fd2a9d8215d8672331984769c9520bShih-wei Liao method->GetName(), 12724b620ffb1b4d0c96a94bb3afe314f35d53990ec6Brian Carlstrom klass->GetSourceFile(), 12734417536522fd2a9d8215d8672331984769c9520bShih-wei Liao dex_file.GetLineNumFromPC(method, 1274aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method->ToDexPC(native_pc))); 1275aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#ifdef MOVING_GARBAGE_COLLECTOR 1276aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers // Re-read after potential GC 1277aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers java_traces = Decode<ObjectArray<Object>*>(ts.Env(), result); 1278aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers method_trace = down_cast<ObjectArray<Object>*>(Decode<Object*>(ts.Env(), internal)); 1279aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); 1280aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers#endif 128155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao java_traces->Set(i, obj); 128255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao } 1283aaa208006d7c8cc0f381c4aa9b525be24066c495Ian Rogers return result; 128455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao} 128555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 1286e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughesvoid Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) { 128737f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes std::string msg; 1288a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_list args; 1289a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_start(args, fmt); 129037f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes StringAppendV(&msg, fmt, args); 1291a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_end(args); 129237f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes 1293e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception". 12940cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers CHECK_EQ('L', exception_class_descriptor[0]); 1295e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes std::string descriptor(exception_class_descriptor + 1); 12960cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers CHECK_EQ(';', descriptor[descriptor.length() - 1]); 1297e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes descriptor.erase(descriptor.length() - 1); 1298e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes 1299e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes JNIEnv* env = GetJniEnv(); 1300e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes jclass exception_class = env->FindClass(descriptor.c_str()); 1301e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\""; 1302e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes int rc = env->ThrowNew(exception_class, msg.c_str()); 1303e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK_EQ(rc, JNI_OK); 1304a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes} 1305a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 130679082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughesvoid Thread::ThrowOutOfMemoryError() { 130779082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes UNIMPLEMENTED(FATAL); 130879082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes} 130979082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes 1310bdb0391258abc54bf77c676e36847d28a783bfe5Ian RogersMethod* Thread::CalleeSaveMethod() const { 1311bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // TODO: we should only allocate this once 1312bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Method* method = Runtime::Current()->GetClassLinker()->AllocMethod(); 131367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#if defined(__arm__) 1314bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers method->SetCode(NULL, art::kThumb2, NULL); 1315bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers method->SetFrameSizeInBytes(64); 1316bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers method->SetReturnPcOffsetInBytes(60); 131767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers method->SetCoreSpillMask((1 << art::arm::R1) | 131867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R2) | 131967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R3) | 132067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R4) | 132167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R5) | 132267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R6) | 132367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R7) | 132467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R8) | 132567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R9) | 132667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R10) | 132767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::R11) | 132867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::arm::LR)); 1329bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers method->SetFpSpillMask(0); 133067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#elif defined(__i386__) 133167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers method->SetCode(NULL, art::kX86, NULL); 133267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers method->SetFrameSizeInBytes(32); 133367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers method->SetReturnPcOffsetInBytes(28); 133467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers method->SetCoreSpillMask((1 << art::x86::EBX) | 133567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::x86::EBP) | 133667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::x86::ESI) | 133767375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers (1 << art::x86::EDI)); 133867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers method->SetFpSpillMask(0); 133967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#else 134067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers UNIMPLEMENTED(FATAL); 134167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#endif 1342bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers return method; 13431a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 13441a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 1345bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersclass CatchBlockStackVisitor : public Thread::StackVisitor { 1346bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers public: 1347bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers CatchBlockStackVisitor(Class* to_find, Context* ljc) 134867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers : found_(false), to_find_(to_find), long_jump_context_(ljc), native_method_count_(0) { 134967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#ifndef NDEBUG 135067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_pc_ = 0xEBADC0DE; 135167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_frame_.SetSP(reinterpret_cast<Method**>(0xEBADF00D)); 135267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers#endif 135367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 1354bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1355bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual void VisitFrame(const Frame& fr, uintptr_t pc) { 1356bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers if (!found_) { 1357bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Method* method = fr.GetMethod(); 135867375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers if (method == NULL) { 135967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // This is the upcall, we remember the frame and last_pc so that we may 136067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // long jump to them 136167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_pc_ = pc; 136267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_frame_ = fr; 136367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers return; 136467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers } 136567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers uint32_t dex_pc = DexFile::kDexNoIndex; 13669086572fa809d1a19d886b467e4da3ce42016982Ian Rogers if (method->IsPhony()) { 13679086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // ignore callee save method 13689086572fa809d1a19d886b467e4da3ce42016982Ian Rogers } else if (method->IsNative()) { 13699086572fa809d1a19d886b467e4da3ce42016982Ian Rogers native_method_count_++; 13709086572fa809d1a19d886b467e4da3ce42016982Ian Rogers } else { 13719086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // Move the PC back 2 bytes as a call will frequently terminate the 13729086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // decoding of a particular instruction and we want to make sure we 13739086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // get the Dex PC of the instruction with the call and not the 13749086572fa809d1a19d886b467e4da3ce42016982Ian Rogers // instruction following. 13759086572fa809d1a19d886b467e4da3ce42016982Ian Rogers pc -= 2; 13769086572fa809d1a19d886b467e4da3ce42016982Ian Rogers dex_pc = method->ToDexPC(pc); 1377bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 1378bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers if (dex_pc != DexFile::kDexNoIndex) { 1379bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers uint32_t found_dex_pc = method->FindCatchBlock(to_find_, dex_pc); 1380bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers if (found_dex_pc != DexFile::kDexNoIndex) { 1381bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers found_ = true; 138267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_pc_ = method->ToNativePC(found_dex_pc); 138367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers handler_frame_ = fr; 1384bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 1385bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 1386bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers if (!found_) { 1387bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Caller may be handler, fill in callee saves in context 1388bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers long_jump_context_->FillCalleeSaves(fr); 1389bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 13901a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 13911a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 13921a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 1393bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Did we find a catch block yet? 1394bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers bool found_; 1395bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // The type of the exception catch block to find 1396bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Class* to_find_; 1397bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Frame with found handler or last frame if no handler found 1398bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Frame handler_frame_; 139967375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // PC to branch to for the handler 140067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers uintptr_t handler_pc_; 1401bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Context that will be the target of the long jump 1402bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Context* long_jump_context_; 140367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // Number of native methods passed in crawl (equates to number of SIRTs to pop) 140467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers uint32_t native_method_count_; 1405bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers}; 1406bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1407bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogersvoid Thread::DeliverException(Throwable* exception) { 1408bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers SetException(exception); // Set exception on thread 1409bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1410bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers Context* long_jump_context = GetLongJumpContext(); 1411bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers CatchBlockStackVisitor catch_finder(exception->GetClass(), long_jump_context); 141267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers WalkStackUntilUpCall(&catch_finder, true); 1413bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 141467375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers // Pop any SIRT 141567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers if (catch_finder.native_method_count_ == 1) { 141667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers PopSirt(); 14171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 1418ad42e1327fca837531e4feac8841de3960c4df45Ian Rogers // We only expect the stack crawl to have passed 1 native method as it's terminated 1419ad42e1327fca837531e4feac8841de3960c4df45Ian Rogers // by an up call 142067375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers DCHECK_EQ(catch_finder.native_method_count_, 0u); 1421bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 142267375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers long_jump_context->SetSP(reinterpret_cast<intptr_t>(catch_finder.handler_frame_.GetSP())); 142367375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers long_jump_context->SetPC(catch_finder.handler_pc_); 1424bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers long_jump_context->DoLongJump(); 1425bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers} 1426bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 1427bdb0391258abc54bf77c676e36847d28a783bfe5Ian RogersContext* Thread::GetLongJumpContext() { 142885d1545e985ac689db4bad7849880e843707c862Elliott Hughes Context* result = long_jump_context_; 1429bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers if (result == NULL) { 1430bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers result = Context::Create(); 143185d1545e985ac689db4bad7849880e843707c862Elliott Hughes long_jump_context_ = result; 14321a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 1433bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers return result; 14341a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 14351a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 14365f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesbool Thread::HoldsLock(Object* object) { 14375f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes if (object == NULL) { 14385f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes return false; 14395f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes } 14405f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes return object->GetLockOwner() == thin_lock_id_; 14415f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes} 14425f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 1443038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughesbool Thread::IsDaemon() { 1444038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes return gThread_daemon->GetBoolean(peer_); 1445038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes} 1446038a806df72f884d22283a84a31c9a1d35ba1fdfElliott Hughes 1447410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughesvoid Thread::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { 1448d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (exception_ != NULL) { 1449d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes visitor(exception_, arg); 1450d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 1451d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes if (peer_ != NULL) { 1452d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes visitor(peer_, arg); 1453d369bb76dee0df2d2a106e9bf7f4e6446ed6deaaElliott Hughes } 1454410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes jni_env_->locals.VisitRoots(visitor, arg); 1455410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes jni_env_->monitors.VisitRoots(visitor, arg); 1456410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes // visitThreadStack(visitor, thread, arg); 1457410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes UNIMPLEMENTED(WARNING) << "some per-Thread roots not visited"; 1458410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes} 1459410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 1460b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstatic const char* kStateNames[] = { 146193e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes "Terminated", 1462b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Runnable", 146393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes "TimedWaiting", 1464b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Blocked", 1465b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Waiting", 146693e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes "Initializing", 146793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes "Starting", 1468b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Native", 146993e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes "VmWait", 147093e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes "Suspended", 1471b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 1472b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state) { 147393e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes int int_state = static_cast<int>(state); 147493e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes if (state >= Thread::kTerminated && state <= Thread::kSuspended) { 147593e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes os << kStateNames[int_state]; 1476b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } else { 147793e74e8d879270071c3aa163f8495ada8d21f42fElliott Hughes os << "State[" << int_state << "]"; 1478b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 1479b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return os; 1480b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 1481b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1482330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread) { 1483330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes os << "Thread[" << &thread 1484e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",pthread_t=" << thread.GetImpl() 1485e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",tid=" << thread.GetTid() 1486dcc247493fd8fb243e335c3ec08e5e625896a47cElliott Hughes << ",id=" << thread.GetThinLockId() 14878daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes << ",state=" << thread.GetState() 14888daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes << ",peer=" << thread.GetPeer() 14898daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes << "]"; 1490330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes return os; 1491330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes} 1492330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 14938daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} // namespace art 1494