blob: 75e671febdb5eb62f7c74ae62170187a8e3d2a8f [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"
18#include "interpreter/interpreter.h"
19#include "object.h" // for JValue
20#include "object_utils.h"
21#include "stack.h"
22#include "thread.h"
23#include "verifier/method_verifier.h"
24
25namespace art {
26
27extern "C" uint64_t artDeoptimize(JValue ret_val, Thread* self, AbstractMethod** sp)
28 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
29 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
30 // Return value may hold Object* so avoid suspension.
31 const char* old_cause = self->StartAssertNoThreadSuspension("Deoptimizing stack frame");
32 CHECK(old_cause == NULL);
33 class DeoptimizationVisitor : public StackVisitor {
34 public:
Ian Rogers7a22fa62013-01-23 12:16:16 -080035 DeoptimizationVisitor(Thread* thread, Context* context)
36 : StackVisitor(thread, context), shadow_frame_(NULL), runtime_frames_(0) { }
Ian Rogers306057f2012-11-26 12:45:53 -080037
38 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
39 AbstractMethod* m = GetMethod();
40 if (m->IsRuntimeMethod()) {
41 if (runtime_frames_ == 0) {
42 runtime_frames_++;
43 return true; // Skip the callee save frame.
44 } else {
45 return false; // Caller was an upcall.
46 }
47 }
48 MethodHelper mh(m);
49 const DexFile::CodeItem* code_item = mh.GetCodeItem();
50 CHECK(code_item != NULL);
51 uint16_t num_regs = code_item->registers_size_;
52 shadow_frame_ = ShadowFrame::Create(num_regs, NULL, m, GetDexPc());
53 std::vector<int32_t> kinds =
54 verifier::MethodVerifier::DescribeVRegs(m->GetDexMethodIndex(), &mh.GetDexFile(),
55 mh.GetDexCache(), mh.GetClassLoader(),
56 mh.GetClassDefIndex(), code_item, m,
57 m->GetAccessFlags(), GetDexPc());
58 for(uint16_t reg = 0; reg < num_regs; reg++) {
59 VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
60 switch (kind) {
61 case kUndefined:
62 shadow_frame_->SetVReg(reg, 0xEBADDE09);
63 break;
64 case kConstant:
65 shadow_frame_->SetVReg(reg, kinds.at((reg * 2) + 1));
66 break;
67 default:
68 shadow_frame_->SetVReg(reg, GetVReg(m, reg, kind));
69 break;
70 }
71 }
72 return false; // Stop now we have built the shadow frame.
73 }
74 ShadowFrame* shadow_frame_;
75 uint32_t runtime_frames_;
Ian Rogers7a22fa62013-01-23 12:16:16 -080076 } visitor(self, self->GetLongJumpContext());
Ian Rogers306057f2012-11-26 12:45:53 -080077 visitor.WalkStack(false);
78 if (visitor.shadow_frame_ != NULL) {
79 self->SetDeoptimizationShadowFrame(visitor.shadow_frame_, ret_val);
80 return (*sp)->GetFrameSizeInBytes();
81 } else {
82 return 0; // Caller was an upcall.
83 }
84}
85
86
87extern "C" JValue artEnterInterpreterFromDeoptimize(Thread* self, AbstractMethod** sp)
88 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
89 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
90 JValue return_value;
91 UniquePtr<ShadowFrame> shadow_frame(self->GetAndClearDeoptimizationShadowFrame(&return_value));
92 self->EndAssertNoThreadSuspension(NULL);
93 return interpreter::EnterInterpreterFromDeoptimize(self, *shadow_frame.get(), return_value);
94}
95
96} // namespace art