Commit 9397e00c authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: It should be possible to query WatchpointSets, and add...

fourthTier: It should be possible to query WatchpointSets, and add Watchpoints, even if the compiler is running in another thread
https://bugs.webkit.org/show_bug.cgi?id=114909

Source/JavaScriptCore:

Reviewed by Oliver Hunt.

The idea here is that a concurrent compiler will use watchpoint sets as follows:

During concurrent compilation: It will create Watchpoints, and query WatchpointSets only
for the purpose of profiling. That is, it will use decide whether it is profitable to
compile the code "as if" the watchpoint sets are valid.

During synchronous linking: By "linking" I don't necessarily mean the LinkBuffer stuff,
but just the very bitter end of compilation where we make the JIT code callable. This
can happen after LinkBuffer stuff. Anyway, this will have to happen synchronously, and
at that point we can (a) check that all WatchpointSets that we assumed were valid are
still valid and (b) if they are then we add the watchpoints to those sets. If any of the
sets are invalid, we give up on this compilation and try again later.

The querying of WatchpointSets is engineered to say that the set is still valid if it
is so *right now*, but this is done in a racy way and so it may say so spuriously: we
may, with hopefully low probability, have a set that says it is valid even though it was
just invalidated. The goal is only to ensure that (i) a set never claims to be invalid
if it is actually valid, (ii) a set doesn't claim to be valid if it was invalidated
before compilation even began, and (iii) querying the validity of a set doesn't cause us
to crash.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/Watchpoint.cpp:
(JSC::InlineWatchpointSet::inflateSlow):
* bytecode/Watchpoint.h:
(WatchpointSet):
(InlineWatchpointSet):
(JSC::InlineWatchpointSet::hasBeenInvalidated):
(JSC::InlineWatchpointSet::isThin):
(JSC::InlineWatchpointSet::isFat):
(JSC::InlineWatchpointSet::fat):
* dfg/DFGDesiredWatchpoints.cpp: Added.
(DFG):
(JSC::DFG::DesiredWatchpoints::DesiredWatchpoints):
(JSC::DFG::DesiredWatchpoints::~DesiredWatchpoints):
(JSC::DFG::DesiredWatchpoints::addLazily):
(JSC::DFG::DesiredWatchpoints::reallyAdd):
(JSC::DFG::DesiredWatchpoints::areStillValid):
* dfg/DFGDesiredWatchpoints.h: Added.
(DFG):
(JSC::DFG::WatchpointForGenericWatchpointSet::WatchpointForGenericWatchpointSet):
(WatchpointForGenericWatchpointSet):
(GenericDesiredWatchpoints):
(JSC::DFG::GenericDesiredWatchpoints::GenericDesiredWatchpoints):
(JSC::DFG::GenericDesiredWatchpoints::addLazily):
(JSC::DFG::GenericDesiredWatchpoints::reallyAdd):
(JSC::DFG::GenericDesiredWatchpoints::areStillValid):
(DesiredWatchpoints):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addLazily):
(JITCompiler):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLCompile.h:
(FTL):
* ftl/FTLState.h:
(State):
* runtime/JSFunction.h:
(JSFunction):
(JSC::JSFunction::allocationProfileWatchpointSet):
* runtime/Structure.h:
(Structure):
(JSC::Structure::transitionWatchpointSet):

Source/WTF:

Reviewed by Oliver Hunt.

Harden our notions of memory fences, now that we're doing racy algorithms.

* wtf/Atomics.h:
(WTF):
(WTF::compilerFence):
(WTF::armV7_dmb):
(WTF::armV7_dmb_st):
(WTF::loadLoadFence):
(WTF::loadStoreFence):
(WTF::storeLoadFence):
(WTF::storeStoreFence):
(WTF::memoryBarrierAfterLock):
(WTF::memoryBarrierBeforeUnlock):
(WTF::x86_mfence):


Conflicts:
	Source/WTF/wtf/Atomics.h

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153124 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c14eb7d0
2013-04-20 Filip Pizlo <fpizlo@apple.com>
2013-07-16 Oliver Hunt <oliver@apple.com>
Merge dfgFourthTier r148836
2013-04-21 Filip Pizlo <fpizlo@apple.com>
fourthTier: It should be possible to query WatchpointSets, and add Watchpoints, even if the compiler is running in another thread
https://bugs.webkit.org/show_bug.cgi?id=114909
Reviewed by Oliver Hunt.
The idea here is that a concurrent compiler will use watchpoint sets as follows:
During concurrent compilation: It will create Watchpoints, and query WatchpointSets only
for the purpose of profiling. That is, it will use decide whether it is profitable to
compile the code "as if" the watchpoint sets are valid.
During synchronous linking: By "linking" I don't necessarily mean the LinkBuffer stuff,
but just the very bitter end of compilation where we make the JIT code callable. This
can happen after LinkBuffer stuff. Anyway, this will have to happen synchronously, and
at that point we can (a) check that all WatchpointSets that we assumed were valid are
still valid and (b) if they are then we add the watchpoints to those sets. If any of the
sets are invalid, we give up on this compilation and try again later.
The querying of WatchpointSets is engineered to say that the set is still valid if it
is so *right now*, but this is done in a racy way and so it may say so spuriously: we
may, with hopefully low probability, have a set that says it is valid even though it was
just invalidated. The goal is only to ensure that (i) a set never claims to be invalid
if it is actually valid, (ii) a set doesn't claim to be valid if it was invalidated
before compilation even began, and (iii) querying the validity of a set doesn't cause us
to crash.
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/Watchpoint.cpp:
(JSC::InlineWatchpointSet::inflateSlow):
* bytecode/Watchpoint.h:
(WatchpointSet):
(InlineWatchpointSet):
(JSC::InlineWatchpointSet::hasBeenInvalidated):
(JSC::InlineWatchpointSet::isThin):
(JSC::InlineWatchpointSet::isFat):
(JSC::InlineWatchpointSet::fat):
* dfg/DFGDesiredWatchpoints.cpp: Added.
(DFG):
(JSC::DFG::DesiredWatchpoints::DesiredWatchpoints):
(JSC::DFG::DesiredWatchpoints::~DesiredWatchpoints):
(JSC::DFG::DesiredWatchpoints::addLazily):
(JSC::DFG::DesiredWatchpoints::reallyAdd):
(JSC::DFG::DesiredWatchpoints::areStillValid):
* dfg/DFGDesiredWatchpoints.h: Added.
(DFG):
(JSC::DFG::WatchpointForGenericWatchpointSet::WatchpointForGenericWatchpointSet):
(WatchpointForGenericWatchpointSet):
(GenericDesiredWatchpoints):
(JSC::DFG::GenericDesiredWatchpoints::GenericDesiredWatchpoints):
(JSC::DFG::GenericDesiredWatchpoints::addLazily):
(JSC::DFG::GenericDesiredWatchpoints::reallyAdd):
(JSC::DFG::GenericDesiredWatchpoints::areStillValid):
(DesiredWatchpoints):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addLazily):
(JITCompiler):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLCompile.h:
(FTL):
* ftl/FTLState.h:
(State):
* runtime/JSFunction.h:
(JSFunction):
(JSC::JSFunction::allocationProfileWatchpointSet):
* runtime/Structure.h:
(Structure):
(JSC::Structure::transitionWatchpointSet):
2013-07-16 Oliver Hunt <oliver@apple.com>
Merge dfgFourthTier r148804
2013-04-20 Filip Pizlo <fpizlo@apple.com>
fourthTier: value profiles and array profiles should be thread-safe enough to be accessible in a concurrent compilation thread
https://bugs.webkit.org/show_bug.cgi?id=114906
......
......@@ -309,6 +309,8 @@
0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */; };
0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEA09FD170513DB00BB722C /* FTLAbbreviations.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FEA0A09170513DB00BB722C /* FTLCapabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEA09FE170513DB00BB722C /* FTLCapabilities.cpp */; };
0FEA0A0A170513DB00BB722C /* FTLCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEA09FF170513DB00BB722C /* FTLCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1293,6 +1295,8 @@
0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = "<group>"; };
0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; };
0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; };
0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredWatchpoints.cpp; path = dfg/DFGDesiredWatchpoints.cpp; sourceTree = "<group>"; };
0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredWatchpoints.h; path = dfg/DFGDesiredWatchpoints.h; sourceTree = "<group>"; };
0FEA09FD170513DB00BB722C /* FTLAbbreviations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLAbbreviations.h; path = ftl/FTLAbbreviations.h; sourceTree = "<group>"; };
0FEA09FE170513DB00BB722C /* FTLCapabilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLCapabilities.cpp; path = ftl/FTLCapabilities.cpp; sourceTree = "<group>"; };
0FEA09FF170513DB00BB722C /* FTLCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLCapabilities.h; path = ftl/FTLCapabilities.h; sourceTree = "<group>"; };
......@@ -2878,6 +2882,8 @@
0FFFC94E14EF909500C72532 /* DFGCSEPhase.h */,
0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */,
0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
0FE8534A1723CDA500B618F5 /* DFGDesiredWatchpoints.h */,
0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */,
0FF427621591A1C9004CB9FF /* DFGDisassembler.h */,
0FD81ACF154FB4EB00983E72 /* DFGDominators.cpp */,
......@@ -3485,6 +3491,7 @@
FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */,
0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */,
0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */,
0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */,
......@@ -4147,6 +4154,7 @@
0FF0F19F16B72A17005DF95B /* FunctionExecutableDump.cpp in Sources */,
147F39CC107EC37600427A48 /* FunctionPrototype.cpp in Sources */,
C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */,
0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
C2239D1A16262BDD005AC5FD /* GCThread.cpp in Sources */,
C21122E115DD9AB300790E3A /* GCThreadSharedData.cpp in Sources */,
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 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
......@@ -87,6 +87,7 @@ WatchpointSet* InlineWatchpointSet::inflateSlow()
fat->m_isInvalidated = true;
if (m_data & IsWatchedFlag)
fat->m_isWatched = true;
WTF::storeStoreFence();
m_data = bitwise_cast<uintptr_t>(fat);
return fat;
}
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 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
......@@ -54,7 +54,11 @@ public:
WatchpointSet(InitialWatchpointSetMode);
~WatchpointSet();
// It is safe to call this from another thread. It may return true
// even if the set actually had been invalidated, but that ought to happen
// only in the case of races, and should be rare.
bool isStillValid() const { return !m_isInvalidated; }
// Like isStillValid(), may be called from another thread.
bool hasBeenInvalidated() const { return m_isInvalidated; }
// As a convenience, this will ignore 0. That's because code paths in the DFG
......@@ -124,13 +128,20 @@ public:
freeFat();
}
// It is safe to call this from another thread. It may return false
// even if the set actually had been invalidated, but that ought to happen
// only in the case of races, and should be rare.
bool hasBeenInvalidated() const
{
if (isFat())
return fat()->hasBeenInvalidated();
return m_data & IsInvalidatedFlag;
uintptr_t data = m_data;
if (isFat(data)) {
WTF::loadLoadFence();
return fat(data)->hasBeenInvalidated();
}
return data & IsInvalidatedFlag;
}
// Like hasBeenInvalidated(), may be called from another thread.
bool isStillValid() const
{
return !hasBeenInvalidated();
......@@ -163,19 +174,27 @@ private:
static const uintptr_t IsInvalidatedFlag = 2;
static const uintptr_t IsWatchedFlag = 4;
bool isThin() const { return m_data & IsThinFlag; }
bool isFat() const { return !isThin(); };
static bool isThin(uintptr_t data) { return data & IsThinFlag; }
static bool isFat(uintptr_t data) { return !isThin(data); }
bool isThin() const { return isThin(m_data); }
bool isFat() const { return isFat(m_data); };
static WatchpointSet* fat(uintptr_t data)
{
return bitwise_cast<WatchpointSet*>(data);
}
WatchpointSet* fat()
{
ASSERT(isFat());
return bitwise_cast<WatchpointSet*>(m_data);
return fat(m_data);
}
const WatchpointSet* fat() const
{
ASSERT(isFat());
return bitwise_cast<WatchpointSet*>(m_data);
return fat(m_data);
}
WatchpointSet* inflate()
......
/*
* 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 "DFGDesiredWatchpoints.h"
#if ENABLE(DFG_JIT)
namespace JSC { namespace DFG {
DesiredWatchpoints::DesiredWatchpoints() { }
DesiredWatchpoints::~DesiredWatchpoints() { }
void DesiredWatchpoints::addLazily(Watchpoint* watchpoint, WatchpointSet* set)
{
m_sets.addLazily(WatchpointForWatchpointSet(watchpoint, set));
}
void DesiredWatchpoints::addLazily(Watchpoint* watchpoint, InlineWatchpointSet& set)
{
m_inlineSets.addLazily(WatchpointForInlineWatchpointSet(watchpoint, &set));
}
void DesiredWatchpoints::reallyAdd()
{
m_sets.reallyAdd();
m_inlineSets.reallyAdd();
}
bool DesiredWatchpoints::areStillValid() const
{
return m_sets.areStillValid() && m_inlineSets.areStillValid();
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
/*
* 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.
*/
#ifndef DFGDesiredWatchpoints_h
#define DFGDesiredWatchpoints_h
#include <wtf/Platform.h>
#if ENABLE(DFG_JIT)
#include "Watchpoint.h"
#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
namespace JSC { namespace DFG {
template<typename WatchpointSetType>
struct WatchpointForGenericWatchpointSet {
WatchpointForGenericWatchpointSet()
: m_watchpoint(0)
, m_set(0)
{
}
WatchpointForGenericWatchpointSet(Watchpoint* watchpoint, WatchpointSetType* set)
: m_watchpoint(watchpoint)
, m_set(set)
{
}
Watchpoint* m_watchpoint;
WatchpointSetType* m_set;
};
typedef WatchpointForGenericWatchpointSet<WatchpointSet> WatchpointForWatchpointSet;
typedef WatchpointForGenericWatchpointSet<InlineWatchpointSet> WatchpointForInlineWatchpointSet;
template<typename WatchpointSetType>
class GenericDesiredWatchpoints {
WTF_MAKE_NONCOPYABLE(GenericDesiredWatchpoints);
public:
GenericDesiredWatchpoints()
: m_reallyAdded(false)
{
}
void addLazily(const WatchpointForGenericWatchpointSet<WatchpointSetType>& watchpoint)
{
m_watchpoints.append(watchpoint);
}
void reallyAdd()
{
RELEASE_ASSERT(!m_reallyAdded);
for (unsigned i = m_watchpoints.size(); i--;)
m_watchpoints[i].m_set->add(m_watchpoints[i].m_watchpoint);
m_reallyAdded = true;
}
bool areStillValid() const
{
for (unsigned i = m_watchpoints.size(); i--;) {
if (m_watchpoints[i].m_set->hasBeenInvalidated())
return false;
}
return true;
}
private:
Vector<WatchpointForGenericWatchpointSet<WatchpointSetType> > m_watchpoints;
bool m_reallyAdded;
};
class DesiredWatchpoints {
public:
DesiredWatchpoints();
~DesiredWatchpoints();
void addLazily(Watchpoint*, WatchpointSet*);
void addLazily(Watchpoint*, InlineWatchpointSet&);
void reallyAdd();
bool areStillValid() const;
private:
GenericDesiredWatchpoints<WatchpointSet> m_sets;
GenericDesiredWatchpoints<InlineWatchpointSet> m_inlineSets;
};
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
#endif // DFGDesiredWatchpoints_h
......@@ -174,12 +174,7 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
FTL::State state(dfg);
FTL::lowerDFGToLLVM(state);
FTL::compile(state, jitCode, *jitCodeWithArityCheck);
// FIXME: Need to add support for the case where JIT memory allocation failed.
// https://bugs.webkit.org/show_bug.cgi?id=113620
return true;
return FTL::compile(state, jitCode, *jitCodeWithArityCheck);
}
#endif // ENABLE(FTL_JIT)
......
......@@ -238,6 +238,8 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
ASSERT(!m_exitSiteLabels.size());
m_jitCode->common.compilation = m_graph.m_compilation;
m_watchpoints.reallyAdd();
}
bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
......@@ -260,6 +262,9 @@ bool JITCompiler::compile(RefPtr<JSC::JITCode>& entry)
speculative.createOSREntries();
setEndOfCode();
if (!m_watchpoints.areStillValid())
return false;
LinkBuffer linkBuffer(*m_vm, this, m_codeBlock, JITCompilationCanFail);
if (linkBuffer.didFailToAllocate())
return false;
......@@ -349,6 +354,9 @@ bool JITCompiler::compileFunction(RefPtr<JSC::JITCode>& entry, MacroAssemblerCod
// Create OSR entry trampolines if necessary.
speculative.createOSREntries();
setEndOfCode();
if (!m_watchpoints.areStillValid())
return false;
// === Link ===
LinkBuffer linkBuffer(*m_vm, this, m_codeBlock, JITCompilationCanFail);
......
......@@ -30,6 +30,7 @@
#include "CodeBlock.h"
#include "DFGCCallHelpers.h"
#include "DFGDesiredWatchpoints.h"
#include "DFGDisassembler.h"
#include "DFGFPRInfo.h"
#include "DFGGPRInfo.h"
......@@ -252,6 +253,15 @@ public:
// Accessors for properties.
Graph& graph() { return m_graph; }
void addLazily(Watchpoint* watchpoint, WatchpointSet* set)
{
m_watchpoints.addLazily(watchpoint, set);
}
void addLazily(Watchpoint* watchpoint, InlineWatchpointSet& set)
{
m_watchpoints.addLazily(watchpoint, set);
}
// Methods to set labels for the disassembler.
void setStartOfCode()
{
......@@ -469,6 +479,8 @@ private:
Vector<OSRExitCompilationInfo> m_exitCompilationInfo;
Vector<Vector<Label> > m_exitSiteLabels;
unsigned m_currentCodeOriginIndex;
DesiredWatchpoints m_watchpoints;
};
} } // namespace JSC::DFG
......
......@@ -1351,7 +1351,9 @@ void SpeculativeJIT::compilePeepHoleObjectEquality(Node* node, Node* branchNode)
GPRReg op2GPR = op2.gpr();
if (m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
m_jit.addLazily(
speculationWatchpoint(),
m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint());
if (m_state.forNode(node->child1()).m_type & ~SpecObject) {
speculationCheck(
BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
......
......@@ -49,7 +49,7 @@ static void compileEntry(CCallHelpers& jit)
jit.emitPutImmediateToCallFrameHeader(jit.codeBlock(), JSStack::CodeBlock);
}
void compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
bool compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
{
LLVMExecutionEngineRef engine;
char* error = 0;
......@@ -80,9 +80,18 @@ void compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr&
// FIXME: LLVM should use our own JIT memory allocator, and we shouldn't have to
// keep around an LLVMExecutionEngineRef to keep code alive.
// https://bugs.webkit.org/show_bug.cgi?id=113619
// FIXME: Need to add support for the case where JIT memory allocation failed.
// https://bugs.webkit.org/show_bug.cgi?id=113620
GeneratedFunction function = reinterpret_cast<GeneratedFunction>(LLVMGetPointerToGlobal(engine, state.function));
LLVMDisposePassManager(pass);
if (!state.watchpoints.areStillValid()) {
LLVMDisposeExecutionEngine(engine);
return false;
}
state.watchpoints.reallyAdd();
// Create the entrypoint.
// FIXME: This is a total kludge - LLVM should just use our calling convention.
// https://bugs.webkit.org/show_bug.cgi?id=113621
......@@ -162,6 +171,8 @@ void compile(State& state, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr&
linkBuffer,
("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT)).data(), function)));
jitCode = state.jitCode;
return true;
}
} } // namespace JSC::FTL
......
......@@ -34,7 +34,7 @@
namespace JSC { namespace FTL {
void compile(State&, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
bool compile(State&, RefPtr<JSC::JITCode>&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
} } // namespace JSC::FTL
......
......@@ -30,6 +30,7 @@
#if ENABLE(FTL_JIT)
#include "DFGDesiredWatchpoints.h"
#include "DFGGraph.h"
#include "FTLAbbreviations.h"
#include "FTLJITCode.h"
......@@ -51,6 +52,7 @@ public:
LValue function;
RefPtr<JITCode> jitCode;
Vector<OSRExitCompilationInfo> osrExit;
DFG::DesiredWatchpoints watchpoints;
void dumpState(const char* when);
};
......
......@@ -153,6 +153,11 @@ namespace JSC {
ASSERT(tryGetAllocationProfile());
m_allocationProfileWatchpoint.add(watchpoint);
}
InlineWatchpointSet& allocationProfileWatchpointSet()
{
return m_allocationProfileWatchpoint;
}
protected:
const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
......
......@@ -344,6 +344,11 @@ public:
{
m_transitionWatchpointSet.notifyWrite();
}
InlineWatchpointSet& transitionWatchpointSet() const
{
return m_transitionWatchpointSet;
}
static JS_EXPORTDATA const ClassInfo s_info;
......
2013-07-16 Oliver Hunt <oliver@apple.com>
Merge dfgFourthTier r148836
2013-04-21 Filip Pizlo <fpizlo@apple.com>
fourthTier: It should be possible to query WatchpointSets, and add Watchpoints, even if the compiler is running in another thread
https://bugs.webkit.org/show_bug.cgi?id=114909
Reviewed by Oliver Hunt.
Harden our notions of memory fences, now that we're doing racy algorithms.
* wtf/Atomics.h:
(WTF):
(WTF::compilerFence):
(WTF::armV7_dmb):
(WTF::armV7_dmb_st):
(WTF::loadLoadFence):
(WTF::loadStoreFence):
(WTF::storeLoadFence):
(WTF::storeStoreFence):
(WTF::memoryBarrierAfterLock):
(WTF::memoryBarrierBeforeUnlock):