diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp')
-rw-r--r-- | Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp | 277 |
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 |