/* * Copyright (C) 2011 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. */ #ifndef ART_RUNTIME_MANAGED_STACK_H_ #define ART_RUNTIME_MANAGED_STACK_H_ #include #include #include #include #include "base/locks.h" #include "base/macros.h" #include "base/bit_utils.h" namespace art { namespace mirror { class Object; } // namespace mirror class ArtMethod; class ShadowFrame; template class StackReference; // The managed stack is used to record fragments of managed code stacks. Managed code stacks // may either be shadow frames or lists of frames using fixed frame sizes. Transition records are // necessary for transitions between code using different frame layouts and transitions into native // code. class PACKED(4) ManagedStack { public: ManagedStack() : tagged_top_quick_frame_(TaggedTopQuickFrame::CreateNotTagged(nullptr)), link_(nullptr), top_shadow_frame_(nullptr) {} void PushManagedStackFragment(ManagedStack* fragment) { // Copy this top fragment into given fragment. memcpy(fragment, this, sizeof(ManagedStack)); // Clear this fragment, which has become the top. memset(this, 0, sizeof(ManagedStack)); // Link our top fragment onto the given fragment. link_ = fragment; } void PopManagedStackFragment(const ManagedStack& fragment) { DCHECK(&fragment == link_); // Copy this given fragment back to the top. memcpy(this, &fragment, sizeof(ManagedStack)); } ManagedStack* GetLink() const { return link_; } ArtMethod** GetTopQuickFrameKnownNotTagged() const { return tagged_top_quick_frame_.GetSpKnownNotTagged(); } ArtMethod** GetTopQuickFrame() const { return tagged_top_quick_frame_.GetSp(); } bool GetTopQuickFrameTag() const { return tagged_top_quick_frame_.GetTag(); } bool HasTopQuickFrame() const { return tagged_top_quick_frame_.GetTaggedSp() != 0u; } void SetTopQuickFrame(ArtMethod** top) { DCHECK(top_shadow_frame_ == nullptr); DCHECK_ALIGNED(top, 4u); tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateNotTagged(top); } void SetTopQuickFrameTagged(ArtMethod** top) { DCHECK(top_shadow_frame_ == nullptr); DCHECK_ALIGNED(top, 4u); tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateTagged(top); } static constexpr size_t TaggedTopQuickFrameOffset() { return OFFSETOF_MEMBER(ManagedStack, tagged_top_quick_frame_); } ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame); ALWAYS_INLINE ShadowFrame* PopShadowFrame(); ShadowFrame* GetTopShadowFrame() const { return top_shadow_frame_; } bool HasTopShadowFrame() const { return GetTopShadowFrame() != nullptr; } void SetTopShadowFrame(ShadowFrame* top) { DCHECK_EQ(tagged_top_quick_frame_.GetTaggedSp(), 0u); top_shadow_frame_ = top; } static size_t TopShadowFrameOffset() { return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); } size_t NumJniShadowFrameReferences() const REQUIRES_SHARED(Locks::mutator_lock_); bool ShadowFramesContain(StackReference* shadow_frame_entry) const; private: // Encodes the top quick frame (which must be at least 4-byte aligned) // and a flag that marks the GenericJNI trampoline. class TaggedTopQuickFrame { public: static TaggedTopQuickFrame CreateNotTagged(ArtMethod** sp) { DCHECK_ALIGNED(sp, 4u); return TaggedTopQuickFrame(reinterpret_cast(sp)); } static TaggedTopQuickFrame CreateTagged(ArtMethod** sp) { DCHECK_ALIGNED(sp, 4u); return TaggedTopQuickFrame(reinterpret_cast(sp) | 1u); } // Get SP known to be not tagged and non-null. ArtMethod** GetSpKnownNotTagged() const { DCHECK(!GetTag()); DCHECK_NE(tagged_sp_, 0u); return reinterpret_cast(tagged_sp_); } ArtMethod** GetSp() const { return reinterpret_cast(tagged_sp_ & ~static_cast(1u)); } bool GetTag() const { return (tagged_sp_ & 1u) != 0u; } uintptr_t GetTaggedSp() const { return tagged_sp_; } private: explicit TaggedTopQuickFrame(uintptr_t tagged_sp) : tagged_sp_(tagged_sp) { } uintptr_t tagged_sp_; }; static_assert(sizeof(TaggedTopQuickFrame) == sizeof(uintptr_t), "TaggedTopQuickFrame size check"); TaggedTopQuickFrame tagged_top_quick_frame_; ManagedStack* link_; ShadowFrame* top_shadow_frame_; }; } // namespace art #endif // ART_RUNTIME_MANAGED_STACK_H_