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