Title: [202588] trunk/Source
Revision
202588
Author
sbar...@apple.com
Date
2016-06-28 14:30:20 -0700 (Tue, 28 Jun 2016)

Log Message

some Watchpoints' ::fireInternal method will call operations that might GC where the GC will cause the watchpoint itself to destruct
https://bugs.webkit.org/show_bug.cgi?id=159198
<rdar://problem/26302360>

Reviewed by Filip Pizlo.

Source/_javascript_Core:

Firing a watchpoint may cause a GC to happen. This GC could destroy various
Watchpoints themselves while they're in the process of firing. It's not safe
for most Watchpoints to be destructed while they're in the middle of firing.
This GC could also destroy the WatchpointSet itself, and it's not in a safe
state to be destroyed. WatchpointSet::fireAllWatchpoints now defers gc for a
while. This prevents a GC from destructing any Watchpoints while they're
in the process of firing. This bug was being hit by the stress GC bots
because we would destruct a particular Watchpoint while it was firing,
and then we would access its field after it had already been destroyed.
This was causing all kinds of weird symptoms. Also, this was easier to
catch when running with guard malloc because the first access after
destruction would lead to a crash.

* bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp:
(JSC::AdaptiveInferredPropertyValueWatchpointBase::fire):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
* bytecode/VariableWriteFireDetail.cpp:
(JSC::VariableWriteFireDetail::dump):
(JSC::VariableWriteFireDetail::touch):
* bytecode/VariableWriteFireDetail.h:
* bytecode/Watchpoint.cpp:
(JSC::WatchpointSet::add):
(JSC::WatchpointSet::fireAllSlow):
(JSC::WatchpointSet::fireAllWatchpoints):
(JSC::InlineWatchpointSet::add):
(JSC::InlineWatchpointSet::fireAll):
(JSC::InlineWatchpointSet::inflateSlow):
* bytecode/Watchpoint.h:
(JSC::WatchpointSet::startWatching):
(JSC::WatchpointSet::fireAll):
(JSC::WatchpointSet::touch):
(JSC::WatchpointSet::invalidate):
(JSC::WatchpointSet::isBeingWatched):
(JSC::WatchpointSet::offsetOfState):
(JSC::WatchpointSet::addressOfSetIsNotEmpty):
(JSC::InlineWatchpointSet::startWatching):
(JSC::InlineWatchpointSet::fireAll):
(JSC::InlineWatchpointSet::invalidate):
(JSC::InlineWatchpointSet::touch):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* dfg/DFGOperations.cpp:
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
* jit/JITOperations.cpp:
* jsc.cpp:
(WTF::Masquerader::create):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/ArrayBufferNeuteringWatchpoint.cpp:
(JSC::ArrayBufferNeuteringWatchpoint::fireAll):
* runtime/FunctionRareData.cpp:
(JSC::FunctionRareData::clear):
* runtime/InferredType.cpp:
(JSC::InferredType::willStoreValueSlow):
(JSC::InferredType::makeTopSlow):
(JSC::InferredType::set):
(JSC::InferredType::removeStructure):
(JSC::InferredType::InferredStructureWatchpoint::fireInternal):
* runtime/InferredValue.cpp:
(JSC::InferredValue::notifyWriteSlow):
(JSC::InferredValue::ValueCleanup::finalizeUnconditionally):
* runtime/InferredValue.h:
(JSC::InferredValue::notifyWrite):
(JSC::InferredValue::invalidate):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::haveABadTime):
* runtime/JSSymbolTableObject.h:
(JSC::symbolTablePutTouchWatchpointSet):
(JSC::symbolTablePutInvalidateWatchpointSet):
* runtime/Structure.cpp:
(JSC::Structure::didCachePropertyReplacement):
(JSC::Structure::startWatchingInternalProperties):
(JSC::DeferredStructureTransitionWatchpointFire::~DeferredStructureTransitionWatchpointFire):
(JSC::DeferredStructureTransitionWatchpointFire::add):
(JSC::Structure::didTransitionFromThisStructure):
(JSC::Structure::prototypeForLookup):
* runtime/StructureInlines.h:
(JSC::Structure::didReplaceProperty):
(JSC::Structure::propertyReplacementWatchpointSet):
* runtime/SymbolTable.h:
(JSC::SymbolTableEntry::isDontEnum):
(JSC::SymbolTableEntry::disableWatching):
* runtime/VM.cpp:
(JSC::VM::addImpureProperty):
(JSC::enableProfilerWithRespectToCount):

Source/WebCore:

* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::fireFrameClearedWatchpointsForWindow):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
* bindings/scripts/test/JS/JSTestEventTarget.h:
(WebCore::JSTestEventTarget::create):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (202587 => 202588)


--- trunk/Source/_javascript_Core/ChangeLog	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-06-28 21:30:20 UTC (rev 202588)
@@ -1,3 +1,99 @@
+2016-06-28  Saam Barati  <sbar...@apple.com>
+
+        some Watchpoints' ::fireInternal method will call operations that might GC where the GC will cause the watchpoint itself to destruct
+        https://bugs.webkit.org/show_bug.cgi?id=159198
+        <rdar://problem/26302360>
+
+        Reviewed by Filip Pizlo.
+
+        Firing a watchpoint may cause a GC to happen. This GC could destroy various
+        Watchpoints themselves while they're in the process of firing. It's not safe
+        for most Watchpoints to be destructed while they're in the middle of firing.
+        This GC could also destroy the WatchpointSet itself, and it's not in a safe
+        state to be destroyed. WatchpointSet::fireAllWatchpoints now defers gc for a
+        while. This prevents a GC from destructing any Watchpoints while they're
+        in the process of firing. This bug was being hit by the stress GC bots
+        because we would destruct a particular Watchpoint while it was firing,
+        and then we would access its field after it had already been destroyed.
+        This was causing all kinds of weird symptoms. Also, this was easier to
+        catch when running with guard malloc because the first access after
+        destruction would lead to a crash.
+
+        * bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp:
+        (JSC::AdaptiveInferredPropertyValueWatchpointBase::fire):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        * bytecode/VariableWriteFireDetail.cpp:
+        (JSC::VariableWriteFireDetail::dump):
+        (JSC::VariableWriteFireDetail::touch):
+        * bytecode/VariableWriteFireDetail.h:
+        * bytecode/Watchpoint.cpp:
+        (JSC::WatchpointSet::add):
+        (JSC::WatchpointSet::fireAllSlow):
+        (JSC::WatchpointSet::fireAllWatchpoints):
+        (JSC::InlineWatchpointSet::add):
+        (JSC::InlineWatchpointSet::fireAll):
+        (JSC::InlineWatchpointSet::inflateSlow):
+        * bytecode/Watchpoint.h:
+        (JSC::WatchpointSet::startWatching):
+        (JSC::WatchpointSet::fireAll):
+        (JSC::WatchpointSet::touch):
+        (JSC::WatchpointSet::invalidate):
+        (JSC::WatchpointSet::isBeingWatched):
+        (JSC::WatchpointSet::offsetOfState):
+        (JSC::WatchpointSet::addressOfSetIsNotEmpty):
+        (JSC::InlineWatchpointSet::startWatching):
+        (JSC::InlineWatchpointSet::fireAll):
+        (JSC::InlineWatchpointSet::invalidate):
+        (JSC::InlineWatchpointSet::touch):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * dfg/DFGOperations.cpp:
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        * jit/JITOperations.cpp:
+        * jsc.cpp:
+        (WTF::Masquerader::create):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/ArrayBufferNeuteringWatchpoint.cpp:
+        (JSC::ArrayBufferNeuteringWatchpoint::fireAll):
+        * runtime/FunctionRareData.cpp:
+        (JSC::FunctionRareData::clear):
+        * runtime/InferredType.cpp:
+        (JSC::InferredType::willStoreValueSlow):
+        (JSC::InferredType::makeTopSlow):
+        (JSC::InferredType::set):
+        (JSC::InferredType::removeStructure):
+        (JSC::InferredType::InferredStructureWatchpoint::fireInternal):
+        * runtime/InferredValue.cpp:
+        (JSC::InferredValue::notifyWriteSlow):
+        (JSC::InferredValue::ValueCleanup::finalizeUnconditionally):
+        * runtime/InferredValue.h:
+        (JSC::InferredValue::notifyWrite):
+        (JSC::InferredValue::invalidate):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::haveABadTime):
+        * runtime/JSSymbolTableObject.h:
+        (JSC::symbolTablePutTouchWatchpointSet):
+        (JSC::symbolTablePutInvalidateWatchpointSet):
+        * runtime/Structure.cpp:
+        (JSC::Structure::didCachePropertyReplacement):
+        (JSC::Structure::startWatchingInternalProperties):
+        (JSC::DeferredStructureTransitionWatchpointFire::~DeferredStructureTransitionWatchpointFire):
+        (JSC::DeferredStructureTransitionWatchpointFire::add):
+        (JSC::Structure::didTransitionFromThisStructure):
+        (JSC::Structure::prototypeForLookup):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::didReplaceProperty):
+        (JSC::Structure::propertyReplacementWatchpointSet):
+        * runtime/SymbolTable.h:
+        (JSC::SymbolTableEntry::isDontEnum):
+        (JSC::SymbolTableEntry::disableWatching):
+        * runtime/VM.cpp:
+        (JSC::VM::addImpureProperty):
+        (JSC::enableProfilerWithRespectToCount):
+
 2016-06-28  Filip Pizlo  <fpi...@apple.com>
 
         JSRopeString should use release asserts, not debug asserts, about substring bounds

Modified: trunk/Source/_javascript_Core/bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -50,10 +50,6 @@
 
 void AdaptiveInferredPropertyValueWatchpointBase::fire(const FireDetail& detail)
 {
-    // We need to defer GC here otherwise we might trigger a GC that could destroy the owner
-    // CodeBlock. In particular, this can happen when we add rare data to a structure when
-    // we EnsureWatchability.
-    DeferGCForAWhile defer(*Heap::heap(m_key.object()));
     // One of the watchpoints fired, but the other one didn't. Make sure that neither of them are
     // in any set anymore. This simplifies things by allowing us to reinstall the watchpoints
     // wherever from scratch.

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -2240,7 +2240,7 @@
                 instructions[i + 5].u.watchpointSet = op.watchpointSet;
             else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) {
                 if (op.watchpointSet)
-                    op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident));
+                    op.watchpointSet->invalidate(vm, PutToScopeFireDetail(this, ident));
             } else if (op.structure)
                 instructions[i + 5].u.structure.set(vm, this, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);

Modified: trunk/Source/_javascript_Core/bytecode/VariableWriteFireDetail.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/bytecode/VariableWriteFireDetail.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/bytecode/VariableWriteFireDetail.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -35,9 +35,9 @@
     out.print("Write to ", m_name, " in ", JSValue(m_object));
 }
 
-void VariableWriteFireDetail::touch(WatchpointSet* set, JSObject* object, const PropertyName& name)
+void VariableWriteFireDetail::touch(VM& vm, WatchpointSet* set, JSObject* object, const PropertyName& name)
 {
-    set->touch(VariableWriteFireDetail(object, name));
+    set->touch(vm, VariableWriteFireDetail(object, name));
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/VariableWriteFireDetail.h (202587 => 202588)


--- trunk/Source/_javascript_Core/bytecode/VariableWriteFireDetail.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/bytecode/VariableWriteFireDetail.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -43,7 +43,7 @@
     
     JS_EXPORT_PRIVATE void dump(PrintStream&) const override;
     
-    JS_EXPORT_PRIVATE static void touch(WatchpointSet*, JSObject*, const PropertyName&);
+    JS_EXPORT_PRIVATE static void touch(VM&, WatchpointSet*, JSObject*, const PropertyName&);
 
 private:
     JSObject* m_object;

Modified: trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "Watchpoint.h"
 
+#include "HeapInlines.h"
+#include "VM.h"
 #include <wtf/CompilationThread.h>
 #include <wtf/PassRefPtr.h>
 
@@ -81,26 +83,33 @@
     m_state = IsWatched;
 }
 
-void WatchpointSet::fireAllSlow(const FireDetail& detail)
+void WatchpointSet::fireAllSlow(VM& vm, const FireDetail& detail)
 {
     ASSERT(state() == IsWatched);
     
     WTF::storeStoreFence();
     m_state = IsInvalidated; // Do this first. Needed for adaptive watchpoints.
-    fireAllWatchpoints(detail);
+    fireAllWatchpoints(vm, detail);
     WTF::storeStoreFence();
 }
 
-void WatchpointSet::fireAllSlow(const char* reason)
+void WatchpointSet::fireAllSlow(VM& vm, const char* reason)
 {
-    fireAllSlow(StringFireDetail(reason));
+    fireAllSlow(vm, StringFireDetail(reason));
 }
 
-void WatchpointSet::fireAllWatchpoints(const FireDetail& detail)
+void WatchpointSet::fireAllWatchpoints(VM& vm, const FireDetail& detail)
 {
     // In case there are any adaptive watchpoints, we need to make sure that they see that this
     // watchpoint has been already invalidated.
     RELEASE_ASSERT(hasBeenInvalidated());
+
+    // Firing a watchpoint may cause a GC to happen. This GC could destroy various
+    // Watchpoints themselves while they're in the process of firing. It's not safe
+    // for most Watchpoints to be destructed while they're in the middle of firing.
+    // This GC could also destroy us, and we're not in a safe state to be destroyed.
+    // The safest thing to do is to DeferGCForAWhile to prevent this GC from happening.
+    DeferGCForAWhile deferGC(vm.heap);
     
     while (!m_set.isEmpty()) {
         Watchpoint* watchpoint = m_set.begin();
@@ -130,9 +139,9 @@
     inflate()->add(watchpoint);
 }
 
-void InlineWatchpointSet::fireAll(const char* reason)
+void InlineWatchpointSet::fireAll(VM& vm, const char* reason)
 {
-    fireAll(StringFireDetail(reason));
+    fireAll(vm, StringFireDetail(reason));
 }
 
 WatchpointSet* InlineWatchpointSet::inflateSlow()

Modified: trunk/Source/_javascript_Core/bytecode/Watchpoint.h (202587 => 202588)


--- trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -90,6 +90,7 @@
 };
 
 class InlineWatchpointSet;
+class VM;
 
 class WatchpointSet : public ThreadSafeRefCounted<WatchpointSet> {
     friend class LLIntOffsetsExtractor;
@@ -152,43 +153,43 @@
         WTF::storeStoreFence();
     }
     
-    void fireAll(const FireDetail& detail)
+    void fireAll(VM& vm, const FireDetail& detail)
     {
         if (LIKELY(m_state != IsWatched))
             return;
-        fireAllSlow(detail);
+        fireAllSlow(vm, detail);
     }
     
-    void fireAll(const char* reason)
+    void fireAll(VM& vm, const char* reason)
     {
         if (LIKELY(m_state != IsWatched))
             return;
-        fireAllSlow(reason);
+        fireAllSlow(vm, reason);
     }
     
-    void touch(const FireDetail& detail)
+    void touch(VM& vm, const FireDetail& detail)
     {
         if (state() == ClearWatchpoint)
             startWatching();
         else
-            fireAll(detail);
+            fireAll(vm, detail);
     }
     
-    void touch(const char* reason)
+    void touch(VM& vm, const char* reason)
     {
-        touch(StringFireDetail(reason));
+        touch(vm, StringFireDetail(reason));
     }
     
-    void invalidate(const FireDetail& detail)
+    void invalidate(VM& vm, const FireDetail& detail)
     {
         if (state() == IsWatched)
-            fireAll(detail);
+            fireAll(vm, detail);
         m_state = IsInvalidated;
     }
     
-    void invalidate(const char* reason)
+    void invalidate(VM& vm, const char* reason)
     {
-        invalidate(StringFireDetail(reason));
+        invalidate(vm, StringFireDetail(reason));
     }
     
     bool isBeingWatched() const
@@ -200,11 +201,11 @@
     static ptrdiff_t offsetOfState() { return OBJECT_OFFSETOF(WatchpointSet, m_state); }
     int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; }
     
-    JS_EXPORT_PRIVATE void fireAllSlow(const FireDetail&); // Call only if you've checked isWatched.
-    JS_EXPORT_PRIVATE void fireAllSlow(const char* reason); // Ditto.
+    JS_EXPORT_PRIVATE void fireAllSlow(VM&, const FireDetail&); // Call only if you've checked isWatched.
+    JS_EXPORT_PRIVATE void fireAllSlow(VM&, const char* reason); // Ditto.
     
 private:
-    void fireAllWatchpoints(const FireDetail&);
+    void fireAllWatchpoints(VM&, const FireDetail&);
     
     friend class InlineWatchpointSet;
 
@@ -296,10 +297,10 @@
         m_data = encodeState(IsWatched);
     }
     
-    void fireAll(const FireDetail& detail)
+    void fireAll(VM& vm, const FireDetail& detail)
     {
         if (isFat()) {
-            fat()->fireAll(detail);
+            fat()->fireAll(vm, detail);
             return;
         }
         if (decodeState(m_data) == ClearWatchpoint)
@@ -308,20 +309,20 @@
         WTF::storeStoreFence();
     }
     
-    void invalidate(const FireDetail& detail)
+    void invalidate(VM& vm, const FireDetail& detail)
     {
         if (isFat())
-            fat()->invalidate(detail);
+            fat()->invalidate(vm, detail);
         else
             m_data = encodeState(IsInvalidated);
     }
     
-    JS_EXPORT_PRIVATE void fireAll(const char* reason);
+    JS_EXPORT_PRIVATE void fireAll(VM&, const char* reason);
     
-    void touch(const FireDetail& detail)
+    void touch(VM& vm, const FireDetail& detail)
     {
         if (isFat()) {
-            fat()->touch(detail);
+            fat()->touch(vm, detail);
             return;
         }
         uintptr_t data = ""
@@ -335,9 +336,9 @@
         WTF::storeStoreFence();
     }
     
-    void touch(const char* reason)
+    void touch(VM& vm, const char* reason)
     {
-        touch(StringFireDetail(reason));
+        touch(vm, StringFireDetail(reason));
     }
 
     // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like:

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -385,7 +385,7 @@
                     // notifyWrite(), since that would be cumbersome. Also, watching formal
                     // parameters when "arguments" is in play is unlikely to be super profitable.
                     // So, we just disable it.
-                    entry.disableWatching();
+                    entry.disableWatching(*m_vm);
                     functionSymbolTable->set(NoLockingNecessary, name, entry);
                 }
                 emitOpcode(op_put_to_scope);

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -1445,7 +1445,7 @@
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
-    set->touch("Executed NotifyWrite");
+    set->touch(vm, "Executed NotifyWrite");
 }
 
 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)

Modified: trunk/Source/_javascript_Core/heap/CopyBarrier.h (202587 => 202588)


--- trunk/Source/_javascript_Core/heap/CopyBarrier.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/heap/CopyBarrier.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -27,6 +27,7 @@
 #define CopyBarrier_h
 
 #include "Heap.h"
+#include "VM.h"
 
 namespace JSC {
 

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -1206,7 +1206,7 @@
     if (numVariables || numFunctions) {
         BatchedTransitionOptimizer optimizer(vm, variableObject);
         if (variableObject->next())
-            variableObject->globalObject()->varInjectionWatchpoint()->fireAll("Executed eval, fired VarInjection watchpoint");
+            variableObject->globalObject()->varInjectionWatchpoint()->fireAll(vm, "Executed eval, fired VarInjection watchpoint");
 
         for (unsigned i = 0; i < numVariables; ++i) {
             const Identifier& ident = codeBlock->variable(i);

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -2078,7 +2078,7 @@
         JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
         environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value);
         if (WatchpointSet* set = pc[5].u.watchpointSet)
-            set->touch("Executed op_put_scope<LocalClosureVar>");
+            set->touch(vm, "Executed op_put_scope<LocalClosureVar>");
         return;
     }
 

Modified: trunk/Source/_javascript_Core/jsc.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/jsc.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/jsc.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -209,7 +209,7 @@
 
     static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
     {
-        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Masquerading object allocated");
+        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(vm, "Masquerading object allocated");
         Structure* structure = createStructure(vm, globalObject, jsNull());
         Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
         result->finishCreation(vm);

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -1554,7 +1554,7 @@
         // to have already changed the value of the variable. Otherwise we might watch and constant-fold
         // to the Undefined value from before the assignment.
         if (WatchpointSet* set = pc[5].u.watchpointSet)
-            set->touch("Executed op_put_scope<LocalClosureVar>");
+            set->touch(vm, "Executed op_put_scope<LocalClosureVar>");
         LLINT_END();
     }
 

Modified: trunk/Source/_javascript_Core/runtime/ArrayBufferNeuteringWatchpoint.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/ArrayBufferNeuteringWatchpoint.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/ArrayBufferNeuteringWatchpoint.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -62,7 +62,7 @@
 
 void ArrayBufferNeuteringWatchpoint::fireAll()
 {
-    set()->fireAll("Array buffer was neutered");
+    set()->fireAll(*vm(), "Array buffer was neutered");
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/FunctionRareData.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/FunctionRareData.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/FunctionRareData.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -88,7 +88,7 @@
 {
     m_objectAllocationProfile.clear();
     m_internalFunctionAllocationProfile.clear();
-    m_objectAllocationProfileWatchpoint.fireAll(reason);
+    m_objectAllocationProfileWatchpoint.fireAll(*vm(), reason);
 }
 
 }

Modified: trunk/Source/_javascript_Core/runtime/InferredType.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/InferredType.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/InferredType.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -419,7 +419,7 @@
     }
     
     InferredTypeFireDetail detail(this, propertyName.uid(), oldType, myType, value);
-    m_watchpointSet.fireAll(detail);
+    m_watchpointSet.fireAll(vm, detail);
     return result;
 }
 
@@ -434,7 +434,7 @@
     }
 
     InferredTypeFireDetail detail(this, propertyName.uid(), oldType, Top, JSValue());
-    m_watchpointSet.fireAll(detail);
+    m_watchpointSet.fireAll(vm, detail);
 }
 
 bool InferredType::set(const ConcurrentJITLocker& locker, VM& vm, Descriptor newDescriptor)
@@ -516,7 +516,7 @@
     }
 
     InferredTypeFireDetail detail(this, nullptr, oldDescriptor, newDescriptor, JSValue());
-    m_watchpointSet.fireAll(detail);
+    m_watchpointSet.fireAll(vm, detail);
 }
 
 void InferredType::InferredStructureWatchpoint::fireInternal(const FireDetail&)

Modified: trunk/Source/_javascript_Core/runtime/InferredValue.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/InferredValue.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/InferredValue.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -92,7 +92,7 @@
         ASSERT(!!m_value);
         if (m_value.get() == value)
             return;
-        invalidate(detail);
+        invalidate(vm, detail);
         return;
         
     case IsInvalidated:
@@ -125,7 +125,7 @@
     if (Heap::isMarked(m_owner->m_value.get().asCell()))
         return;
     
-    m_owner->invalidate(StringFireDetail("InferredValue clean-up during GC"));
+    m_owner->invalidate(*m_owner->vm(), StringFireDetail("InferredValue clean-up during GC"));
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/InferredValue.h (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/InferredValue.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/InferredValue.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -88,10 +88,10 @@
         notifyWriteSlow(vm, value, reason);
     }
     
-    void invalidate(const FireDetail& detail)
+    void invalidate(VM& vm, const FireDetail& detail)
     {
         m_value.clear();
-        m_set.invalidate(detail);
+        m_set.invalidate(vm, detail);
     }
     
     static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -943,7 +943,7 @@
     // Make sure that all allocations or indexed storage transitions that are inlining
     // the assumption that it's safe to transition to a non-SlowPut array storage don't
     // do so anymore.
-    m_havingABadTimeWatchpoint->fireAll("Having a bad time");
+    m_havingABadTimeWatchpoint->fireAll(vm, "Having a bad time");
     ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time.
     
     // Make sure that all JSArray allocations that load the appropriate structure from

Modified: trunk/Source/_javascript_Core/runtime/JSSymbolTableObject.h (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/JSSymbolTableObject.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/JSSymbolTableObject.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -146,7 +146,7 @@
 {
     reg->set(vm, object, value);
     if (set)
-        VariableWriteFireDetail::touch(set, object, propertyName);
+        VariableWriteFireDetail::touch(vm, set, object, propertyName);
 }
 
 template<typename SymbolTableObjectType>
@@ -154,7 +154,7 @@
 {
     reg->set(vm, object, value);
     if (set)
-        set->invalidate(VariableWriteFireDetail(object, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it.
+        set->invalidate(vm, VariableWriteFireDetail(object, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it.
 }
 
 enum class SymbolTablePutMode {

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -858,7 +858,7 @@
 
 void Structure::didCachePropertyReplacement(VM& vm, PropertyOffset offset)
 {
-    ensurePropertyReplacementWatchpointSet(vm, offset)->fireAll("Did cache property replacement");
+    ensurePropertyReplacementWatchpointSet(vm, offset)->fireAll(vm, "Did cache property replacement");
 }
 
 void Structure::startWatchingInternalProperties(VM& vm)
@@ -1075,7 +1075,7 @@
 DeferredStructureTransitionWatchpointFire::~DeferredStructureTransitionWatchpointFire()
 {
     if (m_structure)
-        m_structure->transitionWatchpointSet().fireAll(StructureFireDetail(m_structure));
+        m_structure->transitionWatchpointSet().fireAll(*m_structure->vm(), StructureFireDetail(m_structure));
 }
 
 void DeferredStructureTransitionWatchpointFire::add(const Structure* structure)
@@ -1096,7 +1096,7 @@
     if (deferred)
         deferred->add(this);
     else
-        m_transitionWatchpointSet.fireAll(StructureFireDetail(this));
+        m_transitionWatchpointSet.fireAll(*vm(), StructureFireDetail(this));
 }
 
 JSValue Structure::prototypeForLookup(CodeBlock* codeBlock) const

Modified: trunk/Source/_javascript_Core/runtime/StructureInlines.h (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/StructureInlines.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/StructureInlines.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -256,7 +256,7 @@
     WatchpointSet* set = map->get(offset);
     if (LIKELY(!set))
         return;
-    set->fireAll("Property did get replaced");
+    set->fireAll(*vm(), "Property did get replaced");
 }
 
 inline WatchpointSet* Structure::propertyReplacementWatchpointSet(PropertyOffset offset)

Modified: trunk/Source/_javascript_Core/runtime/SymbolTable.h (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/SymbolTable.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/SymbolTable.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -280,10 +280,10 @@
         return bits() & DontEnumFlag;
     }
     
-    void disableWatching()
+    void disableWatching(VM& vm)
     {
         if (WatchpointSet* set = watchpointSet())
-            set->invalidate("Disabling watching in symbol table");
+            set->invalidate(vm, "Disabling watching in symbol table");
         if (varOffset().isScope())
             pack(varOffset(), false, isReadOnly(), isDontEnum());
     }

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (202587 => 202588)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -748,7 +748,7 @@
 void VM::addImpureProperty(const String& propertyName)
 {
     if (RefPtr<WatchpointSet> watchpointSet = m_impurePropertyWatchpointSets.take(propertyName))
-        watchpointSet->fireAll("Impure property added");
+        watchpointSet->fireAll(*this, "Impure property added");
 }
 
 static bool enableProfilerWithRespectToCount(unsigned& counter, std::function<void()> doEnableWork)

Modified: trunk/Source/WebCore/ChangeLog (202587 => 202588)


--- trunk/Source/WebCore/ChangeLog	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/WebCore/ChangeLog	2016-06-28 21:30:20 UTC (rev 202588)
@@ -1,3 +1,18 @@
+2016-06-28  Saam Barati  <sbar...@apple.com>
+
+        some Watchpoints' ::fireInternal method will call operations that might GC where the GC will cause the watchpoint itself to destruct
+        https://bugs.webkit.org/show_bug.cgi?id=159198
+        <rdar://problem/26302360>
+
+        Reviewed by Filip Pizlo.
+
+        * bindings/js/JSDOMWindowBase.cpp:
+        (WebCore::JSDOMWindowBase::fireFrameClearedWatchpointsForWindow):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateHeader):
+        * bindings/scripts/test/JS/JSTestEventTarget.h:
+        (WebCore::JSTestEventTarget::create):
+
 2016-06-28  Anders Carlsson  <ander...@apple.com>
 
         Move the user gesture requirement to the ApplePaySession constructor

Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp (202587 => 202588)


--- trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp	2016-06-28 21:30:20 UTC (rev 202588)
@@ -318,7 +318,7 @@
         if (!wrapper)
             continue;
         JSDOMWindowBase* jsWindow = JSC::jsCast<JSDOMWindowBase*>(wrapper);
-        jsWindow->m_windowCloseWatchpoints.fireAll("Frame cleared");
+        jsWindow->m_windowCloseWatchpoints.fireAll(vm, "Frame cleared");
     }
 }
 

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (202587 => 202588)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-06-28 21:30:20 UTC (rev 202588)
@@ -1126,7 +1126,7 @@
         AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType;
         push(@headerContent, "    static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<$implType>&& impl)\n");
         push(@headerContent, "    {\n");
-        push(@headerContent, "        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(\"Allocated masquerading object\");\n");
+        push(@headerContent, "        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(globalObject->vm(), \"Allocated masquerading object\");\n");
         push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, *globalObject, WTFMove(impl));\n");
         push(@headerContent, "        ptr->finishCreation(globalObject->vm());\n");
         push(@headerContent, "        return ptr;\n");

Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventTarget.h (202587 => 202588)


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventTarget.h	2016-06-28 21:27:21 UTC (rev 202587)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventTarget.h	2016-06-28 21:30:20 UTC (rev 202588)
@@ -31,7 +31,7 @@
     typedef TestEventTarget DOMWrapped;
     static JSTestEventTarget* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<TestEventTarget>&& impl)
     {
-        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Allocated masquerading object");
+        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(globalObject->vm(), "Allocated masquerading object");
         JSTestEventTarget* ptr = new (NotNull, JSC::allocateCell<JSTestEventTarget>(globalObject->vm().heap)) JSTestEventTarget(structure, *globalObject, WTFMove(impl));
         ptr->finishCreation(globalObject->vm());
         return ptr;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to