blob: 2cc5dd36d76402cd72e35f9692270e8f6294102b [file] [log] [blame]
Ian Rogers306057f2012-11-26 12:45:53 -08001/*
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 "callee_save_frame.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070018#include "dex_file-inl.h"
Ian Rogers306057f2012-11-26 12:45:53 -080019#include "interpreter/interpreter.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/abstract_method-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070021#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080022#include "mirror/object_array-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070023#include "mirror/object-inl.h"
Ian Rogers306057f2012-11-26 12:45:53 -080024#include "object_utils.h"
25#include "stack.h"
26#include "thread.h"
27#include "verifier/method_verifier.h"
28
29namespace art {
30
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080031extern "C" uint64_t artDeoptimize(JValue ret_val, Thread* self, mirror::AbstractMethod** sp)
Ian Rogers306057f2012-11-26 12:45:53 -080032 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
33 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
34 // Return value may hold Object* so avoid suspension.
35 const char* old_cause = self->StartAssertNoThreadSuspension("Deoptimizing stack frame");
36 CHECK(old_cause == NULL);
37 class DeoptimizationVisitor : public StackVisitor {
38 public:
Ian Rogers7a22fa62013-01-23 12:16:16 -080039 DeoptimizationVisitor(Thread* thread, Context* context)
40 : StackVisitor(thread, context), shadow_frame_(NULL), runtime_frames_(0) { }
Ian Rogers306057f2012-11-26 12:45:53 -080041
42 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080043 mirror::AbstractMethod* m = GetMethod();
Ian Rogers306057f2012-11-26 12:45:53 -080044 if (m->IsRuntimeMethod()) {
45 if (runtime_frames_ == 0) {
46 runtime_frames_++;
47 return true; // Skip the callee save frame.
48 } else {
49 return false; // Caller was an upcall.
50 }
51 }
52 MethodHelper mh(m);
53 const DexFile::CodeItem* code_item = mh.GetCodeItem();
54 CHECK(code_item != NULL);
55 uint16_t num_regs = code_item->registers_size_;
56 shadow_frame_ = ShadowFrame::Create(num_regs, NULL, m, GetDexPc());
Ian Rogers7b3ddd22013-02-21 15:19:52 -080057 std::vector<int32_t> kinds = DescribeVRegs(m->GetDexMethodIndex(), &mh.GetDexFile(),
58 mh.GetDexCache(), mh.GetClassLoader(),
59 mh.GetClassDefIndex(), code_item, m,
60 m->GetAccessFlags(), GetDexPc());
Ian Rogers306057f2012-11-26 12:45:53 -080061 for(uint16_t reg = 0; reg < num_regs; reg++) {
62 VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
63 switch (kind) {
64 case kUndefined:
65 shadow_frame_->SetVReg(reg, 0xEBADDE09);
66 break;
67 case kConstant:
68 shadow_frame_->SetVReg(reg, kinds.at((reg * 2) + 1));
69 break;
70 default:
71 shadow_frame_->SetVReg(reg, GetVReg(m, reg, kind));
72 break;
73 }
74 }
75 return false; // Stop now we have built the shadow frame.
76 }
Ian Rogers7b3ddd22013-02-21 15:19:52 -080077
78 std::vector<int32_t> DescribeVRegs(uint32_t dex_method_idx,
79 const DexFile* dex_file,
80 mirror::DexCache* dex_cache,
81 mirror::ClassLoader* class_loader,
82 uint32_t class_def_idx,
83 const DexFile::CodeItem* code_item,
84 mirror::AbstractMethod* method,
85 uint32_t method_access_flags, uint32_t dex_pc)
86 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
87 verifier::MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
88 dex_method_idx, method, method_access_flags, true);
89 verifier.Verify();
90 return verifier.DescribeVRegs(dex_pc);
91 }
92
Ian Rogers306057f2012-11-26 12:45:53 -080093 ShadowFrame* shadow_frame_;
94 uint32_t runtime_frames_;
Ian Rogers7a22fa62013-01-23 12:16:16 -080095 } visitor(self, self->GetLongJumpContext());
Ian Rogers306057f2012-11-26 12:45:53 -080096 visitor.WalkStack(false);
97 if (visitor.shadow_frame_ != NULL) {
98 self->SetDeoptimizationShadowFrame(visitor.shadow_frame_, ret_val);
99 return (*sp)->GetFrameSizeInBytes();
100 } else {
101 return 0; // Caller was an upcall.
102 }
103}
104
105
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800106extern "C" JValue artEnterInterpreterFromDeoptimize(Thread* self, mirror::AbstractMethod** sp)
Ian Rogers306057f2012-11-26 12:45:53 -0800107 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
108 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
109 JValue return_value;
110 UniquePtr<ShadowFrame> shadow_frame(self->GetAndClearDeoptimizationShadowFrame(&return_value));
111 self->EndAssertNoThreadSuspension(NULL);
112 return interpreter::EnterInterpreterFromDeoptimize(self, *shadow_frame.get(), return_value);
113}
114
115} // namespace art