summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp')
-rw-r--r--Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp277
1 files changed, 231 insertions, 46 deletions
diff --git a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
index 76a47fb3a..d42c8968c 100644
--- a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
+++ b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,17 +32,20 @@
#include "config.h"
#include "InspectorRuntimeAgent.h"
-#if ENABLE(INSPECTOR)
-
#include "Completion.h"
+#include "DFGWorklist.h"
+#include "HeapIterationScope.h"
#include "InjectedScript.h"
#include "InjectedScriptManager.h"
+#include "InspectorFrontendRouter.h"
#include "InspectorValues.h"
#include "JSLock.h"
#include "ParserError.h"
#include "ScriptDebugServer.h"
#include "SourceCode.h"
-#include <wtf/PassRefPtr.h>
+#include "TypeProfiler.h"
+#include "TypeProfilerLog.h"
+#include <wtf/CurrentTime.h>
using namespace JSC;
@@ -53,11 +56,11 @@ static bool asBool(const bool* const b)
return b ? *b : false;
}
-InspectorRuntimeAgent::InspectorRuntimeAgent(InjectedScriptManager* injectedScriptManager)
+InspectorRuntimeAgent::InspectorRuntimeAgent(AgentContext& context)
: InspectorAgentBase(ASCIILiteral("Runtime"))
- , m_injectedScriptManager(injectedScriptManager)
- , m_scriptDebugServer(nullptr)
- , m_enabled(false)
+ , m_injectedScriptManager(context.injectedScriptManager)
+ , m_scriptDebugServer(context.environment.scriptDebugServer())
+ , m_vm(context.environment.vm())
{
}
@@ -65,53 +68,51 @@ InspectorRuntimeAgent::~InspectorRuntimeAgent()
{
}
-static ScriptDebugServer::PauseOnExceptionsState setPauseOnExceptionsState(ScriptDebugServer* scriptDebugServer, ScriptDebugServer::PauseOnExceptionsState newState)
+static ScriptDebugServer::PauseOnExceptionsState setPauseOnExceptionsState(ScriptDebugServer& scriptDebugServer, ScriptDebugServer::PauseOnExceptionsState newState)
{
- ASSERT(scriptDebugServer);
- ScriptDebugServer::PauseOnExceptionsState presentState = scriptDebugServer->pauseOnExceptionsState();
+ ScriptDebugServer::PauseOnExceptionsState presentState = scriptDebugServer.pauseOnExceptionsState();
if (presentState != newState)
- scriptDebugServer->setPauseOnExceptionsState(newState);
+ scriptDebugServer.setPauseOnExceptionsState(newState);
return presentState;
}
-static PassRefPtr<Inspector::TypeBuilder::Runtime::ErrorRange> buildErrorRangeObject(const JSTokenLocation& tokenLocation)
+static Ref<Inspector::Protocol::Runtime::ErrorRange> buildErrorRangeObject(const JSTokenLocation& tokenLocation)
{
- RefPtr<Inspector::TypeBuilder::Runtime::ErrorRange> result = Inspector::TypeBuilder::Runtime::ErrorRange::create()
+ return Inspector::Protocol::Runtime::ErrorRange::create()
.setStartOffset(tokenLocation.startOffset)
- .setEndOffset(tokenLocation.endOffset);
- return result.release();
+ .setEndOffset(tokenLocation.endOffset)
+ .release();
}
-void InspectorRuntimeAgent::parse(ErrorString*, const String& expression, Inspector::TypeBuilder::Runtime::SyntaxErrorType::Enum* result, Inspector::TypeBuilder::OptOutput<String>* message, RefPtr<Inspector::TypeBuilder::Runtime::ErrorRange>& range)
+void InspectorRuntimeAgent::parse(ErrorString&, const String& expression, Inspector::Protocol::Runtime::SyntaxErrorType* result, Inspector::Protocol::OptOutput<String>* message, RefPtr<Inspector::Protocol::Runtime::ErrorRange>& range)
{
- VM* vm = globalVM();
- JSLockHolder lock(vm);
+ JSLockHolder lock(m_vm);
ParserError error;
- checkSyntax(*vm, JSC::makeSource(expression), error);
+ checkSyntax(m_vm, JSC::makeSource(expression, { }), error);
- switch (error.m_syntaxErrorType) {
+ switch (error.syntaxErrorType()) {
case ParserError::SyntaxErrorNone:
- *result = Inspector::TypeBuilder::Runtime::SyntaxErrorType::None;
+ *result = Inspector::Protocol::Runtime::SyntaxErrorType::None;
break;
case ParserError::SyntaxErrorIrrecoverable:
- *result = Inspector::TypeBuilder::Runtime::SyntaxErrorType::Irrecoverable;
+ *result = Inspector::Protocol::Runtime::SyntaxErrorType::Irrecoverable;
break;
case ParserError::SyntaxErrorUnterminatedLiteral:
- *result = Inspector::TypeBuilder::Runtime::SyntaxErrorType::UnterminatedLiteral;
+ *result = Inspector::Protocol::Runtime::SyntaxErrorType::UnterminatedLiteral;
break;
case ParserError::SyntaxErrorRecoverable:
- *result = Inspector::TypeBuilder::Runtime::SyntaxErrorType::Recoverable;
+ *result = Inspector::Protocol::Runtime::SyntaxErrorType::Recoverable;
break;
}
- if (error.m_syntaxErrorType != ParserError::SyntaxErrorNone) {
- *message = error.m_message;
- range = buildErrorRangeObject(error.m_token.m_location);
+ if (error.syntaxErrorType() != ParserError::SyntaxErrorNone) {
+ *message = error.message();
+ range = buildErrorRangeObject(error.token().m_location);
}
}
-void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* const returnByValue, const bool* generatePreview, RefPtr<Inspector::TypeBuilder::Runtime::RemoteObject>& result, Inspector::TypeBuilder::OptOutput<bool>* wasThrown)
+void InspectorRuntimeAgent::evaluate(ErrorString& errorString, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* const returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Inspector::Protocol::OptOutput<bool>* wasThrown, Inspector::Protocol::OptOutput<int>* savedResultIndex)
{
InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
if (injectedScript.hasNoValue())
@@ -123,7 +124,7 @@ void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& exp
if (asBool(doNotPauseOnExceptionsAndMuteConsole))
muteConsole();
- injectedScript.evaluate(errorString, expression, objectGroup ? *objectGroup : "", asBool(includeCommandLineAPI), asBool(returnByValue), asBool(generatePreview), &result, wasThrown);
+ injectedScript.evaluate(errorString, expression, objectGroup ? *objectGroup : String(), asBool(includeCommandLineAPI), asBool(returnByValue), asBool(generatePreview), asBool(saveResult), &result, wasThrown, savedResultIndex);
if (asBool(doNotPauseOnExceptionsAndMuteConsole)) {
unmuteConsole();
@@ -131,17 +132,17 @@ void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& exp
}
}
-void InspectorRuntimeAgent::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const RefPtr<InspectorArray>* const optionalArguments, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<Inspector::TypeBuilder::Runtime::RemoteObject>& result, Inspector::TypeBuilder::OptOutput<bool>* wasThrown)
+void InspectorRuntimeAgent::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const InspectorArray* optionalArguments, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Inspector::Protocol::OptOutput<bool>* wasThrown)
{
- InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
if (injectedScript.hasNoValue()) {
- *errorString = ASCIILiteral("Inspected frame has gone");
+ errorString = ASCIILiteral("Could not find InjectedScript for objectId");
return;
}
String arguments;
if (optionalArguments)
- arguments = (*optionalArguments)->toJSONString();
+ arguments = optionalArguments->toJSONString();
ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = ScriptDebugServer::DontPauseOnExceptions;
if (asBool(doNotPauseOnExceptionsAndMuteConsole))
@@ -157,40 +158,224 @@ void InspectorRuntimeAgent::callFunctionOn(ErrorString* errorString, const Strin
}
}
-void InspectorRuntimeAgent::getProperties(ErrorString* errorString, const String& objectId, const bool* const ownProperties, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Runtime::InternalPropertyDescriptor>>& internalProperties)
+void InspectorRuntimeAgent::getProperties(ErrorString& errorString, const String& objectId, const bool* const ownProperties, const bool* const generatePreview, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>& internalProperties)
{
- InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
if (injectedScript.hasNoValue()) {
- *errorString = ASCIILiteral("Inspected frame has gone");
+ errorString = ASCIILiteral("Could not find InjectedScript for objectId");
return;
}
ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions);
muteConsole();
- injectedScript.getProperties(errorString, objectId, ownProperties ? *ownProperties : false, &result);
- injectedScript.getInternalProperties(errorString, objectId, &internalProperties);
+ injectedScript.getProperties(errorString, objectId, asBool(ownProperties), asBool(generatePreview), &result);
+ injectedScript.getInternalProperties(errorString, objectId, asBool(generatePreview), &internalProperties);
unmuteConsole();
setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState);
}
-void InspectorRuntimeAgent::releaseObject(ErrorString*, const String& objectId)
+void InspectorRuntimeAgent::getDisplayableProperties(ErrorString& errorString, const String& objectId, const bool* const generatePreview, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>& internalProperties)
{
- InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
+ if (injectedScript.hasNoValue()) {
+ errorString = ASCIILiteral("Could not find InjectedScript for objectId");
+ return;
+ }
+
+ ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions);
+ muteConsole();
+
+ injectedScript.getDisplayableProperties(errorString, objectId, asBool(generatePreview), &result);
+ injectedScript.getInternalProperties(errorString, objectId, asBool(generatePreview), &internalProperties);
+
+ unmuteConsole();
+ setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState);
+}
+
+void InspectorRuntimeAgent::getCollectionEntries(ErrorString& errorString, const String& objectId, const String* objectGroup, const int* startIndex, const int* numberToFetch, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::CollectionEntry>>& entries)
+{
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
+ if (injectedScript.hasNoValue()) {
+ errorString = ASCIILiteral("Could not find InjectedScript for objectId");
+ return;
+ }
+
+ int start = startIndex && *startIndex >= 0 ? *startIndex : 0;
+ int fetch = numberToFetch && *numberToFetch >= 0 ? *numberToFetch : 0;
+
+ injectedScript.getCollectionEntries(errorString, objectId, objectGroup ? *objectGroup : String(), start, fetch, &entries);
+}
+
+void InspectorRuntimeAgent::saveResult(ErrorString& errorString, const Inspector::InspectorObject& callArgument, const int* executionContextId, Inspector::Protocol::OptOutput<int>* savedResultIndex)
+{
+ InjectedScript injectedScript;
+
+ String objectId;
+ if (callArgument.getString(ASCIILiteral("objectId"), objectId)) {
+ injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
+ if (injectedScript.hasNoValue()) {
+ errorString = ASCIILiteral("Could not find InjectedScript for objectId");
+ return;
+ }
+ } else {
+ injectedScript = injectedScriptForEval(errorString, executionContextId);
+ if (injectedScript.hasNoValue())
+ return;
+ }
+
+ injectedScript.saveResult(errorString, callArgument.toJSONString(), savedResultIndex);
+}
+
+void InspectorRuntimeAgent::releaseObject(ErrorString&, const String& objectId)
+{
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId);
if (!injectedScript.hasNoValue())
injectedScript.releaseObject(objectId);
}
-void InspectorRuntimeAgent::releaseObjectGroup(ErrorString*, const String& objectGroup)
+void InspectorRuntimeAgent::releaseObjectGroup(ErrorString&, const String& objectGroup)
+{
+ m_injectedScriptManager.releaseObjectGroup(objectGroup);
+}
+
+void InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets(ErrorString& errorString, const Inspector::InspectorArray& locations, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::TypeDescription>>& typeDescriptions)
+{
+ static const bool verbose = false;
+
+ typeDescriptions = Inspector::Protocol::Array<Inspector::Protocol::Runtime::TypeDescription>::create();
+ if (!m_vm.typeProfiler()) {
+ errorString = ASCIILiteral("The VM does not currently have Type Information.");
+ return;
+ }
+
+ double start = currentTimeMS();
+ m_vm.typeProfilerLog()->processLogEntries(ASCIILiteral("User Query"));
+
+ for (size_t i = 0; i < locations.length(); i++) {
+ RefPtr<Inspector::InspectorValue> value = locations.get(i);
+ RefPtr<InspectorObject> location;
+ if (!value->asObject(location)) {
+ errorString = ASCIILiteral("Array of TypeLocation objects has an object that does not have type of TypeLocation.");
+ return;
+ }
+
+ int descriptor;
+ String sourceIDAsString;
+ int divot;
+ location->getInteger(ASCIILiteral("typeInformationDescriptor"), descriptor);
+ location->getString(ASCIILiteral("sourceID"), sourceIDAsString);
+ location->getInteger(ASCIILiteral("divot"), divot);
+
+ bool okay;
+ TypeLocation* typeLocation = m_vm.typeProfiler()->findLocation(divot, sourceIDAsString.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 = Inspector::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());
+ }
+
+ typeDescriptions->addItem(WTFMove(description));
+ }
+
+ double end = currentTimeMS();
+ if (verbose)
+ dataLogF("Inspector::getRuntimeTypesForVariablesAtOffsets took %lfms\n", end - start);
+}
+
+void InspectorRuntimeAgent::willDestroyFrontendAndBackend(DisconnectReason reason)
{
- m_injectedScriptManager->releaseObjectGroup(objectGroup);
+ if (reason != DisconnectReason::InspectedTargetDestroyed && m_isTypeProfilingEnabled)
+ setTypeProfilerEnabledState(false);
}
-void InspectorRuntimeAgent::run(ErrorString*)
+void InspectorRuntimeAgent::enableTypeProfiler(ErrorString&)
{
+ setTypeProfilerEnabledState(true);
}
-} // namespace Inspector
+void InspectorRuntimeAgent::disableTypeProfiler(ErrorString&)
+{
+ setTypeProfilerEnabledState(false);
+}
-#endif // ENABLE(INSPECTOR)
+void InspectorRuntimeAgent::enableControlFlowProfiler(ErrorString&)
+{
+ setControlFlowProfilerEnabledState(true);
+}
+
+void InspectorRuntimeAgent::disableControlFlowProfiler(ErrorString&)
+{
+ setControlFlowProfilerEnabledState(false);
+}
+
+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);
+ });
+}
+
+void InspectorRuntimeAgent::getBasicBlocks(ErrorString& errorString, const String& sourceIDAsString, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::BasicBlock>>& basicBlocks)
+{
+ if (!m_vm.controlFlowProfiler()) {
+ errorString = ASCIILiteral("The VM does not currently have a Control Flow Profiler.");
+ return;
+ }
+
+ bool okay;
+ intptr_t sourceID = sourceIDAsString.toIntPtrStrict(&okay);
+ ASSERT(okay);
+ const Vector<BasicBlockRange>& basicBlockRanges = m_vm.controlFlowProfiler()->getBasicBlocksForSourceID(sourceID, m_vm);
+ basicBlocks = Inspector::Protocol::Array<Inspector::Protocol::Runtime::BasicBlock>::create();
+ for (const BasicBlockRange& block : basicBlockRanges) {
+ Ref<Inspector::Protocol::Runtime::BasicBlock> location = Inspector::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));
+ }
+}
+
+} // namespace Inspector