1 /* 2 * Copyright (C) 2012 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 #ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_H_ 18 #define ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_H_ 19 20 #include "base/locks.h" 21 #include "base/macros.h" 22 #include "dex/dex_file.h" 23 #include "dex/code_item_accessors.h" 24 #include "jvalue.h" 25 #include "obj_ptr.h" 26 27 namespace art { 28 29 class ShadowFrame; 30 class Thread; 31 32 namespace interpreter { 33 34 // Group all the data that is needed in the switch interpreter. 35 // We need to pass it to the hand-written assembly and back, 36 // so it is easier to pass it through a single pointer. 37 // Similarly, returning the JValue type would be non-trivial. 38 struct SwitchImplContext { 39 Thread* self; 40 const CodeItemDataAccessor& accessor; 41 ShadowFrame& shadow_frame; 42 JValue& result_register; 43 bool interpret_one_instruction; 44 JValue result; 45 }; 46 47 // The actual internal implementation of the switch interpreter. 48 template<bool do_access_check, bool transaction_active> 49 void ExecuteSwitchImplCpp(SwitchImplContext* ctx) 50 REQUIRES_SHARED(Locks::mutator_lock_); 51 52 // Hand-written assembly method which wraps the C++ implementation, 53 // while defining the DEX PC in the CFI so that libunwind can resolve it. 54 extern "C" void ExecuteSwitchImplAsm(SwitchImplContext* ctx, void* impl, const uint16_t* dexpc) 55 REQUIRES_SHARED(Locks::mutator_lock_); 56 57 // Wrapper around the switch interpreter which ensures we can unwind through it. 58 template<bool do_access_check, bool transaction_active> 59 ALWAYS_INLINE JValue ExecuteSwitchImpl(Thread* self, const CodeItemDataAccessor& accessor, 60 ShadowFrame& shadow_frame, JValue result_register, 61 bool interpret_one_instruction) 62 REQUIRES_SHARED(Locks::mutator_lock_) { 63 SwitchImplContext ctx { 64 .self = self, 65 .accessor = accessor, 66 .shadow_frame = shadow_frame, 67 .result_register = result_register, 68 .interpret_one_instruction = interpret_one_instruction, 69 .result = JValue(), 70 }; 71 void* impl = reinterpret_cast<void*>(&ExecuteSwitchImplCpp<do_access_check, transaction_active>); 72 const uint16_t* dex_pc = ctx.accessor.Insns(); 73 ExecuteSwitchImplAsm(&ctx, impl, dex_pc); 74 return ctx.result; 75 } 76 77 } // namespace interpreter 78 } // namespace art 79 80 #endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_H_ 81