// Invokes the given method. This is part of the invocation support and is used by DoInvoke, // DoFastInvoke and DoInvokeVirtualQuick functions. // Returns true on success, otherwise throws an exception and returns false. template<bool is_range>
EXPORT bool DoCall(ArtMethod* called_method,
Thread* self,
ShadowFrame& shadow_frame, const Instruction* inst,
uint16_t inst_data, bool string_init,
JValue* result);
// Fill the ShadowFrame from stored values in the parked virtual thread.
EXPORT void FillVirtualThreadFrame(Thread* self, ShadowFrame* this_frame)
REQUIRES_SHARED(Locks::mutator_lock_);
// Called by the switch interpreter to know if we can stay in it. bool ShouldStayInSwitchInterpreter(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_);
// Throws exception if we are getting close to the end of the stack.
NO_INLINE bool CheckStackOverflow(Thread* self, size_t frame_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Sends the normal method exit event. // Returns true if the events succeeded and false if there is a pending exception. template <typename T> bool SendMethodExitEvents(
Thread* self, const instrumentation::Instrumentation* instrumentation,
ShadowFrame& frame,
ArtMethod* method,
T& result) REQUIRES_SHARED(Locks::mutator_lock_);
// Handles filled-new-array and filled-new-array-range instructions. // Returns true on success, otherwise throws an exception and returns false. template <bool is_range>
EXPORT bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
Thread* self,
JValue* result);
// Handles packed-switch instruction. // Returns the branch offset to the next instruction to execute. staticinline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
uint16_t inst_data)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH); const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
uint16_t size = switch_data[1]; if (size == 0) { // Empty packed switch, move forward by 3 (size of PACKED_SWITCH). return3;
} const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
DCHECK_ALIGNED(keys, 4);
int32_t first_key = keys[0]; const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
DCHECK_ALIGNED(targets, 4);
int32_t index = test_val - first_key; if (index >= 0 && index < size) { return targets[index];
} else { // No corresponding value: move forward by 3 (size of PACKED_SWITCH). return3;
}
}
// Handles sparse-switch instruction. // Returns the branch offset to the next instruction to execute. staticinline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
uint16_t inst_data)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH); const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
uint16_t size = switch_data[1]; // Return length of SPARSE_SWITCH if size is 0. if (size == 0) { return3;
} const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
DCHECK_ALIGNED(keys, 4); const int32_t* entries = keys + size;
DCHECK_ALIGNED(entries, 4); int lo = 0; int hi = size - 1; while (lo <= hi) { int mid = (lo + hi) / 2;
int32_t foundVal = keys[mid]; if (test_val < foundVal) {
hi = mid - 1;
} elseif (test_val > foundVal) {
lo = mid + 1;
} else { return entries[mid];
}
} // No corresponding value: move forward by 3 (size of SPARSE_SWITCH). return3;
}
// We execute any instrumentation events triggered by throwing and/or handing the pending exception // and change the shadow_frames dex_pc to the appropriate exception handler if the current method // has one. If the exception has been handled and the shadow_frame is now pointing to a catch clause // we return true. If the current method is unable to handle the exception we return false. // This function accepts a null Instrumentation* as a way to cause instrumentation events not to be // reported. // TODO We might wish to reconsider how we cause some events to be ignored.
EXPORT bool MoveToExceptionHandler(Thread* self,
ShadowFrame& shadow_frame, bool skip_listeners, bool skip_throw_listener) REQUIRES_SHARED(Locks::mutator_lock_);
NO_RETURN EXPORT void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame)
COLD_ATTR
REQUIRES_SHARED(Locks::mutator_lock_);
// Set true if you want TraceExecution invocation before each bytecode execution.
constexpr bool kTraceExecutionEnabled = false;
// The arg_offset is the offset to the first input register in the frame. void ArtInterpreterToCompiledCodeBridge(Thread* self,
ArtMethod* caller,
ShadowFrame* shadow_frame,
uint16_t arg_offset,
JValue* result);
// Set string value created from StringFactory.newStringFromXXX() into all aliases of // StringFactory.newEmptyString(). void SetStringInitValueToAllAliases(ShadowFrame* shadow_frame,
uint16_t this_obj_vreg,
JValue result);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.