• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "interpreter.h"
18 
19 #include <limits>
20 
21 #include "common_throws.h"
22 #include "interpreter_common.h"
23 #include "interpreter_mterp_impl.h"
24 #include "interpreter_switch_impl.h"
25 #include "jvalue-inl.h"
26 #include "mirror/string-inl.h"
27 #include "scoped_thread_state_change-inl.h"
28 #include "ScopedLocalRef.h"
29 #include "stack.h"
30 #include "unstarted_runtime.h"
31 #include "mterp/mterp.h"
32 #include "jit/jit.h"
33 #include "jit/jit_code_cache.h"
34 
35 namespace art {
36 namespace interpreter {
37 
ObjArg(uint32_t arg)38 ALWAYS_INLINE static ObjPtr<mirror::Object> ObjArg(uint32_t arg)
39     REQUIRES_SHARED(Locks::mutator_lock_) {
40   return ObjPtr<mirror::Object>(reinterpret_cast<mirror::Object*>(arg));
41 }
42 
InterpreterJni(Thread * self,ArtMethod * method,const StringPiece & shorty,ObjPtr<mirror::Object> receiver,uint32_t * args,JValue * result)43 static void InterpreterJni(Thread* self,
44                            ArtMethod* method,
45                            const StringPiece& shorty,
46                            ObjPtr<mirror::Object> receiver,
47                            uint32_t* args,
48                            JValue* result)
49     REQUIRES_SHARED(Locks::mutator_lock_) {
50   // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
51   //       it should be removed and JNI compiled stubs used instead.
52   ScopedObjectAccessUnchecked soa(self);
53   if (method->IsStatic()) {
54     if (shorty == "L") {
55       typedef jobject (fntype)(JNIEnv*, jclass);
56       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
57       ScopedLocalRef<jclass> klass(soa.Env(),
58                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
59       jobject jresult;
60       {
61         ScopedThreadStateChange tsc(self, kNative);
62         jresult = fn(soa.Env(), klass.get());
63       }
64       result->SetL(soa.Decode<mirror::Object>(jresult));
65     } else if (shorty == "V") {
66       typedef void (fntype)(JNIEnv*, jclass);
67       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
68       ScopedLocalRef<jclass> klass(soa.Env(),
69                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
70       ScopedThreadStateChange tsc(self, kNative);
71       fn(soa.Env(), klass.get());
72     } else if (shorty == "Z") {
73       typedef jboolean (fntype)(JNIEnv*, jclass);
74       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
75       ScopedLocalRef<jclass> klass(soa.Env(),
76                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
77       ScopedThreadStateChange tsc(self, kNative);
78       result->SetZ(fn(soa.Env(), klass.get()));
79     } else if (shorty == "BI") {
80       typedef jbyte (fntype)(JNIEnv*, jclass, jint);
81       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
82       ScopedLocalRef<jclass> klass(soa.Env(),
83                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
84       ScopedThreadStateChange tsc(self, kNative);
85       result->SetB(fn(soa.Env(), klass.get(), args[0]));
86     } else if (shorty == "II") {
87       typedef jint (fntype)(JNIEnv*, jclass, jint);
88       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
89       ScopedLocalRef<jclass> klass(soa.Env(),
90                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
91       ScopedThreadStateChange tsc(self, kNative);
92       result->SetI(fn(soa.Env(), klass.get(), args[0]));
93     } else if (shorty == "LL") {
94       typedef jobject (fntype)(JNIEnv*, jclass, jobject);
95       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
96       ScopedLocalRef<jclass> klass(soa.Env(),
97                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
98       ScopedLocalRef<jobject> arg0(soa.Env(),
99                                    soa.AddLocalReference<jobject>(ObjArg(args[0])));
100       jobject jresult;
101       {
102         ScopedThreadStateChange tsc(self, kNative);
103         jresult = fn(soa.Env(), klass.get(), arg0.get());
104       }
105       result->SetL(soa.Decode<mirror::Object>(jresult));
106     } else if (shorty == "IIZ") {
107       typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
108       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
109       ScopedLocalRef<jclass> klass(soa.Env(),
110                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
111       ScopedThreadStateChange tsc(self, kNative);
112       result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
113     } else if (shorty == "ILI") {
114       typedef jint (fntype)(JNIEnv*, jclass, jobject, jint);
115       fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(
116           method->GetEntryPointFromJni()));
117       ScopedLocalRef<jclass> klass(soa.Env(),
118                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
119       ScopedLocalRef<jobject> arg0(soa.Env(),
120                                    soa.AddLocalReference<jobject>(ObjArg(args[0])));
121       ScopedThreadStateChange tsc(self, kNative);
122       result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
123     } else if (shorty == "SIZ") {
124       typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean);
125       fntype* const fn =
126           reinterpret_cast<fntype*>(const_cast<void*>(method->GetEntryPointFromJni()));
127       ScopedLocalRef<jclass> klass(soa.Env(),
128                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
129       ScopedThreadStateChange tsc(self, kNative);
130       result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
131     } else if (shorty == "VIZ") {
132       typedef void (fntype)(JNIEnv*, jclass, jint, jboolean);
133       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
134       ScopedLocalRef<jclass> klass(soa.Env(),
135                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
136       ScopedThreadStateChange tsc(self, kNative);
137       fn(soa.Env(), klass.get(), args[0], args[1]);
138     } else if (shorty == "ZLL") {
139       typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject);
140       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
141       ScopedLocalRef<jclass> klass(soa.Env(),
142                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
143       ScopedLocalRef<jobject> arg0(soa.Env(),
144                                    soa.AddLocalReference<jobject>(ObjArg(args[0])));
145       ScopedLocalRef<jobject> arg1(soa.Env(),
146                                    soa.AddLocalReference<jobject>(ObjArg(args[1])));
147       ScopedThreadStateChange tsc(self, kNative);
148       result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
149     } else if (shorty == "ZILL") {
150       typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject);
151       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
152       ScopedLocalRef<jclass> klass(soa.Env(),
153                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
154       ScopedLocalRef<jobject> arg1(soa.Env(),
155                                    soa.AddLocalReference<jobject>(ObjArg(args[1])));
156       ScopedLocalRef<jobject> arg2(soa.Env(),
157                                    soa.AddLocalReference<jobject>(ObjArg(args[2])));
158       ScopedThreadStateChange tsc(self, kNative);
159       result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
160     } else if (shorty == "VILII") {
161       typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint);
162       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
163       ScopedLocalRef<jclass> klass(soa.Env(),
164                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
165       ScopedLocalRef<jobject> arg1(soa.Env(),
166                                    soa.AddLocalReference<jobject>(ObjArg(args[1])));
167       ScopedThreadStateChange tsc(self, kNative);
168       fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
169     } else if (shorty == "VLILII") {
170       typedef void (fntype)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
171       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
172       ScopedLocalRef<jclass> klass(soa.Env(),
173                                    soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
174       ScopedLocalRef<jobject> arg0(soa.Env(),
175                                    soa.AddLocalReference<jobject>(ObjArg(args[0])));
176       ScopedLocalRef<jobject> arg2(soa.Env(),
177                                    soa.AddLocalReference<jobject>(ObjArg(args[2])));
178       ScopedThreadStateChange tsc(self, kNative);
179       fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
180     } else {
181       LOG(FATAL) << "Do something with static native method: " << method->PrettyMethod()
182           << " shorty: " << shorty;
183     }
184   } else {
185     if (shorty == "L") {
186       typedef jobject (fntype)(JNIEnv*, jobject);
187       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
188       ScopedLocalRef<jobject> rcvr(soa.Env(),
189                                    soa.AddLocalReference<jobject>(receiver));
190       jobject jresult;
191       {
192         ScopedThreadStateChange tsc(self, kNative);
193         jresult = fn(soa.Env(), rcvr.get());
194       }
195       result->SetL(soa.Decode<mirror::Object>(jresult));
196     } else if (shorty == "V") {
197       typedef void (fntype)(JNIEnv*, jobject);
198       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
199       ScopedLocalRef<jobject> rcvr(soa.Env(),
200                                    soa.AddLocalReference<jobject>(receiver));
201       ScopedThreadStateChange tsc(self, kNative);
202       fn(soa.Env(), rcvr.get());
203     } else if (shorty == "LL") {
204       typedef jobject (fntype)(JNIEnv*, jobject, jobject);
205       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
206       ScopedLocalRef<jobject> rcvr(soa.Env(),
207                                    soa.AddLocalReference<jobject>(receiver));
208       ScopedLocalRef<jobject> arg0(soa.Env(),
209                                    soa.AddLocalReference<jobject>(ObjArg(args[0])));
210       jobject jresult;
211       {
212         ScopedThreadStateChange tsc(self, kNative);
213         jresult = fn(soa.Env(), rcvr.get(), arg0.get());
214       }
215       result->SetL(soa.Decode<mirror::Object>(jresult));
216       ScopedThreadStateChange tsc(self, kNative);
217     } else if (shorty == "III") {
218       typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
219       fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
220       ScopedLocalRef<jobject> rcvr(soa.Env(),
221                                    soa.AddLocalReference<jobject>(receiver));
222       ScopedThreadStateChange tsc(self, kNative);
223       result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
224     } else {
225       LOG(FATAL) << "Do something with native method: " << method->PrettyMethod()
226           << " shorty: " << shorty;
227     }
228   }
229 }
230 
231 enum InterpreterImplKind {
232   kSwitchImplKind,        // Switch-based interpreter implementation.
233   kMterpImplKind          // Assembly interpreter
234 };
235 
236 static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind;
237 
Execute(Thread * self,const DexFile::CodeItem * code_item,ShadowFrame & shadow_frame,JValue result_register,bool stay_in_interpreter=false)238 static inline JValue Execute(
239     Thread* self,
240     const DexFile::CodeItem* code_item,
241     ShadowFrame& shadow_frame,
242     JValue result_register,
243     bool stay_in_interpreter = false) REQUIRES_SHARED(Locks::mutator_lock_) {
244   DCHECK(!shadow_frame.GetMethod()->IsAbstract());
245   DCHECK(!shadow_frame.GetMethod()->IsNative());
246   if (LIKELY(shadow_frame.GetDexPC() == 0)) {  // Entering the method, but not via deoptimization.
247     if (kIsDebugBuild) {
248       self->AssertNoPendingException();
249     }
250     instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
251     ArtMethod *method = shadow_frame.GetMethod();
252 
253     if (UNLIKELY(instrumentation->HasMethodEntryListeners())) {
254       instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
255                                         method, 0);
256     }
257 
258     if (!stay_in_interpreter) {
259       jit::Jit* jit = Runtime::Current()->GetJit();
260       if (jit != nullptr) {
261         jit->MethodEntered(self, shadow_frame.GetMethod());
262         if (jit->CanInvokeCompiledCode(method)) {
263           JValue result;
264 
265           // Pop the shadow frame before calling into compiled code.
266           self->PopShadowFrame();
267           ArtInterpreterToCompiledCodeBridge(self, nullptr, code_item, &shadow_frame, &result);
268           // Push the shadow frame back as the caller will expect it.
269           self->PushShadowFrame(&shadow_frame);
270 
271           return result;
272         }
273       }
274     }
275   }
276 
277   shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
278 
279   // Lock counting is a special version of accessibility checks, and for simplicity and
280   // reduction of template parameters, we gate it behind access-checks mode.
281   ArtMethod* method = shadow_frame.GetMethod();
282   DCHECK(!method->SkipAccessChecks() || !method->MustCountLocks());
283 
284   bool transaction_active = Runtime::Current()->IsActiveTransaction();
285   if (LIKELY(method->SkipAccessChecks())) {
286     // Enter the "without access check" interpreter.
287     if (kInterpreterImplKind == kMterpImplKind) {
288       if (transaction_active) {
289         // No Mterp variant - just use the switch interpreter.
290         return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register,
291                                               false);
292       } else if (UNLIKELY(!Runtime::Current()->IsStarted())) {
293         return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
294                                                false);
295       } else {
296         while (true) {
297           // Mterp does not support all instrumentation/debugging.
298           if (MterpShouldSwitchInterpreters() != 0) {
299             return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
300                                                    false);
301           }
302           bool returned = ExecuteMterpImpl(self, code_item, &shadow_frame, &result_register);
303           if (returned) {
304             return result_register;
305           } else {
306             // Mterp didn't like that instruction.  Single-step it with the reference interpreter.
307             result_register = ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame,
308                                                               result_register, true);
309             if (shadow_frame.GetDexPC() == DexFile::kDexNoIndex) {
310               // Single-stepped a return or an exception not handled locally.  Return to caller.
311               return result_register;
312             }
313           }
314         }
315       }
316     } else {
317       DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
318       if (transaction_active) {
319         return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register,
320                                               false);
321       } else {
322         return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
323                                                false);
324       }
325     }
326   } else {
327     // Enter the "with access check" interpreter.
328     if (kInterpreterImplKind == kMterpImplKind) {
329       // No access check variants for Mterp.  Just use the switch version.
330       if (transaction_active) {
331         return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register,
332                                              false);
333       } else {
334         return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register,
335                                               false);
336       }
337     } else {
338       DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
339       if (transaction_active) {
340         return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register,
341                                              false);
342       } else {
343         return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register,
344                                               false);
345       }
346     }
347   }
348 }
349 
EnterInterpreterFromInvoke(Thread * self,ArtMethod * method,ObjPtr<mirror::Object> receiver,uint32_t * args,JValue * result,bool stay_in_interpreter)350 void EnterInterpreterFromInvoke(Thread* self,
351                                 ArtMethod* method,
352                                 ObjPtr<mirror::Object> receiver,
353                                 uint32_t* args,
354                                 JValue* result,
355                                 bool stay_in_interpreter) {
356   DCHECK_EQ(self, Thread::Current());
357   bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
358   if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
359     ThrowStackOverflowError(self);
360     return;
361   }
362 
363   // This can happen if we are in forced interpreter mode and an obsolete method is called using
364   // reflection.
365   if (UNLIKELY(method->IsObsolete())) {
366     ThrowInternalError("Attempting to invoke obsolete version of '%s'.",
367                        method->PrettyMethod().c_str());
368     return;
369   }
370 
371   const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
372   const DexFile::CodeItem* code_item = method->GetCodeItem();
373   uint16_t num_regs;
374   uint16_t num_ins;
375   if (code_item != nullptr) {
376     num_regs =  code_item->registers_size_;
377     num_ins = code_item->ins_size_;
378   } else if (!method->IsInvokable()) {
379     self->EndAssertNoThreadSuspension(old_cause);
380     method->ThrowInvocationTimeError();
381     return;
382   } else {
383     DCHECK(method->IsNative());
384     num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty());
385     if (!method->IsStatic()) {
386       num_regs++;
387       num_ins++;
388     }
389   }
390   // Set up shadow frame with matching number of reference slots to vregs.
391   ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
392   ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
393       CREATE_SHADOW_FRAME(num_regs, last_shadow_frame, method, /* dex pc */ 0);
394   ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
395   self->PushShadowFrame(shadow_frame);
396 
397   size_t cur_reg = num_regs - num_ins;
398   if (!method->IsStatic()) {
399     CHECK(receiver != nullptr);
400     shadow_frame->SetVRegReference(cur_reg, receiver.Ptr());
401     ++cur_reg;
402   }
403   uint32_t shorty_len = 0;
404   const char* shorty = method->GetShorty(&shorty_len);
405   for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
406     DCHECK_LT(shorty_pos + 1, shorty_len);
407     switch (shorty[shorty_pos + 1]) {
408       case 'L': {
409         ObjPtr<mirror::Object> o =
410             reinterpret_cast<StackReference<mirror::Object>*>(&args[arg_pos])->AsMirrorPtr();
411         shadow_frame->SetVRegReference(cur_reg, o.Ptr());
412         break;
413       }
414       case 'J': case 'D': {
415         uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
416         shadow_frame->SetVRegLong(cur_reg, wide_value);
417         cur_reg++;
418         arg_pos++;
419         break;
420       }
421       default:
422         shadow_frame->SetVReg(cur_reg, args[arg_pos]);
423         break;
424     }
425   }
426   self->EndAssertNoThreadSuspension(old_cause);
427   // Do this after populating the shadow frame in case EnsureInitialized causes a GC.
428   if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitialized())) {
429     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
430     StackHandleScope<1> hs(self);
431     Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
432     if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) {
433       CHECK(self->IsExceptionPending());
434       self->PopShadowFrame();
435       return;
436     }
437   }
438   if (LIKELY(!method->IsNative())) {
439     JValue r = Execute(self, code_item, *shadow_frame, JValue(), stay_in_interpreter);
440     if (result != nullptr) {
441       *result = r;
442     }
443   } else {
444     // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
445     // generated stub) except during testing and image writing.
446     // Update args to be the args in the shadow frame since the input ones could hold stale
447     // references pointers due to moving GC.
448     args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
449     if (!Runtime::Current()->IsStarted()) {
450       UnstartedRuntime::Jni(self, method, receiver.Ptr(), args, result);
451     } else {
452       InterpreterJni(self, method, shorty, receiver, args, result);
453     }
454   }
455   self->PopShadowFrame();
456 }
457 
IsStringInit(const Instruction * instr,ArtMethod * caller)458 static bool IsStringInit(const Instruction* instr, ArtMethod* caller)
459     REQUIRES_SHARED(Locks::mutator_lock_) {
460   if (instr->Opcode() == Instruction::INVOKE_DIRECT ||
461       instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) {
462     // Instead of calling ResolveMethod() which has suspend point and can trigger
463     // GC, look up the callee method symbolically.
464     uint16_t callee_method_idx = (instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) ?
465         instr->VRegB_3rc() : instr->VRegB_35c();
466     const DexFile* dex_file = caller->GetDexFile();
467     const DexFile::MethodId& method_id = dex_file->GetMethodId(callee_method_idx);
468     const char* class_name = dex_file->StringByTypeIdx(method_id.class_idx_);
469     const char* method_name = dex_file->GetMethodName(method_id);
470     // Compare method's class name and method name against string init.
471     // It's ok since it's not allowed to create your own java/lang/String.
472     // TODO: verify that assumption.
473     if ((strcmp(class_name, "Ljava/lang/String;") == 0) &&
474         (strcmp(method_name, "<init>") == 0)) {
475       return true;
476     }
477   }
478   return false;
479 }
480 
GetReceiverRegisterForStringInit(const Instruction * instr)481 static int16_t GetReceiverRegisterForStringInit(const Instruction* instr) {
482   DCHECK(instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE ||
483          instr->Opcode() == Instruction::INVOKE_DIRECT);
484   return (instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) ?
485       instr->VRegC_3rc() : instr->VRegC_35c();
486 }
487 
EnterInterpreterFromDeoptimize(Thread * self,ShadowFrame * shadow_frame,bool from_code,JValue * ret_val)488 void EnterInterpreterFromDeoptimize(Thread* self,
489                                     ShadowFrame* shadow_frame,
490                                     bool from_code,
491                                     JValue* ret_val)
492     REQUIRES_SHARED(Locks::mutator_lock_) {
493   JValue value;
494   // Set value to last known result in case the shadow frame chain is empty.
495   value.SetJ(ret_val->GetJ());
496   // Are we executing the first shadow frame?
497   bool first = true;
498   while (shadow_frame != nullptr) {
499     // We do not want to recover lock state for lock counting when deoptimizing. Currently,
500     // the compiler should not have compiled a method that failed structured-locking checks.
501     DCHECK(!shadow_frame->GetMethod()->MustCountLocks());
502 
503     self->SetTopOfShadowStack(shadow_frame);
504     const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem();
505     const uint32_t dex_pc = shadow_frame->GetDexPC();
506     uint32_t new_dex_pc = dex_pc;
507     if (UNLIKELY(self->IsExceptionPending())) {
508       // If we deoptimize from the QuickExceptionHandler, we already reported the exception to
509       // the instrumentation. To prevent from reporting it a second time, we simply pass a
510       // null Instrumentation*.
511       const instrumentation::Instrumentation* const instrumentation =
512           first ? nullptr : Runtime::Current()->GetInstrumentation();
513       uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc,
514                                                                     instrumentation);
515       new_dex_pc = found_dex_pc;  // the dex pc of a matching catch handler
516                                   // or DexFile::kDexNoIndex if there is none.
517     } else if (!from_code) {
518       // For the debugger and full deoptimization stack, we must go past the invoke
519       // instruction, as it already executed.
520       // TODO: should be tested more once b/17586779 is fixed.
521       const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
522       if (instr->IsInvoke()) {
523         if (IsStringInit(instr, shadow_frame->GetMethod())) {
524           uint16_t this_obj_vreg = GetReceiverRegisterForStringInit(instr);
525           // Move the StringFactory.newStringFromChars() result into the register representing
526           // "this object" when invoking the string constructor in the original dex instruction.
527           // Also move the result into all aliases.
528           DCHECK(value.GetL()->IsString());
529           SetStringInitValueToAllAliases(shadow_frame, this_obj_vreg, value);
530           // Calling string constructor in the original dex code doesn't generate a result value.
531           value.SetJ(0);
532         }
533         new_dex_pc = dex_pc + instr->SizeInCodeUnits();
534       } else if (instr->Opcode() == Instruction::NEW_INSTANCE) {
535         // It's possible to deoptimize at a NEW_INSTANCE dex instruciton that's for a
536         // java string, which is turned into a call into StringFactory.newEmptyString();
537         // Move the StringFactory.newEmptyString() result into the destination register.
538         DCHECK(value.GetL()->IsString());
539         shadow_frame->SetVRegReference(instr->VRegA_21c(), value.GetL());
540         // new-instance doesn't generate a result value.
541         value.SetJ(0);
542         // Skip the dex instruction since we essentially come back from an invocation.
543         new_dex_pc = dex_pc + instr->SizeInCodeUnits();
544         if (kIsDebugBuild) {
545           ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
546           // This is a suspend point. But it's ok since value has been set into shadow_frame.
547           ObjPtr<mirror::Class> klass = class_linker->ResolveType(
548               dex::TypeIndex(instr->VRegB_21c()), shadow_frame->GetMethod());
549           DCHECK(klass->IsStringClass());
550         }
551       } else {
552         CHECK(false) << "Unexpected instruction opcode " << instr->Opcode()
553                      << " at dex_pc " << dex_pc
554                      << " of method: " << ArtMethod::PrettyMethod(shadow_frame->GetMethod(), false);
555       }
556     } else {
557       // Nothing to do, the dex_pc is the one at which the code requested
558       // the deoptimization.
559     }
560     if (new_dex_pc != DexFile::kDexNoIndex) {
561       shadow_frame->SetDexPC(new_dex_pc);
562       value = Execute(self, code_item, *shadow_frame, value);
563     }
564     ShadowFrame* old_frame = shadow_frame;
565     shadow_frame = shadow_frame->GetLink();
566     ShadowFrame::DeleteDeoptimizedFrame(old_frame);
567     // Following deoptimizations of shadow frames must pass the invoke instruction.
568     from_code = false;
569     first = false;
570   }
571   ret_val->SetJ(value.GetJ());
572 }
573 
EnterInterpreterFromEntryPoint(Thread * self,const DexFile::CodeItem * code_item,ShadowFrame * shadow_frame)574 JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item,
575                                       ShadowFrame* shadow_frame) {
576   DCHECK_EQ(self, Thread::Current());
577   bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
578   if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
579     ThrowStackOverflowError(self);
580     return JValue();
581   }
582 
583   jit::Jit* jit = Runtime::Current()->GetJit();
584   if (jit != nullptr) {
585     jit->NotifyCompiledCodeToInterpreterTransition(self, shadow_frame->GetMethod());
586   }
587   return Execute(self, code_item, *shadow_frame, JValue());
588 }
589 
ArtInterpreterToInterpreterBridge(Thread * self,const DexFile::CodeItem * code_item,ShadowFrame * shadow_frame,JValue * result)590 void ArtInterpreterToInterpreterBridge(Thread* self,
591                                        const DexFile::CodeItem* code_item,
592                                        ShadowFrame* shadow_frame,
593                                        JValue* result) {
594   bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
595   if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
596     ThrowStackOverflowError(self);
597     return;
598   }
599 
600   self->PushShadowFrame(shadow_frame);
601   ArtMethod* method = shadow_frame->GetMethod();
602   // Ensure static methods are initialized.
603   const bool is_static = method->IsStatic();
604   if (is_static) {
605     ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
606     if (UNLIKELY(!declaring_class->IsInitialized())) {
607       StackHandleScope<1> hs(self);
608       HandleWrapperObjPtr<mirror::Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class));
609       if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
610           self, h_declaring_class, true, true))) {
611         DCHECK(self->IsExceptionPending());
612         self->PopShadowFrame();
613         return;
614       }
615       CHECK(h_declaring_class->IsInitializing());
616     }
617   }
618 
619   if (LIKELY(!shadow_frame->GetMethod()->IsNative())) {
620     result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ());
621   } else {
622     // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
623     // generated stub) except during testing and image writing.
624     CHECK(!Runtime::Current()->IsStarted());
625     ObjPtr<mirror::Object> receiver = is_static ? nullptr : shadow_frame->GetVRegReference(0);
626     uint32_t* args = shadow_frame->GetVRegArgs(is_static ? 0 : 1);
627     UnstartedRuntime::Jni(self, shadow_frame->GetMethod(), receiver.Ptr(), args, result);
628   }
629 
630   self->PopShadowFrame();
631 }
632 
CheckInterpreterAsmConstants()633 void CheckInterpreterAsmConstants() {
634   CheckMterpAsmConstants();
635 }
636 
InitInterpreterTls(Thread * self)637 void InitInterpreterTls(Thread* self) {
638   InitMterpTls(self);
639 }
640 
641 }  // namespace interpreter
642 }  // namespace art
643