• 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 "entrypoints/entrypoint_utils.h"
18 #include "mirror/art_method.h"
19 #include "mirror/object-inl.h"
20 #include "verifier/dex_gc_map.h"
21 #include "stack.h"
22 
23 namespace art {
24 
25 class ShadowFrameCopyVisitor : public StackVisitor {
26  public:
ShadowFrameCopyVisitor(Thread * self)27   explicit ShadowFrameCopyVisitor(Thread* self) : StackVisitor(self, NULL), prev_frame_(NULL),
28       top_frame_(NULL) {}
29 
VisitFrame()30   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
31     if (IsShadowFrame()) {
32       ShadowFrame* cur_frame = GetCurrentShadowFrame();
33       size_t num_regs = cur_frame->NumberOfVRegs();
34       mirror::ArtMethod* method = cur_frame->GetMethod();
35       uint32_t dex_pc = cur_frame->GetDexPC();
36       ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, method, dex_pc);
37 
38       const uint8_t* gc_map = method->GetNativeGcMap();
39       uint32_t gc_map_length = static_cast<uint32_t>((gc_map[0] << 24) |
40                                                      (gc_map[1] << 16) |
41                                                      (gc_map[2] << 8) |
42                                                      (gc_map[3] << 0));
43       verifier::DexPcToReferenceMap dex_gc_map(gc_map + 4, gc_map_length);
44       const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
45       for (size_t reg = 0; reg < num_regs; ++reg) {
46         if (TestBitmap(reg, reg_bitmap)) {
47           new_frame->SetVRegReference(reg, cur_frame->GetVRegReference(reg));
48         } else {
49           new_frame->SetVReg(reg, cur_frame->GetVReg(reg));
50         }
51       }
52 
53       if (prev_frame_ != NULL) {
54         prev_frame_->SetLink(new_frame);
55       } else {
56         top_frame_ = new_frame;
57       }
58       prev_frame_ = new_frame;
59     }
60     return true;
61   }
62 
GetShadowFrameCopy()63   ShadowFrame* GetShadowFrameCopy() {
64     return top_frame_;
65   }
66 
67  private:
TestBitmap(int reg,const uint8_t * reg_vector)68   static bool TestBitmap(int reg, const uint8_t* reg_vector) {
69     return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
70   }
71 
72   ShadowFrame* prev_frame_;
73   ShadowFrame* top_frame_;
74 };
75 
art_portable_test_suspend_from_code(Thread * self)76 extern "C" void art_portable_test_suspend_from_code(Thread* self)
77     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
78   CheckSuspend(self);
79   if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) {
80     // Save out the shadow frame to the heap
81     ShadowFrameCopyVisitor visitor(self);
82     visitor.WalkStack(true);
83     self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy());
84     self->SetDeoptimizationReturnValue(JValue());
85     self->SetException(ThrowLocation(), reinterpret_cast<mirror::Throwable*>(-1));
86   }
87 }
88 
art_portable_push_shadow_frame_from_code(Thread * thread,ShadowFrame * new_shadow_frame,mirror::ArtMethod * method,uint32_t num_vregs)89 extern "C" ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread,
90                                                                  ShadowFrame* new_shadow_frame,
91                                                                  mirror::ArtMethod* method,
92                                                                  uint32_t num_vregs) {
93   ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
94   new_shadow_frame->SetMethod(method);
95   new_shadow_frame->SetNumberOfVRegs(num_vregs);
96   return old_frame;
97 }
98 
99 }  // namespace art
100