1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
18 #define ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
19 
20 #include "interpreter.h"
21 
22 #include <math.h>
23 
24 #include <iostream>
25 #include <sstream>
26 
27 #include "art_field-inl.h"
28 #include "art_method-inl.h"
29 #include "base/logging.h"
30 #include "base/macros.h"
31 #include "class_linker-inl.h"
32 #include "common_throws.h"
33 #include "dex_file-inl.h"
34 #include "dex_instruction-inl.h"
35 #include "entrypoints/entrypoint_utils-inl.h"
36 #include "handle_scope-inl.h"
37 #include "mirror/class-inl.h"
38 #include "mirror/object-inl.h"
39 #include "mirror/object_array-inl.h"
40 #include "mirror/string-inl.h"
41 #include "thread.h"
42 #include "well_known_classes.h"
43 
44 using ::art::ArtMethod;
45 using ::art::mirror::Array;
46 using ::art::mirror::BooleanArray;
47 using ::art::mirror::ByteArray;
48 using ::art::mirror::CharArray;
49 using ::art::mirror::Class;
50 using ::art::mirror::ClassLoader;
51 using ::art::mirror::IntArray;
52 using ::art::mirror::LongArray;
53 using ::art::mirror::Object;
54 using ::art::mirror::ObjectArray;
55 using ::art::mirror::ShortArray;
56 using ::art::mirror::String;
57 using ::art::mirror::Throwable;
58 
59 namespace art {
60 namespace interpreter {
61 
62 // External references to both interpreter implementations.
63 
64 template<bool do_access_check, bool transaction_active>
65 extern JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
66                                 ShadowFrame& shadow_frame, JValue result_register);
67 
68 template<bool do_access_check, bool transaction_active>
69 extern JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item,
70                               ShadowFrame& shadow_frame, JValue result_register);
71 
72 void ThrowNullPointerExceptionFromInterpreter()
73     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
74 
DoMonitorEnter(Thread * self,Object * ref)75 static inline void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
76   ref->MonitorEnter(self);
77 }
78 
DoMonitorExit(Thread * self,Object * ref)79 static inline void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
80   ref->MonitorExit(self);
81 }
82 
83 void AbortTransactionF(Thread* self, const char* fmt, ...)
84     __attribute__((__format__(__printf__, 2, 3)))
85     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
86 
87 void AbortTransactionV(Thread* self, const char* fmt, va_list args)
88     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
89 
90 void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count)
91     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
92 
93 // Invokes the given method. This is part of the invocation support and is used by DoInvoke and
94 // DoInvokeVirtualQuick functions.
95 // Returns true on success, otherwise throws an exception and returns false.
96 template<bool is_range, bool do_assignability_check>
97 bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame,
98             const Instruction* inst, uint16_t inst_data, JValue* result);
99 
100 // Handles invoke-XXX/range instructions.
101 // Returns true on success, otherwise throws an exception and returns false.
102 template<InvokeType type, bool is_range, bool do_access_check>
DoInvoke(Thread * self,ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result)103 static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
104                             uint16_t inst_data, JValue* result) {
105   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
106   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
107   Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
108   ArtMethod* sf_method = shadow_frame.GetMethod();
109   ArtMethod* const called_method = FindMethodFromCode<type, do_access_check>(
110       method_idx, &receiver, &sf_method, self);
111   // The shadow frame should already be pushed, so we don't need to update it.
112   if (UNLIKELY(called_method == nullptr)) {
113     CHECK(self->IsExceptionPending());
114     result->SetJ(0);
115     return false;
116   } else if (UNLIKELY(called_method->IsAbstract())) {
117     ThrowAbstractMethodError(called_method);
118     result->SetJ(0);
119     return false;
120   } else {
121     return DoCall<is_range, do_access_check>(called_method, self, shadow_frame, inst, inst_data,
122                                              result);
123   }
124 }
125 
126 // Handles invoke-virtual-quick and invoke-virtual-quick-range instructions.
127 // Returns true on success, otherwise throws an exception and returns false.
128 template<bool is_range>
DoInvokeVirtualQuick(Thread * self,ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result)129 static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
130                                         const Instruction* inst, uint16_t inst_data,
131                                         JValue* result) {
132   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
133   Object* const receiver = shadow_frame.GetVRegReference(vregC);
134   if (UNLIKELY(receiver == nullptr)) {
135     // We lost the reference to the method index so we cannot get a more
136     // precised exception message.
137     ThrowNullPointerExceptionFromDexPC();
138     return false;
139   }
140   const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
141   CHECK(receiver->GetClass()->ShouldHaveEmbeddedImtAndVTable());
142   ArtMethod* const called_method = receiver->GetClass()->GetEmbeddedVTableEntry(
143       vtable_idx, sizeof(void*));
144   if (UNLIKELY(called_method == nullptr)) {
145     CHECK(self->IsExceptionPending());
146     result->SetJ(0);
147     return false;
148   } else if (UNLIKELY(called_method->IsAbstract())) {
149     ThrowAbstractMethodError(called_method);
150     result->SetJ(0);
151     return false;
152   } else {
153     // No need to check since we've been quickened.
154     return DoCall<is_range, false>(called_method, self, shadow_frame, inst, inst_data, result);
155   }
156 }
157 
158 // Handles iget-XXX and sget-XXX instructions.
159 // Returns true on success, otherwise throws an exception and returns false.
160 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
161 bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
162                 uint16_t inst_data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
163 
164 // Handles iget-quick, iget-wide-quick and iget-object-quick instructions.
165 // Returns true on success, otherwise throws an exception and returns false.
166 template<Primitive::Type field_type>
167 bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
168     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
169 
170 // Handles iput-XXX and sput-XXX instructions.
171 // Returns true on success, otherwise throws an exception and returns false.
172 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check,
173          bool transaction_active>
174 bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction* inst,
175                 uint16_t inst_data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
176 
177 // Handles iput-quick, iput-wide-quick and iput-object-quick instructions.
178 // Returns true on success, otherwise throws an exception and returns false.
179 template<Primitive::Type field_type, bool transaction_active>
180 bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
181     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
182 
183 
184 // Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
185 // java.lang.String class is initialized.
ResolveString(Thread * self,ShadowFrame & shadow_frame,uint32_t string_idx)186 static inline String* ResolveString(Thread* self, ShadowFrame& shadow_frame, uint32_t string_idx)
187     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
188   Class* java_lang_string_class = String::GetJavaLangString();
189   if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
190     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
191     StackHandleScope<1> hs(self);
192     Handle<mirror::Class> h_class(hs.NewHandle(java_lang_string_class));
193     if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) {
194       DCHECK(self->IsExceptionPending());
195       return nullptr;
196     }
197   }
198   ArtMethod* method = shadow_frame.GetMethod();
199   mirror::Class* declaring_class = method->GetDeclaringClass();
200   mirror::String* s = declaring_class->GetDexCacheStrings()->Get(string_idx);
201   if (UNLIKELY(s == nullptr)) {
202     StackHandleScope<1> hs(self);
203     Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
204     s = Runtime::Current()->GetClassLinker()->ResolveString(*method->GetDexFile(), string_idx,
205                                                             dex_cache);
206   }
207   return s;
208 }
209 
210 // Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions.
211 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoIntDivide(ShadowFrame & shadow_frame,size_t result_reg,int32_t dividend,int32_t divisor)212 static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
213                                int32_t dividend, int32_t divisor)
214     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
215   constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
216   if (UNLIKELY(divisor == 0)) {
217     ThrowArithmeticExceptionDivideByZero();
218     return false;
219   }
220   if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
221     shadow_frame.SetVReg(result_reg, kMinInt);
222   } else {
223     shadow_frame.SetVReg(result_reg, dividend / divisor);
224   }
225   return true;
226 }
227 
228 // Handles rem-int, rem-int/2addr, rem-int/li16 and rem-int/lit8 instructions.
229 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoIntRemainder(ShadowFrame & shadow_frame,size_t result_reg,int32_t dividend,int32_t divisor)230 static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
231                                   int32_t dividend, int32_t divisor)
232     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
233   constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
234   if (UNLIKELY(divisor == 0)) {
235     ThrowArithmeticExceptionDivideByZero();
236     return false;
237   }
238   if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
239     shadow_frame.SetVReg(result_reg, 0);
240   } else {
241     shadow_frame.SetVReg(result_reg, dividend % divisor);
242   }
243   return true;
244 }
245 
246 // Handles div-long and div-long-2addr instructions.
247 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoLongDivide(ShadowFrame & shadow_frame,size_t result_reg,int64_t dividend,int64_t divisor)248 static inline bool DoLongDivide(ShadowFrame& shadow_frame, size_t result_reg,
249                                 int64_t dividend, int64_t divisor)
250     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
251   const int64_t kMinLong = std::numeric_limits<int64_t>::min();
252   if (UNLIKELY(divisor == 0)) {
253     ThrowArithmeticExceptionDivideByZero();
254     return false;
255   }
256   if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
257     shadow_frame.SetVRegLong(result_reg, kMinLong);
258   } else {
259     shadow_frame.SetVRegLong(result_reg, dividend / divisor);
260   }
261   return true;
262 }
263 
264 // Handles rem-long and rem-long-2addr instructions.
265 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoLongRemainder(ShadowFrame & shadow_frame,size_t result_reg,int64_t dividend,int64_t divisor)266 static inline bool DoLongRemainder(ShadowFrame& shadow_frame, size_t result_reg,
267                                    int64_t dividend, int64_t divisor)
268     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
269   const int64_t kMinLong = std::numeric_limits<int64_t>::min();
270   if (UNLIKELY(divisor == 0)) {
271     ThrowArithmeticExceptionDivideByZero();
272     return false;
273   }
274   if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
275     shadow_frame.SetVRegLong(result_reg, 0);
276   } else {
277     shadow_frame.SetVRegLong(result_reg, dividend % divisor);
278   }
279   return true;
280 }
281 
282 // Handles filled-new-array and filled-new-array-range instructions.
283 // Returns true on success, otherwise throws an exception and returns false.
284 template <bool is_range, bool do_access_check, bool transaction_active>
285 bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
286                       Thread* self, JValue* result);
287 
288 // Handles packed-switch instruction.
289 // Returns the branch offset to the next instruction to execute.
DoPackedSwitch(const Instruction * inst,const ShadowFrame & shadow_frame,uint16_t inst_data)290 static inline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
291                                      uint16_t inst_data)
292     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
293   DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH);
294   const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
295   int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
296   DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
297   uint16_t size = switch_data[1];
298   if (size == 0) {
299     // Empty packed switch, move forward by 3 (size of PACKED_SWITCH).
300     return 3;
301   }
302   const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
303   DCHECK(IsAligned<4>(keys));
304   int32_t first_key = keys[0];
305   const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
306   DCHECK(IsAligned<4>(targets));
307   int32_t index = test_val - first_key;
308   if (index >= 0 && index < size) {
309     return targets[index];
310   } else {
311     // No corresponding value: move forward by 3 (size of PACKED_SWITCH).
312     return 3;
313   }
314 }
315 
316 // Handles sparse-switch instruction.
317 // Returns the branch offset to the next instruction to execute.
DoSparseSwitch(const Instruction * inst,const ShadowFrame & shadow_frame,uint16_t inst_data)318 static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
319                                      uint16_t inst_data)
320     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
321   DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
322   const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
323   int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
324   DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
325   uint16_t size = switch_data[1];
326   // Return length of SPARSE_SWITCH if size is 0.
327   if (size == 0) {
328     return 3;
329   }
330   const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
331   DCHECK(IsAligned<4>(keys));
332   const int32_t* entries = keys + size;
333   DCHECK(IsAligned<4>(entries));
334   int lo = 0;
335   int hi = size - 1;
336   while (lo <= hi) {
337     int mid = (lo + hi) / 2;
338     int32_t foundVal = keys[mid];
339     if (test_val < foundVal) {
340       hi = mid - 1;
341     } else if (test_val > foundVal) {
342       lo = mid + 1;
343     } else {
344       return entries[mid];
345     }
346   }
347   // No corresponding value: move forward by 3 (size of SPARSE_SWITCH).
348   return 3;
349 }
350 
351 uint32_t FindNextInstructionFollowingException(Thread* self, ShadowFrame& shadow_frame,
352     uint32_t dex_pc, const instrumentation::Instrumentation* instrumentation)
353         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
354 
355 NO_RETURN void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame)
356   __attribute__((cold))
357   SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
358 
TraceExecution(const ShadowFrame & shadow_frame,const Instruction * inst,const uint32_t dex_pc)359 static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
360                                   const uint32_t dex_pc)
361     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
362   constexpr bool kTracing = false;
363   if (kTracing) {
364 #define TRACE_LOG std::cerr
365     std::ostringstream oss;
366     oss << PrettyMethod(shadow_frame.GetMethod())
367         << StringPrintf("\n0x%x: ", dex_pc)
368         << inst->DumpString(shadow_frame.GetMethod()->GetDexFile()) << "\n";
369     for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
370       uint32_t raw_value = shadow_frame.GetVReg(i);
371       Object* ref_value = shadow_frame.GetVRegReference(i);
372       oss << StringPrintf(" vreg%u=0x%08X", i, raw_value);
373       if (ref_value != nullptr) {
374         if (ref_value->GetClass()->IsStringClass() &&
375             ref_value->AsString()->GetValue() != nullptr) {
376           oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
377         } else {
378           oss << "/" << PrettyTypeOf(ref_value);
379         }
380       }
381     }
382     TRACE_LOG << oss.str() << "\n";
383 #undef TRACE_LOG
384   }
385 }
386 
IsBackwardBranch(int32_t branch_offset)387 static inline bool IsBackwardBranch(int32_t branch_offset) {
388   return branch_offset <= 0;
389 }
390 
391 // Explicitly instantiate all DoInvoke functions.
392 #define EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, _is_range, _do_check)                      \
393   template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                     \
394   bool DoInvoke<_type, _is_range, _do_check>(Thread* self, ShadowFrame& shadow_frame,      \
395                                              const Instruction* inst, uint16_t inst_data,  \
396                                              JValue* result)
397 
398 #define EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(_type)       \
399   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, false);  \
400   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, true);   \
401   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, false);   \
402   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, true);
403 
404 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kStatic)      // invoke-static/range.
405 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kDirect)      // invoke-direct/range.
406 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kVirtual)     // invoke-virtual/range.
407 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kSuper)       // invoke-super/range.
408 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kInterface)   // invoke-interface/range.
409 #undef EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL
410 #undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL
411 
412 // Explicitly instantiate all DoInvokeVirtualQuick functions.
413 #define EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(_is_range)                    \
414   template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                               \
415   bool DoInvokeVirtualQuick<_is_range>(Thread* self, ShadowFrame& shadow_frame,      \
416                                        const Instruction* inst, uint16_t inst_data,  \
417                                        JValue* result)
418 
419 EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(false);  // invoke-virtual-quick.
420 EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(true);   // invoke-virtual-quick-range.
421 #undef EXPLICIT_INSTANTIATION_DO_INVOKE_VIRTUAL_QUICK
422 
423 
424 }  // namespace interpreter
425 }  // namespace art
426 
427 #endif  // ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
428