blob: 13fd3ae4ee45ea362392c560b6ad6e40aca2c735 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "callee_save_frame.h"
#include "interpreter/interpreter.h"
#include "object.h" // for JValue
#include "object_utils.h"
#include "stack.h"
#include "thread.h"
#include "verifier/method_verifier.h"
namespace art {
extern "C" uint64_t artDeoptimize(JValue ret_val, Thread* self, AbstractMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
// Return value may hold Object* so avoid suspension.
const char* old_cause = self->StartAssertNoThreadSuspension("Deoptimizing stack frame");
CHECK(old_cause == NULL);
class DeoptimizationVisitor : public StackVisitor {
public:
DeoptimizationVisitor(const ManagedStack* stack,
const std::deque<InstrumentationStackFrame>* instrumentation_stack,
Context* context)
: StackVisitor(stack, instrumentation_stack, context), shadow_frame_(NULL),
runtime_frames_(0) { }
virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
AbstractMethod* m = GetMethod();
if (m->IsRuntimeMethod()) {
if (runtime_frames_ == 0) {
runtime_frames_++;
return true; // Skip the callee save frame.
} else {
return false; // Caller was an upcall.
}
}
MethodHelper mh(m);
const DexFile::CodeItem* code_item = mh.GetCodeItem();
CHECK(code_item != NULL);
uint16_t num_regs = code_item->registers_size_;
shadow_frame_ = ShadowFrame::Create(num_regs, NULL, m, GetDexPc());
std::vector<int32_t> kinds =
verifier::MethodVerifier::DescribeVRegs(m->GetDexMethodIndex(), &mh.GetDexFile(),
mh.GetDexCache(), mh.GetClassLoader(),
mh.GetClassDefIndex(), code_item, m,
m->GetAccessFlags(), GetDexPc());
for(uint16_t reg = 0; reg < num_regs; reg++) {
VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
switch (kind) {
case kUndefined:
shadow_frame_->SetVReg(reg, 0xEBADDE09);
break;
case kConstant:
shadow_frame_->SetVReg(reg, kinds.at((reg * 2) + 1));
break;
default:
shadow_frame_->SetVReg(reg, GetVReg(m, reg, kind));
break;
}
}
return false; // Stop now we have built the shadow frame.
}
ShadowFrame* shadow_frame_;
uint32_t runtime_frames_;
} visitor(self->GetManagedStack(), self->GetInstrumentationStack(), self->GetLongJumpContext());
visitor.WalkStack(false);
if (visitor.shadow_frame_ != NULL) {
self->SetDeoptimizationShadowFrame(visitor.shadow_frame_, ret_val);
return (*sp)->GetFrameSizeInBytes();
} else {
return 0; // Caller was an upcall.
}
}
extern "C" JValue artEnterInterpreterFromDeoptimize(Thread* self, AbstractMethod** sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
JValue return_value;
UniquePtr<ShadowFrame> shadow_frame(self->GetAndClearDeoptimizationShadowFrame(&return_value));
self->EndAssertNoThreadSuspension(NULL);
return interpreter::EnterInterpreterFromDeoptimize(self, *shadow_frame.get(), return_value);
}
} // namespace art