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