Commit fe0cc19e authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: AbstractValue methods that deal with watchpoints should have...

fourthTier: AbstractValue methods that deal with watchpoints should have access to Graph, so that in debug mode, Graph can track the history of watchpoint states and detect races
https://bugs.webkit.org/show_bug.cgi?id=115084

Reviewed by Geoffrey Garen.

The idea is that as part of https://bugs.webkit.org/show_bug.cgi?id=115083, I'll have
Graph record the initial state of a watchpoint at the time that we decide to take
advantage of it; then I will use this to disable any watchpoint-related assertions
in debug mode. Note that this "watchpoint cache" will only be maintained in debug
mode, so there will be no release performance implications. But to do this, I need to
ensure that all of the places that reason about watchpoints have access to Graph.
For example, I'll want AbstractValue::setFuturePossibleStructure to record the state
of the watchpoint in Graph so that subsequent assertions can check if the watchpoint's
state had changed since that decision was made.

* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::executeEffects):
(JSC::DFG::AbstractState::mergeStateAtTail):
* dfg/DFGAbstractState.h:
(JSC::DFG::AbstractState::trySetConstant):
* dfg/DFGAbstractValue.cpp: Added.
(DFG):
(JSC::DFG::AbstractValue::setMostSpecific):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::filter):
(JSC::DFG::AbstractValue::setFuturePossibleStructure):
(JSC::DFG::AbstractValue::filterFuturePossibleStructure):
(JSC::DFG::AbstractValue::dump):
* dfg/DFGAbstractValue.h:
(DFG):
(AbstractValue):
(JSC::DFG::AbstractValue::setType):
(JSC::DFG::AbstractValue::filterByValue):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153129 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 22fdb104
2013-04-23 Filip Pizlo <fpizlo@apple.com>
fourthTier: AbstractValue methods that deal with watchpoints should have access to Graph, so that in debug mode, Graph can track the history of watchpoint states and detect races
https://bugs.webkit.org/show_bug.cgi?id=115084
Reviewed by Geoffrey Garen.
The idea is that as part of https://bugs.webkit.org/show_bug.cgi?id=115083, I'll have
Graph record the initial state of a watchpoint at the time that we decide to take
advantage of it; then I will use this to disable any watchpoint-related assertions
in debug mode. Note that this "watchpoint cache" will only be maintained in debug
mode, so there will be no release performance implications. But to do this, I need to
ensure that all of the places that reason about watchpoints have access to Graph.
For example, I'll want AbstractValue::setFuturePossibleStructure to record the state
of the watchpoint in Graph so that subsequent assertions can check if the watchpoint's
state had changed since that decision was made.
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::executeEffects):
(JSC::DFG::AbstractState::mergeStateAtTail):
* dfg/DFGAbstractState.h:
(JSC::DFG::AbstractState::trySetConstant):
* dfg/DFGAbstractValue.cpp: Added.
(DFG):
(JSC::DFG::AbstractValue::setMostSpecific):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::filter):
(JSC::DFG::AbstractValue::setFuturePossibleStructure):
(JSC::DFG::AbstractValue::filterFuturePossibleStructure):
(JSC::DFG::AbstractValue::dump):
* dfg/DFGAbstractValue.h:
(DFG):
(AbstractValue):
(JSC::DFG::AbstractValue::setType):
(JSC::DFG::AbstractValue::filterByValue):
2013-07-16 Oliver Hunt <oliver@apple.com>
Merge dfgFourthTier r148936
......
......@@ -168,6 +168,7 @@
0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F493AF816D0CAD10084508B /* SourceProvider.cpp */; };
0F5541B11613C1FB00CE3E25 /* SpecialPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5541AF1613C1FB00CE3E25 /* SpecialPointer.cpp */; };
0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5541B01613C1FB00CE3E25 /* SpecialPointer.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */; };
0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */; };
0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55F0F214D1063600AC7649 /* AbstractPC.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56A1D115000F31002992B1 /* ExecutionCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1141,6 +1142,7 @@
0F493AF816D0CAD10084508B /* SourceProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SourceProvider.cpp; sourceTree = "<group>"; };
0F5541AF1613C1FB00CE3E25 /* SpecialPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpecialPointer.cpp; sourceTree = "<group>"; };
0F5541B01613C1FB00CE3E25 /* SpecialPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecialPointer.h; sourceTree = "<group>"; };
0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractValue.cpp; path = dfg/DFGAbstractValue.cpp; sourceTree = "<group>"; };
0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; };
0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; };
0F56A1D115000F31002992B1 /* ExecutionCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionCounter.h; sourceTree = "<group>"; };
......@@ -2847,6 +2849,7 @@
children = (
0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */,
0F62016E143FCD2F0068B77C /* DFGAbstractState.h */,
0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */,
0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */,
0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */,
0FB4B51916B62772003F696B /* DFGAllocator.h */,
......@@ -4165,6 +4168,7 @@
0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */,
14280855107EC0E70013E7B2 /* GetterSetter.cpp in Sources */,
142E3135134FF0A600AFADB5 /* HandleSet.cpp in Sources */,
0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */,
142E3137134FF0A600AFADB5 /* HandleStack.cpp in Sources */,
14BA7A9713AADFF8005B7C2C /* Heap.cpp in Sources */,
C24D31E2161CD695002AA4DB /* HeapStatistics.cpp in Sources */,
......
......@@ -260,7 +260,7 @@ private:
if (mergeSpeculations(speculationFromValue(value), oldType) != oldType)
return false;
forNode(node).set(value);
forNode(node).set(m_graph, value);
return true;
}
......
/*
* Copyright (C) 2013 Apple 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:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "DFGAbstractValue.h"
#if ENABLE(DFG_JIT)
#include "DFGGraph.h"
#include "Operations.h"
namespace JSC { namespace DFG {
void AbstractValue::setMostSpecific(Graph& graph, JSValue value)
{
if (!!value && value.isCell()) {
Structure* structure = value.asCell()->structure();
m_currentKnownStructure = structure;
setFuturePossibleStructure(graph, structure);
m_arrayModes = asArrayModes(structure->indexingType());
} else {
m_currentKnownStructure.clear();
m_futurePossibleStructure.clear();
m_arrayModes = 0;
}
m_type = speculationFromValue(value);
m_value = value;
checkConsistency();
}
void AbstractValue::set(Graph& graph, JSValue value)
{
if (!!value && value.isCell()) {
m_currentKnownStructure.makeTop();
Structure* structure = value.asCell()->structure();
setFuturePossibleStructure(graph, structure);
m_arrayModes = asArrayModes(structure->indexingType());
clobberArrayModes();
} else {
m_currentKnownStructure.clear();
m_futurePossibleStructure.clear();
m_arrayModes = 0;
}
m_type = speculationFromValue(value);
m_value = value;
checkConsistency();
}
void AbstractValue::set(Graph& graph, Structure* structure)
{
m_currentKnownStructure = structure;
setFuturePossibleStructure(graph, structure);
m_arrayModes = asArrayModes(structure->indexingType());
m_type = speculationFromStructure(structure);
m_value = JSValue();
checkConsistency();
}
void AbstractValue::filter(Graph& graph, const StructureSet& other)
{
// FIXME: This could be optimized for the common case of m_type not
// having structures, array modes, or a specific value.
// https://bugs.webkit.org/show_bug.cgi?id=109663
m_type &= other.speculationFromStructures();
m_arrayModes &= other.arrayModesFromStructures();
m_currentKnownStructure.filter(other);
if (m_currentKnownStructure.isClear())
m_futurePossibleStructure.clear();
else if (m_currentKnownStructure.hasSingleton())
filterFuturePossibleStructure(graph, m_currentKnownStructure.singleton());
// It's possible that prior to the above two statements we had (Foo, TOP), where
// Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
// case, we will now have (None, [someStructure]). In general, we need to make
// sure that new information gleaned from the SpeculatedType needs to be fed back
// into the information gleaned from the StructureSet.
m_currentKnownStructure.filter(m_type);
m_futurePossibleStructure.filter(m_type);
filterArrayModesByType();
filterValueByType();
checkConsistency();
}
void AbstractValue::setFuturePossibleStructure(Graph&, Structure* structure)
{
if (structure->transitionWatchpointSetIsStillValid())
m_futurePossibleStructure = structure;
else
m_futurePossibleStructure.makeTop();
}
void AbstractValue::filterFuturePossibleStructure(Graph&, Structure* structure)
{
if (structure->transitionWatchpointSetIsStillValid())
m_futurePossibleStructure.filter(StructureAbstractValue(structure));
}
void AbstractValue::dump(PrintStream& out) const
{
out.print(
"(", SpeculationDump(m_type), ", ", ArrayModesDump(m_arrayModes), ", ",
m_currentKnownStructure, ", ", m_futurePossibleStructure);
if (!!m_value)
out.print(", ", m_value);
out.print(")");
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
......@@ -38,6 +38,8 @@
namespace JSC { namespace DFG {
class Graph;
struct AbstractValue {
AbstractValue()
: m_type(SpecNone)
......@@ -112,57 +114,11 @@ struct AbstractValue {
return result;
}
void setMostSpecific(JSValue value)
{
if (!!value && value.isCell()) {
Structure* structure = value.asCell()->structure();
m_currentKnownStructure = structure;
setFuturePossibleStructure(structure);
m_arrayModes = asArrayModes(structure->indexingType());
} else {
m_currentKnownStructure.clear();
m_futurePossibleStructure.clear();
m_arrayModes = 0;
}
m_type = speculationFromValue(value);
m_value = value;
checkConsistency();
}
void set(JSValue value)
{
if (!!value && value.isCell()) {
m_currentKnownStructure.makeTop();
Structure* structure = value.asCell()->structure();
setFuturePossibleStructure(structure);
m_arrayModes = asArrayModes(structure->indexingType());
clobberArrayModes();
} else {
m_currentKnownStructure.clear();
m_futurePossibleStructure.clear();
m_arrayModes = 0;
}
m_type = speculationFromValue(value);
m_value = value;
checkConsistency();
}
void set(Structure* structure)
{
m_currentKnownStructure = structure;
setFuturePossibleStructure(structure);
m_arrayModes = asArrayModes(structure->indexingType());
m_type = speculationFromStructure(structure);
m_value = JSValue();
checkConsistency();
}
void setMostSpecific(Graph&, JSValue);
void set(Graph&, JSValue);
void set(Graph&, Structure*);
void set(SpeculatedType type)
void setType(SpeculatedType type)
{
if (type & SpecCell) {
m_currentKnownStructure.makeTop();
......@@ -232,32 +188,7 @@ struct AbstractValue {
checkConsistency();
}
void filter(const StructureSet& other)
{
// FIXME: This could be optimized for the common case of m_type not
// having structures, array modes, or a specific value.
// https://bugs.webkit.org/show_bug.cgi?id=109663
m_type &= other.speculationFromStructures();
m_arrayModes &= other.arrayModesFromStructures();
m_currentKnownStructure.filter(other);
if (m_currentKnownStructure.isClear())
m_futurePossibleStructure.clear();
else if (m_currentKnownStructure.hasSingleton())
filterFuturePossibleStructure(m_currentKnownStructure.singleton());
// It's possible that prior to the above two statements we had (Foo, TOP), where
// Foo is a SpeculatedType that is disjoint with the passed StructureSet. In that
// case, we will now have (None, [someStructure]). In general, we need to make
// sure that new information gleaned from the SpeculatedType needs to be fed back
// into the information gleaned from the StructureSet.
m_currentKnownStructure.filter(m_type);
m_futurePossibleStructure.filter(m_type);
filterArrayModesByType();
filterValueByType();
checkConsistency();
}
void filter(Graph&, const StructureSet&);
void filterArrayModes(ArrayModes arrayModes)
{
......@@ -369,15 +300,7 @@ struct AbstractValue {
// complexity of the code.
}
void dump(PrintStream& out) const
{
out.print(
"(", SpeculationDump(m_type), ", ", ArrayModesDump(m_arrayModes), ", ",
m_currentKnownStructure, ", ", m_futurePossibleStructure);
if (!!m_value)
out.print(", ", m_value);
out.print(")");
}
void dump(PrintStream&) const;
// A great way to think about the difference between m_currentKnownStructure and
// m_futurePossibleStructure is to consider these four examples:
......@@ -486,19 +409,8 @@ private:
m_arrayModes = ALL_ARRAY_MODES;
}
void setFuturePossibleStructure(Structure* structure)
{
if (structure->transitionWatchpointSetIsStillValid())
m_futurePossibleStructure = structure;
else
m_futurePossibleStructure.makeTop();
}
void filterFuturePossibleStructure(Structure* structure)
{
if (structure->transitionWatchpointSetIsStillValid())
m_futurePossibleStructure.filter(StructureAbstractValue(structure));
}
void setFuturePossibleStructure(Graph&, Structure* structure);
void filterFuturePossibleStructure(Graph&, Structure* structure);
// We could go further, and ensure that if the futurePossibleStructure contravenes
// the value, then we could clear both of those things. But that's unlikely to help
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment