mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2024-11-23 12:19:46 +00:00
520 lines
20 KiB
C++
520 lines
20 KiB
C++
/*
|
|
* Copyright (C) 2013-2019 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2011 Google Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following disclaimer
|
|
* in the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Google Inc. nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "InspectorRuntimeAgent.h"
|
|
|
|
#include "Completion.h"
|
|
#include "ControlFlowProfiler.h"
|
|
#include "Debugger.h"
|
|
#include "InjectedScript.h"
|
|
#include "InjectedScriptHost.h"
|
|
#include "InjectedScriptManager.h"
|
|
#include "JSLock.h"
|
|
#include "ParserError.h"
|
|
#include "SourceCode.h"
|
|
#include "TypeProfiler.h"
|
|
#include "TypeProfilerLog.h"
|
|
#include <wtf/JSONValues.h>
|
|
|
|
namespace Inspector {
|
|
|
|
using namespace JSC;
|
|
|
|
InspectorRuntimeAgent::InspectorRuntimeAgent(AgentContext& context)
|
|
: InspectorAgentBase("Runtime"_s)
|
|
, m_injectedScriptManager(context.injectedScriptManager)
|
|
, m_debugger(context.environment.debugger())
|
|
, m_vm(context.environment.vm())
|
|
{
|
|
}
|
|
|
|
InspectorRuntimeAgent::~InspectorRuntimeAgent()
|
|
{
|
|
}
|
|
|
|
static Ref<Protocol::Runtime::ErrorRange> buildErrorRangeObject(const JSTokenLocation& tokenLocation)
|
|
{
|
|
return Protocol::Runtime::ErrorRange::create()
|
|
.setStartOffset(tokenLocation.startOffset)
|
|
.setEndOffset(tokenLocation.endOffset)
|
|
.release();
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::enable()
|
|
{
|
|
m_enabled = true;
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::disable()
|
|
{
|
|
m_enabled = false;
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<std::tuple<Protocol::Runtime::SyntaxErrorType, String /* message */, RefPtr<Protocol::Runtime::ErrorRange>>> InspectorRuntimeAgent::parse(const String& expression)
|
|
{
|
|
JSLockHolder lock(m_vm);
|
|
|
|
ParserError error;
|
|
checkSyntax(m_vm, JSC::makeSource(expression, { }), error);
|
|
|
|
Optional<Protocol::Runtime::SyntaxErrorType> result;
|
|
String message;
|
|
RefPtr<Protocol::Runtime::ErrorRange> range;
|
|
|
|
switch (error.syntaxErrorType()) {
|
|
case ParserError::SyntaxErrorNone:
|
|
result = Protocol::Runtime::SyntaxErrorType::None;
|
|
break;
|
|
|
|
case ParserError::SyntaxErrorIrrecoverable:
|
|
result = Protocol::Runtime::SyntaxErrorType::Irrecoverable;
|
|
break;
|
|
|
|
case ParserError::SyntaxErrorUnterminatedLiteral:
|
|
result = Protocol::Runtime::SyntaxErrorType::UnterminatedLiteral;
|
|
break;
|
|
|
|
case ParserError::SyntaxErrorRecoverable:
|
|
result = Protocol::Runtime::SyntaxErrorType::Recoverable;
|
|
break;
|
|
}
|
|
|
|
if (error.syntaxErrorType() != ParserError::SyntaxErrorNone) {
|
|
message = error.message();
|
|
range = buildErrorRangeObject(error.token().m_location);
|
|
}
|
|
|
|
return { { *result, message, WTFMove(range) } };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, Optional<bool> /* wasThrown */, Optional<int> /* savedResultIndex */>> InspectorRuntimeAgent::evaluate(const String& expression, const String& objectGroup, Optional<bool>&& includeCommandLineAPI, Optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, Optional<Protocol::Runtime::ExecutionContextId>&& executionContextId, Optional<bool>&& returnByValue, Optional<bool>&& generatePreview, Optional<bool>&& saveResult, Optional<bool>&& /* emulateUserGesture */)
|
|
{
|
|
Protocol::ErrorString errorString;
|
|
|
|
InjectedScript injectedScript = injectedScriptForEval(errorString, WTFMove(executionContextId));
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected(errorString);
|
|
|
|
RefPtr<Protocol::Runtime::RemoteObject> result;
|
|
Optional<bool> wasThrown;
|
|
Optional<int> savedResultIndex;
|
|
|
|
JSC::Debugger::TemporarilyDisableExceptionBreakpoints temporarilyDisableExceptionBreakpoints(m_debugger);
|
|
|
|
bool pauseAndMute = doNotPauseOnExceptionsAndMuteConsole.valueOr(false);
|
|
if (pauseAndMute) {
|
|
temporarilyDisableExceptionBreakpoints.replace();
|
|
muteConsole();
|
|
}
|
|
|
|
injectedScript.evaluate(errorString, expression, objectGroup, includeCommandLineAPI.valueOr(false), returnByValue.valueOr(false), generatePreview.valueOr(false), saveResult.valueOr(false), result, wasThrown, savedResultIndex);
|
|
|
|
if (pauseAndMute)
|
|
unmuteConsole();
|
|
|
|
if (!result)
|
|
return makeUnexpected(errorString);
|
|
|
|
return { {result.releaseNonNull(), WTFMove(wasThrown), WTFMove(savedResultIndex) } };
|
|
}
|
|
|
|
void InspectorRuntimeAgent::awaitPromise(const Protocol::Runtime::RemoteObjectId& promiseObjectId, Optional<bool>&& returnByValue, Optional<bool>&& generatePreview, Optional<bool>&& saveResult, Ref<AwaitPromiseCallback>&& callback)
|
|
{
|
|
InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(promiseObjectId);
|
|
if (injectedScript.hasNoValue()) {
|
|
callback->sendFailure("Missing injected script for given promiseObjectId"_s);
|
|
return;
|
|
}
|
|
|
|
injectedScript.awaitPromise(promiseObjectId, returnByValue.valueOr(false), generatePreview.valueOr(false), saveResult.valueOr(false), [callback = WTFMove(callback)] (Protocol::ErrorString& errorString, RefPtr<Protocol::Runtime::RemoteObject>&& result, Optional<bool>&& wasThrown, Optional<int>&& savedResultIndex) {
|
|
if (!result)
|
|
callback->sendFailure(errorString);
|
|
else
|
|
callback->sendSuccess(result.releaseNonNull(), WTFMove(wasThrown), WTFMove(savedResultIndex));
|
|
});
|
|
}
|
|
|
|
Protocol::ErrorStringOr<std::tuple<Ref<Protocol::Runtime::RemoteObject>, Optional<bool> /* wasThrown */>> InspectorRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& functionDeclaration, RefPtr<JSON::Array>&& arguments, Optional<bool>&& doNotPauseOnExceptionsAndMuteConsole, Optional<bool>&& returnByValue, Optional<bool>&& generatePreview, Optional<bool>&& /* emulateUserGesture */)
|
|
{
|
|
Protocol::ErrorString errorString;
|
|
|
|
InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected("Missing injected script for given objectId"_s);
|
|
|
|
RefPtr<Protocol::Runtime::RemoteObject> result;
|
|
Optional<bool> wasThrown;
|
|
|
|
JSC::Debugger::TemporarilyDisableExceptionBreakpoints temporarilyDisableExceptionBreakpoints(m_debugger);
|
|
|
|
bool pauseAndMute = doNotPauseOnExceptionsAndMuteConsole.valueOr(false);
|
|
if (pauseAndMute) {
|
|
temporarilyDisableExceptionBreakpoints.replace();
|
|
muteConsole();
|
|
}
|
|
|
|
injectedScript.callFunctionOn(errorString, objectId, functionDeclaration, arguments ? arguments->toJSONString() : nullString(), returnByValue.valueOr(false), generatePreview.valueOr(false), result, wasThrown);
|
|
|
|
if (pauseAndMute)
|
|
unmuteConsole();
|
|
|
|
if (!result)
|
|
return makeUnexpected(errorString);
|
|
|
|
return { { result.releaseNonNull(), WTFMove(wasThrown) } };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<Ref<Protocol::Runtime::ObjectPreview>> InspectorRuntimeAgent::getPreview(const Protocol::Runtime::RemoteObjectId& objectId)
|
|
{
|
|
Protocol::ErrorString errorString;
|
|
|
|
InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected("Missing injected script for given objectId"_s);
|
|
|
|
JSC::Debugger::TemporarilyDisableExceptionBreakpoints temporarilyDisableExceptionBreakpoints(m_debugger);
|
|
temporarilyDisableExceptionBreakpoints.replace();
|
|
|
|
RefPtr<Protocol::Runtime::ObjectPreview> preview;
|
|
|
|
muteConsole();
|
|
|
|
injectedScript.getPreview(errorString, objectId, preview);
|
|
|
|
unmuteConsole();
|
|
|
|
if (!preview)
|
|
return makeUnexpected(errorString);
|
|
|
|
return preview.releaseNonNull();
|
|
}
|
|
|
|
Protocol::ErrorStringOr<std::tuple<Ref<JSON::ArrayOf<Protocol::Runtime::PropertyDescriptor>>, RefPtr<JSON::ArrayOf<Protocol::Runtime::InternalPropertyDescriptor>>>> InspectorRuntimeAgent::getProperties(const Protocol::Runtime::RemoteObjectId& objectId, Optional<bool>&& ownProperties, Optional<int>&& fetchStart, Optional<int>&& fetchCount, Optional<bool>&& generatePreview)
|
|
{
|
|
Protocol::ErrorString errorString;
|
|
|
|
InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected("Missing injected script for given objectId"_s);
|
|
|
|
int start = fetchStart.valueOr(0);
|
|
if (start < 0)
|
|
return makeUnexpected("fetchStart cannot be negative"_s);
|
|
|
|
int count = fetchCount.valueOr(0);
|
|
if (count < 0)
|
|
return makeUnexpected("fetchCount cannot be negative"_s);
|
|
|
|
RefPtr<JSON::ArrayOf<Protocol::Runtime::PropertyDescriptor>> properties;
|
|
RefPtr<JSON::ArrayOf<Protocol::Runtime::InternalPropertyDescriptor>> internalProperties;
|
|
|
|
JSC::Debugger::TemporarilyDisableExceptionBreakpoints temporarilyDisableExceptionBreakpoints(m_debugger);
|
|
temporarilyDisableExceptionBreakpoints.replace();
|
|
|
|
muteConsole();
|
|
|
|
injectedScript.getProperties(errorString, objectId, ownProperties.valueOr(false), start, count, generatePreview.valueOr(false), properties);
|
|
|
|
// Only include internal properties for the first fetch.
|
|
if (!start)
|
|
injectedScript.getInternalProperties(errorString, objectId, generatePreview.valueOr(false), internalProperties);
|
|
|
|
unmuteConsole();
|
|
|
|
if (!properties)
|
|
return makeUnexpected(errorString);
|
|
|
|
return { { properties.releaseNonNull(), WTFMove(internalProperties) } };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<std::tuple<Ref<JSON::ArrayOf<Protocol::Runtime::PropertyDescriptor>>, RefPtr<JSON::ArrayOf<Protocol::Runtime::InternalPropertyDescriptor>>>> InspectorRuntimeAgent::getDisplayableProperties(const Protocol::Runtime::RemoteObjectId& objectId, Optional<int>&& fetchStart, Optional<int>&& fetchCount, Optional<bool>&& generatePreview)
|
|
{
|
|
Protocol::ErrorString errorString;
|
|
|
|
InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected("Missing injected script for given objectId"_s);
|
|
|
|
int start = fetchStart.valueOr(0);
|
|
if (start < 0)
|
|
return makeUnexpected("fetchStart cannot be negative"_s);
|
|
|
|
int count = fetchCount.valueOr(0);
|
|
if (count < 0)
|
|
return makeUnexpected("fetchCount cannot be negative"_s);
|
|
|
|
RefPtr<JSON::ArrayOf<Protocol::Runtime::PropertyDescriptor>> properties;
|
|
RefPtr<JSON::ArrayOf<Protocol::Runtime::InternalPropertyDescriptor>> internalProperties;
|
|
|
|
JSC::Debugger::TemporarilyDisableExceptionBreakpoints temporarilyDisableExceptionBreakpoints(m_debugger);
|
|
temporarilyDisableExceptionBreakpoints.replace();
|
|
|
|
muteConsole();
|
|
|
|
injectedScript.getDisplayableProperties(errorString, objectId, start, count, generatePreview.valueOr(false), properties);
|
|
|
|
// Only include internal properties for the first fetch.
|
|
if (!start)
|
|
injectedScript.getInternalProperties(errorString, objectId, generatePreview.valueOr(false), internalProperties);
|
|
|
|
unmuteConsole();
|
|
|
|
if (!properties)
|
|
return makeUnexpected(errorString);
|
|
|
|
return { { properties.releaseNonNull(), WTFMove(internalProperties) } };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::Runtime::CollectionEntry>>> InspectorRuntimeAgent::getCollectionEntries(const Protocol::Runtime::RemoteObjectId& objectId, const String& objectGroup, Optional<int>&& fetchStart, Optional<int>&& fetchCount)
|
|
{
|
|
Protocol::ErrorString errorString;
|
|
|
|
InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected("Missing injected script for given objectId"_s);
|
|
|
|
int start = fetchStart.valueOr(0);
|
|
if (start < 0)
|
|
return makeUnexpected("fetchStart cannot be negative"_s);
|
|
|
|
int count = fetchCount.valueOr(0);
|
|
if (count < 0)
|
|
return makeUnexpected("fetchCount cannot be negative"_s);
|
|
|
|
RefPtr<JSON::ArrayOf<Protocol::Runtime::CollectionEntry>> entries;
|
|
|
|
injectedScript.getCollectionEntries(errorString, objectId, objectGroup, start, count, entries);
|
|
|
|
if (!entries)
|
|
return makeUnexpected(errorString);
|
|
|
|
return entries.releaseNonNull();
|
|
}
|
|
|
|
Protocol::ErrorStringOr<Optional<int> /* saveResultIndex */> InspectorRuntimeAgent::saveResult(Ref<JSON::Object>&& callArgument, Optional<Protocol::Runtime::ExecutionContextId>&& executionContextId)
|
|
{
|
|
Protocol::ErrorString errorString;
|
|
|
|
InjectedScript injectedScript;
|
|
|
|
auto objectId = callArgument->getString(Protocol::Runtime::CallArgument::objectIdKey);
|
|
if (!objectId) {
|
|
injectedScript = injectedScriptForEval(errorString, WTFMove(executionContextId));
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected(errorString);
|
|
} else {
|
|
injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
|
|
if (injectedScript.hasNoValue())
|
|
return makeUnexpected("Missing injected script for given objectId"_s);
|
|
}
|
|
|
|
Optional<int> savedResultIndex;
|
|
|
|
injectedScript.saveResult(errorString, callArgument->toJSONString(), savedResultIndex);
|
|
|
|
if (!savedResultIndex)
|
|
return makeUnexpected(errorString);
|
|
|
|
return savedResultIndex;
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::setSavedResultAlias(const String& savedResultAlias)
|
|
{
|
|
m_injectedScriptManager.injectedScriptHost().setSavedResultAlias(savedResultAlias);
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::releaseObject(const Protocol::Runtime::RemoteObjectId& objectId)
|
|
{
|
|
InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
|
|
if (!injectedScript.hasNoValue())
|
|
injectedScript.releaseObject(objectId);
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::releaseObjectGroup(const String& objectGroup)
|
|
{
|
|
m_injectedScriptManager.releaseObjectGroup(objectGroup);
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::Runtime::TypeDescription>>> InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets(Ref<JSON::Array>&& locations)
|
|
{
|
|
static constexpr bool verbose = false;
|
|
|
|
if (!m_vm.typeProfiler())
|
|
return makeUnexpected("VM has no type information"_s);
|
|
|
|
auto types = JSON::ArrayOf<Protocol::Runtime::TypeDescription>::create();
|
|
|
|
MonotonicTime start = MonotonicTime::now();
|
|
m_vm.typeProfilerLog()->processLogEntries(m_vm, "User Query"_s);
|
|
|
|
for (size_t i = 0; i < locations->length(); i++) {
|
|
auto location = locations->get(i)->asObject();
|
|
if (!location)
|
|
return makeUnexpected("Unexpected non-object item in locations"_s);
|
|
|
|
auto descriptor = location->getInteger(Protocol::Runtime::TypeLocation::typeInformationDescriptorKey).valueOr(TypeProfilerSearchDescriptorNormal);
|
|
auto sourceIDString = location->getString(Protocol::Runtime::TypeLocation::sourceIDKey);
|
|
auto divot = location->getInteger(Protocol::Runtime::TypeLocation::divotKey).valueOr(0);
|
|
|
|
bool okay;
|
|
TypeLocation* typeLocation = m_vm.typeProfiler()->findLocation(divot, sourceIDString.toIntPtrStrict(&okay), static_cast<TypeProfilerSearchDescriptor>(descriptor), m_vm);
|
|
ASSERT(okay);
|
|
|
|
RefPtr<TypeSet> typeSet;
|
|
if (typeLocation) {
|
|
if (typeLocation->m_globalTypeSet && typeLocation->m_globalVariableID != TypeProfilerNoGlobalIDExists)
|
|
typeSet = typeLocation->m_globalTypeSet;
|
|
else
|
|
typeSet = typeLocation->m_instructionTypeSet;
|
|
}
|
|
|
|
bool isValid = typeLocation && typeSet && !typeSet->isEmpty();
|
|
auto description = Protocol::Runtime::TypeDescription::create()
|
|
.setIsValid(isValid)
|
|
.release();
|
|
|
|
if (isValid) {
|
|
description->setLeastCommonAncestor(typeSet->leastCommonAncestor());
|
|
description->setStructures(typeSet->allStructureRepresentations());
|
|
description->setTypeSet(typeSet->inspectorTypeSet());
|
|
description->setIsTruncated(typeSet->isOverflown());
|
|
}
|
|
|
|
types->addItem(WTFMove(description));
|
|
}
|
|
|
|
MonotonicTime end = MonotonicTime::now();
|
|
if (verbose)
|
|
dataLogF("Inspector::getRuntimeTypesForVariablesAtOffsets took %lfms\n", (end - start).milliseconds());
|
|
|
|
return types;
|
|
}
|
|
|
|
void InspectorRuntimeAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*)
|
|
{
|
|
}
|
|
|
|
void InspectorRuntimeAgent::willDestroyFrontendAndBackend(DisconnectReason reason)
|
|
{
|
|
if (reason != DisconnectReason::InspectedTargetDestroyed && m_isTypeProfilingEnabled)
|
|
setTypeProfilerEnabledState(false);
|
|
|
|
disable();
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::enableTypeProfiler()
|
|
{
|
|
setTypeProfilerEnabledState(true);
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::disableTypeProfiler()
|
|
{
|
|
setTypeProfilerEnabledState(false);
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::enableControlFlowProfiler()
|
|
{
|
|
setControlFlowProfilerEnabledState(true);
|
|
|
|
return { };
|
|
}
|
|
|
|
Protocol::ErrorStringOr<void> InspectorRuntimeAgent::disableControlFlowProfiler()
|
|
{
|
|
setControlFlowProfilerEnabledState(false);
|
|
|
|
return { };
|
|
}
|
|
|
|
void InspectorRuntimeAgent::setTypeProfilerEnabledState(bool isTypeProfilingEnabled)
|
|
{
|
|
if (m_isTypeProfilingEnabled == isTypeProfilingEnabled)
|
|
return;
|
|
m_isTypeProfilingEnabled = isTypeProfilingEnabled;
|
|
|
|
VM& vm = m_vm;
|
|
vm.whenIdle([&vm, isTypeProfilingEnabled] () {
|
|
bool shouldRecompileFromTypeProfiler = (isTypeProfilingEnabled ? vm.enableTypeProfiler() : vm.disableTypeProfiler());
|
|
if (shouldRecompileFromTypeProfiler)
|
|
vm.deleteAllCode(PreventCollectionAndDeleteAllCode);
|
|
});
|
|
}
|
|
|
|
void InspectorRuntimeAgent::setControlFlowProfilerEnabledState(bool isControlFlowProfilingEnabled)
|
|
{
|
|
if (m_isControlFlowProfilingEnabled == isControlFlowProfilingEnabled)
|
|
return;
|
|
m_isControlFlowProfilingEnabled = isControlFlowProfilingEnabled;
|
|
|
|
VM& vm = m_vm;
|
|
vm.whenIdle([&vm, isControlFlowProfilingEnabled] () {
|
|
bool shouldRecompileFromControlFlowProfiler = (isControlFlowProfilingEnabled ? vm.enableControlFlowProfiler() : vm.disableControlFlowProfiler());
|
|
|
|
if (shouldRecompileFromControlFlowProfiler)
|
|
vm.deleteAllCode(PreventCollectionAndDeleteAllCode);
|
|
});
|
|
}
|
|
|
|
Protocol::ErrorStringOr<Ref<JSON::ArrayOf<Protocol::Runtime::BasicBlock>>> InspectorRuntimeAgent::getBasicBlocks(const String& sourceID)
|
|
{
|
|
if (!m_vm.controlFlowProfiler())
|
|
return makeUnexpected("VM has no control flow information"_s);
|
|
|
|
auto basicBlocks = JSON::ArrayOf<Protocol::Runtime::BasicBlock>::create();
|
|
for (const auto& block : m_vm.controlFlowProfiler()->getBasicBlocksForSourceID(sourceID.toIntPtr(), m_vm)) {
|
|
auto location = Protocol::Runtime::BasicBlock::create()
|
|
.setStartOffset(block.m_startOffset)
|
|
.setEndOffset(block.m_endOffset)
|
|
.setHasExecuted(block.m_hasExecuted)
|
|
.setExecutionCount(block.m_executionCount)
|
|
.release();
|
|
basicBlocks->addItem(WTFMove(location));
|
|
}
|
|
return basicBlocks;
|
|
}
|
|
|
|
} // namespace Inspector
|