• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "runtime/tooling/inspector/object_repository.h"
17 
18 #include "runtime/handle_scope-inl.h"
19 #include "runtime/include/tooling/inspector_extension.h"
20 
21 namespace panda::tooling::inspector {
ObjectRepository()22 ObjectRepository::ObjectRepository()
23     : extension_(ManagedThread::GetCurrent()->GetLanguageContext().CreateInspectorExtension()),
24       scope_(ManagedThread::GetCurrent())
25 {
26 }
27 
CreateGlobalObject()28 RemoteObject ObjectRepository::CreateGlobalObject()
29 {
30     return RemoteObject::Object("[Global]", GLOBAL_OBJECT_ID, "Global object");
31 }
32 
CreateFrameObject(const PtFrame & frame,const std::map<std::string,TypedValue> & locals)33 RemoteObject ObjectRepository::CreateFrameObject(const PtFrame &frame, const std::map<std::string, TypedValue> &locals)
34 {
35     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
36 
37     std::vector<PropertyDescriptor> properties;
38     properties.reserve(locals.size());
39     for (auto &local : locals) {
40         properties.emplace_back(local.first, CreateObject(local.second));
41     }
42 
43     auto id = counter_++;
44     frames_.emplace(id, std::move(properties));
45 
46     return RemoteObject::Object("", id, "Frame #" + std::to_string(frame.GetFrameId()));
47 }
48 
CreateObject(TypedValue value)49 RemoteObject ObjectRepository::CreateObject(TypedValue value)
50 {
51     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
52 
53     switch (value.GetType()) {
54         case panda_file::Type::TypeId::INVALID:
55         case panda_file::Type::TypeId::VOID:
56             return RemoteObject::Undefined();
57         case panda_file::Type::TypeId::U1:
58             return RemoteObject::Boolean(value.GetAsU1());
59         case panda_file::Type::TypeId::I8:
60             return RemoteObject::Number(value.GetAsI8());
61         case panda_file::Type::TypeId::U8:
62             return RemoteObject::Number(value.GetAsU8());
63         case panda_file::Type::TypeId::I16:
64             return RemoteObject::Number(value.GetAsI16());
65         case panda_file::Type::TypeId::U16:
66             return RemoteObject::Number(value.GetAsU16());
67         case panda_file::Type::TypeId::I32:
68             return RemoteObject::Number(value.GetAsI32());
69         case panda_file::Type::TypeId::U32:
70             return RemoteObject::Number(value.GetAsU32());
71         case panda_file::Type::TypeId::F32:
72             return RemoteObject::Number(value.GetAsF32());
73         case panda_file::Type::TypeId::F64:
74             return RemoteObject::Number(value.GetAsF64());
75         case panda_file::Type::TypeId::I64:
76             return RemoteObject::Number(value.GetAsI64());
77         case panda_file::Type::TypeId::U64:
78             return RemoteObject::Number(value.GetAsU64());
79         case panda_file::Type::TypeId::REFERENCE:
80             return CreateObject(value.GetAsReference());
81         case panda_file::Type::TypeId::TAGGED:
82             return CreateObject(value.GetAsTagged());
83     }
84     UNREACHABLE();
85 }
86 
GetProperties(RemoteObjectId id,bool generatePreview)87 std::vector<PropertyDescriptor> ObjectRepository::GetProperties(RemoteObjectId id, bool generatePreview)
88 {
89     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
90 
91     auto properties = GetProperties(id);
92 
93     if (generatePreview) {
94         for (auto &property : properties) {
95             if (property.IsAccessor()) {
96                 continue;
97             }
98 
99             auto &value = property.GetValue();
100             if (auto valueId = value.GetObjectId()) {
101                 value.GeneratePreview(GetProperties(*valueId));
102             }
103         }
104     }
105 
106     return properties;
107 }
108 
CreateObject(coretypes::TaggedValue value)109 RemoteObject ObjectRepository::CreateObject(coretypes::TaggedValue value)
110 {
111     if (value.IsHeapObject()) {
112         return CreateObject(value.GetHeapObject());
113     }
114     if (value.IsUndefined() || value.IsHole()) {
115         return RemoteObject::Undefined();
116     }
117     if (value.IsNull()) {
118         return RemoteObject::Null();
119     }
120     if (value.IsBoolean()) {
121         return RemoteObject::Boolean(value.IsTrue());
122     }
123     if (value.IsInt()) {
124         return RemoteObject::Number(value.GetInt());
125     }
126     if (value.IsDouble()) {
127         return RemoteObject::Number(value.GetDouble());
128     }
129     UNREACHABLE();
130 }
131 
CreateObject(ObjectHeader * object)132 RemoteObject ObjectRepository::CreateObject(ObjectHeader *object)
133 {
134     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
135 
136     if (object == nullptr) {
137         return RemoteObject::Null();
138     }
139 
140     if (auto str = extension_->GetAsString(object)) {
141         return RemoteObject::String(*str);
142     }
143 
144     RemoteObjectId id;
145 
146     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
147     auto it = std::find_if(objects_.begin(), objects_.end(), [object](auto &p) { return p.second.GetPtr() == object; });
148     if (it == objects_.end()) {
149         id = counter_++;
150 
151         objects_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
152                          std::forward_as_tuple(ManagedThread::GetCurrent(), object));
153     } else {
154         id = it->first;
155     }
156 
157     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
158     if (auto arrayLen = extension_->GetLengthIfArray(object)) {
159         // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
160         return RemoteObject::Array(extension_->GetClassName(object), *arrayLen, id);
161     }
162 
163     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
164     return RemoteObject::Object(extension_->GetClassName(object), id);
165 }
166 
GetProperties(RemoteObjectId id)167 std::vector<PropertyDescriptor> ObjectRepository::GetProperties(RemoteObjectId id)
168 {
169     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
170 
171     auto fIt = frames_.find(id);
172     if (fIt != frames_.end()) {
173         ASSERT(objects_.find(id) == objects_.end());
174         return fIt->second;
175     }
176 
177     std::vector<PropertyDescriptor> properties;
178     auto propertyHandler = [this, &properties](auto &name, auto value, auto isArrayElement, auto isFinal,
179                                                auto isAccessor) {
180         auto property = isAccessor ? PropertyDescriptor::Accessor(name, CreateObject(value))
181                                    : PropertyDescriptor(name, CreateObject(value), isArrayElement);
182         if (!isAccessor && isFinal) {
183             property.SetWritable(false);
184         }
185         properties.emplace_back(std::move(property));
186     };
187 
188     if (id == GLOBAL_OBJECT_ID) {
189         ASSERT(objects_.find(id) == objects_.end());
190         extension_->EnumerateGlobals(propertyHandler);
191     } else {
192         auto oIt = objects_.find(id);
193         if (oIt == objects_.end()) {
194             LOG(INFO, DEBUGGER) << "Unknown object ID " << id;
195             return {};
196         }
197 
198         extension_->EnumerateProperties(oIt->second.GetPtr(), propertyHandler);
199     }
200 
201     return properties;
202 }
203 }  // namespace panda::tooling::inspector
204