11452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee/*
21452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * Copyright (C) 2016 The Android Open Source Project
31452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee *
41452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * Licensed under the Apache License, Version 2.0 (the "License");
51452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * you may not use this file except in compliance with the License.
61452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * You may obtain a copy of the License at
71452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee *
81452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee *      http://www.apache.org/licenses/LICENSE-2.0
91452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee *
101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * Unless required by applicable law or agreed to in writing, software
111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * distributed under the License is distributed on an "AS IS" BASIS,
121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * See the License for the specific language governing permissions and
141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * limitations under the License.
151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee */
161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee/*
181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * Mterp entry point and support functions.
191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee */
201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee#include "interpreter/interpreter_common.h"
211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee#include "entrypoints/entrypoint_utils-inl.h"
221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee#include "mterp.h"
23fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee#include "debugger.h"
241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeenamespace art {
261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeenamespace interpreter {
271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee/*
281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * Verify some constants used by the mterp interpreter.
291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee */
301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeevoid CheckMterpAsmConstants() {
311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  /*
321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * If we're using computed goto instruction transitions, make sure
331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * none of the handlers overflows the 128-byte limit.  This won't tell
341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * which one did, but if any one is too big the total size will
351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * overflow.
361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   */
371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const int width = 128;
381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  int interp_size = (uintptr_t) artMterpAsmInstructionEnd -
391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                    (uintptr_t) artMterpAsmInstructionStart;
401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if ((interp_size == 0) || (interp_size != (art::kNumPackedOpcodes * width))) {
411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      LOG(art::FATAL) << "ERROR: unexpected asm interp size " << interp_size
421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                      << "(did an instruction handler exceed " << width << " bytes?)";
431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeevoid InitMterpTls(Thread* self) {
471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  self->SetMterpDefaultIBase(artMterpAsmInstructionStart);
481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  self->SetMterpAltIBase(artMterpAsmAltInstructionStart);
499fb0ac70e4627be7113533cc126483117bfca068Serguei Katkov  self->SetMterpCurrentIBase(TraceExecutionEnabled() ?
509fb0ac70e4627be7113533cc126483117bfca068Serguei Katkov                             artMterpAsmAltInstructionStart :
519fb0ac70e4627be7113533cc126483117bfca068Serguei Katkov                             artMterpAsmInstructionStart);
521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee/*
551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * Find the matching case.  Returns the offset to the handler instructions.
561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee *
571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * Returns 3 if we don't find a match (it's the size of the sparse-switch
581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * instruction).
591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee */
601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int32_t MterpDoSparseSwitch(const uint16_t* switchData, int32_t testVal) {
611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const int kInstrLen = 3;
621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t size;
631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const int32_t* keys;
641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const int32_t* entries;
651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  /*
671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * Sparse switch data format:
681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  ushort ident = 0x0200   magic value
691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  ushort size             number of entries in the table; > 0
701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  int targets[size]       branch targets, relative to switch opcode
721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *
731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * Total size is (2+size*4) 16-bit code units.
741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   */
751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t signature = *switchData++;
771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  DCHECK_EQ(signature, static_cast<uint16_t>(art::Instruction::kSparseSwitchSignature));
781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  size = *switchData++;
801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  /* The keys are guaranteed to be aligned on a 32-bit boundary;
821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * we can treat them as a native int array.
831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   */
841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  keys = reinterpret_cast<const int32_t*>(switchData);
851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  /* The entries are guaranteed to be aligned on a 32-bit boundary;
871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * we can treat them as a native int array.
881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   */
891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  entries = keys + size;
901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  /*
921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * Binary-search through the array of keys, which are guaranteed to
931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * be sorted low-to-high.
941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   */
951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  int lo = 0;
961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  int hi = size - 1;
971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  while (lo <= hi) {
981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    int mid = (lo + hi) >> 1;
991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    int32_t foundVal = keys[mid];
1011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    if (testVal < foundVal) {
1021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      hi = mid - 1;
1031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    } else if (testVal > foundVal) {
1041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      lo = mid + 1;
1051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    } else {
1061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      return entries[mid];
1071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    }
1081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
1091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return kInstrLen;
1101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
1111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int32_t MterpDoPackedSwitch(const uint16_t* switchData, int32_t testVal) {
1131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const int kInstrLen = 3;
1141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  /*
1161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * Packed switch data format:
1171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  ushort ident = 0x0100   magic value
1181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  ushort size             number of entries in the table
1191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  int first_key           first (and lowest) switch case value
1201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *  int targets[size]       branch targets, relative to switch opcode
1211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   *
1221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * Total size is (4+size*2) 16-bit code units.
1231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   */
1241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t signature = *switchData++;
1251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  DCHECK_EQ(signature, static_cast<uint16_t>(art::Instruction::kPackedSwitchSignature));
1261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t size = *switchData++;
1281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  int32_t firstKey = *switchData++;
1301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  firstKey |= (*switchData++) << 16;
1311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  int index = testVal - firstKey;
1331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (index < 0 || index >= size) {
1341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return kInstrLen;
1351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
1361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  /*
1381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * The entries are guaranteed to be aligned on a 32-bit boundary;
1391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   * we can treat them as a native int array.
1401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee   */
1411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const int32_t* entries = reinterpret_cast<const int32_t*>(switchData);
1421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return entries[index];
1431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
1441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
145fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbeeextern "C" bool MterpShouldSwitchInterpreters()
146fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
147fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  const instrumentation::Instrumentation* const instrumentation =
148fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee      Runtime::Current()->GetInstrumentation();
149db045bea24d28ce6ad932fec4ce055af7be530e2Alexey Frunze  return instrumentation->NonJitProfilingActive() || Dbg::IsDebuggerActive();
150fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee}
151fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee
1521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeVirtual(Thread* self, ShadowFrame* shadow_frame,
1541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                   uint16_t* dex_pc_ptr,  uint16_t inst_data )
1551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
1561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
1571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
1581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kVirtual, false, false>(
1591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
1601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
1611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeSuper(Thread* self, ShadowFrame* shadow_frame,
1631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                 uint16_t* dex_pc_ptr,  uint16_t inst_data )
1641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
1651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
1661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
1671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kSuper, false, false>(
1681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
1691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
1701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeInterface(Thread* self, ShadowFrame* shadow_frame,
1721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                     uint16_t* dex_pc_ptr,  uint16_t inst_data )
1731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
1741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
1751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
1761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kInterface, false, false>(
1771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
1781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
1791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeDirect(Thread* self, ShadowFrame* shadow_frame,
1811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                  uint16_t* dex_pc_ptr,  uint16_t inst_data )
1821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
1831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
1841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
1851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kDirect, false, false>(
1861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
1871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
1881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeStatic(Thread* self, ShadowFrame* shadow_frame,
1901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                  uint16_t* dex_pc_ptr,  uint16_t inst_data )
1911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
1921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
1931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
1941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kStatic, false, false>(
1951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
1961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
1971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
1981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeVirtualRange(Thread* self, ShadowFrame* shadow_frame,
1991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                        uint16_t* dex_pc_ptr,  uint16_t inst_data )
2001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
2021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
2031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kVirtual, true, false>(
2041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
2051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeSuperRange(Thread* self, ShadowFrame* shadow_frame,
2081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                      uint16_t* dex_pc_ptr,  uint16_t inst_data )
2091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
2111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
2121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kSuper, true, false>(
2131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
2141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeInterfaceRange(Thread* self, ShadowFrame* shadow_frame,
2171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                          uint16_t* dex_pc_ptr,  uint16_t inst_data )
2181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
2201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
2211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kInterface, true, false>(
2221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
2231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeDirectRange(Thread* self, ShadowFrame* shadow_frame,
2261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                       uint16_t* dex_pc_ptr,  uint16_t inst_data )
2271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
2291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
2301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kDirect, true, false>(
2311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
2321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeStaticRange(Thread* self, ShadowFrame* shadow_frame,
2351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                       uint16_t* dex_pc_ptr,  uint16_t inst_data )
2361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
2381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
2391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvoke<kStatic, true, false>(
2401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
2411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeVirtualQuick(Thread* self, ShadowFrame* shadow_frame,
2441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                        uint16_t* dex_pc_ptr,  uint16_t inst_data )
2451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
2471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
2481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvokeVirtualQuick<false>(
2491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
2501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpInvokeVirtualQuickRange(Thread* self, ShadowFrame* shadow_frame,
2531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                             uint16_t* dex_pc_ptr,  uint16_t inst_data )
2541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  JValue* result_register = shadow_frame->GetResultRegister();
2561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
2571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoInvokeVirtualQuick<true>(
2581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      self, *shadow_frame, inst, inst_data, result_register);
2591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpThreadFenceForConstructor() {
2621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  QuasiAtomic::ThreadFenceForConstructor();
2631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpConstString(uint32_t index, uint32_t tgt_vreg, ShadowFrame* shadow_frame,
2661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                 Thread* self)
2671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  String* s = ResolveString(self, *shadow_frame,  index);
2691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(s == nullptr)) {
2701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return true;
2711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
2721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  shadow_frame->SetVRegReference(tgt_vreg, s);
2731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return false;
2741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
2761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpConstClass(uint32_t index, uint32_t tgt_vreg, ShadowFrame* shadow_frame,
2771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                Thread* self)
2781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Class* c = ResolveVerifyAndClinit(index, shadow_frame->GetMethod(), self, false, false);
2801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(c == nullptr)) {
2811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return true;
2821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
2831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  shadow_frame->SetVRegReference(tgt_vreg, c);
2841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return false;
2851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
2861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
287a2c97a94ee9379b23204bfef87afacd4b60cae37buzbeeextern "C" bool MterpCheckCast(uint32_t index, StackReference<mirror::Object>* vreg_addr,
288a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee                               art::ArtMethod* method, Thread* self)
2891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
2901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Class* c = ResolveVerifyAndClinit(index, method, self, false, false);
2911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(c == nullptr)) {
2921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return true;
2931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
294a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee  // Must load obj from vreg following ResolveVerifyAndClinit due to moving gc.
295a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee  Object* obj = vreg_addr->AsMirrorPtr();
2961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
2971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    ThrowClassCastException(c, obj->GetClass());
2981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return true;
2991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
3001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return false;
3011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
303a2c97a94ee9379b23204bfef87afacd4b60cae37buzbeeextern "C" bool MterpInstanceOf(uint32_t index, StackReference<mirror::Object>* vreg_addr,
304a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee                                art::ArtMethod* method, Thread* self)
3051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Class* c = ResolveVerifyAndClinit(index, method, self, false, false);
3071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(c == nullptr)) {
3081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return false;  // Caller will check for pending exception.  Return value unimportant.
3091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
310a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee  // Must load obj from vreg following ResolveVerifyAndClinit due to moving gc.
311a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee  Object* obj = vreg_addr->AsMirrorPtr();
3121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return (obj != nullptr) && obj->InstanceOf(c);
3131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpFillArrayData(Object* obj, const Instruction::ArrayDataPayload* payload)
3161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return FillArrayData(obj, payload);
3181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpNewInstance(ShadowFrame* shadow_frame, Thread* self, uint32_t inst_data)
3211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
3231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Object* obj = nullptr;
3241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame->GetMethod(),
3251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                    self, false, false);
3261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(c != nullptr)) {
3271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    if (UNLIKELY(c->IsStringClass())) {
3281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
3291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      mirror::SetStringCountVisitor visitor(0);
3301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      obj = String::Alloc<true>(self, 0, allocator_type, visitor);
3311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    } else {
3321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      obj = AllocObjectFromCode<false, true>(
3331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee        inst->VRegB_21c(), shadow_frame->GetMethod(), self,
3341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee        Runtime::Current()->GetHeap()->GetCurrentAllocator());
3351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    }
3361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
3371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(obj == nullptr)) {
3381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return false;
3391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
3401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  obj->GetClass()->AssertInitializedOrInitializingInThread(self);
3411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  shadow_frame->SetVRegReference(inst->VRegA_21c(inst_data), obj);
3421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return true;
3431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpSputObject(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr,
3461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                uint32_t inst_data, Thread* self)
3471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
3491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, false, false>
3501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      (self, *shadow_frame, inst, inst_data);
3511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpIputObject(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr,
3541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                uint32_t inst_data, Thread* self)
3551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
3571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, false, false>
3581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      (self, *shadow_frame, inst, inst_data);
3591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpIputObjectQuick(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr,
3621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                     uint32_t inst_data)
3631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
3651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoIPutQuick<Primitive::kPrimNot, false>(*shadow_frame, inst, inst_data);
3661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpAputObject(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr,
3691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                uint32_t inst_data)
3701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
3721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Object* a = shadow_frame->GetVRegReference(inst->VRegB_23x());
3731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(a == nullptr)) {
3741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return false;
3751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
3761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  int32_t index = shadow_frame->GetVReg(inst->VRegC_23x());
3771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Object* val = shadow_frame->GetVRegReference(inst->VRegA_23x(inst_data));
3781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  ObjectArray<Object>* array = a->AsObjectArray<Object>();
3791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
3801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    array->SetWithoutChecks<false>(index, val);
3811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return true;
3821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
3831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return false;
3841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpFilledNewArray(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr,
3871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                    Thread* self)
3881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
3901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoFilledNewArray<false, false, false>(inst, *shadow_frame, self,
3911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                               shadow_frame->GetResultRegister());
3921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
3931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
3941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpFilledNewArrayRange(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr,
3951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                         Thread* self)
3961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
3971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
3981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return DoFilledNewArray<true, false, false>(inst, *shadow_frame, self,
3991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                              shadow_frame->GetResultRegister());
4001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpNewArray(ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr,
4031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                              uint32_t inst_data, Thread* self)
4041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(dex_pc_ptr);
4061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  int32_t length = shadow_frame->GetVReg(inst->VRegB_22c(inst_data));
4071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  Object* obj = AllocArrayFromCode<false, true>(
4081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      inst->VRegC_22c(), length, shadow_frame->GetMethod(), self,
4091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      Runtime::Current()->GetHeap()->GetCurrentAllocator());
4101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(obj == nullptr)) {
4111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      return false;
4121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
4131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  shadow_frame->SetVRegReference(inst->VRegA_22c(inst_data), obj);
4141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return true;
4151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" bool MterpHandleException(Thread* self, ShadowFrame* shadow_frame)
4181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  DCHECK(self->IsExceptionPending());
4201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const instrumentation::Instrumentation* const instrumentation =
4211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      Runtime::Current()->GetInstrumentation();
4221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame,
4231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                                                shadow_frame->GetDexPC(),
4241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                                                instrumentation);
4251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (found_dex_pc == DexFile::kDexNoIndex) {
4261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return false;
4271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
4281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  // OK - we can deal with it.  Update and continue.
4291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  shadow_frame->SetDexPC(found_dex_pc);
4301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return true;
4311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpCheckBefore(Thread* self, ShadowFrame* shadow_frame)
4341d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (inst->Opcode(inst_data) == Instruction::MOVE_EXCEPTION) {
4381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    self->AssertPendingException();
4391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  } else {
4401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    self->AssertNoPendingException();
4411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
4429fb0ac70e4627be7113533cc126483117bfca068Serguei Katkov  TraceExecution(*shadow_frame, inst, shadow_frame->GetDexPC());
4431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogDivideByZeroException(Thread* self, ShadowFrame* shadow_frame)
4461d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
4481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  LOG(INFO) << "DivideByZero: " << inst->Opcode(inst_data);
4511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogArrayIndexException(Thread* self, ShadowFrame* shadow_frame)
4541d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
4561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  LOG(INFO) << "ArrayIndex: " << inst->Opcode(inst_data);
4591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogNegativeArraySizeException(Thread* self, ShadowFrame* shadow_frame)
4621d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
4641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  LOG(INFO) << "NegativeArraySize: " << inst->Opcode(inst_data);
4671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogNoSuchMethodException(Thread* self, ShadowFrame* shadow_frame)
4701d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
4721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  LOG(INFO) << "NoSuchMethod: " << inst->Opcode(inst_data);
4751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogExceptionThrownException(Thread* self, ShadowFrame* shadow_frame)
4781d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
4801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  LOG(INFO) << "ExceptionThrown: " << inst->Opcode(inst_data);
4831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogNullObjectException(Thread* self, ShadowFrame* shadow_frame)
4861d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
4881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  LOG(INFO) << "NullObject: " << inst->Opcode(inst_data);
4911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
4921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
4931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogFallback(Thread* self, ShadowFrame* shadow_frame)
4941d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
4951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
4961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
4971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
4981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  LOG(INFO) << "Fallback: " << inst->Opcode(inst_data) << ", Suspend Pending?: "
4991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee            << self->IsExceptionPending();
5001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
5011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
502fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbeeextern "C" void MterpLogOSR(Thread* self, ShadowFrame* shadow_frame, int32_t offset)
5031d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
504fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  UNUSED(self);
505fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
506fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  uint16_t inst_data = inst->Fetch16(0);
507fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  LOG(INFO) << "OSR: " << inst->Opcode(inst_data) << ", offset = " << offset;
508fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee}
509fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee
5101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" void MterpLogSuspendFallback(Thread* self, ShadowFrame* shadow_frame, uint32_t flags)
5111d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
5121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  UNUSED(self);
5131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  const Instruction* inst = Instruction::At(shadow_frame->GetDexPCPtr());
5141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  uint16_t inst_data = inst->Fetch16(0);
5151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (flags & kCheckpointRequest) {
5161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    LOG(INFO) << "Checkpoint fallback: " << inst->Opcode(inst_data);
5171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  } else if (flags & kSuspendRequest) {
5181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    LOG(INFO) << "Suspend fallback: " << inst->Opcode(inst_data);
5191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
5201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
5211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
522fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbeeextern "C" bool MterpSuspendCheck(Thread* self)
5231d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
5241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  self->AllowThreadSuspension();
525fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  return MterpShouldSwitchInterpreters();
5261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
5271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
5281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int artSet64IndirectStaticFromMterp(uint32_t field_idx, ArtMethod* referrer,
5291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                               uint64_t* new_value, Thread* self)
5301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
5311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  ScopedQuickEntrypointChecks sqec(self);
532a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
5331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(field != nullptr)) {
5341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    // Compiled code can't use transactional mode.
5351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    field->Set64<false>(field->GetDeclaringClass(), *new_value);
5361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return 0;  // success
5371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
5381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
5391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(field != nullptr)) {
5401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    // Compiled code can't use transactional mode.
5411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    field->Set64<false>(field->GetDeclaringClass(), *new_value);
5421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return 0;  // success
5431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
5441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return -1;  // failure
5451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
5461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
5471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int artSet8InstanceFromMterp(uint32_t field_idx, mirror::Object* obj, uint8_t new_value,
5481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                        ArtMethod* referrer)
5491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
550a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
5511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(field != nullptr && obj != nullptr)) {
5521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    Primitive::Type type = field->GetTypeAsPrimitiveType();
5531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    if (type == Primitive::kPrimBoolean) {
5541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      field->SetBoolean<false>(obj, new_value);
5551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    } else {
5561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      DCHECK_EQ(Primitive::kPrimByte, type);
5571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      field->SetByte<false>(obj, new_value);
5581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    }
5591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return 0;  // success
5601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
5611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return -1;  // failure
5621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
5631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
5641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int artSet16InstanceFromMterp(uint32_t field_idx, mirror::Object* obj, uint16_t new_value,
5651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                        ArtMethod* referrer)
5661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
5671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
5681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                          sizeof(int16_t));
5691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(field != nullptr && obj != nullptr)) {
5701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    Primitive::Type type = field->GetTypeAsPrimitiveType();
5711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    if (type == Primitive::kPrimChar) {
5721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      field->SetChar<false>(obj, new_value);
5731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    } else {
5741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      DCHECK_EQ(Primitive::kPrimShort, type);
5751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee      field->SetShort<false>(obj, new_value);
5761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    }
5771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return 0;  // success
5781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
5791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return -1;  // failure
5801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
5811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
5821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int artSet32InstanceFromMterp(uint32_t field_idx, mirror::Object* obj,
5831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                         uint32_t new_value, ArtMethod* referrer)
5841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
5851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
5861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                          sizeof(int32_t));
5871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(field != nullptr && obj != nullptr)) {
5881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    field->Set32<false>(obj, new_value);
5891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return 0;  // success
5901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
5911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return -1;  // failure
5921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
5931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
5941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int artSet64InstanceFromMterp(uint32_t field_idx, mirror::Object* obj,
5951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                         uint64_t* new_value, ArtMethod* referrer)
5961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
5971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
5981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                          sizeof(int64_t));
5991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(field != nullptr  && obj != nullptr)) {
6001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    field->Set64<false>(obj, *new_value);
6011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return 0;  // success
6021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
6031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return -1;  // failure
6041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
6051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
6061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" int artSetObjInstanceFromMterp(uint32_t field_idx, mirror::Object* obj,
607a2c97a94ee9379b23204bfef87afacd4b60cae37buzbee                                          mirror::Object* new_value, ArtMethod* referrer)
6081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
6091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
6101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee                                          sizeof(mirror::HeapReference<mirror::Object>));
6111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(field != nullptr && obj != nullptr)) {
6121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    field->SetObj<false>(obj, new_value);
6131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return 0;  // success
6141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
6151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  return -1;  // failure
6161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
6171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
6181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeextern "C" mirror::Object* artAGetObjectFromMterp(mirror::Object* arr, int32_t index)
6191d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
6201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (UNLIKELY(arr == nullptr)) {
6211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    ThrowNullPointerExceptionFromInterpreter();
6221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return nullptr;
6231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
6241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  ObjectArray<Object>* array = arr->AsObjectArray<Object>();
6251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  if (LIKELY(array->CheckIsValidIndex(index))) {
6261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return array->GetWithoutChecks(index);
6271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  } else {
6281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee    return nullptr;
6291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee  }
6301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}
6311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee
63276833da70bb9e493201a675d2718dca0f2cc256cbuzbeeextern "C" mirror::Object* artIGetObjectFromMterp(mirror::Object* obj, uint32_t field_offset)
6331d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
63476833da70bb9e493201a675d2718dca0f2cc256cbuzbee  if (UNLIKELY(obj == nullptr)) {
63576833da70bb9e493201a675d2718dca0f2cc256cbuzbee    ThrowNullPointerExceptionFromInterpreter();
63676833da70bb9e493201a675d2718dca0f2cc256cbuzbee    return nullptr;
63776833da70bb9e493201a675d2718dca0f2cc256cbuzbee  }
63876833da70bb9e493201a675d2718dca0f2cc256cbuzbee  return obj->GetFieldObject<mirror::Object>(MemberOffset(field_offset));
63976833da70bb9e493201a675d2718dca0f2cc256cbuzbee}
64076833da70bb9e493201a675d2718dca0f2cc256cbuzbee
6411d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee/*
6421d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee * Create a hotness_countdown based on the current method hotness_count and profiling
6431d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee * mode.  In short, determine how many hotness events we hit before reporting back
6441d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee * to the full instrumentation via MterpAddHotnessBatch.  Called once on entry to the method,
6451d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee * and regenerated following batch updates.
6461d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee */
6471d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbeeextern "C" int MterpSetUpHotnessCountdown(ArtMethod* method, ShadowFrame* shadow_frame)
6481d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
6491d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  uint16_t hotness_count = method->GetCounter();
6501d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  int32_t countdown_value = jit::kJitHotnessDisabled;
6511d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  jit::Jit* jit = Runtime::Current()->GetJit();
6521d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  if (jit != nullptr) {
653bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray    int32_t warm_threshold = jit->WarmMethodThreshold();
654bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray    int32_t hot_threshold = jit->HotMethodThreshold();
655bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray    int32_t osr_threshold = jit->OSRMethodThreshold();
6561d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    if (hotness_count < warm_threshold) {
6571d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee      countdown_value = warm_threshold - hotness_count;
6581d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    } else if (hotness_count < hot_threshold) {
6591d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee      countdown_value = hot_threshold - hotness_count;
6601d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    } else if (hotness_count < osr_threshold) {
6611d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee      countdown_value = osr_threshold - hotness_count;
6621d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    } else {
6631d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee      countdown_value = jit::kJitCheckForOSR;
6641d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    }
665b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle    if (jit::Jit::ShouldUsePriorityThreadWeight()) {
666bb11c8b1219f5b4b3154c2c83fca19ec8add6646Nicolas Geoffray      int32_t priority_thread_weight = jit->PriorityThreadWeight();
667b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle      countdown_value = std::min(countdown_value, countdown_value / priority_thread_weight);
668b2771b41a956b50266d4d83fbb067f99faf7b7dcCalin Juravle    }
6691d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  }
6701d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  /*
6711d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee   * The actual hotness threshold may exceed the range of our int16_t countdown value.  This is
6721d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee   * not a problem, though.  We can just break it down into smaller chunks.
6731d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee   */
6741d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  countdown_value = std::min(countdown_value,
6751d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee                             static_cast<int32_t>(std::numeric_limits<int16_t>::max()));
6761d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  shadow_frame->SetCachedHotnessCountdown(countdown_value);
6771d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  shadow_frame->SetHotnessCountdown(countdown_value);
6781d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  return countdown_value;
6791d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee}
6801d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee
6811d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee/*
6821d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee * Report a batch of hotness events to the instrumentation and then return the new
6831d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee * countdown value to the next time we should report.
6841d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee */
6851d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbeeextern "C" int16_t MterpAddHotnessBatch(ArtMethod* method,
6861d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee                                        ShadowFrame* shadow_frame,
6871d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee                                        Thread* self)
6881d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
6891d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  jit::Jit* jit = Runtime::Current()->GetJit();
6901d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  if (jit != nullptr) {
6911d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    int16_t count = shadow_frame->GetCachedHotnessCountdown() - shadow_frame->GetHotnessCountdown();
692f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray    jit->AddSamples(self, method, count, /*with_backedges*/ true);
6931d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  }
6941d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  return MterpSetUpHotnessCountdown(method, shadow_frame);
6951d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee}
6961d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee
6978a06497868d5b5cb990a04fbd8ab20b3edec139cBill Buzbee// TUNING: Unused by arm/arm64/x86/x86_64.  Remove when mips/mips64 mterps support batch updates.
698fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbeeextern "C" bool  MterpProfileBranch(Thread* self, ShadowFrame* shadow_frame, int32_t offset)
6991d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
7001d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  ArtMethod* method = shadow_frame->GetMethod();
7011d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  JValue* result = shadow_frame->GetResultRegister();
7021d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  uint32_t dex_pc = shadow_frame->GetDexPC();
7031d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  jit::Jit* jit = Runtime::Current()->GetJit();
7041d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  if ((jit != nullptr) && (offset <= 0)) {
705f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray    jit->AddSamples(self, method, 1, /*with_backedges*/ true);
7061d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  }
7071d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  int16_t countdown_value = MterpSetUpHotnessCountdown(method, shadow_frame);
7081d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  if (countdown_value == jit::kJitCheckForOSR) {
7091d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    return jit::Jit::MaybeDoOnStackReplacement(self, method, dex_pc, offset, result);
7101d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  } else {
7111d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    return false;
7121d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  }
7131d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee}
7141d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee
7151d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbeeextern "C" bool MterpMaybeDoOnStackReplacement(Thread* self,
7161d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee                                               ShadowFrame* shadow_frame,
7171d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee                                               int32_t offset)
7181d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee    SHARED_REQUIRES(Locks::mutator_lock_) {
719fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  ArtMethod* method = shadow_frame->GetMethod();
720fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  JValue* result = shadow_frame->GetResultRegister();
721fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  uint32_t dex_pc = shadow_frame->GetDexPC();
7220e6aa6d945048345dee93f87070df6a62b31f680buzbee  jit::Jit* jit = Runtime::Current()->GetJit();
7230e6aa6d945048345dee93f87070df6a62b31f680buzbee  if (offset <= 0) {
7240e6aa6d945048345dee93f87070df6a62b31f680buzbee    // Keep updating hotness in case a compilation request was dropped.  Eventually it will retry.
725f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray    jit->AddSamples(self, method, 1, /*with_backedges*/ true);
7260e6aa6d945048345dee93f87070df6a62b31f680buzbee  }
7271d011d9306fd4ff57d72411775d415a86f5ed398Bill Buzbee  // Assumes caller has already determined that an OSR check is appropriate.
728fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee  return jit::Jit::MaybeDoOnStackReplacement(self, method, dex_pc, offset, result);
729fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee}
730fd522f9039befff986701ff05054ffdd1be1dd33Bill Buzbee
7311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}  // namespace interpreter
7321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee}  // namespace art
733