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()29bool IsNterpSupported() { 30 return !kPoisonHeapReferences && kReserveMarkingRegister && 31 kRuntimeISA != InstructionSet::kRiscv64; 32 } 33 CanRuntimeUseNterp()34bool 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()53const 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()60const void* GetNterpWithClinitEntryPoint() { 61 return reinterpret_cast<const void*>(interpreter::ExecuteNterpWithClinitImpl); 62 } 63 64 /* 65 * Verify some constants used by the nterp interpreter. 66 */ CheckNterpAsmConstants()67void 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