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
}