WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
more
blah.patch (text/plain), 84.67 KB, created by
Filip Pizlo
on 2015-03-30 15:30:05 PDT
(
hide
)
Description:
more
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2015-03-30 15:30:05 PDT
Size:
84.67 KB
patch
obsolete
>Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 182069) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -383,6 +383,8 @@ > 0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC21862C47800845D97 /* FTLUnwindInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F6B1CC918641DF800845D97 /* ArityCheckFailReturnThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CC718641DF800845D97 /* ArityCheckFailReturnThunks.cpp */; }; > 0F6B1CCA18641DF800845D97 /* ArityCheckFailReturnThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F6C73501AC9F99F00BE1682 /* VariableWriteFireDetail.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6C734E1AC9F99F00BE1682 /* VariableWriteFireDetail.cpp */; }; >+ 0F6C73511AC9F99F00BE1682 /* VariableWriteFireDetail.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6C734F1AC9F99F00BE1682 /* VariableWriteFireDetail.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F6E845A19030BEF00562741 /* DFGVariableAccessData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */; }; > 0F6FC750196110A800E1D02D /* ComplexGetStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */; }; > 0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -2100,6 +2102,8 @@ > 0F6B1CC21862C47800845D97 /* FTLUnwindInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLUnwindInfo.h; path = ftl/FTLUnwindInfo.h; sourceTree = "<group>"; }; > 0F6B1CC718641DF800845D97 /* ArityCheckFailReturnThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArityCheckFailReturnThunks.cpp; sourceTree = "<group>"; }; > 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArityCheckFailReturnThunks.h; sourceTree = "<group>"; }; >+ 0F6C734E1AC9F99F00BE1682 /* VariableWriteFireDetail.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableWriteFireDetail.cpp; sourceTree = "<group>"; }; >+ 0F6C734F1AC9F99F00BE1682 /* VariableWriteFireDetail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableWriteFireDetail.h; sourceTree = "<group>"; }; > 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessData.cpp; path = dfg/DFGVariableAccessData.cpp; sourceTree = "<group>"; }; > 0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComplexGetStatus.cpp; sourceTree = "<group>"; }; > 0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComplexGetStatus.h; sourceTree = "<group>"; }; >@@ -5280,6 +5284,8 @@ > 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */, > 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */, > FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */, >+ 0F6C734E1AC9F99F00BE1682 /* VariableWriteFireDetail.cpp */, >+ 0F6C734F1AC9F99F00BE1682 /* VariableWriteFireDetail.h */, > 0F20C2581A8013AB00DA3229 /* VirtualRegister.cpp */, > 0F426A461460CBAB00131F8F /* VirtualRegister.h */, > 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */, >@@ -6354,6 +6360,7 @@ > A709F2F017A0AC0400512E98 /* SlowPathCall.h in Headers */, > 933040040E6A749400786E6A /* SmallStrings.h in Headers */, > BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */, >+ 0F6C73511AC9F99F00BE1682 /* VariableWriteFireDetail.h in Headers */, > BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */, > 70EC0EC31AA0D7DA00B6AAFA /* JSStringIterator.h in Headers */, > E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */, >@@ -6963,6 +6970,7 @@ > A77F1821164088B200640A47 /* CodeCache.cpp in Sources */, > 0F8F9446166764F100D61971 /* CodeOrigin.cpp in Sources */, > 86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */, >+ 0F6C73501AC9F99F00BE1682 /* VariableWriteFireDetail.cpp in Sources */, > 86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */, > 0F8F943C1667631300D61971 /* CodeSpecializationKind.cpp in Sources */, > 0F8F94421667633500D61971 /* CodeType.cpp in Sources */, >Index: Source/JavaScriptCore/bytecode/BytecodeList.json >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeList.json (revision 182069) >+++ Source/JavaScriptCore/bytecode/BytecodeList.json (working copy) >@@ -6,7 +6,6 @@ > { "name" : "op_enter", "length" : 1 }, > { "name" : "op_create_lexical_environment", "length" : 3 }, > { "name" : "op_get_scope", "length" : 2 }, >- { "name" : "op_touch_entry", "length" : 1 }, > { "name" : "op_create_direct_arguments", "length" : 2 }, > { "name" : "op_create_scoped_arguments", "length" : 3 }, > { "name" : "op_create_out_of_band_arguments", "length" : 2 }, >@@ -103,7 +102,7 @@ > { "name" : "op_construct_varargs", "length" : 9 }, > { "name" : "op_strcat", "length" : 4 }, > { "name" : "op_to_primitive", "length" : 3 }, >- { "name" : "op_resolve_scope", "length" : 7 }, >+ { "name" : "op_resolve_scope", "length" : 6 }, > { "name" : "op_get_from_scope", "length" : 8 }, > { "name" : "op_put_to_scope", "length" : 7 }, > { "name" : "op_get_from_arguments", "length" : 5 }, >Index: Source/JavaScriptCore/bytecode/BytecodeUseDef.h >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeUseDef.h (revision 182069) >+++ Source/JavaScriptCore/bytecode/BytecodeUseDef.h (working copy) >@@ -50,7 +50,6 @@ void computeUsesForBytecodeOffset( > case op_new_object: > case op_enter: > case op_catch: >- case op_touch_entry: > case op_profile_control_flow: > case op_create_direct_arguments: > case op_create_out_of_band_arguments: >@@ -278,7 +277,6 @@ void computeDefsForBytecodeOffset(CodeBl > case op_put_by_index: > case op_profile_type: > case op_profile_control_flow: >- case op_touch_entry: > case op_put_to_arguments: > #define LLINT_HELPER_OPCODES(opcode, length) case opcode: > FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES); >Index: Source/JavaScriptCore/bytecode/CodeBlock.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.cpp (revision 182069) >+++ Source/JavaScriptCore/bytecode/CodeBlock.cpp (working copy) >@@ -733,10 +733,6 @@ void CodeBlock::dumpBytecode( > printLocationAndOp(out, exec, location, it, "enter"); > break; > } >- case op_touch_entry: { >- printLocationAndOp(out, exec, location, it, "touch_entry"); >- break; >- } > case op_create_lexical_environment: { > int r0 = (++it)->u.operand; > int r1 = (++it)->u.operand; >@@ -1484,7 +1480,6 @@ void CodeBlock::dumpBytecode( > out.printf("%s, %s, %s, %u<%s|%s>, %d", registerName(r0).data(), registerName(scope).data(), idName(id0, identifier(id0)).data(), > modeAndType.operand(), resolveModeName(modeAndType.mode()), resolveTypeName(modeAndType.type()), > depth); >- ++it; > break; > } > case op_get_from_scope: { >@@ -1931,8 +1926,6 @@ CodeBlock::CodeBlock(ScriptExecutable* o > ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), needsActivation(), scope, ident, Get, type); > instructions[i + 4].u.operand = op.type; > instructions[i + 5].u.operand = op.depth; >- if (op.lexicalEnvironment) >- instructions[i + 6].u.lexicalEnvironment.set(*vm(), ownerExecutable, op.lexicalEnvironment); > break; > } > >@@ -2520,15 +2513,6 @@ void CodeBlock::finalizeUnconditionally( > curInstruction[3].u.toThisStatus = merge( > curInstruction[3].u.toThisStatus, ToThisClearedByGC); > break; >- case op_resolve_scope: { >- WriteBarrierBase<JSLexicalEnvironment>& lexicalEnvironment = curInstruction[6].u.lexicalEnvironment; >- if (!lexicalEnvironment || Heap::isMarked(lexicalEnvironment.get())) >- break; >- if (Options::verboseOSR()) >- dataLogF("Clearing dead lexicalEnvironment %p.\n", lexicalEnvironment.get()); >- lexicalEnvironment.clear(); >- break; >- } > case op_get_from_scope: > case op_put_to_scope: { > ResolveModeAndType modeAndType = >Index: Source/JavaScriptCore/bytecode/CodeOrigin.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeOrigin.cpp (revision 182069) >+++ Source/JavaScriptCore/bytecode/CodeOrigin.cpp (working copy) >@@ -141,6 +141,18 @@ void CodeOrigin::dumpInContext(PrintStre > dump(out); > } > >+JSFunction* InlineCallFrame::calleeConstant() const >+{ >+ if (calleeRecovery.isConstant()) >+ return jsCast<JSFunction*>(calleeRecovery.constant()); >+ return nullptr; >+} >+ >+void InlineCallFrame::visitAggregate(SlotVisitor& visitor) >+{ >+ visitor.append(&executable); >+} >+ > JSFunction* InlineCallFrame::calleeForCallFrame(ExecState* exec) const > { > return jsCast<JSFunction*>(calleeRecovery.recover(exec)); >Index: Source/JavaScriptCore/bytecode/CodeOrigin.h >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeOrigin.h (revision 182069) >+++ Source/JavaScriptCore/bytecode/CodeOrigin.h (working copy) >@@ -28,7 +28,6 @@ > > #include "CodeBlockHash.h" > #include "CodeSpecializationKind.h" >-#include "JSFunction.h" > #include "ValueRecovery.h" > #include "WriteBarrier.h" > #include <wtf/BitVector.h> >@@ -207,17 +206,8 @@ struct InlineCallFrame { > > CodeSpecializationKind specializationKind() const { return specializationKindFor(static_cast<Kind>(kind)); } > >- JSFunction* calleeConstant() const >- { >- if (calleeRecovery.isConstant()) >- return jsCast<JSFunction*>(calleeRecovery.constant()); >- return 0; >- } >- >- void visitAggregate(SlotVisitor& visitor) >- { >- visitor.append(&executable); >- } >+ JSFunction* calleeConstant() const; >+ void visitAggregate(SlotVisitor&); > > // Get the callee given a machine call frame to which this InlineCallFrame belongs. > JSFunction* calleeForCallFrame(ExecState*) const; >Index: Source/JavaScriptCore/bytecode/Instruction.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Instruction.h (revision 182069) >+++ Source/JavaScriptCore/bytecode/Instruction.h (working copy) >@@ -46,7 +46,7 @@ namespace JSC { > class ArrayAllocationProfile; > class ArrayProfile; > class ObjectAllocationProfile; >-class VariableWatchpointSet; >+class WatchpointSet; > struct LLIntCallLinkInfo; > struct ValueProfile; > >@@ -117,8 +117,7 @@ struct Instruction { > ArrayProfile* arrayProfile; > ArrayAllocationProfile* arrayAllocationProfile; > ObjectAllocationProfile* objectAllocationProfile; >- VariableWatchpointSet* watchpointSet; >- WriteBarrierBase<JSLexicalEnvironment> lexicalEnvironment; >+ WatchpointSet* watchpointSet; > void* pointer; > bool* predicatePointer; > ToThisStatus toThisStatus; >Index: Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp (revision 182069) >+++ Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -35,14 +35,9 @@ void VariableWriteFireDetail::dump(Print > out.print("Write to ", m_name, " in ", JSValue(m_object)); > } > >-void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, JSObject* baseObject, const PropertyName& propertyName) >+void VariableWatchpointSet::notifyWrite(VM& vm, JSCell* owner, JSValue value, const char* reason) > { >- notifyWrite(vm, value, VariableWriteFireDetail(baseObject, propertyName)); >-} >- >-void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const char* reason) >-{ >- notifyWrite(vm, value, StringFireDetail(reason)); >+ notifyWrite(vm, owner, value, StringFireDetail(reason)); > } > > } // namespace JSC >Index: Source/JavaScriptCore/bytecode/VariableWatchpointSet.h >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWatchpointSet.h (revision 182069) >+++ Source/JavaScriptCore/bytecode/VariableWatchpointSet.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012-2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2012-2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -32,29 +32,12 @@ > namespace JSC { > > class JSObject; >-class SymbolTable; >- >-class VariableWriteFireDetail : public FireDetail { >-public: >- VariableWriteFireDetail(JSObject* object, const PropertyName& name) >- : m_object(object) >- , m_name(name) >- { >- } >- >- virtual void dump(PrintStream&) const override; >- >-private: >- JSObject* m_object; >- const PropertyName& m_name; >-}; > > class VariableWatchpointSet : public WatchpointSet { > friend class LLIntOffsetsExtractor; > public: >- VariableWatchpointSet(SymbolTable& symbolTable) >+ VariableWatchpointSet() > : WatchpointSet(ClearWatchpoint) >- , m_symbolTable(symbolTable) > { > } > >@@ -73,9 +56,8 @@ public: > // you will have been notified that the watchpoint was fired. > JSValue inferredValue() const { return m_inferredValue.get(); } > >- void notifyWrite(VM&, JSValue, const FireDetail&); >- JS_EXPORT_PRIVATE void notifyWrite(VM&, JSValue, JSObject* baseObject, const PropertyName&); >- void notifyWrite(VM&, JSValue, const char* reason); >+ void notifyWrite(VM&, JSCell* owner, JSValue, const FireDetail&); >+ void notifyWrite(VM&, JSCell* owner, JSValue, const char* reason); > > void invalidate(const FireDetail& detail) > { >@@ -83,15 +65,19 @@ public: > WatchpointSet::invalidate(detail); > } > >- void finalizeUnconditionally(const FireDetail& detail) >+ bool needToFinalize() > { > ASSERT(!!m_inferredValue == (state() == IsWatched)); > if (!m_inferredValue) >+ return false; >+ return m_inferredValue.get().isCell(); >+ } >+ >+ void finalizeUnconditionally(const FireDetail& detail) >+ { >+ if (!needToFinalize()) > return; >- JSValue inferredValue = m_inferredValue.get(); >- if (!inferredValue.isCell()) >- return; >- JSCell* cell = inferredValue.asCell(); >+ JSCell* cell = m_inferredValue.get().asCell(); > if (Heap::isMarked(cell)) > return; > invalidate(detail); >@@ -100,7 +86,6 @@ public: > WriteBarrier<Unknown>* addressOfInferredValue() { return &m_inferredValue; } > > private: >- SymbolTable& m_symbolTable; > WriteBarrier<Unknown> m_inferredValue; > }; > >Index: Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h (revision 182069) >+++ Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -26,17 +26,17 @@ > #ifndef VariableWatchpointSetInlines_h > #define VariableWatchpointSetInlines_h > >-#include "SymbolTable.h" > #include "VariableWatchpointSet.h" > > namespace JSC { > >-inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const FireDetail& detail) >+inline void VariableWatchpointSet::notifyWrite( >+ VM& vm, JSCell* owner, JSValue value, const FireDetail& detail) > { > ASSERT(!!value); > switch (state()) { > case ClearWatchpoint: >- m_inferredValue.set(vm, &m_symbolTable, value); >+ m_inferredValue.set(vm, owner, value); > startWatching(); > return; > >Index: Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp (revision 0) >+++ Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp (working copy) >@@ -0,0 +1,39 @@ >+/* >+ * Copyright (C) 2015 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 "VariableWriteFireDetail.h" >+ >+#include "JSCInlines.h" >+ >+namespace JSC { >+ >+void VariableWriteFireDetail::dump(PrintStream& out) const >+{ >+ out.print("Write to ", m_name, " in ", JSValue(m_object)); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/bytecode/VariableWriteFireDetail.h >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWriteFireDetail.h (revision 0) >+++ Source/JavaScriptCore/bytecode/VariableWriteFireDetail.h (working copy) >@@ -0,0 +1,53 @@ >+/* >+ * Copyright (C) 2015 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 VariableWriteFireDetail_h >+#define VariableWriteFireDetail_h >+ >+#include "Watchpoint.h" >+ >+namespace JSC { >+ >+class JSObject; >+class PropertyName; >+ >+class VariableWriteFireDetail : public FireDetail { >+public: >+ VariableWriteFireDetail(JSObject* object, const PropertyName& name) >+ : m_object(object) >+ , m_name(name) >+ { >+ } >+ >+ virtual void dump(PrintStream&) const override; >+ >+private: >+ JSObject* m_object; >+ const PropertyName& m_name; >+}; >+ >+} // namespace JSC >+ >+#endif // VariableWriteFireDetail_h >Index: Source/JavaScriptCore/bytecode/Watchpoint.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Watchpoint.h (revision 182069) >+++ Source/JavaScriptCore/bytecode/Watchpoint.h (working copy) >@@ -125,20 +125,24 @@ public: > // set watchpoints that we believe will actually be fired. > void startWatching() > { >- ASSERT(state() != IsInvalidated); >+ ASSERT(m_state != IsInvalidated); >+ if (m_state == IsWatched) >+ return; >+ WTF::storeStoreFence(); > m_state = IsWatched; >+ WTF::storeStoreFence(); > } > > void fireAll(const FireDetail& detail) > { >- if (LIKELY(state() != IsWatched)) >+ if (LIKELY(m_state != IsWatched)) > return; > fireAllSlow(detail); > } > > void fireAll(const char* reason) > { >- if (LIKELY(state() != IsWatched)) >+ if (LIKELY(m_state != IsWatched)) > return; > fireAllSlow(reason); > } >@@ -151,13 +155,23 @@ public: > fireAll(detail); > } > >+ void touch(const char* reason) >+ { >+ touch(StringFireDetail(reason)); >+ } >+ > void invalidate(const FireDetail& detail) > { > if (state() == IsWatched) > fireAll(detail); > m_state = IsInvalidated; > } >- >+ >+ void invalidate(const char* reason) >+ { >+ invalidate(StringFireDetail(reason)); >+ } >+ > int8_t* addressOfState() { return &m_state; } > int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; } > >@@ -261,7 +275,11 @@ public: > fat()->touch(detail); > return; > } >- if (decodeState(m_data) == ClearWatchpoint) >+ uintptr_t data = m_data; >+ if (decodeState(data) == IsInvalidated) >+ return; >+ WTF::storeStoreFence(); >+ if (decodeState(data) == ClearWatchpoint) > m_data = encodeState(IsWatched); > else > m_data = encodeState(IsInvalidated); >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (revision 182069) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (working copy) >@@ -466,9 +466,6 @@ BytecodeGenerator::BytecodeGenerator(VM& > } > } > >- if (m_symbolTable->scopeSize()) >- emitOpcode(op_touch_entry); >- > if (isConstructor()) { > if (constructorKind() == ConstructorKind::Derived) { > m_newTargetRegister = addVar(); >@@ -1324,8 +1321,6 @@ RegisterID* BytecodeGenerator::emitResol > > ASSERT(!m_symbolTable || !m_symbolTable->contains(variable.ident().impl()) || resolveType() == Dynamic); > >- m_codeBlock->addPropertyAccessInstruction(instructions().size()); >- > // resolve_scope dst, id, ResolveType, depth > emitOpcode(op_resolve_scope); > dst = tempDestination(dst); >@@ -1334,7 +1329,6 @@ RegisterID* BytecodeGenerator::emitResol > instructions().append(addConstant(variable.ident())); > instructions().append(resolveType()); > instructions().append(0); >- instructions().append(0); > return dst; > } > >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -1341,6 +1341,7 @@ bool AbstractInterpreter<AbstractStateTy > } > > case CreateThis: { >+ // FIXME: We can fold this to NewObject if the incoming callee is a constant. > forNode(node).setType(SpecFinalObject); > break; > } >@@ -1403,6 +1404,15 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case GetCallee: >+ if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) { >+ VariableWatchpointSet& set = executable->functionReallocationWatchpointSet(); >+ if (JSValue value = set.inferredValue()) { >+ m_graph.watchpoints().addLazily(&set); >+ JSFunction* function = jsCast<JSFunction*>(value); >+ setConstant(node, *m_graph.freeze(function)); >+ break; >+ } >+ } > forNode(node).setType(SpecFunction); > break; > >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -278,8 +278,20 @@ private: > if (operand.offset() == JSStack::Callee) > return weakJSConstant(callee); > } >- } else if (operand.offset() == JSStack::Callee) >+ } else if (operand.offset() == JSStack::Callee) { >+ // We have to do some constant-folding here because this enables CreateThis folding. Note >+ // that we don't have such watchpoint-based folding for inlined uses of Callee, since in that >+ // case if the function is a singleton then we already know it. >+ if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) { >+ VariableWatchpointSet& set = executable->functionReallocationWatchpointSet(); >+ if (JSValue value = set.inferredValue()) { >+ m_graph.watchpoints().addLazily(&set); >+ JSFunction* function = jsCast<JSFunction*>(value); >+ return weakJSConstant(function); >+ } >+ } > return addToGraph(GetCallee); >+ } > > return getDirect(m_inlineStackTop->remapOperand(operand)); > } >@@ -2519,6 +2531,12 @@ void ByteCodeParser::clearCaches() > Node* ByteCodeParser::getScope(VirtualRegister scopeChain, unsigned skipCount) > { > Node* localBase = get(scopeChain); >+ addToGraph(Phantom, localBase); // OSR exit cannot handle resolve_scope on a DCE'd scope. >+ if (JSScope* scope = localBase->dynamicCastConstant<JSScope*>()) { >+ for (unsigned n = skipCount; n--;) >+ scope = scope->next(); >+ return weakJSConstant(scope); >+ } > for (unsigned n = skipCount; n--;) > localBase = addToGraph(SkipScope, localBase); > return localBase; >@@ -2593,11 +2611,6 @@ bool ByteCodeParser::parseBlock(unsigned > NEXT_OPCODE(op_enter); > } > >- case op_touch_entry: >- if (m_inlineStackTop->m_codeBlock->symbolTable()->m_functionEnteredOnce.isStillValid()) >- addToGraph(ForceOSRExit); >- NEXT_OPCODE(op_touch_entry); >- > case op_to_this: { > Node* op1 = getThis(); > if (op1->op() != ToThis) { >@@ -3375,17 +3388,7 @@ bool ByteCodeParser::parseBlock(unsigned > case LocalClosureVar: > case ClosureVar: > case ClosureVarWithVarInjectionChecks: { >- JSLexicalEnvironment* lexicalEnvironment = currentInstruction[6].u.lexicalEnvironment.get(); >- if (lexicalEnvironment >- && lexicalEnvironment->symbolTable()->m_functionEnteredOnce.isStillValid()) { >- m_graph.watchpoints().addLazily(lexicalEnvironment->symbolTable()->m_functionEnteredOnce); >- addToGraph(Phantom, getDirect(m_inlineStackTop->remapOperand(VirtualRegister(currentInstruction[2].u.operand)))); >- set(VirtualRegister(dst), weakJSConstant(lexicalEnvironment)); >- break; >- } > set(VirtualRegister(dst), getScope(VirtualRegister(currentInstruction[2].u.operand), depth)); >- if (inlineCallFrame()) >- addToGraph(Phantom, getDirect(m_inlineStackTop->remapOperand(VirtualRegister(currentInstruction[2].u.operand)))); > break; > } > case Dynamic: >@@ -3437,19 +3440,58 @@ bool ByteCodeParser::parseBlock(unsigned > case GlobalVar: > case GlobalVarWithVarInjectionChecks: { > addToGraph(Phantom, get(VirtualRegister(scope))); >- ConcurrentJITLocker locker(globalObject->symbolTable()->m_lock); >- SymbolTableEntry entry = globalObject->symbolTable()->get(locker, uid); >- VariableWatchpointSet* watchpointSet = entry.watchpointSet(); >- JSValue inferredValue = >- watchpointSet ? watchpointSet->inferredValue() : JSValue(); >- if (!inferredValue) { >- SpeculatedType prediction = getPrediction(); >- set(VirtualRegister(dst), addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction))); >- break; >+ WatchpointSet* watchpointSet; >+ ScopeOffset offset; >+ { >+ ConcurrentJITLocker locker(globalObject->symbolTable()->m_lock); >+ SymbolTableEntry entry = globalObject->symbolTable()->get(locker, uid); >+ watchpointSet = entry.watchpointSet(); >+ offset = entry.scopeOffset(); >+ } >+ if (watchpointSet && watchpointSet->state() == IsWatched) { >+ // This has a fun concurrency story. There is the possibility of a race in two >+ // directions: >+ // >+ // We see that the set IsWatched, but in the meantime it gets invalidated: this is >+ // fine because if we saw that it IsWatched then we add a watchpoint. If it gets >+ // invalidated, then this compilation is invalidated. Note that in the meantime we >+ // may load an absurd value from the global object. It's fine to load an absurd >+ // value if the compilation is invalidated anyway. >+ // >+ // We see that the set IsWatched, but the value isn't yet initialized: this isn't >+ // possible because of the ordering of operations. >+ // >+ // Here's how we order operations: >+ // >+ // Main thread stores to the global object: always first store a value first, and >+ // only after that we touch the watchpoint set. There is a fence in the touch, that >+ // ensures that the store to the global object always happens before the touch on the >+ // set. >+ // >+ // Compilation thread: always first load the state of the watchpoint set, and then >+ // load the value. The WatchpointSet::state() method does fences for us to ensure >+ // that the load of the state happens before our load of the value. >+ // >+ // Finalizing compilation: this happens on the main thread and synchronously checks >+ // validity of all watchpoint sets. >+ // >+ // We will only perform optimizations if the load of the state yields IsWatched. That >+ // means that at least one store would have happened to initialize the original value >+ // of the variable (that is, the value we'd like to constant fold to). There may be >+ // other stores that happen after that, but those stores will invalidate the >+ // watchpoint set and also the compilation. >+ >+ ASSERT(bitwise_cast<uintptr_t>(&globalObject->variableAt(offset)) == operand); >+ JSValue value = globalObject->variableAt(offset).get(); >+ if (value) { >+ m_graph.watchpoints().addLazily(watchpointSet); >+ set(VirtualRegister(dst), weakJSConstant(value)); >+ break; >+ } > } > >- m_graph.watchpoints().addLazily(watchpointSet); >- set(VirtualRegister(dst), weakJSConstant(inferredValue)); >+ SpeculatedType prediction = getPrediction(); >+ set(VirtualRegister(dst), addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction))); > break; > } > case LocalClosureVar: >@@ -3496,7 +3538,7 @@ bool ByteCodeParser::parseBlock(unsigned > uid = nullptr; > > Structure* structure = nullptr; >- VariableWatchpointSet* watchpoints = nullptr; >+ WatchpointSet* watchpoints = nullptr; > uintptr_t operand; > { > ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock); >@@ -3539,8 +3581,10 @@ bool ByteCodeParser::parseBlock(unsigned > } > Node* valueNode = get(VirtualRegister(value)); > addToGraph(PutGlobalVar, OpInfo(operand), valueNode); >- if (watchpoints && watchpoints->state() != IsInvalidated) >- addToGraph(NotifyWrite, OpInfo(watchpoints), valueNode); >+ if (watchpoints && watchpoints->state() != IsInvalidated) { >+ // Must happen after the store. See comment for GetGlobalVar. >+ addToGraph(NotifyWrite, OpInfo(watchpoints)); >+ } > // Keep scope alive until after put. > addToGraph(Phantom, get(VirtualRegister(scope))); > break; >@@ -3551,10 +3595,12 @@ bool ByteCodeParser::parseBlock(unsigned > Node* scopeNode = get(VirtualRegister(scope)); > Node* valueNode = get(VirtualRegister(value)); > >- if (watchpoints && watchpoints->state() != IsInvalidated) >- addToGraph(NotifyWrite, OpInfo(watchpoints), valueNode); >- > addToGraph(PutClosureVar, OpInfo(operand), scopeNode, valueNode); >+ >+ if (watchpoints && watchpoints->state() != IsInvalidated) { >+ // Must happen after the store. See comment for GetGlobalVar. >+ addToGraph(NotifyWrite, OpInfo(watchpoints)); >+ } > break; > } > case Dynamic: >Index: Source/JavaScriptCore/dfg/DFGCapabilities.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCapabilities.cpp (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGCapabilities.cpp (working copy) >@@ -96,7 +96,6 @@ CapabilityLevel capabilityLevel(OpcodeID > > switch (opcodeID) { > case op_enter: >- case op_touch_entry: > case op_to_this: > case op_check_tdz: > case op_create_this: >Index: Source/JavaScriptCore/dfg/DFGClobberize.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGClobberize.h (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGClobberize.h (working copy) >@@ -860,11 +860,17 @@ void clobberize(Graph& graph, Node* node > case NewStringObject: > case PhantomNewObject: > case MaterializeNewObject: >- case NewFunction: > read(HeapObjectCount); > write(HeapObjectCount); > return; > >+ case NewFunction: >+ if (node->castOperand<FunctionExecutable*>()->functionReallocationWatchpointSet().isStillValid()) >+ write(Watchpoint_fire); >+ read(HeapObjectCount); >+ write(HeapObjectCount); >+ return; >+ > case RegExpExec: > case RegExpTest: > read(RegExpState); >Index: Source/JavaScriptCore/dfg/DFGGraph.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.cpp (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGGraph.cpp (working copy) >@@ -308,8 +308,8 @@ void Graph::dump(PrintStream& out, const > out.print(comma, "^", node->phi()->index()); > if (node->hasExecutionCounter()) > out.print(comma, RawPointer(node->executionCounter())); >- if (node->hasVariableWatchpointSet()) >- out.print(comma, RawPointer(node->variableWatchpointSet())); >+ if (node->hasWatchpointSet()) >+ out.print(comma, RawPointer(node->watchpointSet())); > if (node->hasTypedArray()) > out.print(comma, inContext(JSValue(node->typedArray()), context)); > if (node->hasStoragePointer()) >@@ -1025,6 +1025,8 @@ JSValue Graph::tryGetConstantProperty(co > > JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset) > { >+ // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser. >+ > if (!base) > return JSValue(); > >@@ -1033,24 +1035,28 @@ JSValue Graph::tryGetConstantClosureVar( > return JSValue(); > > SymbolTable* symbolTable = activation->symbolTable(); >- ConcurrentJITLocker locker(symbolTable->m_lock); >- >- if (symbolTable->m_functionEnteredOnce.hasBeenInvalidated()) >- return JSValue(); >- >- SymbolTableEntry* entry = symbolTable->entryFor(locker, offset); >- if (!entry) >- return JSValue(); >- >- VariableWatchpointSet* set = entry->watchpointSet(); >- if (!set) >- return JSValue(); >- >- JSValue value = set->inferredValue(); >- if (!value) >- return JSValue(); >+ JSValue value; >+ WatchpointSet* set; >+ { >+ ConcurrentJITLocker locker(symbolTable->m_lock); >+ >+ SymbolTableEntry* entry = symbolTable->entryFor(locker, offset); >+ if (!entry) >+ return JSValue(); >+ >+ set = entry->watchpointSet(); >+ if (!set) >+ return JSValue(); >+ >+ if (set->state() != IsWatched) >+ return JSValue(); >+ >+ ASSERT(entry->scopeOffset() == offset); >+ value = activation->variableAt(offset).get(); >+ if (!value) >+ return JSValue(); >+ } > >- watchpoints().addLazily(symbolTable->m_functionEnteredOnce); > watchpoints().addLazily(set); > > return value; >Index: Source/JavaScriptCore/dfg/DFGNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNode.h (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGNode.h (working copy) >@@ -1219,14 +1219,14 @@ struct Node { > m_opInfo = bitwise_cast<uintptr_t>(value); > } > >- bool hasVariableWatchpointSet() >+ bool hasWatchpointSet() > { > return op() == NotifyWrite; > } > >- VariableWatchpointSet* variableWatchpointSet() >+ WatchpointSet* watchpointSet() > { >- return reinterpret_cast<VariableWatchpointSet*>(m_opInfo); >+ return reinterpret_cast<WatchpointSet*>(m_opInfo); > } > > bool hasTypedArray() >Index: Source/JavaScriptCore/dfg/DFGOperations.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOperations.cpp (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGOperations.cpp (working copy) >@@ -1054,13 +1054,12 @@ char* JIT_OPERATION operationSwitchStrin > return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress()); > } > >-void JIT_OPERATION operationNotifyWrite(ExecState* exec, VariableWatchpointSet* set, EncodedJSValue encodedValue) >+void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set) > { > VM& vm = exec->vm(); > NativeCallFrameTracer tracer(&vm, exec); >- JSValue value = JSValue::decode(encodedValue); > >- set->notifyWrite(vm, value, "Executed NotifyWrite"); >+ set->touch("Executed NotifyWrite"); > } > > void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec) >Index: Source/JavaScriptCore/dfg/DFGOperations.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOperations.h (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGOperations.h (working copy) >@@ -125,7 +125,7 @@ JSCell* JIT_OPERATION operationMakeRope2 > JSCell* JIT_OPERATION operationMakeRope3(ExecState*, JSString*, JSString*, JSString*); > char* JIT_OPERATION operationFindSwitchImmTargetForDouble(ExecState*, EncodedJSValue, size_t tableIndex); > char* JIT_OPERATION operationSwitchString(ExecState*, size_t tableIndex, JSString*); >-void JIT_OPERATION operationNotifyWrite(ExecState*, VariableWatchpointSet*, EncodedJSValue); >+void JIT_OPERATION operationNotifyWrite(ExecState*, WatchpointSet*); > void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState*) WTF_INTERNAL; > int32_t JIT_OPERATION operationSizeOfVarargs(ExecState*, EncodedJSValue arguments, int32_t firstVarArgOffset); > void JIT_OPERATION operationLoadVarargs(ExecState*, int32_t firstElementDest, EncodedJSValue arguments, int32_t offset, int32_t length, int32_t mandatoryMinimum); >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -4014,24 +4014,15 @@ void SpeculativeJIT::compile(Node* node) > } > > case NotifyWrite: { >- VariableWatchpointSet* set = node->variableWatchpointSet(); >- >- JSValueOperand value(this, node->child1()); >- GPRReg valueGPR = value.gpr(); >- >- GPRTemporary temp(this); >- GPRReg tempGPR = temp.gpr(); >- >- m_jit.load8(set->addressOfState(), tempGPR); >- >- JITCompiler::Jump isDone = >- m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated)); >- JITCompiler::Jump slowCase = m_jit.branch64(JITCompiler::NotEqual, >- JITCompiler::AbsoluteAddress(set->addressOfInferredValue()), valueGPR); >- isDone.link(&m_jit); >- >+ WatchpointSet* set = node->watchpointSet(); >+ >+ JITCompiler::Jump slowCase = m_jit.branch8( >+ JITCompiler::NotEqual, >+ JITCompiler::AbsoluteAddress(set->addressOfState()), >+ TrustedImm32(IsInvalidated)); >+ > addSlowPathGenerator( >- slowPathCall(slowCase, this, operationNotifyWrite, NoResult, set, valueGPR)); >+ slowPathCall(slowCase, this, operationNotifyWrite, NoResult, set)); > > noResult(node); > break; >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (working copy) >@@ -4365,8 +4365,13 @@ void SpeculativeJIT::compileNewFunction( > SpeculateCellOperand scope(this, node->child1()); > GPRReg scopeGPR = scope.gpr(); > flushRegisters(); >- callOperation( >- operationNewFunction, resultGPR, scopeGPR, node->castOperand<FunctionExecutable*>()); >+ FunctionExecutable* executable = node->castOperand<FunctionExecutable*>(); >+ J_JITOperation_EJscC function; >+ if (executable->functionReallocationWatchpointSet().isStillValid()) >+ function = operationNewFunction; >+ else >+ function = operationNewFunctionWithInvalidatedReallocationWatchpoint; >+ callOperation(function, resultGPR, scopeGPR, executable); > cellResult(resultGPR, node); > } > >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (working copy) >@@ -1466,6 +1466,12 @@ public: > return appendCall(operation); > } > >+ JITCompiler::Call callOperation(V_JITOperation_EWs operation, WatchpointSet* watchpointSet) >+ { >+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet)); >+ return appendCall(operation); >+ } >+ > JITCompiler::Call callOperation(D_JITOperation_EJ operation, FPRReg result, GPRReg arg1) > { > m_jit.setupArgumentsWithExecState(arg1); >Index: Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp (revision 182069) >+++ Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp (working copy) >@@ -32,6 +32,7 @@ > #include "DFGClobberize.h" > #include "DFGGraph.h" > #include "DFGPhase.h" >+#include "JSCInlines.h" > > namespace JSC { namespace DFG { > >Index: Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (revision 182069) >+++ Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (working copy) >@@ -106,6 +106,7 @@ namespace JSC { namespace FTL { > macro(V_JITOperation_EC, functionType(voidType, intPtr, intPtr)) \ > macro(V_JITOperation_ECb, functionType(voidType, intPtr, intPtr)) \ > macro(V_JITOperation_EVwsJ, functionType(voidType, intPtr, intPtr, int64)) \ >+ macro(V_JITOperation_EWs, functionType(voidType, intPtr, intPtr)) \ > macro(V_JITOperation_EZJZZZ, functionType(voidType, intPtr, int32, int64, int32, int32, int32)) \ > macro(V_JITOperation_J, functionType(voidType, int64)) \ > macro(V_JITOperation_Z, functionType(voidType, int32)) \ >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (revision 182069) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (working copy) >@@ -3783,29 +3783,19 @@ private: > > void compileNotifyWrite() > { >- VariableWatchpointSet* set = m_node->variableWatchpointSet(); >- >- LValue value = lowJSValue(m_node->child1()); >+ WatchpointSet* set = m_node->watchpointSet(); > > LBasicBlock isNotInvalidated = FTL_NEW_BLOCK(m_out, ("NotifyWrite not invalidated case")); >- LBasicBlock notifySlow = FTL_NEW_BLOCK(m_out, ("NotifyWrite notify slow case")); > LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NotifyWrite continuation")); > > LValue state = m_out.load8(m_out.absolute(set->addressOfState())); >- > m_out.branch( > m_out.equal(state, m_out.constInt8(IsInvalidated)), > usually(continuation), rarely(isNotInvalidated)); > >- LBasicBlock lastNext = m_out.appendTo(isNotInvalidated, notifySlow); >- >- m_out.branch( >- m_out.equal(value, m_out.load64(m_out.absolute(set->addressOfInferredValue()))), >- unsure(continuation), unsure(notifySlow)); >- >- m_out.appendTo(notifySlow, continuation); >+ LBasicBlock lastNext = m_out.appendTo(isNotInvalidated, continuation); > >- vmCall(m_out.operation(operationNotifyWrite), m_callFrame, m_out.constIntPtr(set), value); >+ vmCall(m_out.operation(operationNotifyWrite), m_callFrame, m_out.constIntPtr(set)); > m_out.jump(continuation); > > m_out.appendTo(continuation, lastNext); >Index: Source/JavaScriptCore/interpreter/Interpreter.cpp >=================================================================== >--- Source/JavaScriptCore/interpreter/Interpreter.cpp (revision 182069) >+++ Source/JavaScriptCore/interpreter/Interpreter.cpp (working copy) >@@ -89,6 +89,47 @@ using namespace std; > > namespace JSC { > >+String StackFrame::friendlySourceURL() const >+{ >+ String traceLine; >+ >+ switch (codeType) { >+ case StackFrameEvalCode: >+ case StackFrameFunctionCode: >+ case StackFrameGlobalCode: >+ if (!sourceURL.isEmpty()) >+ traceLine = sourceURL.impl(); >+ break; >+ case StackFrameNativeCode: >+ traceLine = "[native code]"; >+ break; >+ } >+ return traceLine.isNull() ? emptyString() : traceLine; >+} >+ >+String StackFrame::friendlyFunctionName(CallFrame* callFrame) const >+{ >+ String traceLine; >+ JSObject* stackFrameCallee = callee.get(); >+ >+ switch (codeType) { >+ case StackFrameEvalCode: >+ traceLine = "eval code"; >+ break; >+ case StackFrameNativeCode: >+ if (callee) >+ traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl(); >+ break; >+ case StackFrameFunctionCode: >+ traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl(); >+ break; >+ case StackFrameGlobalCode: >+ traceLine = "global code"; >+ break; >+ } >+ return traceLine.isNull() ? emptyString() : traceLine; >+} >+ > JSValue eval(CallFrame* callFrame) > { > if (!callFrame->argumentCount()) >Index: Source/JavaScriptCore/interpreter/Interpreter.h >=================================================================== >--- Source/JavaScriptCore/interpreter/Interpreter.h (revision 182069) >+++ Source/JavaScriptCore/interpreter/Interpreter.h (working copy) >@@ -90,45 +90,8 @@ namespace JSC { > unsigned bytecodeOffset; > String sourceURL; > JS_EXPORT_PRIVATE String toString(CallFrame*); >- String friendlySourceURL() const >- { >- String traceLine; >- >- switch (codeType) { >- case StackFrameEvalCode: >- case StackFrameFunctionCode: >- case StackFrameGlobalCode: >- if (!sourceURL.isEmpty()) >- traceLine = sourceURL.impl(); >- break; >- case StackFrameNativeCode: >- traceLine = "[native code]"; >- break; >- } >- return traceLine.isNull() ? emptyString() : traceLine; >- } >- String friendlyFunctionName(CallFrame* callFrame) const >- { >- String traceLine; >- JSObject* stackFrameCallee = callee.get(); >- >- switch (codeType) { >- case StackFrameEvalCode: >- traceLine = "eval code"; >- break; >- case StackFrameNativeCode: >- if (callee) >- traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl(); >- break; >- case StackFrameFunctionCode: >- traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl(); >- break; >- case StackFrameGlobalCode: >- traceLine = "global code"; >- break; >- } >- return traceLine.isNull() ? emptyString() : traceLine; >- } >+ String friendlySourceURL() const; >+ String friendlyFunctionName(CallFrame*) const; > JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column); > > private: >Index: Source/JavaScriptCore/jit/JIT.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JIT.cpp (revision 182069) >+++ Source/JavaScriptCore/jit/JIT.cpp (working copy) >@@ -189,7 +189,6 @@ void JIT::privateCompileMainPass() > DEFINE_SLOW_OP(is_object_or_null) > DEFINE_SLOW_OP(typeof) > >- DEFINE_OP(op_touch_entry) > DEFINE_OP(op_add) > DEFINE_OP(op_bitand) > DEFINE_OP(op_bitor) >Index: Source/JavaScriptCore/jit/JIT.h >=================================================================== >--- Source/JavaScriptCore/jit/JIT.h (revision 182069) >+++ Source/JavaScriptCore/jit/JIT.h (working copy) >@@ -457,7 +457,6 @@ namespace JSC { > > void assertStackPointerOffset(); > >- void emit_op_touch_entry(Instruction*); > void emit_op_add(Instruction*); > void emit_op_bitand(Instruction*); > void emit_op_bitor(Instruction*); >@@ -640,13 +639,9 @@ namespace JSC { > void emitGetGlobalVar(uintptr_t operand); > void emitGetClosureVar(int scope, uintptr_t operand); > void emitPutGlobalProperty(uintptr_t* operandSlot, int value); >-#if USE(JSVALUE64) >- void emitNotifyWrite(RegisterID value, RegisterID scratch, VariableWatchpointSet*); >-#else >- void emitNotifyWrite(RegisterID tag, RegisterID payload, RegisterID scratch, VariableWatchpointSet*); >-#endif >- void emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet*); >- void emitPutClosureVar(int scope, uintptr_t operand, int value, VariableWatchpointSet*); >+ void emitNotifyWrite(WatchpointSet*); >+ void emitPutGlobalVar(uintptr_t operand, int value, WatchpointSet*); >+ void emitPutClosureVar(int scope, uintptr_t operand, int value, WatchpointSet*); > > void emitInitRegister(int dst); > >Index: Source/JavaScriptCore/jit/JITOpcodes.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITOpcodes.cpp (revision 182069) >+++ Source/JavaScriptCore/jit/JITOpcodes.cpp (working copy) >@@ -879,15 +879,6 @@ void JIT::emitSlow_op_to_number(Instruct > > #endif // USE(JSVALUE64) > >-void JIT::emit_op_touch_entry(Instruction* currentInstruction) >-{ >- if (m_codeBlock->symbolTable()->m_functionEnteredOnce.hasBeenInvalidated()) >- return; >- >- JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_touch_entry); >- slowPathCall.call(); >-} >- > void JIT::emit_op_loop_hint(Instruction*) > { > // Emit the JIT optimization check: >Index: Source/JavaScriptCore/jit/JITOperations.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITOperations.cpp (revision 182069) >+++ Source/JavaScriptCore/jit/JITOperations.cpp (working copy) >@@ -933,6 +933,14 @@ EncodedJSValue JIT_OPERATION operationNe > return JSValue::encode(JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope)); > } > >+EncodedJSValue JIT_OPERATION operationNewFunctionWithInvalidatedReallocationWatchpoint(ExecState* exec, JSScope* scope, JSCell* functionExecutable) >+{ >+ ASSERT(functionExecutable->inherits(FunctionExecutable::info())); >+ VM& vm = exec->vm(); >+ NativeCallFrameTracer tracer(&vm, exec); >+ return JSValue::encode(JSFunction::createWithInvalidatedReallocationWatchpoint(vm, static_cast<FunctionExecutable*>(functionExecutable), scope)); >+} >+ > JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure) > { > VM* vm = &exec->vm(); >@@ -1703,8 +1711,8 @@ void JIT_OPERATION operationPutToScope(E > if (modeAndType.type() == LocalClosureVar) { > JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope); > environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value); >- if (VariableWatchpointSet* set = pc[5].u.watchpointSet) >- set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>"); >+ if (WatchpointSet* set = pc[5].u.watchpointSet) >+ set->touch("Executed op_put_scope<LocalClosureVar>"); > return; > } > if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) { >Index: Source/JavaScriptCore/jit/JITOperations.h >=================================================================== >--- Source/JavaScriptCore/jit/JITOperations.h (revision 182069) >+++ Source/JavaScriptCore/jit/JITOperations.h (working copy) >@@ -86,6 +86,7 @@ extern "C" { > V: void > Vm: VM* > Vws: VariableWatchpointSet* >+ Ws: WatchpointSet* > Z: int32_t > */ > >@@ -192,6 +193,7 @@ typedef void JIT_OPERATION (*V_JITOperat > typedef void JIT_OPERATION (*V_JITOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue); > typedef void JIT_OPERATION (*V_JITOperation_ESsiJJI)(ExecState*, StructureStubInfo*, EncodedJSValue, EncodedJSValue, StringImpl*); > typedef void JIT_OPERATION (*V_JITOperation_EVwsJ)(ExecState*, VariableWatchpointSet*, EncodedJSValue); >+typedef void JIT_OPERATION (*V_JITOperation_EWs)(ExecState*, WatchpointSet*); > typedef void JIT_OPERATION (*V_JITOperation_EZ)(ExecState*, int32_t); > typedef void JIT_OPERATION (*V_JITOperation_EZJ)(ExecState*, int32_t, EncodedJSValue); > typedef void JIT_OPERATION (*V_JITOperation_EZJZZZ)(ExecState*, int32_t, EncodedJSValue, int32_t, int32_t, int32_t); >@@ -278,6 +280,7 @@ EncodedJSValue JIT_OPERATION operationNe > EncodedJSValue JIT_OPERATION operationNewArrayBufferWithProfile(ExecState*, ArrayAllocationProfile*, const JSValue* values, int32_t size) WTF_INTERNAL; > EncodedJSValue JIT_OPERATION operationNewArrayWithSizeAndProfile(ExecState*, ArrayAllocationProfile*, EncodedJSValue size) WTF_INTERNAL; > EncodedJSValue JIT_OPERATION operationNewFunction(ExecState*, JSScope*, JSCell*) WTF_INTERNAL; >+EncodedJSValue JIT_OPERATION operationNewFunctionWithInvalidatedReallocationWatchpoint(ExecState*, JSScope*, JSCell*) WTF_INTERNAL; > JSCell* JIT_OPERATION operationNewObject(ExecState*, Structure*) WTF_INTERNAL; > EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL; > void JIT_OPERATION operationHandleWatchdogTimer(ExecState*) WTF_INTERNAL; >Index: Source/JavaScriptCore/jit/JITPropertyAccess.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITPropertyAccess.cpp (revision 182069) >+++ Source/JavaScriptCore/jit/JITPropertyAccess.cpp (working copy) >@@ -728,29 +728,26 @@ void JIT::emitPutGlobalProperty(uintptr_ > storePtr(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue))); > } > >-void JIT::emitNotifyWrite(RegisterID value, RegisterID scratch, VariableWatchpointSet* set) >+void JIT::emitNotifyWrite(WatchpointSet* set) > { > if (!set || set->state() == IsInvalidated) > return; > >- load8(set->addressOfState(), scratch); >- Jump isDone = branch32(Equal, scratch, TrustedImm32(IsInvalidated)); >- addSlowCase(branch64(NotEqual, AbsoluteAddress(set->addressOfInferredValue()), value)); >- isDone.link(this); >+ addSlowCase(branch8(NotEqual, AbsoluteAddress(set->addressOfState()), TrustedImm32(IsInvalidated))); > } > >-void JIT::emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet* set) >+void JIT::emitPutGlobalVar(uintptr_t operand, int value, WatchpointSet* set) > { > emitGetVirtualRegister(value, regT0); >- emitNotifyWrite(regT0, regT1, set); >+ emitNotifyWrite(set); > storePtr(regT0, reinterpret_cast<void*>(operand)); > } > >-void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value, VariableWatchpointSet* set) >+void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value, WatchpointSet* set) > { > emitGetVirtualRegister(value, regT1); > emitGetVirtualRegister(scope, regT0); >- emitNotifyWrite(regT1, regT2, set); >+ emitNotifyWrite(set); > storePtr(regT1, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register))); > } > >Index: Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >=================================================================== >--- Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (revision 182069) >+++ Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (working copy) >@@ -1384,8 +1384,12 @@ LLINT_SLOW_PATH_DECL(slow_path_put_to_sc > if (modeAndType.type() == LocalClosureVar) { > JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope); > environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value); >- if (VariableWatchpointSet* set = pc[5].u.watchpointSet) >- set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>"); >+ >+ // Have to do this *after* the write, because if this puts the set into IsWatched, then we need >+ // 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>"); > LLINT_END(); > } > >Index: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (revision 182069) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (working copy) >@@ -690,11 +690,8 @@ _llint_op_mov: > dispatch(3) > > >-macro notifyWrite(set, value, scratch, slow) >- loadb VariableWatchpointSet::m_state[set], scratch >- bieq scratch, IsInvalidated, .done >- bqneq value, VariableWatchpointSet::m_inferredValue[set], slow >-.done: >+macro notifyWrite(set, slow) >+ bbneq WatchpointSet::m_state[set], IsInvalidated, slow > end > > _llint_op_not: >@@ -1944,39 +1941,39 @@ _llint_op_resolve_scope: > #rGlobalProperty: > bineq t0, GlobalProperty, .rGlobalVar > getGlobalObject(1) >- dispatch(7) >+ dispatch(6) > > .rGlobalVar: > bineq t0, GlobalVar, .rClosureVar > getGlobalObject(1) >- dispatch(7) >+ dispatch(6) > > .rClosureVar: > bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks > resolveScope() >- dispatch(7) >+ dispatch(6) > > .rGlobalPropertyWithVarInjectionChecks: > bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) > getGlobalObject(1) >- dispatch(7) >+ dispatch(6) > > .rGlobalVarWithVarInjectionChecks: > bineq t0, GlobalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) > getGlobalObject(1) >- dispatch(7) >+ dispatch(6) > > .rClosureVarWithVarInjectionChecks: > bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic > varInjectionCheck(.rDynamic) > resolveScope() >- dispatch(7) >+ dispatch(6) > > .rDynamic: > callSlowPath(_llint_slow_path_resolve_scope) >- dispatch(7) >+ dispatch(6) > > > macro loadWithStructureCheck(operand, slowPath) >@@ -2069,8 +2066,8 @@ macro putGlobalVar() > loadisFromInstruction(3, t0) > loadConstantOrVariable(t0, t1) > loadpFromInstruction(5, t2) >- notifyWrite(t2, t1, t0, .pDynamic) > loadpFromInstruction(6, t0) >+ notifyWrite(t2, .pDynamic) > storeq t1, [t0] > end > >@@ -2086,7 +2083,7 @@ macro putLocalClosureVar() > loadConstantOrVariable(t1, t2) > loadpFromInstruction(5, t3) > btpz t3, .noVariableWatchpointSet >- notifyWrite(t3, t2, t1, .pDynamic) >+ notifyWrite(t3, .pDynamic) > .noVariableWatchpointSet: > loadisFromInstruction(6, t1) > storeq t2, JSEnvironmentRecord_variables[t0, t1, 8] >Index: Source/JavaScriptCore/llint/LowLevelInterpreter.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter.asm (revision 182069) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter.asm (working copy) >@@ -920,12 +920,6 @@ end > > > # Value-representation-agnostic code. >-_llint_op_touch_entry: >- traceExecution() >- callSlowPath(_slow_path_touch_entry) >- dispatch(1) >- >- > _llint_op_create_direct_arguments: > traceExecution() > callSlowPath(_slow_path_create_direct_arguments) >Index: Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (revision 182069) >+++ Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (working copy) >@@ -206,13 +206,6 @@ SLOW_PATH_DECL(slow_path_construct_arity > RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd)); > } > >-SLOW_PATH_DECL(slow_path_touch_entry) >-{ >- BEGIN(); >- exec->codeBlock()->symbolTable()->m_functionEnteredOnce.touch("Function (re)entered"); >- END(); >-} >- > SLOW_PATH_DECL(slow_path_create_direct_arguments) > { > BEGIN(); >Index: Source/JavaScriptCore/runtime/CommonSlowPaths.h >=================================================================== >--- Source/JavaScriptCore/runtime/CommonSlowPaths.h (revision 182069) >+++ Source/JavaScriptCore/runtime/CommonSlowPaths.h (working copy) >@@ -181,7 +181,6 @@ SLOW_PATH_DECL(name) WTF_INTERNAL > > SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck); > SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck); >-SLOW_PATH_HIDDEN_DECL(slow_path_touch_entry); > SLOW_PATH_HIDDEN_DECL(slow_path_create_direct_arguments); > SLOW_PATH_HIDDEN_DECL(slow_path_create_scoped_arguments); > SLOW_PATH_HIDDEN_DECL(slow_path_create_out_of_band_arguments); >Index: Source/JavaScriptCore/runtime/Executable.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/Executable.cpp (revision 182069) >+++ Source/JavaScriptCore/runtime/Executable.cpp (working copy) >@@ -567,6 +567,12 @@ void FunctionExecutable::visitChildren(J > if (thisObject->m_codeBlockForConstruct) > thisObject->m_codeBlockForConstruct->visitAggregate(visitor); > visitor.append(&thisObject->m_unlinkedExecutable); >+ >+ if (thisObject->m_functionReallocationWatchpointSet.needToFinalize()) { >+ if (!thisObject->m_watchpointCleanup) >+ thisObject->m_watchpointCleanup = std::make_unique<WatchpointCleanup>(thisObject); >+ visitor.addUnconditionalFinalizer(thisObject->m_watchpointCleanup.get()); >+ } > } > > SymbolTable* FunctionExecutable::symbolTable(CodeSpecializationKind kind) >@@ -622,6 +628,21 @@ FunctionExecutable* FunctionExecutable:: > return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber); > } > >+FunctionExecutable::WatchpointCleanup::WatchpointCleanup(FunctionExecutable* executable) >+ : m_executable(executable) >+{ >+} >+ >+FunctionExecutable::WatchpointCleanup::~WatchpointCleanup() >+{ >+} >+ >+void FunctionExecutable::WatchpointCleanup::finalizeUnconditionally() >+{ >+ m_executable->functionReallocationWatchpointSet().finalizeUnconditionally( >+ StringFireDetail("FunctionExecutable clean-up during GC")); >+} >+ > void ExecutableBase::dump(PrintStream& out) const > { > ExecutableBase* realThis = const_cast<ExecutableBase*>(this); >Index: Source/JavaScriptCore/runtime/Executable.h >=================================================================== >--- Source/JavaScriptCore/runtime/Executable.h (revision 182069) >+++ Source/JavaScriptCore/runtime/Executable.h (working copy) >@@ -33,8 +33,6 @@ > #include "CompilationResult.h" > #include "DFGPlan.h" > #include "HandlerInfo.h" >-#include "JSFunction.h" >-#include "Interpreter.h" > #include "JITCode.h" > #include "JSGlobalObject.h" > #include "RegisterPreservationMode.h" >@@ -42,6 +40,7 @@ > #include "SourceCode.h" > #include "TypeSet.h" > #include "UnlinkedCodeBlock.h" >+#include "VariableWatchpointSet.h" > > namespace JSC { > >@@ -649,6 +648,8 @@ public: > void unlinkCalls(); > > void clearCode(); >+ >+ VariableWatchpointSet& functionReallocationWatchpointSet() { return m_functionReallocationWatchpointSet; } > > private: > FunctionExecutable( >@@ -667,12 +668,26 @@ private: > } > > friend class ScriptExecutable; >+ >+ class WatchpointCleanup : public UnconditionalFinalizer { >+ public: >+ WatchpointCleanup(FunctionExecutable*); >+ virtual ~WatchpointCleanup(); >+ >+ protected: >+ void finalizeUnconditionally() override; >+ >+ private: >+ FunctionExecutable* m_executable; >+ }; > > WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; > RefPtr<FunctionCodeBlock> m_codeBlockForCall; > RefPtr<FunctionCodeBlock> m_codeBlockForConstruct; > RefPtr<TypeSet> m_returnStatementTypeSet; > unsigned m_parametersStartOffset; >+ VariableWatchpointSet m_functionReallocationWatchpointSet; >+ std::unique_ptr<WatchpointCleanup> m_watchpointCleanup; > }; > > inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) >Index: Source/JavaScriptCore/runtime/JSCInlines.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSCInlines.h (revision 182069) >+++ Source/JavaScriptCore/runtime/JSCInlines.h (working copy) >@@ -51,6 +51,7 @@ > #include "Operations.h" > #include "SlotVisitorInlines.h" > #include "StructureInlines.h" >+#include "VariableWatchpointSetInlines.h" > #include "WeakGCMapInlines.h" > > #endif // JSCInlines_h >Index: Source/JavaScriptCore/runtime/JSFunction.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSFunction.cpp (revision 182069) >+++ Source/JavaScriptCore/runtime/JSFunction.cpp (working copy) >@@ -59,6 +59,14 @@ bool JSFunction::isHostFunctionNonInline > return isHostFunction(); > } > >+JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope) >+{ >+ JSFunction* result = createImpl(vm, executable, scope); >+ executable->functionReallocationWatchpointSet().notifyWrite( >+ vm, executable, result, "Allocating a function"); >+ return result; >+} >+ > JSFunction* JSFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor) > { > NativeExecutable* executable; >Index: Source/JavaScriptCore/runtime/JSFunction.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSFunction.h (revision 182069) >+++ Source/JavaScriptCore/runtime/JSFunction.h (working copy) >@@ -24,6 +24,7 @@ > #ifndef JSFunction_h > #define JSFunction_h > >+#include "Executable.h" > #include "InternalFunction.h" > #include "JSCallee.h" > #include "JSScope.h" >@@ -59,15 +60,15 @@ public: > typedef JSCallee Base; > > JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor); >- >- static JSFunction* create(VM& vm, FunctionExecutable* executable, JSScope* scope) >+ >+ static JSFunction* createWithInvalidatedReallocationWatchpoint(VM& vm, FunctionExecutable* executable, JSScope* scope) > { >- JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope); >- ASSERT(function->structure()->globalObject()); >- function->finishCreation(vm); >- return function; >+ ASSERT(executable->functionReallocationWatchpointSet().hasBeenInvalidated()); >+ return createImpl(vm, executable, scope); > } > >+ static JSFunction* create(VM& vm, FunctionExecutable* executable, JSScope* scope); >+ > static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*); > > static void destroy(JSCell*); >@@ -149,6 +150,14 @@ protected: > static void visitChildren(JSCell*, SlotVisitor&); > > private: >+ static JSFunction* createImpl(VM& vm, FunctionExecutable* executable, JSScope* scope) >+ { >+ JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope); >+ ASSERT(function->structure()->globalObject()); >+ function->finishCreation(vm); >+ return function; >+ } >+ > friend class LLIntOffsetsExtractor; > > static EncodedJSValue argumentsGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName); >Index: Source/JavaScriptCore/runtime/JSGlobalObject.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSGlobalObject.cpp (revision 182069) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.cpp (working copy) >@@ -125,6 +125,7 @@ > #include "SymbolConstructor.h" > #include "SymbolPrototype.h" > #include "VariableWatchpointSetInlines.h" >+#include "VariableWriteFireDetail.h" > #include "WeakGCMapInlines.h" > #include "WeakMapConstructor.h" > #include "WeakMapPrototype.h" >@@ -510,7 +511,7 @@ void JSGlobalObject::addFunction(ExecSta > NewGlobalVar var = addGlobalVar(propertyName, IsVariable); > variableAt(var.offset).set(exec->vm(), this, value); > if (var.set) >- var.set->notifyWrite(vm, value, VariableWriteFireDetail(this, propertyName)); >+ var.set->touch(VariableWriteFireDetail(this, propertyName)); > } > > static inline JSObject* lastInPrototypeChain(JSObject* object) >Index: Source/JavaScriptCore/runtime/JSGlobalObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSGlobalObject.h (revision 182069) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.h (working copy) >@@ -332,7 +332,7 @@ protected: > > struct NewGlobalVar { > ScopeOffset offset; >- VariableWatchpointSet* set; >+ WatchpointSet* set; > }; > NewGlobalVar addGlobalVar(const Identifier&, ConstantMode); > >Index: Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp (revision 182069) >+++ Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp (working copy) >@@ -77,6 +77,7 @@ inline bool JSLexicalEnvironment::symbol > ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); > > WriteBarrierBase<Unknown>* reg; >+ WatchpointSet* set; > { > GCSafeConcurrentJITLocker locker(symbolTable()->m_lock, exec->vm().heap); > SymbolTable::Map::iterator iter = symbolTable()->find(locker, propertyName.uid()); >@@ -92,11 +93,11 @@ inline bool JSLexicalEnvironment::symbol > // Defend against the inspector asking for a var after it has been optimized out. > if (!isValid(offset)) > return false; >- if (VariableWatchpointSet* set = iter->value.watchpointSet()) >- set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it. >+ set = iter->value.watchpointSet(); > reg = &variableAt(offset); > } > reg->set(vm, this, value); >+ set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it. > return true; > } > >Index: Source/JavaScriptCore/runtime/JSScope.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSScope.h (revision 182069) >+++ Source/JavaScriptCore/runtime/JSScope.h (working copy) >@@ -31,7 +31,7 @@ > namespace JSC { > > class ScopeChainIterator; >-class VariableWatchpointSet; >+class WatchpointSet; > > enum ResolveMode { > ThrowIfNotFound, >@@ -102,7 +102,7 @@ inline bool needsVarInjectionChecks(Reso > } > > struct ResolveOp { >- ResolveOp(ResolveType type, size_t depth, Structure* structure, JSLexicalEnvironment* lexicalEnvironment, VariableWatchpointSet* watchpointSet, uintptr_t operand) >+ ResolveOp(ResolveType type, size_t depth, Structure* structure, JSLexicalEnvironment* lexicalEnvironment, WatchpointSet* watchpointSet, uintptr_t operand) > : type(type) > , depth(depth) > , structure(structure) >@@ -116,7 +116,7 @@ struct ResolveOp { > size_t depth; > Structure* structure; > JSLexicalEnvironment* lexicalEnvironment; >- VariableWatchpointSet* watchpointSet; >+ WatchpointSet* watchpointSet; > uintptr_t operand; > }; > >Index: Source/JavaScriptCore/runtime/JSSymbolTableObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSSymbolTableObject.h (revision 182069) >+++ Source/JavaScriptCore/runtime/JSSymbolTableObject.h (working copy) >@@ -32,7 +32,7 @@ > #include "JSScope.h" > #include "PropertyDescriptor.h" > #include "SymbolTable.h" >-#include "VariableWatchpointSetInlines.h" >+#include "VariableWriteFireDetail.h" > > namespace JSC { > >@@ -126,6 +126,7 @@ inline bool symbolTablePut( > ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object)); > > WriteBarrierBase<Unknown>* reg; >+ WatchpointSet* set; > { > SymbolTable& symbolTable = *object->symbolTable(); > // FIXME: This is very suspicious. We shouldn't need a GC-safe lock here. >@@ -142,17 +143,14 @@ inline bool symbolTablePut( > throwTypeError(exec, StrictModeReadonlyPropertyWriteError); > return true; > } >- if (VariableWatchpointSet* set = iter->value.watchpointSet()) { >- // FIXME: It's strange that we're doing this while holding the symbol table's lock. >- // https://bugs.webkit.org/show_bug.cgi?id=134601 >- set->notifyWrite(vm, value, object, propertyName); >- } >+ set = iter->value.watchpointSet(); > reg = &object->variableAt(fastEntry.scopeOffset()); > } > // I'd prefer we not hold lock while executing barriers, since I prefer to reserve > // the right for barriers to be able to trigger GC. And I don't want to hold VM > // locks while GC'ing. > reg->set(vm, object, value); >+ set->touch(VariableWriteFireDetail(object, propertyName)); > return true; > } > >@@ -164,6 +162,7 @@ inline bool symbolTablePutWithAttributes > ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object)); > > WriteBarrierBase<Unknown>* reg; >+ WatchpointSet* set; > { > SymbolTable& symbolTable = *object->symbolTable(); > ConcurrentJITLocker locker(symbolTable.m_lock); >@@ -172,12 +171,12 @@ inline bool symbolTablePutWithAttributes > return false; > SymbolTableEntry& entry = iter->value; > ASSERT(!entry.isNull()); >- if (VariableWatchpointSet* set = entry.watchpointSet()) >- set->notifyWrite(vm, value, object, propertyName); >+ set = entry.watchpointSet(); > entry.setAttributes(attributes); > reg = &object->variableAt(entry.scopeOffset()); > } > reg->set(vm, object, value); >+ set->touch(VariableWriteFireDetail(object, propertyName)); > return true; > } > >Index: Source/JavaScriptCore/runtime/PutPropertySlot.h >=================================================================== >--- Source/JavaScriptCore/runtime/PutPropertySlot.h (revision 182069) >+++ Source/JavaScriptCore/runtime/PutPropertySlot.h (working copy) >@@ -28,6 +28,7 @@ > #define PutPropertySlot_h > > #include "JSCJSValue.h" >+#include "PropertyOffset.h" > > #include <wtf/Assertions.h> > >Index: Source/JavaScriptCore/runtime/SymbolTable.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.cpp (revision 182069) >+++ Source/JavaScriptCore/runtime/SymbolTable.cpp (working copy) >@@ -33,7 +33,6 @@ > #include "JSCInlines.h" > #include "SlotVisitorInlines.h" > #include "TypeProfiler.h" >-#include "VariableWatchpointSetInlines.h" > > namespace JSC { > >@@ -60,13 +59,6 @@ void SymbolTableEntry::freeFatEntrySlow( > delete fatEntry(); > } > >-JSValue SymbolTableEntry::inferredValue() >-{ >- if (!isFat()) >- return JSValue(); >- return fatEntry()->m_watchpoints->inferredValue(); >-} >- > void SymbolTableEntry::prepareToWatch(SymbolTable* symbolTable) > { > if (!isWatchable()) >@@ -74,7 +66,7 @@ void SymbolTableEntry::prepareToWatch(Sy > FatEntry* entry = inflate(); > if (entry->m_watchpoints) > return; >- entry->m_watchpoints = adoptRef(new VariableWatchpointSet(*symbolTable)); >+ entry->m_watchpoints = adoptRef(new WatchpointSet(ClearWatchpoint)); > } > > void SymbolTableEntry::addWatchpoint(Watchpoint* watchpoint) >@@ -82,15 +74,6 @@ void SymbolTableEntry::addWatchpoint(Wat > fatEntry()->m_watchpoints->add(watchpoint); > } > >-void SymbolTableEntry::notifyWriteSlow(VM& vm, JSValue value, const FireDetail& detail) >-{ >- VariableWatchpointSet* watchpoints = fatEntry()->m_watchpoints.get(); >- if (!watchpoints) >- return; >- >- watchpoints->notifyWrite(vm, value, detail); >-} >- > SymbolTableEntry::FatEntry* SymbolTableEntry::inflateSlow() > { > FatEntry* entry = new FatEntry(m_bits); >@@ -101,7 +84,6 @@ SymbolTableEntry::FatEntry* SymbolTableE > SymbolTable::SymbolTable(VM& vm) > : JSCell(vm, vm.symbolTableStructure.get()) > , m_usesNonStrictEval(false) >- , m_functionEnteredOnce(ClearWatchpoint) > { > } > >@@ -113,36 +95,11 @@ void SymbolTable::visitChildren(JSCell* > > visitor.append(&thisSymbolTable->m_arguments); > >- if (!thisSymbolTable->m_watchpointCleanup) { >- thisSymbolTable->m_watchpointCleanup = >- std::make_unique<WatchpointCleanup>(thisSymbolTable); >- } >- >- visitor.addUnconditionalFinalizer(thisSymbolTable->m_watchpointCleanup.get()); >- > // Save some memory. This is O(n) to rebuild and we do so on the fly. > ConcurrentJITLocker locker(thisSymbolTable->m_lock); > thisSymbolTable->m_localToEntry = nullptr; > } > >-SymbolTable::WatchpointCleanup::WatchpointCleanup(SymbolTable* symbolTable) >- : m_symbolTable(symbolTable) >-{ >-} >- >-SymbolTable::WatchpointCleanup::~WatchpointCleanup() { } >- >-void SymbolTable::WatchpointCleanup::finalizeUnconditionally() >-{ >- StringFireDetail detail("Symbol table clean-up during GC"); >- Map::iterator iter = m_symbolTable->m_map.begin(); >- Map::iterator end = m_symbolTable->m_map.end(); >- for (; iter != end; ++iter) { >- if (VariableWatchpointSet* set = iter->value.watchpointSet()) >- set->finalizeUnconditionally(detail); >- } >-} >- > const SymbolTable::LocalToEntryVec& SymbolTable::localToEntry(const ConcurrentJITLocker&) > { > if (UNLIKELY(!m_localToEntry)) { >Index: Source/JavaScriptCore/runtime/SymbolTable.h >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.h (revision 182069) >+++ Source/JavaScriptCore/runtime/SymbolTable.h (working copy) >@@ -35,13 +35,15 @@ > #include "ScopedArgumentsTable.h" > #include "TypeLocation.h" > #include "VarOffset.h" >-#include "VariableWatchpointSet.h" >+#include "Watchpoint.h" > #include <memory> > #include <wtf/HashTraits.h> > #include <wtf/text/StringImpl.h> > > namespace JSC { > >+class SymbolTable; >+ > static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); } > > // The bit twiddling in this class assumes that every register index is a >@@ -63,11 +65,11 @@ static ALWAYS_INLINE int missingSymbolMa > // counted pointer to a shared WatchpointSet. Thus, in-place edits of the > // WatchpointSet will manifest in all copies. Here's a picture: > // >-// SymbolTableEntry --> FatEntry --> VariableWatchpointSet >+// SymbolTableEntry --> FatEntry --> WatchpointSet > // > // If you make a copy of a SymbolTableEntry, you will have: > // >-// original: SymbolTableEntry --> FatEntry --> VariableWatchpointSet >+// original: SymbolTableEntry --> FatEntry --> WatchpointSet > // copy: SymbolTableEntry --> FatEntry -----^ > > struct SymbolTableEntry { >@@ -260,10 +262,10 @@ public: > return bits() & DontEnumFlag; > } > >- JSValue inferredValue(); >- > void disableWatching() > { >+ if (WatchpointSet* set = watchpointSet()) >+ set->invalidate("Disabling watching in symbol table"); > if (varOffset().isScope()) > pack(varOffset(), false, isReadOnly(), isDontEnum()); > } >@@ -272,20 +274,13 @@ public: > > void addWatchpoint(Watchpoint*); > >- VariableWatchpointSet* watchpointSet() >+ WatchpointSet* watchpointSet() > { > if (!isFat()) > return 0; > return fatEntry()->m_watchpoints.get(); > } > >- ALWAYS_INLINE void notifyWrite(VM& vm, JSValue value, const FireDetail& detail) >- { >- if (LIKELY(!isFat())) >- return; >- notifyWriteSlow(vm, value, detail); >- } >- > private: > static const intptr_t SlimFlag = 0x1; > static const intptr_t ReadOnlyFlag = 0x2; >@@ -308,7 +303,7 @@ private: > > intptr_t m_bits; // always has FatFlag set and exactly matches what the bits would have been if this wasn't fat. > >- RefPtr<VariableWatchpointSet> m_watchpoints; >+ RefPtr<WatchpointSet> m_watchpoints; > }; > > SymbolTableEntry& copySlow(const SymbolTableEntry&); >@@ -646,18 +641,6 @@ protected: > static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags; > > private: >- class WatchpointCleanup : public UnconditionalFinalizer { >- public: >- WatchpointCleanup(SymbolTable*); >- virtual ~WatchpointCleanup(); >- >- protected: >- virtual void finalizeUnconditionally() override; >- >- private: >- SymbolTable* m_symbolTable; >- }; >- > JS_EXPORT_PRIVATE SymbolTable(VM&); > ~SymbolTable(); > >@@ -675,12 +658,9 @@ private: > > WriteBarrier<ScopedArgumentsTable> m_arguments; > >- std::unique_ptr<WatchpointCleanup> m_watchpointCleanup; > std::unique_ptr<LocalToEntryVec> m_localToEntry; > > public: >- InlineWatchpointSet m_functionEnteredOnce; >- > mutable ConcurrentJITLock m_lock; > }; > >Index: Source/JavaScriptCore/runtime/TypeProfiler.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/TypeProfiler.cpp (revision 182069) >+++ Source/JavaScriptCore/runtime/TypeProfiler.cpp (working copy) >@@ -28,6 +28,7 @@ > > #include "InspectorProtocolObjects.h" > #include "TypeLocation.h" >+#include <wtf/text/StringBuilder.h> > > namespace JSC { >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 143232
:
249753
|
249774
|
249840
|
249844
|
249865
|
250317
|
250327
|
250331
|
250374
|
250384
|
250392
|
250407