• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "arch/instruction_set.h"
18 #include "interpreter/interpreter_common.h"
19 #include "nterp.h"
20 
21 /*
22  * Definitions for targets that support nterp.
23  */
24 
25 namespace art {
26 
27 namespace interpreter {
28 
IsNterpSupported()29 bool IsNterpSupported() {
30   return !kPoisonHeapReferences && kReserveMarkingRegister &&
31          kRuntimeISA != InstructionSet::kRiscv64;
32 }
33 
CanRuntimeUseNterp()34 bool CanRuntimeUseNterp() REQUIRES_SHARED(Locks::mutator_lock_) {
35   Runtime* runtime = Runtime::Current();
36   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
37   // If the runtime is interpreter only, we currently don't use nterp as some
38   // parts of the runtime (like instrumentation) make assumption on an
39   // interpreter-only runtime to always be in a switch-like interpreter.
40   return IsNterpSupported() && !runtime->IsJavaDebuggable() && !instr->EntryExitStubsInstalled() &&
41          !instr->InterpretOnly() && !runtime->IsAotCompiler() &&
42          !instr->NeedsSlowInterpreterForListeners() &&
43          // An async exception has been thrown. We need to go to the switch interpreter. nterp
44          // doesn't know how to deal with these so we could end up never dealing with it if we are
45          // in an infinite loop.
46          !runtime->AreAsyncExceptionsThrown() &&
47          (runtime->GetJit() == nullptr || !runtime->GetJit()->JitAtFirstUse());
48 }
49 
50 // The entrypoint for nterp, which ArtMethods can directly point to.
51 extern "C" void ExecuteNterpImpl() REQUIRES_SHARED(Locks::mutator_lock_);
52 
GetNterpEntryPoint()53 const void* GetNterpEntryPoint() {
54   return reinterpret_cast<const void*>(interpreter::ExecuteNterpImpl);
55 }
56 
57 // Another entrypoint, which does a clinit check at entry.
58 extern "C" void ExecuteNterpWithClinitImpl() REQUIRES_SHARED(Locks::mutator_lock_);
59 
GetNterpWithClinitEntryPoint()60 const void* GetNterpWithClinitEntryPoint() {
61   return reinterpret_cast<const void*>(interpreter::ExecuteNterpWithClinitImpl);
62 }
63 
64 /*
65  * Verify some constants used by the nterp interpreter.
66  */
CheckNterpAsmConstants()67 void CheckNterpAsmConstants() {
68   /*
69    * If we're using computed goto instruction transitions, make sure
70    * none of the handlers overflows the byte limit.  This won't tell
71    * which one did, but if any one is too big the total size will
72    * overflow.
73    */
74   const int width = kNterpHandlerSize;
75   ptrdiff_t interp_size = reinterpret_cast<uintptr_t>(artNterpAsmInstructionEnd) -
76                           reinterpret_cast<uintptr_t>(artNterpAsmInstructionStart);
77   if ((interp_size == 0) || (interp_size != (art::kNumPackedOpcodes * width))) {
78     LOG(FATAL) << "ERROR: unexpected asm interp size " << interp_size
79                << "(did an instruction handler exceed " << width << " bytes?)";
80   }
81 }
82 
83 }  // namespace interpreter
84 }  // namespace art
85