mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 12:10:47 +00:00
Debugger breakpoint adapts sendable features
Reconstruct and revise debugger breakpoint module to adapt sendable features Issue: #IAE06X Signed-off-by: huangtianzhi <huangtianzhi1@huawei.com>
This commit is contained in:
parent
9175348584
commit
f516e8568f
@ -337,9 +337,24 @@ void DebuggerApi::GetObjectClassName(const EcmaVM *ecmaVM, Local<JSValueRef> &ta
|
||||
}
|
||||
}
|
||||
|
||||
bool DebuggerApi::RemoveBreakpointsByUrl(JSDebugger *debugger, const std::string &url)
|
||||
bool DebuggerApi::SetBreakpointWithNoMatchUrl(JSDebugger *debugger, const JSPtLocation &location)
|
||||
{
|
||||
return debugger->RemoveBreakpointsByUrl(url);
|
||||
return debugger->SetUrlNotMatchedBreakpoint(location);
|
||||
}
|
||||
|
||||
std::vector<bool> DebuggerApi::SetBreakpointByList(JSDebugger *debugger, std::vector<JSPtLocation> &list)
|
||||
{
|
||||
return debugger->SetBreakpointUsingList(list);
|
||||
}
|
||||
|
||||
bool DebuggerApi::RemoveBreakpointWithNoMatchUrl(JSDebugger *debugger, const JSPtLocation &location)
|
||||
{
|
||||
return debugger->RemoveUrlNotMatchedBreakpoint(location);
|
||||
}
|
||||
|
||||
bool DebuggerApi::RemoveAllBreakpointsByUrl(JSDebugger *debugger, const std::string &url, bool skipGlobal)
|
||||
{
|
||||
return debugger->RemoveAllBreakpointsByUrl(url, skipGlobal);
|
||||
}
|
||||
|
||||
// ScopeInfo
|
||||
@ -1365,4 +1380,4 @@ DebuggerApi::DebuggerManagedScope::~DebuggerManagedScope()
|
||||
thread_->UpdateState(static_cast<ecmascript::ThreadState>(oldThreadState_));
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::tooling
|
||||
} // namespace panda::ecmascript::tooling
|
@ -157,7 +157,11 @@ public:
|
||||
|
||||
static int32_t GetObjectHash(const EcmaVM *ecmaVM, const JSHandle<JSTaggedValue> &tagged);
|
||||
static void GetObjectClassName(const EcmaVM *ecmaVM, Local<JSValueRef> &tagged, std::string &className);
|
||||
static bool RemoveBreakpointsByUrl(JSDebugger *debugger, const std::string &url);
|
||||
// JSDebugger new added
|
||||
static bool SetBreakpointWithNoMatchUrl(JSDebugger *debugger, const JSPtLocation &location);
|
||||
static std::vector<bool> SetBreakpointByList(JSDebugger *debugger, std::vector<JSPtLocation> &list);
|
||||
static bool RemoveBreakpointWithNoMatchUrl(JSDebugger *debugger, const JSPtLocation &location);
|
||||
static bool RemoveAllBreakpointsByUrl(JSDebugger *debugger, const std::string &url, bool skipGlobal);
|
||||
|
||||
// HotReload
|
||||
static std::vector<DebugInfoExtractor *> GetPatchExtractors(const EcmaVM *ecmaVm, const std::string &url);
|
||||
@ -203,4 +207,4 @@ public:
|
||||
};
|
||||
} // namespace panda::ecmascript::tooling
|
||||
|
||||
#endif // ECMASCRIPT_DEBUGGER_DEBUGGER_API_H
|
||||
#endif // ECMASCRIPT_DEBUGGER_DEBUGGER_API_H
|
@ -27,27 +27,332 @@
|
||||
namespace panda::ecmascript::tooling {
|
||||
using panda::ecmascript::base::BuiltinsBase;
|
||||
|
||||
std::shared_mutex JSDebugger::listMutex_;
|
||||
CUnorderedMap<CString, CUnorderedMap<std::string,
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint>>> JSDebugger::globalBpList_ {};
|
||||
bool JSDebugger::SetBreakpoint(const JSPtLocation &location, Local<FunctionRef> condFuncRef)
|
||||
{
|
||||
// acquire write lock of global list
|
||||
std::unique_lock<std::shared_mutex> globalListLock(listMutex_);
|
||||
Global<FunctionRef> funcRef = Global<FunctionRef>(ecmaVm_, condFuncRef);
|
||||
return SetBreakpointWithMatchedUrl(location, funcRef);
|
||||
}
|
||||
|
||||
bool JSDebugger::SetUrlNotMatchedBreakpoint(const JSPtLocation &location)
|
||||
{
|
||||
// acquire write lock of global list
|
||||
std::unique_lock<std::shared_mutex> globalListLock(listMutex_);
|
||||
return SetBreakpointWithoutMatchedUrl(location);
|
||||
}
|
||||
|
||||
std::vector<bool> JSDebugger::SetBreakpointUsingList(std::vector<JSPtLocation> &list)
|
||||
{
|
||||
// acquire write lock of global list
|
||||
std::unique_lock<std::shared_mutex> globalListLock(listMutex_);
|
||||
return SetBreakpointByList(list);
|
||||
}
|
||||
|
||||
std::vector<bool> JSDebugger::SetBreakpointByList(std::vector<JSPtLocation> &list)
|
||||
{
|
||||
std::vector<bool> result;
|
||||
for (const auto &location : list) {
|
||||
if (location.GetJsPandaFile() != nullptr) {
|
||||
// URL matched breakpoint
|
||||
auto funcRef = location.GetCondFuncRef();
|
||||
result.emplace_back(SetBreakpointWithMatchedUrl(location, funcRef));
|
||||
} else if (location.GetSourceFile() == "invalid") {
|
||||
// Invalid breakpoint (condition check failed or match location failed)
|
||||
result.emplace_back(false);
|
||||
} else {
|
||||
// URL not matched breakpoint
|
||||
result.emplace_back(SetBreakpointWithoutMatchedUrl(location));
|
||||
}
|
||||
}
|
||||
DumpBreakpoints();
|
||||
DumpGlobalBreakpoints();
|
||||
ASSERT(list.size() == result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
bool JSDebugger::SetBreakpointWithMatchedUrl(const JSPtLocation &location, Global<FunctionRef> condFuncRef)
|
||||
{
|
||||
std::unique_ptr<PtMethod> ptMethod = FindMethod(location);
|
||||
if (ptMethod == nullptr) {
|
||||
LOG_DEBUGGER(ERROR) << "SetBreakpoint: Cannot find MethodLiteral";
|
||||
LOG_DEBUGGER(ERROR) << "SetBreakpointWithMatchedUrl: Cannot find MethodLiteral";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (location.GetBytecodeOffset() >= ptMethod->GetCodeSize()) {
|
||||
LOG_DEBUGGER(ERROR) << "SetBreakpoint: Invalid breakpoint location";
|
||||
LOG_DEBUGGER(ERROR) << "SetBreakpointWithMatchedUrl: Invalid breakpoint location";
|
||||
return false;
|
||||
}
|
||||
auto ptMethodPtr = ptMethod.get();
|
||||
JSBreakpoint jsBreakpoint{location.GetSourceFile(), ptMethod.release(), location.GetBytecodeOffset(),
|
||||
Global<FunctionRef>(ecmaVm_, condFuncRef), location.GetSourceFile(), location.GetLine(), location.GetColumn()};
|
||||
|
||||
auto [_, success] = breakpoints_.emplace(location.GetSourceFile(), ptMethod.release(),
|
||||
location.GetBytecodeOffset(), Global<FunctionRef>(ecmaVm_, condFuncRef));
|
||||
bool success = PushBreakpointToLocal(jsBreakpoint, location);
|
||||
if (!success) {
|
||||
// also return true
|
||||
LOG_DEBUGGER(WARN) << "SetBreakpoint: Breakpoint already exists";
|
||||
LOG_DEBUGGER(WARN) << "SetBreakpointWithMatchedUrl: Breakpoint already exists in localList";
|
||||
}
|
||||
|
||||
DumpBreakpoints();
|
||||
auto breakpoint = SearchBreakpointInGlobalList(location, ptMethodPtr);
|
||||
if (!breakpoint.has_value() && ecmaVm_->GetJsDebuggerManager()->IsBreakpointSyncEnabled()) {
|
||||
// global list does not have this breakpoint, push it to the global list
|
||||
PushBreakpointToGlobal(jsBreakpoint, location);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSDebugger::SetBreakpointWithoutMatchedUrl(const JSPtLocation &location)
|
||||
{
|
||||
// try to find this breakpoint in local list
|
||||
auto breakpointList = SearchNoMatchBreakpointInLocalList(location);
|
||||
if (!breakpointList.empty()) {
|
||||
// found this breakpoint in local list, return success
|
||||
return true;
|
||||
}
|
||||
// if not found in local, try to find it in global list
|
||||
breakpointList = SearchNoMatchBreakpointInGlobalList(location);
|
||||
if (!breakpointList.empty()) {
|
||||
// found this breakpoint in global list, return success
|
||||
for (const auto &breakpoint : breakpointList) {
|
||||
PullBreakpointFromGlobal(breakpoint);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSDebugger::PushBreakpointToLocal(const JSBreakpoint &breakpoint, const JSPtLocation &location)
|
||||
{
|
||||
auto pandaFileKey = location.GetJsPandaFile()->GetJSPandaFileDesc();
|
||||
auto urlKey = location.GetSourceFile();
|
||||
if (breakpoints_.find(pandaFileKey) == breakpoints_.end()) {
|
||||
CUnorderedMap<std::string, CUnorderedSet<JSBreakpoint, HashJSBreakpoint>> urlHashMap;
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> breakpointSet;
|
||||
breakpointSet.emplace(breakpoint);
|
||||
urlHashMap[urlKey] = breakpointSet;
|
||||
breakpoints_[pandaFileKey] = urlHashMap;
|
||||
return true;
|
||||
} else {
|
||||
auto urlHashMap = breakpoints_[pandaFileKey];
|
||||
if (urlHashMap.find(urlKey) == urlHashMap.end()) {
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> breakpointSet;
|
||||
breakpointSet.emplace(breakpoint);
|
||||
urlHashMap[urlKey] = breakpointSet;
|
||||
breakpoints_[pandaFileKey] = urlHashMap;
|
||||
return true;
|
||||
} else {
|
||||
auto [_, success] = breakpoints_[pandaFileKey][urlKey].emplace(breakpoint);
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JSDebugger::PushBreakpointToGlobal(const JSBreakpoint &breakpoint, const JSPtLocation &location)
|
||||
{
|
||||
auto pandaFileKey = location.GetJsPandaFile()->GetJSPandaFileDesc();
|
||||
auto urlKey = location.GetSourceFile();
|
||||
if (globalBpList_.find(pandaFileKey) == globalBpList_.end()) {
|
||||
CUnorderedMap<std::string, CUnorderedSet<JSBreakpoint, HashJSBreakpoint>> urlHashMap;
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> breakpointSet;
|
||||
breakpointSet.emplace(breakpoint);
|
||||
urlHashMap[urlKey] = breakpointSet;
|
||||
globalBpList_[pandaFileKey] = urlHashMap;
|
||||
} else {
|
||||
auto urlHashMap = breakpoints_[pandaFileKey];
|
||||
if (urlHashMap.find(urlKey) == urlHashMap.end()) {
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> breakpointSet;
|
||||
breakpointSet.emplace(breakpoint);
|
||||
urlHashMap[urlKey] = breakpointSet;
|
||||
globalBpList_[pandaFileKey] = urlHashMap;
|
||||
} else {
|
||||
globalBpList_[pandaFileKey][urlKey].emplace(breakpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool JSDebugger::PullBreakpointFromGlobal(const JSBreakpoint &breakpoint)
|
||||
{
|
||||
auto pandaFileKey = breakpoint.GetPtMethod()->GetJSPandaFile()->GetJSPandaFileDesc();
|
||||
auto urlKey = breakpoint.GetUrl();
|
||||
if (breakpoints_.find(pandaFileKey) == breakpoints_.end()) {
|
||||
CUnorderedMap<std::string, CUnorderedSet<JSBreakpoint, HashJSBreakpoint>> urlHashMap;
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> breakpointSet;
|
||||
breakpointSet.emplace(breakpoint);
|
||||
urlHashMap[urlKey] = breakpointSet;
|
||||
breakpoints_[pandaFileKey] = urlHashMap;
|
||||
return true;
|
||||
} else {
|
||||
auto urlHashMap = breakpoints_[pandaFileKey];
|
||||
if (urlHashMap.find(urlKey) == urlHashMap.end()) {
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> breakpointSet;
|
||||
breakpointSet.emplace(breakpoint);
|
||||
urlHashMap[urlKey] = breakpointSet;
|
||||
breakpoints_[pandaFileKey] = urlHashMap;
|
||||
return true;
|
||||
} else {
|
||||
auto [_, success] = breakpoints_[pandaFileKey][urlKey].emplace(breakpoint);
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<JSBreakpoint> JSDebugger::SearchNoMatchBreakpointInLocalList(const JSPtLocation &location)
|
||||
{
|
||||
std::vector<JSBreakpoint> result{};
|
||||
if (breakpoints_.empty()) {
|
||||
return result;
|
||||
}
|
||||
for (const auto &entry : breakpoints_) {
|
||||
auto urlHashMap = breakpoints_[entry.first];
|
||||
auto urlKey = location.GetSourceFile();
|
||||
if (urlHashMap.find(urlKey) != urlHashMap.end()) {
|
||||
auto breakpointSet = urlHashMap[urlKey];
|
||||
for (const auto &bp : breakpointSet) {
|
||||
if ((bp.GetLine() == location.GetLine()) &&
|
||||
(bp.GetColumn() == location.GetColumn())) {
|
||||
result.emplace_back(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<JSBreakpoint> JSDebugger::SearchNoMatchBreakpointInGlobalList(const JSPtLocation &location)
|
||||
{
|
||||
std::vector<JSBreakpoint> result{};
|
||||
if (breakpoints_.empty()) {
|
||||
return result;
|
||||
}
|
||||
for (const auto &entry : globalBpList_) {
|
||||
auto urlHashMap = globalBpList_[entry.first];
|
||||
auto urlKey = location.GetSourceFile();
|
||||
if (urlHashMap.find(urlKey) != urlHashMap.end()) {
|
||||
auto breakpointSet = urlHashMap[urlKey];
|
||||
for (const auto &bp : breakpointSet) {
|
||||
if ((bp.GetLine() == location.GetLine()) &&
|
||||
(bp.GetColumn() == location.GetColumn())) {
|
||||
result.emplace_back(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<JSBreakpoint> JSDebugger::SearchBreakpointInGlobalList(const JSPtLocation &location, PtMethod *ptMethod)
|
||||
{
|
||||
auto pandaFileKey = ptMethod->GetJSPandaFile()->GetJSPandaFileDesc();
|
||||
if (globalBpList_.empty() || globalBpList_.find(pandaFileKey) == globalBpList_.end()) {
|
||||
return {};
|
||||
}
|
||||
auto urlHashMap = globalBpList_[pandaFileKey];
|
||||
if (urlHashMap.empty() || urlHashMap.find(location.GetSourceFile()) == urlHashMap.end()) {
|
||||
return {};
|
||||
}
|
||||
for (const auto &bp : urlHashMap[location.GetSourceFile()]) {
|
||||
if ((bp.GetBytecodeOffset() == location.GetBytecodeOffset()) &&
|
||||
(bp.GetPtMethod()->GetJSPandaFile() == ptMethod->GetJSPandaFile()) &&
|
||||
(bp.GetPtMethod()->GetMethodId() == ptMethod->GetMethodId())) {
|
||||
return bp;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<JSBreakpoint> JSDebugger::SearchBreakpointInGlobalList(JSHandle<Method> method, uint32_t bcOffset)
|
||||
{
|
||||
auto pandaFileKey = method->GetJSPandaFile()->GetJSPandaFileDesc();
|
||||
if (globalBpList_.empty() || globalBpList_.find(pandaFileKey) == globalBpList_.end()) {
|
||||
return {};
|
||||
}
|
||||
auto urlHashMap = globalBpList_.at(pandaFileKey);
|
||||
for (const auto &entry : urlHashMap) {
|
||||
for (const auto &bp : urlHashMap[entry.first]) {
|
||||
if ((bp.GetBytecodeOffset() == bcOffset) &&
|
||||
(bp.GetPtMethod()->GetJSPandaFile() == method->GetJSPandaFile()) &&
|
||||
(bp.GetPtMethod()->GetMethodId() == method->GetMethodId())) {
|
||||
return bp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool JSDebugger::RemoveUrlNotMatchedBreakpoint(const JSPtLocation &location)
|
||||
{
|
||||
for (const auto &pandafileEntry : breakpoints_) {
|
||||
for (const auto &urlHashMapEntry : breakpoints_[pandafileEntry.first]) {
|
||||
if (location.GetSourceFile() == urlHashMapEntry.first) {
|
||||
for (auto it = breakpoints_[pandafileEntry.first][urlHashMapEntry.first].begin();
|
||||
it != breakpoints_[pandafileEntry.first][urlHashMapEntry.first].end();) {
|
||||
const auto &bp = *it;
|
||||
if ((bp.GetLine() == location.GetLine()) && (bp.GetColumn() == location.GetColumn())) {
|
||||
it = breakpoints_[pandafileEntry.first][urlHashMapEntry.first].erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(listMutex_);
|
||||
RemoveGlobalBreakpoint(location);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSDebugger::RemoveGlobalBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, const JSPtLocation &location)
|
||||
{
|
||||
auto pandaFileKey = location.GetJsPandaFile()->GetJSPandaFileDesc();
|
||||
if (globalBpList_.empty() || globalBpList_.find(pandaFileKey) == globalBpList_.end()) {
|
||||
return false;
|
||||
}
|
||||
auto urlHashMap = globalBpList_[pandaFileKey];
|
||||
if (urlHashMap.empty() || urlHashMap.find(location.GetSourceFile()) == urlHashMap.end()) {
|
||||
return false;
|
||||
}
|
||||
for (auto it = urlHashMap[location.GetSourceFile()].begin(); it != urlHashMap[location.GetSourceFile()].end();) {
|
||||
const auto &bp = *it;
|
||||
if ((bp.GetBytecodeOffset() == location.GetBytecodeOffset()) &&
|
||||
(bp.GetPtMethod()->GetJSPandaFile() == ptMethod->GetJSPandaFile()) &&
|
||||
(bp.GetPtMethod()->GetMethodId() == ptMethod->GetMethodId())) {
|
||||
it = urlHashMap[location.GetSourceFile()].erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSDebugger::RemoveGlobalBreakpoint(const JSPtLocation &location)
|
||||
{
|
||||
for (const auto &entry : globalBpList_) {
|
||||
if (globalBpList_[entry.first].find(location.GetSourceFile()) != globalBpList_[entry.first].end()) {
|
||||
for (auto it = globalBpList_[entry.first][location.GetSourceFile()].begin();
|
||||
it != globalBpList_[entry.first][location.GetSourceFile()].end();) {
|
||||
const auto &bp = *it;
|
||||
if ((bp.GetLine() == location.GetLine()) && (bp.GetColumn() == location.GetColumn())) {
|
||||
it = globalBpList_[entry.first][location.GetSourceFile()].erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSDebugger::RemoveGlobalBreakpoint(const std::string &url)
|
||||
{
|
||||
for (const auto &entry : globalBpList_) {
|
||||
if (globalBpList_[entry.first].find(url) != globalBpList_[entry.first].end()) {
|
||||
globalBpList_[entry.first].erase(url);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -65,7 +370,8 @@ bool JSDebugger::SetSmartBreakpoint(const JSPtLocation &location)
|
||||
}
|
||||
|
||||
auto [_, success] = smartBreakpoints_.emplace(location.GetSourceFile(), ptMethod.release(),
|
||||
location.GetBytecodeOffset(), Global<FunctionRef>(ecmaVm_, FunctionRef::Undefined(ecmaVm_)));
|
||||
location.GetBytecodeOffset(), Global<FunctionRef>(ecmaVm_, FunctionRef::Undefined(ecmaVm_)),
|
||||
location.GetSourceFile(), location.GetLine(), location.GetColumn());
|
||||
if (!success) {
|
||||
// also return true
|
||||
LOG_DEBUGGER(WARN) << "SetSmartBreakpoint: Breakpoint already exists";
|
||||
@ -83,32 +389,51 @@ bool JSDebugger::RemoveBreakpoint(const JSPtLocation &location)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RemoveBreakpoint(ptMethod, location.GetBytecodeOffset())) {
|
||||
if (!RemoveLocalBreakpoint(ptMethod, location.GetBytecodeOffset())) {
|
||||
LOG_DEBUGGER(ERROR) << "RemoveBreakpoint: Breakpoint not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
DumpBreakpoints();
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(listMutex_);
|
||||
RemoveGlobalBreakpoint(ptMethod, location);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void JSDebugger::RemoveAllBreakpoints()
|
||||
{
|
||||
breakpoints_.clear();
|
||||
if (!globalBpList_.empty()) {
|
||||
{
|
||||
// acquire write lock of global list
|
||||
std::unique_lock<std::shared_mutex> globalListLock(listMutex_);
|
||||
globalBpList_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool JSDebugger::RemoveBreakpointsByUrl(const std::string &url)
|
||||
{
|
||||
for (auto it = breakpoints_.begin(); it != breakpoints_.end();) {
|
||||
const auto &bp = *it;
|
||||
if (bp.GetSourceFile() == url) {
|
||||
it = breakpoints_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
for (const auto &entry : breakpoints_) {
|
||||
if (breakpoints_[entry.first].find(url) != breakpoints_[entry.first].end()) {
|
||||
breakpoints_[entry.first].erase(url);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DumpBreakpoints();
|
||||
bool JSDebugger::RemoveAllBreakpointsByUrl(const std::string &url, bool skipGlobal)
|
||||
{
|
||||
RemoveBreakpointsByUrl(url);
|
||||
|
||||
if (!skipGlobal && !globalBpList_.empty()) {
|
||||
{
|
||||
// acquire write lock of global list
|
||||
std::unique_lock<std::shared_mutex> globalListLock(listMutex_);
|
||||
RemoveGlobalBreakpoint(url);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -144,25 +469,51 @@ bool JSDebugger::HandleBreakpoint(JSHandle<Method> method, uint32_t bcOffset)
|
||||
if (hooks_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Global<FunctionRef> funcRef = Global<FunctionRef>(ecmaVm_, FunctionRef::Undefined(ecmaVm_));
|
||||
auto smartBreakpoint = FindSmartBreakpoint(method, bcOffset);
|
||||
if (smartBreakpoint.has_value()) {
|
||||
JSPtLocation smartLocation {method->GetJSPandaFile(), method->GetMethodId(), bcOffset,
|
||||
smartBreakpoint.value().GetSourceFile()};
|
||||
JSPtLocation smartLocation {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, funcRef,
|
||||
smartBreakpoint.value().GetLine(),
|
||||
smartBreakpoint.value().GetColumn(), smartBreakpoint.value().GetSourceFile()};
|
||||
std::unique_ptr<PtMethod> ptMethod = FindMethod(smartLocation);
|
||||
RemoveSmartBreakpoint(ptMethod, bcOffset);
|
||||
hooks_->Breakpoint(smartLocation);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto breakpoint = FindBreakpoint(method, bcOffset);
|
||||
if (!breakpoint.has_value() || !IsBreakpointCondSatisfied(breakpoint)) {
|
||||
return false;
|
||||
auto breakpoint = FindLocalBreakpoint(method, bcOffset);
|
||||
if (breakpoint.has_value()) {
|
||||
// find breakpoint in Local list
|
||||
if (!IsBreakpointCondSatisfied(breakpoint)) {
|
||||
return false;
|
||||
}
|
||||
JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, funcRef,
|
||||
breakpoint.value().GetLine(), breakpoint.value().GetColumn(),
|
||||
breakpoint.value().GetSourceFile(), false, method->GetRecordNameStr()};
|
||||
hooks_->Breakpoint(location);
|
||||
} else {
|
||||
// if not found in local, try to find it in global list
|
||||
{
|
||||
// acquire read lock of global list
|
||||
std::shared_lock<std::shared_mutex> globalListLock(listMutex_);
|
||||
breakpoint = SearchBreakpointInGlobalList(method, bcOffset);
|
||||
}
|
||||
if (!breakpoint.has_value()) {
|
||||
return false;
|
||||
}
|
||||
if (!IsBreakpointCondSatisfied(breakpoint)) {
|
||||
return false;
|
||||
}
|
||||
JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, funcRef,
|
||||
breakpoint.value().GetLine(), breakpoint.value().GetColumn(),
|
||||
breakpoint.value().GetSourceFile(), true, method->GetRecordNameStr()};
|
||||
hooks_->Breakpoint(location);
|
||||
|
||||
if (ecmaVm_->GetJsDebuggerManager()->IsBreakpointSyncEnabled()) {
|
||||
PullBreakpointFromGlobal(breakpoint.value());
|
||||
}
|
||||
}
|
||||
JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset,
|
||||
breakpoint.value().GetSourceFile()};
|
||||
|
||||
hooks_->Breakpoint(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -176,13 +527,25 @@ bool JSDebugger::HandleDebuggerStmt(JSHandle<Method> method, uint32_t bcOffset)
|
||||
if (singleStepOnDebuggerStmt_) {
|
||||
return false;
|
||||
}
|
||||
auto breakpointAtDebugger = FindBreakpoint(method, bcOffset);
|
||||
auto breakpointAtDebugger = FindLocalBreakpoint(method, bcOffset);
|
||||
// if a breakpoint is set on the same line as debugger stmt,
|
||||
// the debugger stmt is ineffective
|
||||
if (breakpointAtDebugger.has_value()) {
|
||||
return false;
|
||||
}
|
||||
JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset};
|
||||
{
|
||||
// acquire read lock of global list
|
||||
std::shared_lock<std::shared_mutex> globalListLock(listMutex_);
|
||||
breakpointAtDebugger = SearchBreakpointInGlobalList(method, bcOffset);
|
||||
}
|
||||
if (breakpointAtDebugger.has_value()) {
|
||||
return false;
|
||||
}
|
||||
Global<FunctionRef> funcRef = Global<FunctionRef>(ecmaVm_, FunctionRef::Undefined(ecmaVm_));
|
||||
|
||||
JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, funcRef,
|
||||
breakpointAtDebugger.value().GetLine(),
|
||||
breakpointAtDebugger.value().GetColumn(), breakpointAtDebugger.value().GetUrl()};
|
||||
hooks_->DebuggerStmt(location);
|
||||
|
||||
return true;
|
||||
@ -193,8 +556,11 @@ void JSDebugger::HandleExceptionThrowEvent(const JSThread *thread, JSHandle<Meth
|
||||
if (hooks_ == nullptr || !thread->HasPendingException()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSPtLocation throwLocation {method->GetJSPandaFile(), method->GetMethodId(), bcOffset};
|
||||
Global<FunctionRef> funcRef = Global<FunctionRef>(ecmaVm_, FunctionRef::Undefined(ecmaVm_));
|
||||
const std::string emptyUrl = "";
|
||||
int32_t invalidLine = -1;
|
||||
JSPtLocation throwLocation {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, funcRef,
|
||||
invalidLine, invalidLine, emptyUrl};
|
||||
|
||||
hooks_->Exception(throwLocation);
|
||||
}
|
||||
@ -204,19 +570,27 @@ bool JSDebugger::HandleStep(JSHandle<Method> method, uint32_t bcOffset)
|
||||
if (hooks_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset};
|
||||
Global<FunctionRef> funcRef = Global<FunctionRef>(ecmaVm_, FunctionRef::Undefined(ecmaVm_));
|
||||
const std::string emptyUrl = "";
|
||||
int32_t invalidLine = -1;
|
||||
JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, funcRef,
|
||||
invalidLine, invalidLine, emptyUrl};
|
||||
|
||||
return hooks_->SingleStep(location);
|
||||
}
|
||||
|
||||
std::optional<JSBreakpoint> JSDebugger::FindBreakpoint(JSHandle<Method> method, uint32_t bcOffset) const
|
||||
std::optional<JSBreakpoint> JSDebugger::FindLocalBreakpoint(JSHandle<Method> method, uint32_t bcOffset)
|
||||
{
|
||||
for (const auto &bp : breakpoints_) {
|
||||
if ((bp.GetBytecodeOffset() == bcOffset) &&
|
||||
(bp.GetPtMethod()->GetJSPandaFile() == method->GetJSPandaFile()) &&
|
||||
(bp.GetPtMethod()->GetMethodId() == method->GetMethodId())) {
|
||||
return bp;
|
||||
for (const auto &pandafileEntry : breakpoints_) {
|
||||
for (const auto &urlHashMapEntry : breakpoints_[pandafileEntry.first]) {
|
||||
auto breakpointSet = breakpoints_[pandafileEntry.first][urlHashMapEntry.first];
|
||||
for (const auto &bp : breakpointSet) {
|
||||
if ((bp.GetBytecodeOffset() == bcOffset) &&
|
||||
(bp.GetPtMethod()->GetJSPandaFile() == method->GetJSPandaFile()) &&
|
||||
(bp.GetPtMethod()->GetMethodId() == method->GetMethodId())) {
|
||||
return bp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
@ -234,19 +608,24 @@ std::optional<JSBreakpoint> JSDebugger::FindSmartBreakpoint(JSHandle<Method> met
|
||||
return {};
|
||||
}
|
||||
|
||||
bool JSDebugger::RemoveBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset)
|
||||
bool JSDebugger::RemoveLocalBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset)
|
||||
{
|
||||
for (auto it = breakpoints_.begin(); it != breakpoints_.end(); ++it) {
|
||||
const auto &bp = *it;
|
||||
if ((bp.GetBytecodeOffset() == bcOffset) &&
|
||||
(bp.GetPtMethod()->GetJSPandaFile() == ptMethod->GetJSPandaFile()) &&
|
||||
(bp.GetPtMethod()->GetMethodId() == ptMethod->GetMethodId())) {
|
||||
it = breakpoints_.erase(it);
|
||||
return true;
|
||||
for (const auto &pandafileEntry : breakpoints_) {
|
||||
for (const auto &urlHashMapEntry : breakpoints_[pandafileEntry.first]) {
|
||||
for (auto it = breakpoints_[pandafileEntry.first][urlHashMapEntry.first].begin();
|
||||
it != breakpoints_[pandafileEntry.first][urlHashMapEntry.first].end();) {
|
||||
const auto &bp = *it;
|
||||
if ((bp.GetBytecodeOffset() == bcOffset) &&
|
||||
(bp.GetPtMethod()->GetJSPandaFile() == ptMethod->GetJSPandaFile()) &&
|
||||
(bp.GetPtMethod()->GetMethodId() == ptMethod->GetMethodId())) {
|
||||
it = breakpoints_[pandafileEntry.first][urlHashMapEntry.first].erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSDebugger::RemoveSmartBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset)
|
||||
@ -288,10 +667,37 @@ std::unique_ptr<PtMethod> JSDebugger::FindMethod(const JSPtLocation &location) c
|
||||
|
||||
void JSDebugger::DumpBreakpoints()
|
||||
{
|
||||
LOG_DEBUGGER(INFO) << "dump breakpoints with size " << breakpoints_.size();
|
||||
for (const auto &bp : breakpoints_) {
|
||||
LOG_DEBUGGER(DEBUG) << bp.ToString();
|
||||
int32_t size = 0;
|
||||
LOG_DEBUGGER(DEBUG) << "Dumping breakpoints in local list:";
|
||||
for (const auto &entry : breakpoints_) {
|
||||
auto urlHashMap = breakpoints_[entry.first];
|
||||
for (const auto &pair : urlHashMap) {
|
||||
LOG_DEBUGGER(DEBUG) << "URL: " << pair.first;
|
||||
for (const auto &bp : urlHashMap[pair.first]) {
|
||||
size++;
|
||||
LOG_DEBUGGER(DEBUG) << "Local #" << size << ": " << bp.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_DEBUGGER(INFO) << "Dumpped breakpoints in local list with size " << size;
|
||||
}
|
||||
|
||||
void JSDebugger::DumpGlobalBreakpoints()
|
||||
{
|
||||
// Should call this function after acquiring the lock of global list
|
||||
int32_t size = 0;
|
||||
LOG_DEBUGGER(DEBUG) << "Dumping breakpoints in global list:";
|
||||
for (const auto &entry : globalBpList_) {
|
||||
auto urlHashMap = globalBpList_[entry.first];
|
||||
for (const auto &pair : urlHashMap) {
|
||||
LOG_DEBUGGER(DEBUG) << "URL: " << pair.first;
|
||||
for (const auto &bp : urlHashMap[pair.first]) {
|
||||
size++;
|
||||
LOG_DEBUGGER(DEBUG) << "Global #" << size << ": " << bp.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_DEBUGGER(INFO) << "Dumpped breakpoints in global list with size " << size;
|
||||
}
|
||||
|
||||
bool JSDebugger::IsBreakpointCondSatisfied(std::optional<JSBreakpoint> breakpoint) const
|
||||
@ -301,7 +707,7 @@ bool JSDebugger::IsBreakpointCondSatisfied(std::optional<JSBreakpoint> breakpoin
|
||||
}
|
||||
JSThread *thread = ecmaVm_->GetJSThread();
|
||||
auto condFuncRef = breakpoint.value().GetConditionFunction();
|
||||
if (condFuncRef->IsFunction(ecmaVm_)) {
|
||||
if (!condFuncRef->IsHole() && condFuncRef->IsFunction(ecmaVm_)) {
|
||||
LOG_DEBUGGER(INFO) << "BreakpointCondition: evaluating condition";
|
||||
auto handlerPtr = std::make_shared<FrameHandler>(ecmaVm_->GetJSThread());
|
||||
auto evalResult = DebuggerApi::EvaluateViaFuncCall(const_cast<EcmaVM *>(ecmaVm_),
|
||||
@ -345,4 +751,4 @@ void JSDebugger::MethodExit([[maybe_unused]] JSHandle<Method> method)
|
||||
auto *debuggerMgr = ecmaVm_->GetJsDebuggerManager();
|
||||
debuggerMgr->MethodExit(method);
|
||||
}
|
||||
} // namespace panda::tooling::ecmascript
|
||||
} // namespace panda::tooling::ecmascript
|
@ -27,8 +27,9 @@ class JSBreakpoint {
|
||||
public:
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
|
||||
JSBreakpoint(const std::string &sourceFile, PtMethod *ptMethod, uint32_t bcOffset,
|
||||
const Global<FunctionRef> &condFuncRef) : sourceFile_(sourceFile), ptMethod_(ptMethod),
|
||||
bcOffset_(bcOffset), condFuncRef_(condFuncRef) {}
|
||||
const Global<FunctionRef> &condFuncRef, const std::string &url,
|
||||
int32_t line, int32_t column) : sourceFile_(sourceFile), ptMethod_(ptMethod),
|
||||
bcOffset_(bcOffset), condFuncRef_(condFuncRef), url_(url), line_(line), column_(column) {}
|
||||
~JSBreakpoint() = default;
|
||||
|
||||
const std::string &GetSourceFile() const
|
||||
@ -46,6 +47,21 @@ public:
|
||||
return bcOffset_;
|
||||
}
|
||||
|
||||
const std::string &GetUrl() const
|
||||
{
|
||||
return url_;
|
||||
}
|
||||
|
||||
int32_t GetLine() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
|
||||
int32_t GetColumn() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
||||
bool operator==(const JSBreakpoint &bpoint) const
|
||||
{
|
||||
return bcOffset_ == bpoint.GetBytecodeOffset() &&
|
||||
@ -62,6 +78,9 @@ public:
|
||||
breakpoint << "bytecodeOffset:" << bcOffset_ << ", ";
|
||||
breakpoint << "sourceFile:" << "\""<< sourceFile_ << "\""<< ", ";
|
||||
breakpoint << "jsPandaFile:" << "\"" << ptMethod_->GetJSPandaFile()->GetJSPandaFileDesc() << "\"";
|
||||
breakpoint << "url:" << "\""<< url_ << "\""<< ", ";
|
||||
breakpoint << "line:" << line_ << ", ";
|
||||
breakpoint << "column:" << column_;
|
||||
breakpoint << "]";
|
||||
return breakpoint.str();
|
||||
}
|
||||
@ -79,6 +98,11 @@ private:
|
||||
PtMethod *ptMethod_ {nullptr};
|
||||
uint32_t bcOffset_;
|
||||
Global<FunctionRef> condFuncRef_;
|
||||
|
||||
// Used by new Breakpoint logic
|
||||
std::string url_;
|
||||
int32_t line_;
|
||||
int32_t column_;
|
||||
};
|
||||
|
||||
class HashJSBreakpoint {
|
||||
@ -168,11 +192,13 @@ public:
|
||||
{
|
||||
singleStepOnDebuggerStmt_ = status;
|
||||
}
|
||||
bool SetUrlNotMatchedBreakpoint(const JSPtLocation &location);
|
||||
std::vector<bool> SetBreakpointUsingList(std::vector<JSPtLocation> &list);
|
||||
bool RemoveUrlNotMatchedBreakpoint(const JSPtLocation &location);
|
||||
bool RemoveAllBreakpointsByUrl(const std::string &url, bool skipGlobal);
|
||||
private:
|
||||
std::unique_ptr<PtMethod> FindMethod(const JSPtLocation &location) const;
|
||||
std::optional<JSBreakpoint> FindBreakpoint(JSHandle<Method> method, uint32_t bcOffset) const;
|
||||
std::optional<JSBreakpoint> FindSmartBreakpoint(JSHandle<Method> method, uint32_t bcOffset) const;
|
||||
bool RemoveBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset);
|
||||
bool RemoveSmartBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset);
|
||||
void HandleExceptionThrowEvent(const JSThread *thread, JSHandle<Method> method, uint32_t bcOffset);
|
||||
bool HandleStep(JSHandle<Method> method, uint32_t bcOffset);
|
||||
@ -180,15 +206,38 @@ private:
|
||||
bool HandleBreakpoint(JSHandle<Method> method, uint32_t bcOffset);
|
||||
void DumpBreakpoints();
|
||||
bool IsBreakpointCondSatisfied(std::optional<JSBreakpoint> breakpoint) const;
|
||||
bool PushBreakpointToLocal(const JSBreakpoint &breakpoint, const JSPtLocation &location);
|
||||
// All methods which manipulates the globalBpList_ should be called with write lock acquired
|
||||
// All methods thatsearches/pulls breakpoints from the globalBpList_ should be used with read lock acquired
|
||||
std::optional<JSBreakpoint> FindLocalBreakpoint(JSHandle<Method> method, uint32_t bcOffset);
|
||||
bool RemoveLocalBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset);
|
||||
bool SetBreakpointWithMatchedUrl(const JSPtLocation &location, Global<FunctionRef> condFuncRef);
|
||||
bool SetBreakpointWithoutMatchedUrl(const JSPtLocation &location);
|
||||
std::vector<bool> SetBreakpointByList(std::vector<JSPtLocation> &list);
|
||||
void PushBreakpointToGlobal(const JSBreakpoint &breakpoint, const JSPtLocation &location);
|
||||
bool PullBreakpointFromGlobal(const JSBreakpoint &breakpoint);
|
||||
void DumpGlobalBreakpoints();
|
||||
std::optional<JSBreakpoint> SearchBreakpointInGlobalList(const JSPtLocation &location, PtMethod *ptMethod);
|
||||
std::optional<JSBreakpoint> SearchBreakpointInGlobalList(JSHandle<Method> method, uint32_t bcOffset);
|
||||
std::vector<JSBreakpoint> SearchNoMatchBreakpointInLocalList(const JSPtLocation &location);
|
||||
std::vector<JSBreakpoint> SearchNoMatchBreakpointInGlobalList(const JSPtLocation &location);
|
||||
bool RemoveGlobalBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, const JSPtLocation &location);
|
||||
bool RemoveGlobalBreakpoint(const JSPtLocation &location);
|
||||
bool RemoveGlobalBreakpoint(const std::string &url);
|
||||
|
||||
const EcmaVM *ecmaVm_;
|
||||
PtHooks *hooks_ {nullptr};
|
||||
NotificationManager *notificationMgr_ {nullptr};
|
||||
bool singleStepOnDebuggerStmt_ {false};
|
||||
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> breakpoints_ {};
|
||||
static std::shared_mutex listMutex_;
|
||||
// Map<JSPandafile, Map<url, Set<JSBreakpoint>>>
|
||||
static CUnorderedMap<CString, CUnorderedMap<std::string,
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint>>> globalBpList_;
|
||||
CUnorderedMap<CString, CUnorderedMap<std::string,
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint>>> breakpoints_ {};
|
||||
CUnorderedSet<JSBreakpoint, HashJSBreakpoint> smartBreakpoints_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript::tooling
|
||||
|
||||
#endif // ECMASCRIPT_DEBUGGER_JS_DEBUGGER_H
|
||||
#endif // ECMASCRIPT_DEBUGGER_JS_DEBUGGER_H
|
@ -219,6 +219,21 @@ public:
|
||||
{
|
||||
return isObjHashDisplayEnabled_;
|
||||
}
|
||||
|
||||
void EnableBreakpointSync()
|
||||
{
|
||||
isBreakpointSyncEnabled_ = true;
|
||||
}
|
||||
|
||||
void DisableBreakpointSync()
|
||||
{
|
||||
isBreakpointSyncEnabled_ = false;
|
||||
}
|
||||
|
||||
bool IsBreakpointSyncEnabled()
|
||||
{
|
||||
return isBreakpointSyncEnabled_;
|
||||
}
|
||||
|
||||
void EnableSerializationTimeoutCheck()
|
||||
{
|
||||
@ -256,6 +271,7 @@ private:
|
||||
bool isMixedStackEnabled_ { false };
|
||||
bool isSignalInterrupt_ {false};
|
||||
bool isObjHashDisplayEnabled_ { true };
|
||||
bool isBreakpointSyncEnabled_ { true };
|
||||
ProtocolHandler *debuggerHandler_ {nullptr};
|
||||
LibraryHandle debuggerLibraryHandle_ {nullptr};
|
||||
ObjectUpdaterFunc *updaterFunc_ {nullptr};
|
||||
@ -278,4 +294,4 @@ private:
|
||||
};
|
||||
} // panda::ecmascript::tooling
|
||||
|
||||
#endif // ECMASCRIPT_DEBUGGER_JS_DEBUGGER_MANAGER_H
|
||||
#endif // ECMASCRIPT_DEBUGGER_JS_DEBUGGER_MANAGER_H
|
@ -33,6 +33,20 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
JSPtLocation(const JSPandaFile *jsPandaFile, EntityId methodId, uint32_t bytecodeOffset,
|
||||
Global<FunctionRef> &condFuncRef, int32_t line = -1,
|
||||
int32_t column = -1, const std::string &sourceFile = "",
|
||||
bool needResetBreakpoint = false, CString recordName = "") : jsPandaFile_(jsPandaFile),
|
||||
methodId_(methodId), bytecodeOffset_(bytecodeOffset),
|
||||
condFuncRef_(condFuncRef), line_(line), column_(column),
|
||||
sourceFile_(sourceFile), needResetBreakpoint_(needResetBreakpoint), recordName_(recordName)
|
||||
{
|
||||
}
|
||||
|
||||
JSPtLocation(const std::string &url, int32_t line, int32_t column) : line_(line), column_(column), sourceFile_(url)
|
||||
{
|
||||
}
|
||||
|
||||
const JSPandaFile *GetJsPandaFile() const
|
||||
{
|
||||
return jsPandaFile_;
|
||||
@ -53,6 +67,31 @@ public:
|
||||
return bytecodeOffset_;
|
||||
}
|
||||
|
||||
const Global<FunctionRef> &GetCondFuncRef() const
|
||||
{
|
||||
return condFuncRef_;
|
||||
}
|
||||
|
||||
int32_t GetLine() const
|
||||
{
|
||||
return line_;
|
||||
}
|
||||
|
||||
int32_t GetColumn() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
||||
const bool &GetNeedResetBreakpoint() const
|
||||
{
|
||||
return needResetBreakpoint_;
|
||||
}
|
||||
|
||||
const CString &GetRecordName() const
|
||||
{
|
||||
return recordName_;
|
||||
}
|
||||
|
||||
bool operator==(const JSPtLocation &location) const
|
||||
{
|
||||
return methodId_ == location.methodId_ && bytecodeOffset_ == location.bytecodeOffset_ &&
|
||||
@ -66,7 +105,12 @@ public:
|
||||
location << "methodId:" << methodId_ << ", ";
|
||||
location << "bytecodeOffset:" << bytecodeOffset_ << ", ";
|
||||
location << "sourceFile:" << "\""<< sourceFile_ << "\""<< ", ";
|
||||
location << "jsPandaFile:" << "\"" << jsPandaFile_->GetJSPandaFileDesc() << "\"";
|
||||
if (jsPandaFile_ != nullptr) {
|
||||
location << "jsPandaFile:" << "\"" << jsPandaFile_->GetJSPandaFileDesc() << "\"";
|
||||
}
|
||||
location << "line: " << line_ << ", ";
|
||||
location << "column: " << column_ << ", ";
|
||||
location << "needResetBreakpoint: " << needResetBreakpoint_;
|
||||
location << "]";
|
||||
return location.str();
|
||||
}
|
||||
@ -80,8 +124,13 @@ private:
|
||||
const JSPandaFile *jsPandaFile_ {nullptr};
|
||||
EntityId methodId_;
|
||||
uint32_t bytecodeOffset_ {0};
|
||||
Global<FunctionRef> condFuncRef_;
|
||||
int32_t line_;
|
||||
int32_t column_;
|
||||
std::string sourceFile_; // mainly used for breakpoint
|
||||
bool needResetBreakpoint_ {false};
|
||||
CString recordName_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript::tooling
|
||||
|
||||
#endif // ECMASCRIPT_DEBUGGER_JS_PT_LOCATION_H
|
||||
#endif // ECMASCRIPT_DEBUGGER_JS_PT_LOCATION_H
|
@ -93,7 +93,8 @@ public:
|
||||
|
||||
template<class Callback>
|
||||
bool MatchWithLocation(const Callback &cb, int32_t line, int32_t column,
|
||||
const std::string &url, const std::unordered_set<std::string> &debugRecordName)
|
||||
const std::string &url, const std::unordered_set<std::string> &debugRecordName,
|
||||
Global<FunctionRef> funcRef)
|
||||
{
|
||||
if (line == SPECIAL_LINE_MARK) {
|
||||
return false;
|
||||
@ -146,7 +147,8 @@ public:
|
||||
for (const auto &pair : columnTable) {
|
||||
if (pair.offset >= currentOffset && pair.offset < nextOffset) {
|
||||
if (pair.column == column) {
|
||||
return cb(JSPtLocation(jsPandaFile_, methodId, pair.offset, url));
|
||||
return cb(JSPtLocation(jsPandaFile_, methodId, pair.offset, funcRef,
|
||||
line, column, url));
|
||||
} else if (pair.column < minColumn && currentOffset < minColumnOffset) {
|
||||
minColumn = pair.column;
|
||||
minColumnOffset = currentOffset;
|
||||
@ -157,10 +159,12 @@ public:
|
||||
}
|
||||
}
|
||||
if (minColumn != INT32_MAX) { // find the smallest column for the corresponding row
|
||||
return cb(JSPtLocation(jsPandaFile_, minColumnMethodId, minColumnOffset, url));
|
||||
return cb(JSPtLocation(jsPandaFile_, minColumnMethodId, minColumnOffset, funcRef,
|
||||
line, column, url));
|
||||
}
|
||||
if (currentOffset != UINT32_MAX) { // find corresponding row, but not find corresponding column
|
||||
return cb(JSPtLocation(jsPandaFile_, currentMethodId, currentOffset, url));
|
||||
return cb(JSPtLocation(jsPandaFile_, currentMethodId, currentOffset, funcRef,
|
||||
line, column, url));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -242,4 +246,4 @@ private:
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_JSPANDAFILE_DEBUG_INFO_EXTRACTOR_H
|
||||
#endif // ECMASCRIPT_JSPANDAFILE_DEBUG_INFO_EXTRACTOR_H
|
Loading…
Reference in New Issue
Block a user