1725a957985171d712d5c048cc3d00ff14968784bjeffhao/*
2725a957985171d712d5c048cc3d00ff14968784bjeffhao * Copyright (C) 2012 The Android Open Source Project
3725a957985171d712d5c048cc3d00ff14968784bjeffhao *
4725a957985171d712d5c048cc3d00ff14968784bjeffhao * Licensed under the Apache License, Version 2.0 (the "License");
5725a957985171d712d5c048cc3d00ff14968784bjeffhao * you may not use this file except in compliance with the License.
6725a957985171d712d5c048cc3d00ff14968784bjeffhao * You may obtain a copy of the License at
7725a957985171d712d5c048cc3d00ff14968784bjeffhao *
8725a957985171d712d5c048cc3d00ff14968784bjeffhao *      http://www.apache.org/licenses/LICENSE-2.0
9725a957985171d712d5c048cc3d00ff14968784bjeffhao *
10725a957985171d712d5c048cc3d00ff14968784bjeffhao * Unless required by applicable law or agreed to in writing, software
11725a957985171d712d5c048cc3d00ff14968784bjeffhao * distributed under the License is distributed on an "AS IS" BASIS,
12725a957985171d712d5c048cc3d00ff14968784bjeffhao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13725a957985171d712d5c048cc3d00ff14968784bjeffhao * See the License for the specific language governing permissions and
14725a957985171d712d5c048cc3d00ff14968784bjeffhao * limitations under the License.
15725a957985171d712d5c048cc3d00ff14968784bjeffhao */
16725a957985171d712d5c048cc3d00ff14968784bjeffhao
17e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h"
1862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "callee_save_frame.h"
196f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers#include "entrypoints/runtime_asm_entrypoints.h"
20725a957985171d712d5c048cc3d00ff14968784bjeffhao#include "instrumentation.h"
2162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "mirror/object-inl.h"
22725a957985171d712d5c048cc3d00ff14968784bjeffhao#include "runtime.h"
2304d7aa92bc5548bc4d272b9480614f06248194ccIan Rogers#include "thread-inl.h"
24725a957985171d712d5c048cc3d00ff14968784bjeffhao
25725a957985171d712d5c048cc3d00ff14968784bjeffhaonamespace art {
26725a957985171d712d5c048cc3d00ff14968784bjeffhao
27e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierextern "C" const void* artInstrumentationMethodEntryFromCode(ArtMethod* method,
2862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                                             mirror::Object* this_object,
292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                                                             Thread* self,
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                                                             uintptr_t lr)
3190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
323b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe  // Instrumentation changes the stack. Thus, when exiting, the stack cannot be verified, so skip
333b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe  // that part.
343b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe  ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
3562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
36320deb2ebe5cce96ca2779875c82853182326685Sebastien Hertz  const void* result;
37320deb2ebe5cce96ca2779875c82853182326685Sebastien Hertz  if (instrumentation->IsDeoptimized(method)) {
38320deb2ebe5cce96ca2779875c82853182326685Sebastien Hertz    result = GetQuickToInterpreterBridge();
39320deb2ebe5cce96ca2779875c82853182326685Sebastien Hertz  } else {
40a7dd0386f35c0ba4aef3f5b16bc84c6f4e2fc702Mathieu Chartier    result = instrumentation->GetQuickCodeFor(method, sizeof(void*));
418315ee03dbee3c48881191b3aedb108d1b626c0bSebastien Hertz    DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(result));
42320deb2ebe5cce96ca2779875c82853182326685Sebastien Hertz  }
43848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  bool interpreter_entry = (result == GetQuickToInterpreterBridge());
44320deb2ebe5cce96ca2779875c82853182326685Sebastien Hertz  instrumentation->PushInstrumentationStackFrame(self, method->IsStatic() ? nullptr : this_object,
459a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao                                                 method, lr, interpreter_entry);
462cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  CHECK(result != nullptr) << PrettyMethod(method);
4762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return result;
48725a957985171d712d5c048cc3d00ff14968784bjeffhao}
49725a957985171d712d5c048cc3d00ff14968784bjeffhao
50e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierextern "C" TwoWordReturn artInstrumentationMethodExitFromCode(Thread* self, ArtMethod** sp,
51d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe                                                              uint64_t gpr_result,
52d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe                                                              uint64_t fpr_result)
5390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
540747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz  // Instrumentation exit stub must not be entered with a pending exception.
550747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz  CHECK(!self->IsExceptionPending()) << "Enter instrumentation exit stub with pending exception "
560747466fca310eedea5fc49e37d54f240a0b3c0fSebastien Hertz                                     << self->GetException()->Dump();
571d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers  // Compute address of return PC and sanity check that it currently holds 0.
58c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers  size_t return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, Runtime::kRefsOnly);
5913735955f39b3b304c37d2b2840663c131262c18Ian Rogers  uintptr_t* return_pc = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(sp) +
604c1c510bea6f20f4d8b09e15547cd2967ad51c88Vladimir Marko                                                      return_pc_offset);
614274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom  CHECK_EQ(*return_pc, 0U);
621d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers
631d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers  // Pop the frame filling in the return pc. The low half of the return value is 0 when
641d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers  // deoptimization shouldn't be performed with the high-half having the return address. When
651d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers  // deoptimization should be performed the low half is zero and the high-half the address of the
661d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers  // deoptimization entry point.
6762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
68d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe  TwoWordReturn return_or_deoptimize_pc = instrumentation->PopInstrumentationStackFrame(
69d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe      self, return_pc, gpr_result, fpr_result);
7062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  return return_or_deoptimize_pc;
71725a957985171d712d5c048cc3d00ff14968784bjeffhao}
72725a957985171d712d5c048cc3d00ff14968784bjeffhao
73725a957985171d712d5c048cc3d00ff14968784bjeffhao}  // namespace art
74