WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
fix some builds
blah.patch (text/plain), 163.53 KB, created by
Filip Pizlo
on 2015-04-08 14:14:57 PDT
(
hide
)
Description:
fix some builds
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2015-04-08 14:14:57 PDT
Size:
163.53 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 182559) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,257 @@ >+2015-04-08 Filip Pizlo <fpizlo@apple.com> >+ >+ JSC should detect singleton functions >+ https://bugs.webkit.org/show_bug.cgi?id=143232 >+ >+ Reviewed by NOBODY (OOPS!!). >+ >+ This started out as an attempt to make constructors faster by detecting when a constructor is a >+ singleton. The idea is that each FunctionExecutable has a VariableWatchpointSet - a watchpoint >+ along with an inferred value - that detects if only one JSFunction has been allocated for that >+ executable, and if so, what that JSFunction is. Then, inside the code for the FunctionExecutable, >+ if the watchpoint set has an inferred value (i.e. it's been initialized and it is still valid), >+ we can constant-fold GetCallee. >+ >+ Unfortunately, constructors don't use GetCallee anymore, so that didn't pan out. But in the >+ process I realized a bunch of things: >+ >+ - This allows us to completely eliminate the GetCallee/GetScope sequence that we still sometimes >+ had even in code where our singleton-closure detection worked. That's because singleton-closure >+ inference worked at the op_resolve_scope, and that op_resolve_scope still needed to keep alive >+ the incoming scope in case we OSR exit. But by constant-folding GetCallee, that sequence >+ disappears. OSR exit can rematerialize the callee or the scope by just knowing their constant >+ values. >+ >+ - Singleton detection should be a reusable thing. So, I got rid of VariableWatchpointSet and >+ created InferredValue. InferredValue is a cell, so it can handle its own GC magic. >+ FunctionExecutable uses an InferredValue to tell you about singleton JSFunctions. >+ >+ - The old singleton-scope detection in op_resolve_scope is better abstracted as a SymbolTable >+ detecting a singleton JSSymbolTableObject. So, SymbolTable uses an InferredValue to tell you >+ about singleton JSSymbolTableObjects. It's curious that we want to have singleton detection in >+ SymbolTable if we already have it in FunctionExecutable. This comes into play in two ways. >+ First, it means that the DFG can realize sooner that a resolve_scope resolves to a constant >+ scope. Ths saves compile times and it allows prediction propagation to benefit from the >+ constant folding. Second, it means that we will detect a singlton scope even if it is >+ referenced from a non-singleton scope that is nearer to us in the scope chain. This refactoring >+ allows us to eliminate the function reentry watchpoint. >+ >+ - This allows us to use a normal WatchpointSet, instead of a VariableWatchpointSet, for inferring >+ constant values in scopes. Previously when the DFG inferred that a closure variable was >+ constant, it wouldn't know which closure that variable was in and so it couldn't just load that >+ value. But now we are first inferring that the function is a singleton, which means that we >+ know exactly what scope it points to, and we can load the value from the scope. Using a >+ WatchpointSet instead of a VariableWatchpointSet saves some memory and simplifies a bunch of >+ code. This also means that now, the only user of VariableWatchpointSet is FunctionExecutable. >+ I've tweaked the code of VariableWatchpointSet to reduce its power to just be what >+ FunctionExecutable wants. >+ >+ This also has the effect of simplifying the implementation of block scoping. Prior to this >+ change, block scoping would had had to have some story for the function reentry watchpoint on any >+ nested symbol table. That's totally weird to think about; it's not really a function reentry but >+ a scope reentry. Now we don't have to think about this. Constant inference on nested scopes will >+ "just work": if we prove that we know the constant value of the scope then the machinery kicks >+ in, otherwise it doesn't. >+ >+ This is a small Octane and AsmBench speed-up. AsmBench sees 1% while Octane sees sub-1%. >+ >+ * CMakeLists.txt: >+ * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * bytecode/BytecodeList.json: >+ * bytecode/BytecodeUseDef.h: >+ (JSC::computeUsesForBytecodeOffset): >+ (JSC::computeDefsForBytecodeOffset): >+ * bytecode/CodeBlock.cpp: >+ (JSC::CodeBlock::dumpBytecode): >+ (JSC::CodeBlock::CodeBlock): >+ (JSC::CodeBlock::finalizeUnconditionally): >+ (JSC::CodeBlock::valueProfileForBytecodeOffset): >+ * bytecode/CodeBlock.h: >+ (JSC::CodeBlock::valueProfileForBytecodeOffset): Deleted. >+ * bytecode/CodeOrigin.cpp: >+ (JSC::InlineCallFrame::calleeConstant): >+ (JSC::InlineCallFrame::visitAggregate): >+ * bytecode/CodeOrigin.h: >+ (JSC::InlineCallFrame::calleeConstant): Deleted. >+ (JSC::InlineCallFrame::visitAggregate): Deleted. >+ * bytecode/Instruction.h: >+ * bytecode/VariableWatchpointSet.cpp: Removed. >+ * bytecode/VariableWatchpointSet.h: Removed. >+ * bytecode/VariableWatchpointSetInlines.h: Removed. >+ * bytecode/VariableWriteFireDetail.cpp: Added. >+ (JSC::VariableWriteFireDetail::dump): >+ (JSC::VariableWriteFireDetail::touch): >+ * bytecode/VariableWriteFireDetail.h: Added. >+ (JSC::VariableWriteFireDetail::VariableWriteFireDetail): >+ * bytecode/Watchpoint.h: >+ (JSC::WatchpointSet::stateOnMainThread): >+ (JSC::WatchpointSet::startWatching): >+ (JSC::WatchpointSet::fireAll): >+ (JSC::WatchpointSet::touch): >+ (JSC::WatchpointSet::invalidate): >+ (JSC::InlineWatchpointSet::stateOnMainThread): >+ (JSC::InlineWatchpointSet::state): >+ (JSC::InlineWatchpointSet::hasBeenInvalidated): >+ (JSC::InlineWatchpointSet::invalidate): >+ (JSC::InlineWatchpointSet::touch): >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::BytecodeGenerator): >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::get): >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ (JSC::DFG::ByteCodeParser::getScope): Deleted. >+ * dfg/DFGCapabilities.cpp: >+ (JSC::DFG::capabilityLevel): >+ * dfg/DFGClobberize.h: >+ (JSC::DFG::clobberize): >+ * dfg/DFGDesiredWatchpoints.cpp: >+ (JSC::DFG::InferredValueAdaptor::add): >+ (JSC::DFG::DesiredWatchpoints::addLazily): >+ (JSC::DFG::DesiredWatchpoints::reallyAdd): >+ (JSC::DFG::DesiredWatchpoints::areStillValid): >+ * dfg/DFGDesiredWatchpoints.h: >+ (JSC::DFG::InferredValueAdaptor::hasBeenInvalidated): >+ (JSC::DFG::DesiredWatchpoints::isWatched): >+ * dfg/DFGGraph.cpp: >+ (JSC::DFG::Graph::dump): >+ (JSC::DFG::Graph::tryGetConstantClosureVar): >+ * dfg/DFGNode.h: >+ (JSC::DFG::Node::hasWatchpointSet): >+ (JSC::DFG::Node::watchpointSet): >+ (JSC::DFG::Node::hasVariableWatchpointSet): Deleted. >+ (JSC::DFG::Node::variableWatchpointSet): Deleted. >+ * dfg/DFGOperations.cpp: >+ * dfg/DFGOperations.h: >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::compileNewFunction): >+ (JSC::DFG::SpeculativeJIT::compileCreateActivation): >+ (JSC::DFG::SpeculativeJIT::compileNotifyWrite): >+ * dfg/DFGSpeculativeJIT.h: >+ (JSC::DFG::SpeculativeJIT::callOperation): >+ * dfg/DFGSpeculativeJIT32_64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGVarargsForwardingPhase.cpp: >+ * ftl/FTLIntrinsicRepository.h: >+ * ftl/FTLLowerDFGToLLVM.cpp: >+ (JSC::FTL::LowerDFGToLLVM::compileCreateActivation): >+ (JSC::FTL::LowerDFGToLLVM::compileNewFunction): >+ (JSC::FTL::LowerDFGToLLVM::compileNotifyWrite): >+ * interpreter/Interpreter.cpp: >+ (JSC::StackFrame::friendlySourceURL): >+ (JSC::StackFrame::friendlyFunctionName): >+ * interpreter/Interpreter.h: >+ (JSC::StackFrame::friendlySourceURL): Deleted. >+ (JSC::StackFrame::friendlyFunctionName): Deleted. >+ * jit/JIT.cpp: >+ (JSC::JIT::emitNotifyWrite): >+ (JSC::JIT::privateCompileMainPass): >+ * jit/JIT.h: >+ * jit/JITOpcodes.cpp: >+ (JSC::JIT::emit_op_touch_entry): Deleted. >+ * jit/JITOperations.cpp: >+ * jit/JITOperations.h: >+ * jit/JITPropertyAccess.cpp: >+ (JSC::JIT::emitPutGlobalVar): >+ (JSC::JIT::emitPutClosureVar): >+ (JSC::JIT::emitNotifyWrite): Deleted. >+ * jit/JITPropertyAccess32_64.cpp: >+ (JSC::JIT::emitPutGlobalVar): >+ (JSC::JIT::emitPutClosureVar): >+ (JSC::JIT::emitNotifyWrite): Deleted. >+ * llint/LLIntSlowPaths.cpp: >+ (JSC::LLInt::LLINT_SLOW_PATH_DECL): >+ * llint/LowLevelInterpreter.asm: >+ * llint/LowLevelInterpreter32_64.asm: >+ * llint/LowLevelInterpreter64.asm: >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::SLOW_PATH_DECL): Deleted. >+ * runtime/CommonSlowPaths.h: >+ * runtime/Executable.cpp: >+ (JSC::FunctionExecutable::finishCreation): >+ (JSC::FunctionExecutable::visitChildren): >+ * runtime/Executable.h: >+ (JSC::FunctionExecutable::singletonFunction): >+ * runtime/InferredValue.cpp: Added. >+ (JSC::InferredValue::create): >+ (JSC::InferredValue::destroy): >+ (JSC::InferredValue::createStructure): >+ (JSC::InferredValue::visitChildren): >+ (JSC::InferredValue::InferredValue): >+ (JSC::InferredValue::~InferredValue): >+ (JSC::InferredValue::notifyWriteSlow): >+ (JSC::InferredValue::ValueCleanup::ValueCleanup): >+ (JSC::InferredValue::ValueCleanup::~ValueCleanup): >+ (JSC::InferredValue::ValueCleanup::finalizeUnconditionally): >+ * runtime/InferredValue.h: Added. >+ (JSC::InferredValue::inferredValue): >+ (JSC::InferredValue::state): >+ (JSC::InferredValue::isStillValid): >+ (JSC::InferredValue::hasBeenInvalidated): >+ (JSC::InferredValue::add): >+ (JSC::InferredValue::notifyWrite): >+ (JSC::InferredValue::invalidate): >+ * runtime/JSEnvironmentRecord.cpp: >+ (JSC::JSEnvironmentRecord::visitChildren): >+ * runtime/JSEnvironmentRecord.h: >+ (JSC::JSEnvironmentRecord::isValid): >+ (JSC::JSEnvironmentRecord::finishCreation): >+ * runtime/JSFunction.cpp: >+ (JSC::JSFunction::create): >+ * runtime/JSFunction.h: >+ (JSC::JSFunction::createWithInvalidatedReallocationWatchpoint): >+ (JSC::JSFunction::createImpl): >+ (JSC::JSFunction::create): Deleted. >+ * runtime/JSGlobalObject.cpp: >+ (JSC::JSGlobalObject::addGlobalVar): >+ (JSC::JSGlobalObject::addFunction): >+ * runtime/JSGlobalObject.h: >+ * runtime/JSLexicalEnvironment.cpp: >+ (JSC::JSLexicalEnvironment::symbolTablePut): >+ * runtime/JSScope.h: >+ (JSC::ResolveOp::ResolveOp): >+ * runtime/JSSegmentedVariableObject.h: >+ (JSC::JSSegmentedVariableObject::finishCreation): >+ * runtime/JSSymbolTableObject.h: >+ (JSC::JSSymbolTableObject::JSSymbolTableObject): >+ (JSC::JSSymbolTableObject::setSymbolTable): >+ (JSC::symbolTablePut): >+ (JSC::symbolTablePutWithAttributes): >+ * runtime/PutPropertySlot.h: >+ * runtime/SymbolTable.cpp: >+ (JSC::SymbolTableEntry::prepareToWatch): >+ (JSC::SymbolTable::SymbolTable): >+ (JSC::SymbolTable::finishCreation): >+ (JSC::SymbolTable::visitChildren): >+ (JSC::SymbolTableEntry::inferredValue): Deleted. >+ (JSC::SymbolTableEntry::notifyWriteSlow): Deleted. >+ (JSC::SymbolTable::WatchpointCleanup::WatchpointCleanup): Deleted. >+ (JSC::SymbolTable::WatchpointCleanup::~WatchpointCleanup): Deleted. >+ (JSC::SymbolTable::WatchpointCleanup::finalizeUnconditionally): Deleted. >+ * runtime/SymbolTable.h: >+ (JSC::SymbolTableEntry::disableWatching): >+ (JSC::SymbolTableEntry::watchpointSet): >+ (JSC::SymbolTable::singletonScope): >+ (JSC::SymbolTableEntry::notifyWrite): Deleted. >+ * runtime/TypeProfiler.cpp: >+ * runtime/VM.cpp: >+ (JSC::VM::VM): >+ * runtime/VM.h: >+ * tests/stress/infer-uninitialized-closure-var.js: Added. >+ (foo.f): >+ (foo): >+ * tests/stress/singleton-scope-then-overwrite.js: Added. >+ (foo.f): >+ (foo): >+ * tests/stress/singleton-scope-then-realloc-and-overwrite.js: Added. >+ (foo): >+ * tests/stress/singleton-scope-then-realloc.js: Added. >+ (foo): >+ > 2015-04-07 Michael Saboff <msaboff@apple.com> > > Lazily initialize LogToSystemConsole flag to reduce memory usage >Index: Source/JavaScriptCore/CMakeLists.txt >=================================================================== >--- Source/JavaScriptCore/CMakeLists.txt (revision 182498) >+++ Source/JavaScriptCore/CMakeLists.txt (working copy) >@@ -105,7 +105,7 @@ set(JavaScriptCore_SOURCES > bytecode/UnlinkedCodeBlock.cpp > bytecode/UnlinkedInstructionStream.cpp > bytecode/ValueRecovery.cpp >- bytecode/VariableWatchpointSet.cpp >+ bytecode/VariableWriteFireDetail.cpp > bytecode/VirtualRegister.cpp > bytecode/Watchpoint.cpp > >@@ -452,6 +452,7 @@ set(JavaScriptCore_RUNTIME_SOURCES > runtime/GetterSetter.cpp > runtime/Identifier.cpp > runtime/IndexingType.cpp >+ runtime/InferredValue.cpp > runtime/InitializeThreading.cpp > runtime/IntendedStructureChain.cpp > runtime/InternalFunction.cpp >Index: Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (revision 182498) >+++ Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (working copy) >@@ -352,7 +352,7 @@ > <ClCompile Include="..\bytecode\UnlinkedCodeBlock.cpp" /> > <ClCompile Include="..\bytecode\UnlinkedInstructionStream.cpp" /> > <ClCompile Include="..\bytecode\ValueRecovery.cpp" /> >- <ClCompile Include="..\bytecode\VariableWatchpointSet.cpp" /> >+ <ClCompile Include="..\bytecode\VariableWriteFireDetail.cpp" /> > <ClCompile Include="..\bytecode\VirtualRegister.cpp" /> > <ClCompile Include="..\bytecode\Watchpoint.cpp" /> > <ClCompile Include="..\bytecompiler\BytecodeGenerator.cpp" /> >@@ -720,6 +720,7 @@ > <ClCompile Include="..\runtime\GetterSetter.cpp" /> > <ClCompile Include="..\runtime\Identifier.cpp" /> > <ClCompile Include="..\runtime\IndexingType.cpp" /> >+ <ClCompile Include="..\runtime\InferredValue.cpp" /> > <ClCompile Include="..\runtime\InitializeThreading.cpp" /> > <ClCompile Include="..\runtime\IntendedStructureChain.cpp" /> > <ClCompile Include="..\runtime\InternalFunction.cpp" /> >@@ -1004,7 +1005,7 @@ > <ClInclude Include="..\bytecode\UnlinkedInstructionStream.h" /> > <ClInclude Include="..\bytecode\ValueProfile.h" /> > <ClInclude Include="..\bytecode\ValueRecovery.h" /> >- <ClInclude Include="..\bytecode\VariableWatchpointSet.h" /> >+ <ClInclude Include="..\bytecode\VariableWriteFireDetail.h" /> > <ClInclude Include="..\bytecode\VirtualRegister.h" /> > <ClInclude Include="..\bytecode\Watchpoint.h" /> > <ClInclude Include="..\bytecompiler\BytecodeGenerator.h" /> >@@ -1507,6 +1508,7 @@ > <ClInclude Include="..\runtime\IndexingHeader.h" /> > <ClInclude Include="..\runtime\IndexingHeaderInlines.h" /> > <ClInclude Include="..\runtime\IndexingType.h" /> >+ <ClInclude Include="..\runtime\InferredValue.h" /> > <ClInclude Include="..\runtime\InitializeThreading.h" /> > <ClInclude Include="..\runtime\Int16Array.h" /> > <ClInclude Include="..\runtime\Int32Array.h" /> >Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 182498) >+++ 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, ); }; }; >@@ -425,7 +427,6 @@ > 0F8F94421667633500D61971 /* CodeType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F943F1667632D00D61971 /* CodeType.cpp */; }; > 0F8F94441667635400D61971 /* JITCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F94431667635200D61971 /* JITCode.cpp */; }; > 0F8F9446166764F100D61971 /* CodeOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F9445166764EE00D61971 /* CodeOrigin.cpp */; }; >- 0F9181C718415CA50057B669 /* VariableWatchpointSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */; }; > 0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */; }; >@@ -550,7 +551,6 @@ > 0FC97F4018202119002C9B26 /* DFGJumpReplacement.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F3A18202119002C9B26 /* DFGJumpReplacement.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FC97F4118202119002C9B26 /* DFGWatchpointCollectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3B18202119002C9B26 /* DFGWatchpointCollectionPhase.cpp */; }; > 0FC97F4218202119002C9B26 /* DFGWatchpointCollectionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F3C18202119002C9B26 /* DFGWatchpointCollectionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 0FCA9113195E66A000426438 /* VariableWatchpointSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */; }; > 0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; }; > 0FCEFAAC1804C13E00472CE4 /* FTLSaveRestore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -719,6 +719,8 @@ > 0FF729BE166AD360000F5BA3 /* ProfilerExecutionCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF7299E166AD347000F5BA3 /* ProfilerExecutionCounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FF729BF166AD360000F5BA3 /* ProfilerOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF729A0166AD347000F5BA3 /* ProfilerOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FF729C0166AD360000F5BA3 /* ProfilerOriginStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF729A2166AD347000F5BA3 /* ProfilerOriginStack.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */; }; >+ 0FF8BDEB1AD4CF7100DFE884 /* InferredValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; }; > 0FFA549716B8835000B3A982 /* A64DOpcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 652A3A221651C69700A80AFE /* A64DOpcode.cpp */; }; > 0FFA549816B8835300B3A982 /* A64DOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 652A3A231651C69700A80AFE /* A64DOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -1644,7 +1646,6 @@ > FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */; settings = {ATTRIBUTES = (Private, ); }; }; > FE4A331F15BD2E07006F54F3 /* VMInspector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */; }; > FE4A332015BD2E07006F54F3 /* VMInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4A331E15BD2E07006F54F3 /* VMInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- FE5248F9191442D900B7FDE4 /* VariableWatchpointSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; > FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; }; > FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */; settings = {ATTRIBUTES = (Private, ); }; }; > FE7BA60F1A1A7CEC00F1F7B4 /* HeapVerifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */; }; >@@ -2100,6 +2101,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>"; }; >@@ -2140,7 +2143,6 @@ > 0F8F943F1667632D00D61971 /* CodeType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeType.cpp; sourceTree = "<group>"; }; > 0F8F94431667635200D61971 /* JITCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITCode.cpp; sourceTree = "<group>"; }; > 0F8F9445166764EE00D61971 /* CodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeOrigin.cpp; sourceTree = "<group>"; }; >- 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableWatchpointSet.h; sourceTree = "<group>"; }; > 0F919D09157EE09D004A4E7D /* JSSymbolTableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSymbolTableObject.cpp; sourceTree = "<group>"; }; > 0F919D0A157EE09D004A4E7D /* JSSymbolTableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSymbolTableObject.h; sourceTree = "<group>"; }; > 0F919D0E157F3327004A4E7D /* JSSegmentedVariableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSegmentedVariableObject.cpp; sourceTree = "<group>"; }; >@@ -2276,7 +2278,6 @@ > 0FC97F3A18202119002C9B26 /* DFGJumpReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGJumpReplacement.h; path = dfg/DFGJumpReplacement.h; sourceTree = "<group>"; }; > 0FC97F3B18202119002C9B26 /* DFGWatchpointCollectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGWatchpointCollectionPhase.cpp; path = dfg/DFGWatchpointCollectionPhase.cpp; sourceTree = "<group>"; }; > 0FC97F3C18202119002C9B26 /* DFGWatchpointCollectionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGWatchpointCollectionPhase.h; path = dfg/DFGWatchpointCollectionPhase.h; sourceTree = "<group>"; }; >- 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableWatchpointSet.cpp; sourceTree = "<group>"; }; > 0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitorInlines.h; sourceTree = "<group>"; }; > 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParserError.h; sourceTree = "<group>"; }; > 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSaveRestore.cpp; path = ftl/FTLSaveRestore.cpp; sourceTree = "<group>"; }; >@@ -2441,6 +2442,8 @@ > 0FF729A0166AD347000F5BA3 /* ProfilerOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOrigin.h; path = profiler/ProfilerOrigin.h; sourceTree = "<group>"; }; > 0FF729A1166AD347000F5BA3 /* ProfilerOriginStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerOriginStack.cpp; path = profiler/ProfilerOriginStack.cpp; sourceTree = "<group>"; }; > 0FF729A2166AD347000F5BA3 /* ProfilerOriginStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOriginStack.h; path = profiler/ProfilerOriginStack.h; sourceTree = "<group>"; }; >+ 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredValue.cpp; sourceTree = "<group>"; }; >+ 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredValue.h; sourceTree = "<group>"; }; > 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; }; > 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; }; > 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; }; >@@ -3421,7 +3424,6 @@ > FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCLoop.h; path = llint/LLIntCLoop.h; sourceTree = "<group>"; }; > FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMInspector.cpp; sourceTree = "<group>"; }; > FE4A331E15BD2E07006F54F3 /* VMInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInspector.h; sourceTree = "<group>"; }; >- FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableWatchpointSetInlines.h; sourceTree = "<group>"; }; > FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; }; > FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMEntryScope.h; sourceTree = "<group>"; }; > FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapVerifier.cpp; sourceTree = "<group>"; }; >@@ -4409,6 +4411,8 @@ > 0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */, > 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */, > 0FB7F38F15ED8E3800F167B2 /* IndexingType.h */, >+ 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */, >+ 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */, > E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */, > E178633F0D9BEC0000D74E75 /* InitializeThreading.h */, > A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */, >@@ -5277,9 +5281,8 @@ > 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */, > 0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */, > 0F426A451460CBAB00131F8F /* ValueRecovery.h */, >- 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */, >- 0F9181C618415CA50057B669 /* VariableWatchpointSet.h */, >- FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */, >+ 0F6C734E1AC9F99F00BE1682 /* VariableWriteFireDetail.cpp */, >+ 0F6C734F1AC9F99F00BE1682 /* VariableWriteFireDetail.h */, > 0F20C2581A8013AB00DA3229 /* VirtualRegister.cpp */, > 0F426A461460CBAB00131F8F /* VirtualRegister.h */, > 0F919D2215853CDE004A4E7D /* Watchpoint.cpp */, >@@ -5565,7 +5568,6 @@ > C4F4B6F51A05C984005CAB76 /* generate_objc_protocol_types_implementation.py in Headers */, > A584032018BFFBE1005A0811 /* InspectorAgent.h in Headers */, > 2AABCDE718EF294200002096 /* GCLogging.h in Headers */, >- FE5248F9191442D900B7FDE4 /* VariableWatchpointSetInlines.h in Headers */, > FE7BA6101A1A7CEC00F1F7B4 /* HeapVerifier.h in Headers */, > A5EF9B141A1D43F600702E90 /* generate_cpp_backend_dispatcher_header.py in Headers */, > C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */, >@@ -6347,6 +6349,7 @@ > A790DD6E182F499700588807 /* SetIteratorPrototype.h in Headers */, > A7299DA217D12848005F5FF9 /* SetPrototype.h in Headers */, > 86AE64AA135E5E1C00963012 /* SH4Assembler.h in Headers */, >+ 0FF8BDEB1AD4CF7100DFE884 /* InferredValue.h in Headers */, > 0F2B670517B6B5AB00A7AE3F /* SimpleTypedArrayController.h in Headers */, > 14BA78F113AAB88F005B7C2C /* SlotVisitor.h in Headers */, > 0FB17661196B8F9E0091052A /* DFGHeapLocation.h in Headers */, >@@ -6354,6 +6357,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 */, >@@ -6421,7 +6425,6 @@ > 0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */, > 0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */, > 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */, >- 0F9181C718415CA50057B669 /* VariableWatchpointSet.h in Headers */, > 0F9C5E5F18E35F5E00D431C3 /* FTLDWARFRegister.h in Headers */, > 0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */, > BC18C4200E16F5CD00B34460 /* VM.h in Headers */, >@@ -6963,6 +6966,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 */, >@@ -7027,7 +7031,6 @@ > C2981FD817BAEE4B00A3BC98 /* DFGDesiredWeakReferences.cpp in Sources */, > C2981FDC17BAFF4400A3BC98 /* DFGDesiredWriteBarriers.cpp in Sources */, > 0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */, >- 0FCA9113195E66A000426438 /* VariableWatchpointSet.cpp in Sources */, > 0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */, > 0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */, > 0F2B9CE219D0BA7D00B1D1B5 /* DFGAvailabilityMap.cpp in Sources */, >@@ -7331,6 +7334,7 @@ > 0F2B66FE17B6B5AB00A7AE3F /* JSTypedArrays.cpp in Sources */, > 0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */, > 86E3C61A167BABEE006D760A /* JSValue.mm in Sources */, >+ 0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */, > 14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */, > 147F39D7107EC37600427A48 /* JSEnvironmentRecord.cpp in Sources */, > 86E3C61C167BABEE006D760A /* JSVirtualMachine.mm in Sources */, >Index: Source/JavaScriptCore/bytecode/BytecodeList.json >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeList.json (revision 182498) >+++ 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 }, >Index: Source/JavaScriptCore/bytecode/BytecodeUseDef.h >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeUseDef.h (revision 182498) >+++ 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 182498) >+++ Source/JavaScriptCore/bytecode/CodeBlock.cpp (working copy) >@@ -758,10 +758,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; >@@ -1957,7 +1953,7 @@ CodeBlock::CodeBlock(ScriptExecutable* o > 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); >+ instructions[i + 6].u.symbolTable.set(*vm(), ownerExecutable, op.lexicalEnvironment->symbolTable()); > break; > } > >@@ -1985,7 +1981,6 @@ CodeBlock::CodeBlock(ScriptExecutable* o > else if (op.structure) > instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure); > instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand); >- > break; > } > >@@ -2001,7 +1996,7 @@ CodeBlock::CodeBlock(ScriptExecutable* o > ConcurrentJITLocker locker(m_symbolTable->m_lock); > SymbolTable::Map::iterator iter = m_symbolTable->find(locker, uid); > ASSERT(iter != m_symbolTable->end(locker)); >- iter->value.prepareToWatch(symbolTable()); >+ iter->value.prepareToWatch(); > instructions[i + 5].u.watchpointSet = iter->value.watchpointSet(); > } else > instructions[i + 5].u.watchpointSet = nullptr; >@@ -2546,12 +2541,15 @@ void CodeBlock::finalizeUnconditionally( > curInstruction[3].u.toThisStatus, ToThisClearedByGC); > break; > case op_resolve_scope: { >- WriteBarrierBase<JSLexicalEnvironment>& lexicalEnvironment = curInstruction[6].u.lexicalEnvironment; >- if (!lexicalEnvironment || Heap::isMarked(lexicalEnvironment.get())) >+ // Right now this isn't strictly necessary. Any symbol tables that this will refer to >+ // are for outer functions, and we refer to those functions strongly, and they refer >+ // to the symbol table strongly. But it's nice to be on the safe side. >+ WriteBarrierBase<SymbolTable>& symbolTable = curInstruction[6].u.symbolTable; >+ if (!symbolTable || Heap::isMarked(symbolTable.get())) > break; > if (Options::verboseOSR()) >- dataLogF("Clearing dead lexicalEnvironment %p.\n", lexicalEnvironment.get()); >- lexicalEnvironment.clear(); >+ dataLogF("Clearing dead symbolTable %p.\n", symbolTable.get()); >+ symbolTable.clear(); > break; > } > case op_get_from_scope: >@@ -3815,6 +3813,18 @@ String CodeBlock::nameForRegister(Virtua > return ""; > } > >+ValueProfile* CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset) >+{ >+ ValueProfile* result = binarySearch<ValueProfile, int>( >+ m_valueProfiles, m_valueProfiles.size(), bytecodeOffset, >+ getValueProfileBytecodeOffset<ValueProfile>); >+ ASSERT(result->m_bytecodeOffset != -1); >+ ASSERT(instructions()[bytecodeOffset + opcodeLength( >+ m_vm->interpreter->getOpcodeID( >+ instructions()[bytecodeOffset].u.opcode)) - 1].u.profile == result); >+ return result; >+} >+ > void CodeBlock::validate() > { > BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint. >Index: Source/JavaScriptCore/bytecode/CodeBlock.h >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.h (revision 182498) >+++ Source/JavaScriptCore/bytecode/CodeBlock.h (working copy) >@@ -386,17 +386,7 @@ public: > > unsigned numberOfValueProfiles() { return m_valueProfiles.size(); } > ValueProfile* valueProfile(int index) { return &m_valueProfiles[index]; } >- ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset) >- { >- ValueProfile* result = binarySearch<ValueProfile, int>( >- m_valueProfiles, m_valueProfiles.size(), bytecodeOffset, >- getValueProfileBytecodeOffset<ValueProfile>); >- ASSERT(result->m_bytecodeOffset != -1); >- ASSERT(instructions()[bytecodeOffset + opcodeLength( >- m_vm->interpreter->getOpcodeID( >- instructions()[bytecodeOffset].u.opcode)) - 1].u.profile == result); >- return result; >- } >+ ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset); > SpeculatedType valueProfilePredictionForBytecodeOffset(const ConcurrentJITLocker& locker, int bytecodeOffset) > { > return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction(locker); >Index: Source/JavaScriptCore/bytecode/CodeOrigin.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeOrigin.cpp (revision 182498) >+++ 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 182498) >+++ 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 182498) >+++ Source/JavaScriptCore/bytecode/Instruction.h (working copy) >@@ -32,6 +32,7 @@ > #include "BasicBlockLocation.h" > #include "MacroAssembler.h" > #include "Opcode.h" >+#include "SymbolTable.h" > #include "TypeLocation.h" > #include "PropertySlot.h" > #include "SpecialPointer.h" >@@ -46,7 +47,7 @@ namespace JSC { > class ArrayAllocationProfile; > class ArrayProfile; > class ObjectAllocationProfile; >-class VariableWatchpointSet; >+class WatchpointSet; > struct LLIntCallLinkInfo; > struct ValueProfile; > >@@ -106,6 +107,7 @@ struct Instruction { > Opcode opcode; > int operand; > WriteBarrierBase<Structure> structure; >+ WriteBarrierBase<SymbolTable> symbolTable; > WriteBarrierBase<StructureChain> structureChain; > WriteBarrierBase<JSCell> jsCell; > WriteBarrier<Unknown>* variablePointer; >@@ -117,8 +119,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 182498) >+++ Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp (working copy) >@@ -1,49 +0,0 @@ >-/* >- * Copyright (C) 2014 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 "VariableWatchpointSet.h" >- >-#include "JSCInlines.h" >- >-namespace JSC { >- >-void VariableWriteFireDetail::dump(PrintStream& out) const >-{ >- out.print("Write to ", m_name, " in ", JSValue(m_object)); >-} >- >-void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, JSObject* baseObject, const PropertyName& propertyName) >-{ >- notifyWrite(vm, value, VariableWriteFireDetail(baseObject, propertyName)); >-} >- >-void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const char* reason) >-{ >- notifyWrite(vm, value, StringFireDetail(reason)); >-} >- >-} // namespace JSC >- >Index: Source/JavaScriptCore/bytecode/VariableWatchpointSet.h >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWatchpointSet.h (revision 182498) >+++ Source/JavaScriptCore/bytecode/VariableWatchpointSet.h (working copy) >@@ -1,110 +0,0 @@ >-/* >- * Copyright (C) 2012-2014 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 VariableWatchpointSet_h >-#define VariableWatchpointSet_h >- >-#include "Watchpoint.h" >-#include "WriteBarrier.h" >- >-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) >- : WatchpointSet(ClearWatchpoint) >- , m_symbolTable(symbolTable) >- { >- } >- >- ~VariableWatchpointSet() { } >- >- // For the purpose of deciding whether or not to watch this variable, you only need >- // to inspect inferredValue(). If this returns something other than the empty >- // value, then it means that at all future safepoints, this watchpoint set will be >- // in one of these states: >- // >- // IsWatched: in this case, the variable's value must still be the >- // inferredValue. >- // >- // IsInvalidated: in this case the variable's value may be anything but you'll >- // either notice that it's invalidated and not install the watchpoint, or >- // 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 invalidate(const FireDetail& detail) >- { >- m_inferredValue.clear(); >- WatchpointSet::invalidate(detail); >- } >- >- void finalizeUnconditionally(const FireDetail& detail) >- { >- ASSERT(!!m_inferredValue == (state() == IsWatched)); >- if (!m_inferredValue) >- return; >- JSValue inferredValue = m_inferredValue.get(); >- if (!inferredValue.isCell()) >- return; >- JSCell* cell = inferredValue.asCell(); >- if (Heap::isMarked(cell)) >- return; >- invalidate(detail); >- } >- >- WriteBarrier<Unknown>* addressOfInferredValue() { return &m_inferredValue; } >- >-private: >- SymbolTable& m_symbolTable; >- WriteBarrier<Unknown> m_inferredValue; >-}; >- >-} // namespace JSC >- >-#endif // VariableWatchpointSet_h >- >Index: Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h (revision 182498) >+++ Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h (working copy) >@@ -1,60 +0,0 @@ >-/* >- * Copyright (C) 2014 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 VariableWatchpointSetInlines_h >-#define VariableWatchpointSetInlines_h >- >-#include "SymbolTable.h" >-#include "VariableWatchpointSet.h" >- >-namespace JSC { >- >-inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const FireDetail& detail) >-{ >- ASSERT(!!value); >- switch (state()) { >- case ClearWatchpoint: >- m_inferredValue.set(vm, &m_symbolTable, value); >- startWatching(); >- return; >- >- case IsWatched: >- ASSERT(!!m_inferredValue); >- if (value == m_inferredValue.get()) >- return; >- invalidate(detail); >- return; >- >- case IsInvalidated: >- ASSERT(!m_inferredValue); >- return; >- } >- >- ASSERT_NOT_REACHED(); >-} >- >-} // namespace JSC >- >-#endif // VariableWatchpointSetInlines_h >Index: Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp (revision 0) >+++ Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp (working copy) >@@ -0,0 +1,44 @@ >+/* >+ * 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)); >+} >+ >+void VariableWriteFireDetail::touch(WatchpointSet* set, JSObject* object, const PropertyName& name) >+{ >+ set->touch(VariableWriteFireDetail(object, name)); >+} >+ >+} // 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,55 @@ >+/* >+ * 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; >+ >+ JS_EXPORT_PRIVATE static void touch(WatchpointSet*, JSObject*, const PropertyName&); >+ >+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 182498) >+++ Source/JavaScriptCore/bytecode/Watchpoint.h (working copy) >@@ -87,6 +87,12 @@ public: > JS_EXPORT_PRIVATE WatchpointSet(WatchpointState); > JS_EXPORT_PRIVATE ~WatchpointSet(); // Note that this will not fire any of the watchpoints; if you need to know when a WatchpointSet dies then you need a separate mechanism for this. > >+ // Fast way of getting the state, which only works from the main thread. >+ WatchpointState stateOnMainThread() const >+ { >+ return static_cast<WatchpointState>(m_state); >+ } >+ > // It is safe to call this from another thread. It may return an old > // state. Guarantees that if *first* read the state() of the thing being > // watched and it returned IsWatched and *second* you actually read its >@@ -125,20 +131,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 +161,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; } > >@@ -209,18 +229,34 @@ public: > freeFat(); > } > >+ // Fast way of getting the state, which only works from the main thread. >+ WatchpointState stateOnMainThread() const >+ { >+ uintptr_t data = m_data; >+ if (isFat(data)) >+ return fat(data)->stateOnMainThread(); >+ return decodeState(data); >+ } >+ >+ // It is safe to call this from another thread. It may return a prior state, >+ // but that should be fine since you should only perform actions based on the >+ // state if you also add a watchpoint. >+ WatchpointState state() const >+ { >+ WTF::loadLoadFence(); >+ uintptr_t data = m_data; >+ WTF::loadLoadFence(); >+ if (isFat(data)) >+ return fat(data)->state(); >+ return decodeState(data); >+ } >+ > // It is safe to call this from another thread. It may return false > // even if the set actually had been invalidated, but that ought to happen > // only in the case of races, and should be rare. > bool hasBeenInvalidated() const > { >- WTF::loadLoadFence(); >- uintptr_t data = m_data; >- if (isFat(data)) { >- WTF::loadLoadFence(); >- return fat(data)->hasBeenInvalidated(); >- } >- return decodeState(data) == IsInvalidated; >+ return state() == IsInvalidated; > } > > // Like hasBeenInvalidated(), may be called from another thread. >@@ -253,6 +289,14 @@ public: > WTF::storeStoreFence(); > } > >+ void invalidate(const FireDetail& detail) >+ { >+ if (isFat()) >+ fat()->invalidate(detail); >+ else >+ m_data = encodeState(IsInvalidated); >+ } >+ > JS_EXPORT_PRIVATE void fireAll(const char* reason); > > void touch(const FireDetail& detail) >@@ -261,7 +305,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 182498) >+++ 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(); >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -1342,6 +1342,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; > } >@@ -1401,6 +1402,15 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case GetCallee: >+ if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())) { >+ InferredValue* singleton = executable->singletonFunction(); >+ if (JSValue value = singleton->inferredValue()) { >+ m_graph.watchpoints().addLazily(singleton); >+ 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 182498) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -215,8 +215,6 @@ private: > bool isDirect); > void emitChecks(const ConstantStructureCheckVector&); > >- Node* getScope(VirtualRegister scopeChain, unsigned skipCount); >- > void prepareToParseBlock(); > void clearCaches(); > >@@ -279,8 +277,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())) { >+ InferredValue* singleton = executable->singletonFunction(); >+ if (JSValue value = singleton->inferredValue()) { >+ m_graph.watchpoints().addLazily(singleton); >+ JSFunction* function = jsCast<JSFunction*>(value); >+ return weakJSConstant(function); >+ } >+ } > return addToGraph(GetCallee); >+ } > > return getDirect(m_inlineStackTop->remapOperand(operand)); > } >@@ -2529,14 +2539,6 @@ void ByteCodeParser::clearCaches() > m_constants.resize(0); > } > >-Node* ByteCodeParser::getScope(VirtualRegister scopeChain, unsigned skipCount) >-{ >- Node* localBase = get(scopeChain); >- for (unsigned n = skipCount; n--;) >- localBase = addToGraph(SkipScope, localBase); >- return localBase; >-} >- > bool ByteCodeParser::parseBlock(unsigned limit) > { > bool shouldContinueParsing = true; >@@ -2606,11 +2608,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) { >@@ -3388,17 +3385,28 @@ 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)); >+ Node* localBase = get(VirtualRegister(currentInstruction[2].u.operand)); >+ addToGraph(Phantom, localBase); // OSR exit cannot handle resolve_scope on a DCE'd scope. >+ >+ // We have various forms of constant folding here. This is necessary to avoid >+ // spurious recompiles in dead-but-foldable code. >+ if (SymbolTable* symbolTable = currentInstruction[6].u.symbolTable.get()) { >+ InferredValue* singleton = symbolTable->singletonScope(); >+ if (JSValue value = singleton->inferredValue()) { >+ m_graph.watchpoints().addLazily(singleton); >+ set(VirtualRegister(dst), weakJSConstant(value)); >+ break; >+ } >+ } >+ if (JSScope* scope = localBase->dynamicCastConstant<JSScope*>()) { >+ for (unsigned n = depth; n--;) >+ scope = scope->next(); >+ set(VirtualRegister(dst), weakJSConstant(scope)); > break; > } >- set(VirtualRegister(dst), getScope(VirtualRegister(currentInstruction[2].u.operand), depth)); >- if (inlineCallFrame()) >- addToGraph(Phantom, getDirect(m_inlineStackTop->remapOperand(VirtualRegister(currentInstruction[2].u.operand)))); >+ for (unsigned n = depth; n--;) >+ localBase = addToGraph(SkipScope, localBase); >+ set(VirtualRegister(dst), localBase); > break; > } > case Dynamic: >@@ -3450,19 +3458,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 store a value first, and only >+ // after that do 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: >@@ -3479,6 +3526,10 @@ bool ByteCodeParser::parseBlock(unsigned > // won't be able to handle an Undefined scope. > addToGraph(Phantom, scopeNode); > >+ // Constant folding in the bytecode parser is important for performance. This may not >+ // have executed yet. If it hasn't, then we won't have a prediction. Lacking a >+ // prediction, we'd otherwise think that it has to exit. Then when it did execute, we >+ // would recompile. But if we can fold it here, we avoid the exit. > if (JSValue value = m_graph.tryGetConstantClosureVar(scopeNode, ScopeOffset(operand))) { > set(VirtualRegister(dst), weakJSConstant(value)); > break; >@@ -3509,7 +3560,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); >@@ -3552,8 +3603,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; >@@ -3564,10 +3617,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 182498) >+++ 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 182498) >+++ Source/JavaScriptCore/dfg/DFGClobberize.h (working copy) >@@ -311,10 +311,14 @@ void clobberize(Graph& graph, Node* node > write(SideState); > return; > >- case CreateActivation: >+ case CreateActivation: { >+ SymbolTable* table = graph.symbolTableFor(node->origin.semantic); >+ if (table->singletonScope()->isStillValid()) >+ write(Watchpoint_fire); > read(HeapObjectCount); > write(HeapObjectCount); > return; >+ } > > case CreateDirectArguments: > case CreateScopedArguments: >@@ -858,11 +862,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*>()->singletonFunction()->isStillValid()) >+ write(Watchpoint_fire); >+ read(HeapObjectCount); >+ write(HeapObjectCount); >+ return; >+ > case RegExpExec: > case RegExpTest: > read(RegExpState); >Index: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-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 >@@ -44,6 +44,13 @@ void ArrayBufferViewWatchpointAdaptor::a > codeBlock->vm()->heap.addReference(neuteringWatchpoint, view->buffer()); > } > >+void InferredValueAdaptor::add( >+ CodeBlock* codeBlock, InferredValue* inferredValue, Watchpoint* watchpoint) >+{ >+ codeBlock->addConstant(inferredValue); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too. >+ inferredValue->add(watchpoint); >+} >+ > DesiredWatchpoints::DesiredWatchpoints() { } > DesiredWatchpoints::~DesiredWatchpoints() { } > >@@ -57,6 +64,11 @@ void DesiredWatchpoints::addLazily(Inlin > m_inlineSets.addLazily(&set); > } > >+void DesiredWatchpoints::addLazily(InferredValue* inferredValue) >+{ >+ m_inferredValues.addLazily(inferredValue); >+} >+ > void DesiredWatchpoints::addLazily(JSArrayBufferView* view) > { > m_bufferViews.addLazily(view); >@@ -74,6 +86,7 @@ void DesiredWatchpoints::reallyAdd(CodeB > { > m_sets.reallyAdd(codeBlock, commonData); > m_inlineSets.reallyAdd(codeBlock, commonData); >+ m_inferredValues.reallyAdd(codeBlock, commonData); > m_bufferViews.reallyAdd(codeBlock, commonData); > } > >@@ -81,6 +94,7 @@ bool DesiredWatchpoints::areStillValid() > { > return m_sets.areStillValid() > && m_inlineSets.areStillValid() >+ && m_inferredValues.areStillValid() > && m_bufferViews.areStillValid(); > } > >Index: Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-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 >@@ -30,6 +30,7 @@ > > #include "CodeOrigin.h" > #include "DFGCommonData.h" >+#include "InferredValue.h" > #include "JSArrayBufferView.h" > #include "Watchpoint.h" > #include <wtf/HashMap.h> >@@ -50,6 +51,14 @@ struct GenericSetAdaptor { > static bool hasBeenInvalidated(T* set) { return set->hasBeenInvalidated(); } > }; > >+struct InferredValueAdaptor { >+ static void add(CodeBlock*, InferredValue*, Watchpoint*); >+ static bool hasBeenInvalidated(InferredValue* inferredValue) >+ { >+ return inferredValue->hasBeenInvalidated(); >+ } >+}; >+ > struct ArrayBufferViewWatchpointAdaptor { > static void add(CodeBlock*, JSArrayBufferView*, Watchpoint*); > static bool hasBeenInvalidated(JSArrayBufferView* view) >@@ -119,6 +128,7 @@ public: > > void addLazily(WatchpointSet*); > void addLazily(InlineWatchpointSet&); >+ void addLazily(InferredValue*); > void addLazily(JSArrayBufferView*); > > bool consider(Structure*); >@@ -135,6 +145,10 @@ public: > { > return m_inlineSets.isWatched(&set); > } >+ bool isWatched(InferredValue* inferredValue) >+ { >+ return m_inferredValues.isWatched(inferredValue); >+ } > bool isWatched(JSArrayBufferView* view) > { > return m_bufferViews.isWatched(view); >@@ -143,6 +157,7 @@ public: > private: > GenericDesiredWatchpoints<WatchpointSet> m_sets; > GenericDesiredWatchpoints<InlineWatchpointSet> m_inlineSets; >+ GenericDesiredWatchpoints<InferredValue, InferredValueAdaptor> m_inferredValues; > GenericDesiredWatchpoints<JSArrayBufferView, ArrayBufferViewWatchpointAdaptor> m_bufferViews; > }; > >Index: Source/JavaScriptCore/dfg/DFGGraph.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.cpp (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGGraph.cpp (working copy) >@@ -311,8 +311,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->hasStoragePointer()) > out.print(comma, RawPointer(node->storagePointer())); > if (node->hasObjectMaterializationData()) >@@ -1026,6 +1026,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(); > >@@ -1034,24 +1036,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 182498) >+++ 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 hasStoragePointer() >Index: Source/JavaScriptCore/dfg/DFGOperations.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOperations.cpp (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGOperations.cpp (working copy) >@@ -1077,13 +1077,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 182498) >+++ Source/JavaScriptCore/dfg/DFGOperations.h (working copy) >@@ -127,7 +127,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/DFGSpeculativeJIT32_64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (working copy) >@@ -3987,32 +3987,7 @@ void SpeculativeJIT::compile(Node* node) > } > > case NotifyWrite: { >- VariableWatchpointSet* set = node->variableWatchpointSet(); >- >- JSValueOperand value(this, node->child1()); >- GPRReg valueTagGPR = value.tagGPR(); >- GPRReg valuePayloadGPR = value.payloadGPR(); >- >- 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::JumpList notifySlow; >- notifySlow.append(m_jit.branch32( >- JITCompiler::NotEqual, >- JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->payloadPointer()), >- valuePayloadGPR)); >- notifySlow.append(m_jit.branch32( >- JITCompiler::NotEqual, >- JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->tagPointer()), >- valueTagGPR)); >- addSlowPathGenerator( >- slowPathCall(notifySlow, this, operationNotifyWrite, NoResult, set, valueTagGPR, valuePayloadGPR)); >- isDone.link(&m_jit); >- >- noResult(node); >+ compileNotifyWrite(node); > break; > } > >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -4019,26 +4019,7 @@ 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); >- >- addSlowPathGenerator( >- slowPathCall(slowCase, this, operationNotifyWrite, NoResult, set, valueGPR)); >- >- noResult(node); >+ compileNotifyWrite(node); > break; > } > >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (working copy) >@@ -4367,8 +4367,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->singletonFunction()->isStillValid()) >+ function = operationNewFunction; >+ else >+ function = operationNewFunctionWithInvalidatedReallocationWatchpoint; >+ callOperation(function, resultGPR, scopeGPR, executable); > cellResult(resultGPR, node); > } > >@@ -4436,19 +4441,31 @@ void SpeculativeJIT::compileForwardVarar > > void SpeculativeJIT::compileCreateActivation(Node* node) > { >+ SymbolTable* table = m_jit.graph().symbolTableFor(node->origin.semantic); >+ Structure* structure = m_jit.graph().globalObjectFor( >+ node->origin.semantic)->activationStructure(); >+ > SpeculateCellOperand scope(this, node->child1()); >+ GPRReg scopeGPR = scope.gpr(); >+ >+ if (table->singletonScope()->isStillValid()) { >+ GPRFlushedCallResult result(this); >+ GPRReg resultGPR = result.gpr(); >+ >+ flushRegisters(); >+ >+ callOperation(operationCreateActivationDirect, resultGPR, structure, scopeGPR, table); >+ cellResult(resultGPR, node); >+ return; >+ } >+ > GPRTemporary result(this); > GPRTemporary scratch1(this); > GPRTemporary scratch2(this); >- GPRReg scopeGPR = scope.gpr(); > GPRReg resultGPR = result.gpr(); > GPRReg scratch1GPR = scratch1.gpr(); > GPRReg scratch2GPR = scratch2.gpr(); > >- SymbolTable* table = m_jit.graph().symbolTableFor(node->origin.semantic); >- Structure* structure = m_jit.graph().globalObjectFor( >- node->origin.semantic)->activationStructure(); >- > JITCompiler::JumpList slowPath; > emitAllocateJSObjectWithKnownSize<JSLexicalEnvironment>( > resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratch1GPR, scratch2GPR, >@@ -4714,6 +4731,21 @@ void SpeculativeJIT::compileCreateCloned > cellResult(resultGPR, node); > } > >+void SpeculativeJIT::compileNotifyWrite(Node* node) >+{ >+ 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)); >+ >+ noResult(node); >+} >+ > bool SpeculativeJIT::compileRegExpExec(Node* node) > { > unsigned branchIndexInBlock = detectPeepHoleBranch(); >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (revision 182498) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (working copy) >@@ -1460,9 +1460,9 @@ public: > return appendCallWithExceptionCheck(operation); > } > >- JITCompiler::Call callOperation(V_JITOperation_EVwsJ operation, VariableWatchpointSet* watchpointSet, GPRReg arg) >+ JITCompiler::Call callOperation(V_JITOperation_EWs operation, WatchpointSet* watchpointSet) > { >- m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet), arg); >+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet)); > return appendCall(operation); > } > >@@ -1776,12 +1776,6 @@ public: > return appendCallWithExceptionCheck(operation); > } > >- JITCompiler::Call callOperation(V_JITOperation_EVwsJ operation, VariableWatchpointSet* watchpointSet, GPRReg argTag, GPRReg argPayload) >- { >- m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet), argPayload, argTag); >- return appendCall(operation); >- } >- > JITCompiler::Call callOperation(D_JITOperation_EJ operation, FPRReg result, GPRReg arg1Tag, GPRReg arg1Payload) > { > m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag); >@@ -2213,6 +2207,7 @@ public: > void compilePutToArguments(Node*); > void compileCreateScopedArguments(Node*); > void compileCreateClonedArguments(Node*); >+ void compileNotifyWrite(Node*); > bool compileRegExpExec(Node*); > > JITCompiler::Jump branchIsCell(JSValueRegs); >Index: Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp (revision 182498) >+++ 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 182498) >+++ Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (working copy) >@@ -105,7 +105,7 @@ namespace JSC { namespace FTL { > macro(V_JITOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64)) \ > 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 182498) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (working copy) >@@ -2877,6 +2877,14 @@ private: > SymbolTable* table = m_graph.symbolTableFor(m_node->origin.semantic); > Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure(); > >+ if (table->singletonScope()->isStillValid()) { >+ LValue callResult = vmCall( >+ m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure), >+ scope, weakPointer(table)); >+ setJSValue(callResult); >+ return; >+ } >+ > LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateActivation slow path")); > LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateActivation continuation")); > >@@ -2912,9 +2920,16 @@ private: > > void compileNewFunction() > { >+ FunctionExecutable* executable = m_node->castOperand<FunctionExecutable*>(); >+ J_JITOperation_EJscC function; >+ if (executable->singletonFunction()->isStillValid()) >+ function = operationNewFunction; >+ else >+ function = operationNewFunctionWithInvalidatedReallocationWatchpoint; >+ > LValue result = vmCall( >- m_out.operation(operationNewFunction), m_callFrame, >- lowCell(m_node->child1()), weakPointer(m_node->castOperand<FunctionExecutable*>())); >+ m_out.operation(function), m_callFrame, lowCell(m_node->child1()), >+ weakPointer(executable)); > setJSValue(result); > } > >@@ -3783,29 +3798,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 182498) >+++ 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 182498) >+++ Source/JavaScriptCore/interpreter/Interpreter.h (working copy) >@@ -33,7 +33,6 @@ > #include "ArgList.h" > #include "JSCJSValue.h" > #include "JSCell.h" >-#include "JSFunction.h" > #include "JSObject.h" > #include "JSStack.h" > #include "LLIntData.h" >@@ -51,6 +50,7 @@ namespace JSC { > class ExecutableBase; > class FunctionExecutable; > class VM; >+ class JSFunction; > class JSGlobalObject; > class LLIntOffsetsExtractor; > class ProgramExecutable; >@@ -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 182498) >+++ Source/JavaScriptCore/jit/JIT.cpp (working copy) >@@ -105,6 +105,14 @@ void JIT::emitEnterOptimizationCheck() > } > #endif > >+void JIT::emitNotifyWrite(WatchpointSet* set) >+{ >+ if (!set || set->state() == IsInvalidated) >+ return; >+ >+ addSlowCase(branch8(NotEqual, AbsoluteAddress(set->addressOfState()), TrustedImm32(IsInvalidated))); >+} >+ > void JIT::assertStackPointerOffset() > { > if (ASSERT_DISABLED) >@@ -189,7 +197,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 182498) >+++ 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 182498) >+++ 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 182498) >+++ Source/JavaScriptCore/jit/JITOperations.cpp (working copy) >@@ -952,6 +952,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(); >@@ -1722,8 +1730,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 182498) >+++ Source/JavaScriptCore/jit/JITOperations.h (working copy) >@@ -37,7 +37,6 @@ > #include "PutKind.h" > #include "SpillRegistersMode.h" > #include "StructureStubInfo.h" >-#include "VariableWatchpointSet.h" > > > namespace JSC { >@@ -85,7 +84,7 @@ extern "C" { > Symtab: SymbolTable* > V: void > Vm: VM* >- Vws: VariableWatchpointSet* >+ Ws: WatchpointSet* > Z: int32_t > */ > >@@ -191,7 +190,7 @@ typedef void JIT_OPERATION (*V_JITOperat > typedef void JIT_OPERATION (*V_JITOperation_EPc)(ExecState*, Instruction*); > 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 +277,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/JITPropertyAccess32_64.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (revision 182498) >+++ Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (working copy) >@@ -750,27 +750,10 @@ void JIT::emitPutGlobalProperty(uintptr_ > store32(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); > } > >-void JIT::emitNotifyWrite(RegisterID tag, RegisterID payload, RegisterID scratch, VariableWatchpointSet* set) >-{ >- if (!set || set->state() == IsInvalidated) >- return; >- >- load8(set->addressOfState(), scratch); >- Jump isDone = branch32(Equal, scratch, TrustedImm32(IsInvalidated)); >- >- JumpList notifySlow = branch32( >- NotEqual, AbsoluteAddress(set->addressOfInferredValue()->payloadPointer()), payload); >- notifySlow.append(branch32( >- NotEqual, AbsoluteAddress(set->addressOfInferredValue()->tagPointer()), tag)); >- addSlowCase(notifySlow); >- >- isDone.link(this); >-} >- > void JIT::emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet* set) > { > emitLoad(value, regT1, regT0); >- emitNotifyWrite(regT1, regT0, regT2, set); >+ emitNotifyWrite(set); > store32(regT1, reinterpret_cast<char*>(operand) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); > store32(regT0, reinterpret_cast<char*>(operand) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); > } >@@ -779,7 +762,7 @@ void JIT::emitPutClosureVar(int scope, u > { > emitLoad(value, regT3, regT2); > emitLoad(scope, regT1, regT0); >- emitNotifyWrite(regT3, regT2, regT4, set); >+ emitNotifyWrite(set); > store32(regT3, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + TagOffset)); > store32(regT2, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + PayloadOffset)); > } >Index: Source/JavaScriptCore/jit/JITPropertyAccess.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITPropertyAccess.cpp (revision 182498) >+++ Source/JavaScriptCore/jit/JITPropertyAccess.cpp (working copy) >@@ -728,29 +728,18 @@ void JIT::emitPutGlobalProperty(uintptr_ > storePtr(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue))); > } > >-void JIT::emitNotifyWrite(RegisterID value, RegisterID scratch, VariableWatchpointSet* 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); >-} >- >-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 182498) >+++ Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (working copy) >@@ -1402,8 +1402,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/LowLevelInterpreter32_64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (revision 182498) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (working copy) >@@ -805,14 +805,6 @@ _llint_op_mov: > dispatch(3) > > >-macro notifyWrite(set, valueTag, valuePayload, scratch, slow) >- loadb VariableWatchpointSet::m_state[set], scratch >- bieq scratch, IsInvalidated, .done >- bineq valuePayload, VariableWatchpointSet::m_inferredValue + PayloadOffset[set], slow >- bineq valueTag, VariableWatchpointSet::m_inferredValue + TagOffset[set], slow >-.done: >-end >- > _llint_op_not: > traceExecution() > loadi 8[PC], t0 >@@ -2204,7 +2196,7 @@ macro putGlobalVar() > loadisFromInstruction(3, t0) > loadConstantOrVariable(t0, t1, t2) > loadpFromInstruction(5, t3) >- notifyWrite(t3, t1, t2, t0, .pDynamic) >+ notifyWrite(t3, .pDynamic) > loadpFromInstruction(6, t0) > storei t1, TagOffset[t0] > storei t2, PayloadOffset[t0] >@@ -2223,7 +2215,7 @@ macro putLocalClosureVar() > loadConstantOrVariable(t1, t2, t3) > loadpFromInstruction(5, t4) > btpz t4, .noVariableWatchpointSet >- notifyWrite(t4, t2, t3, t1, .pDynamic) >+ notifyWrite(t4, .pDynamic) > .noVariableWatchpointSet: > loadisFromInstruction(6, t1) > storei t2, JSEnvironmentRecord_variables + TagOffset[t0, t1, 8] >Index: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (revision 182498) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (working copy) >@@ -690,13 +690,6 @@ _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: >-end >- > _llint_op_not: > traceExecution() > loadisFromInstruction(2, t0) >@@ -2069,8 +2062,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 +2079,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 182498) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter.asm (working copy) >@@ -519,6 +519,10 @@ macro skipIfIsRememberedOrInEden(cell, s > continuation(scratch1) > end > >+macro notifyWrite(set, slow) >+ bbneq WatchpointSet::m_state[set], IsInvalidated, slow >+end >+ > macro checkSwitchToJIT(increment, action) > loadp CodeBlock[cfr], t0 > baddis increment, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t0], .continue >@@ -920,12 +924,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 182498) >+++ Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (working copy) >@@ -55,7 +55,6 @@ > #include "ScopedArguments.h" > #include "StructureRareDataInlines.h" > #include "TypeProfilerLog.h" >-#include "VariableWatchpointSetInlines.h" > #include <wtf/StringPrintStream.h> > > namespace JSC { >@@ -206,13 +205,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 182498) >+++ 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 182498) >+++ Source/JavaScriptCore/runtime/Executable.cpp (working copy) >@@ -414,6 +414,12 @@ FunctionExecutable::FunctionExecutable(V > m_typeProfilingEndOffset = unlinkedExecutable->typeProfilingEndOffset(); > } > >+void FunctionExecutable::finishCreation(VM& vm) >+{ >+ Base::finishCreation(vm); >+ m_singletonFunction.set(vm, this, InferredValue::create(vm)); >+} >+ > void FunctionExecutable::destroy(JSCell* cell) > { > static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable(); >@@ -567,6 +573,7 @@ void FunctionExecutable::visitChildren(J > if (thisObject->m_codeBlockForConstruct) > thisObject->m_codeBlockForConstruct->visitAggregate(visitor); > visitor.append(&thisObject->m_unlinkedExecutable); >+ visitor.append(&thisObject->m_singletonFunction); > } > > SymbolTable* FunctionExecutable::symbolTable(CodeSpecializationKind kind) >Index: Source/JavaScriptCore/runtime/Executable.h >=================================================================== >--- Source/JavaScriptCore/runtime/Executable.h (revision 182498) >+++ Source/JavaScriptCore/runtime/Executable.h (working copy) >@@ -33,8 +33,7 @@ > #include "CompilationResult.h" > #include "DFGPlan.h" > #include "HandlerInfo.h" >-#include "JSFunction.h" >-#include "Interpreter.h" >+#include "InferredValue.h" > #include "JITCode.h" > #include "JSGlobalObject.h" > #include "RegisterPreservationMode.h" >@@ -649,11 +648,15 @@ public: > void unlinkCalls(); > > void clearCode(); >+ >+ InferredValue* singletonFunction() { return m_singletonFunction.get(); } > > private: > FunctionExecutable( > VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, > unsigned lastLine, unsigned startColumn, unsigned endColumn); >+ >+ void finishCreation(VM&); > > bool isCompiling() > { >@@ -667,12 +670,13 @@ private: > } > > friend class ScriptExecutable; >- >+ > WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; > RefPtr<FunctionCodeBlock> m_codeBlockForCall; > RefPtr<FunctionCodeBlock> m_codeBlockForConstruct; > RefPtr<TypeSet> m_returnStatementTypeSet; > unsigned m_parametersStartOffset; >+ WriteBarrier<InferredValue> m_singletonFunction; > }; > > inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) >Index: Source/JavaScriptCore/runtime/InferredValue.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/InferredValue.cpp (revision 0) >+++ Source/JavaScriptCore/runtime/InferredValue.cpp (working copy) >@@ -0,0 +1,132 @@ >+/* >+ * 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 "InferredValue.h" >+ >+#include "JSCInlines.h" >+ >+namespace JSC { >+ >+const ClassInfo InferredValue::s_info = { "InferredValue", 0, 0, CREATE_METHOD_TABLE(InferredValue) }; >+ >+InferredValue* InferredValue::create(VM& vm) >+{ >+ InferredValue* result = new (NotNull, allocateCell<InferredValue>(vm.heap)) InferredValue(vm); >+ result->finishCreation(vm); >+ return result; >+} >+ >+void InferredValue::destroy(JSCell* cell) >+{ >+ InferredValue* inferredValue = static_cast<InferredValue*>(cell); >+ inferredValue->InferredValue::~InferredValue(); >+} >+ >+Structure* InferredValue::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) >+{ >+ return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info()); >+} >+ >+void InferredValue::visitChildren(JSCell* cell, SlotVisitor& visitor) >+{ >+ InferredValue* inferredValue = jsCast<InferredValue*>(cell); >+ >+ if (inferredValue->m_set.hasBeenInvalidated()) { >+ inferredValue->m_cleanup = nullptr; >+ return; >+ } >+ >+ if (!inferredValue->m_value) >+ return; >+ if (!inferredValue->m_value.get().isCell()) >+ return; >+ >+ if (!inferredValue->m_cleanup) >+ inferredValue->m_cleanup = std::make_unique<ValueCleanup>(inferredValue); >+ visitor.addUnconditionalFinalizer(inferredValue->m_cleanup.get()); >+} >+ >+InferredValue::InferredValue(VM& vm) >+ : Base(vm, vm.inferredValueStructure.get()) >+ , m_set(ClearWatchpoint) >+{ >+} >+ >+InferredValue::~InferredValue() >+{ >+} >+ >+void InferredValue::notifyWriteSlow(VM& vm, JSValue value, const FireDetail& detail) >+{ >+ ASSERT(!!value); >+ switch (m_set.state()) { >+ case ClearWatchpoint: >+ m_value.set(vm, this, value); >+ m_set.startWatching(); >+ return; >+ >+ case IsWatched: >+ ASSERT(!!m_value); >+ if (m_value.get() == value) >+ return; >+ invalidate(detail); >+ return; >+ >+ case IsInvalidated: >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ >+ ASSERT_NOT_REACHED(); >+} >+ >+void InferredValue::notifyWriteSlow(VM& vm, JSValue value, const char* reason) >+{ >+ notifyWriteSlow(vm, value, StringFireDetail(reason)); >+} >+ >+InferredValue::ValueCleanup::ValueCleanup(InferredValue* owner) >+ : m_owner(owner) >+{ >+} >+ >+InferredValue::ValueCleanup::~ValueCleanup() >+{ >+} >+ >+void InferredValue::ValueCleanup::finalizeUnconditionally() >+{ >+ ASSERT(m_owner->m_value); >+ ASSERT(m_owner->m_value.get().isCell()); >+ >+ if (Heap::isMarked(m_owner->m_value.get().asCell())) >+ return; >+ >+ m_owner->invalidate(StringFireDetail("InferredValue clean-up during GC")); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/runtime/InferredValue.h >=================================================================== >--- Source/JavaScriptCore/runtime/InferredValue.h (revision 0) >+++ Source/JavaScriptCore/runtime/InferredValue.h (working copy) >@@ -0,0 +1,136 @@ >+/* >+ * 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 InferredValue_h >+#define InferredValue_h >+ >+#include "JSCell.h" >+#include "Watchpoint.h" >+#include "WriteBarrier.h" >+ >+namespace JSC { >+ >+// Allocate one of these if you'd like to infer a constant value. Writes to the value should use >+// notifyWrite(). So long as exactly one value had ever been written and invalidate() has never been >+// called, and you register a watchpoint, you can rely on the inferredValue() being the one true >+// value. >+// >+// Commonly used for inferring singletons - in that case each allocation does notifyWrite(). But you >+// can use if for other things as well. >+ >+class InferredValue : public JSCell { >+public: >+ typedef JSCell Base; >+ >+ static InferredValue* create(VM&); >+ >+ static const bool needsDestruction = true; >+ static const bool hasImmortalStructure = true; >+ static void destroy(JSCell*); >+ >+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); >+ >+ static void visitChildren(JSCell*, SlotVisitor&); >+ >+ DECLARE_INFO; >+ >+ // For the purpose of deciding whether or not to watch this variable, you only need >+ // to inspect inferredValue(). If this returns something other than the empty >+ // value, then it means that at all future safepoints, this watchpoint set will be >+ // in one of these states: >+ // >+ // IsWatched: in this case, the variable's value must still be the >+ // inferredValue. >+ // >+ // IsInvalidated: in this case the variable's value may be anything but you'll >+ // either notice that it's invalidated and not install the watchpoint, or >+ // you will have been notified that the watchpoint was fired. >+ JSValue inferredValue() { return m_value.get(); } >+ >+ // Forwards some WatchpointSet methods. >+ WatchpointState state() const { return m_set.state(); } >+ bool isStillValid() const { return m_set.isStillValid(); } >+ bool hasBeenInvalidated() const { return m_set.hasBeenInvalidated(); } >+ void add(Watchpoint* watchpoint) { m_set.add(watchpoint); } >+ >+ void notifyWrite(VM& vm, JSValue value, const FireDetail& detail) >+ { >+ if (LIKELY(m_set.stateOnMainThread() == IsInvalidated)) >+ return; >+ notifyWriteSlow(vm, value, detail); >+ } >+ >+ void notifyWrite(VM& vm, JSValue value, const char* reason) >+ { >+ if (LIKELY(m_set.stateOnMainThread() == IsInvalidated)) >+ return; >+ notifyWriteSlow(vm, value, reason); >+ } >+ >+ void invalidate(const FireDetail& detail) >+ { >+ m_value.clear(); >+ m_set.invalidate(detail); >+ } >+ >+protected: >+ static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags; >+ >+private: >+ InferredValue(VM&); >+ ~InferredValue(); >+ >+ JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&); >+ JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const char* reason); >+ >+ // We could have used Weak<>. But we want arbitrary JSValues, not just cells. It's also somewhat >+ // convenient to have eager notification of death. >+ class ValueCleanup : public UnconditionalFinalizer { >+ public: >+ ValueCleanup(InferredValue*); >+ virtual ~ValueCleanup(); >+ >+ protected: >+ void finalizeUnconditionally() override; >+ >+ private: >+ InferredValue* m_owner; >+ }; >+ >+ friend class ValueCleanup; >+ >+ InlineWatchpointSet m_set; >+ WriteBarrier<Unknown> m_value; >+ std::unique_ptr<ValueCleanup> m_cleanup; >+}; >+ >+// FIXME: We could have an InlineInferredValue, which only allocates the InferredValue object when >+// a notifyWrite() transitions us towards watching, and then clears the reference (allowing the object >+// to die) when we get invalidated. >+ >+} // namespace JSC >+ >+#endif // InferredValue_h >+ >Index: Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp (revision 182498) >+++ Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp (working copy) >@@ -40,7 +40,7 @@ void JSEnvironmentRecord::visitChildren( > JSEnvironmentRecord* thisObject = jsCast<JSEnvironmentRecord*>(cell); > ASSERT_GC_OBJECT_INHERITS(thisObject, info()); > Base::visitChildren(thisObject, visitor); >- visitor.appendValues(thisObject->variables(), thisObject->m_symbolTable->scopeSize()); >+ visitor.appendValues(thisObject->variables(), thisObject->symbolTable()->scopeSize()); > } > > } // namespace JSC >Index: Source/JavaScriptCore/runtime/JSEnvironmentRecord.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSEnvironmentRecord.h (revision 182498) >+++ Source/JavaScriptCore/runtime/JSEnvironmentRecord.h (working copy) >@@ -53,7 +53,7 @@ public: > > bool isValid(ScopeOffset offset) > { >- return !!offset && offset.offset() < m_symbolTable->scopeSize(); >+ return !!offset && offset.offset() < symbolTable()->scopeSize(); > } > > WriteBarrierBase<Unknown>& variableAt(ScopeOffset offset) >@@ -104,7 +104,7 @@ protected: > void finishCreation(VM& vm) > { > finishCreationUninitialized(vm); >- for (unsigned i = m_symbolTable->scopeSize(); i--;) { >+ for (unsigned i = symbolTable()->scopeSize(); i--;) { > // Filling this with undefined is useful because that's what variables start out as. > variableAt(ScopeOffset(i)).setUndefined(); > } >Index: Source/JavaScriptCore/runtime/JSFunction.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSFunction.cpp (revision 182498) >+++ Source/JavaScriptCore/runtime/JSFunction.cpp (working copy) >@@ -59,6 +59,13 @@ bool JSFunction::isHostFunctionNonInline > return isHostFunction(); > } > >+JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope) >+{ >+ JSFunction* result = createImpl(vm, executable, scope); >+ executable->singletonFunction()->notifyWrite(vm, 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 182498) >+++ 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->singletonFunction()->hasBeenInvalidated()); >+ return createImpl(vm, executable, scope); > } > >+ static JSFunction* create(VM&, FunctionExecutable*, JSScope*); >+ > 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 182498) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.cpp (working copy) >@@ -124,7 +124,7 @@ > #include "Symbol.h" > #include "SymbolConstructor.h" > #include "SymbolPrototype.h" >-#include "VariableWatchpointSetInlines.h" >+#include "VariableWriteFireDetail.h" > #include "WeakGCMapInlines.h" > #include "WeakMapConstructor.h" > #include "WeakMapPrototype.h" >@@ -489,7 +489,7 @@ JSGlobalObject::NewGlobalVar JSGlobalObj > ScopeOffset offset = symbolTable()->takeNextScopeOffset(locker); > SymbolTableEntry newEntry(VarOffset(offset), (constantMode == IsConstant) ? ReadOnly : 0); > if (constantMode == IsVariable) >- newEntry.prepareToWatch(symbolTable()); >+ newEntry.prepareToWatch(); > else > newEntry.disableWatching(); > symbolTable()->add(locker, ident.impl(), newEntry); >@@ -510,7 +510,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 182498) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.h (working copy) >@@ -334,7 +334,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 182498) >+++ 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,12 @@ 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); >+ if (set) >+ 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 182498) >+++ 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/JSSegmentedVariableObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h (revision 182498) >+++ Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h (working copy) >@@ -86,7 +86,7 @@ protected: > void finishCreation(VM& vm) > { > Base::finishCreation(vm); >- m_symbolTable.set(vm, this, SymbolTable::create(vm)); >+ setSymbolTable(vm, SymbolTable::create(vm)); > } > > SegmentedVector<WriteBarrier<Unknown>, 16> m_variables; >Index: Source/JavaScriptCore/runtime/JSSymbolTableObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSSymbolTableObject.h (revision 182498) >+++ 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 { > >@@ -61,11 +61,19 @@ protected: > : Base(vm, structure, scope) > { > ASSERT(symbolTable); >+ setSymbolTable(vm, symbolTable); >+ } >+ >+ void setSymbolTable(VM& vm, SymbolTable* symbolTable) >+ { >+ ASSERT(!m_symbolTable); >+ symbolTable->singletonScope()->notifyWrite(vm, this, "Allocated a scope"); > m_symbolTable.set(vm, this, symbolTable); > } >- >+ > static void visitChildren(JSCell*, SlotVisitor&); >- >+ >+private: > WriteBarrier<SymbolTable> m_symbolTable; > }; > >@@ -126,6 +134,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 +151,15 @@ 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); >+ if (set) >+ VariableWriteFireDetail::touch(set, object, propertyName); > return true; > } > >@@ -164,6 +171,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 +180,13 @@ 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); >+ if (set) >+ VariableWriteFireDetail::touch(set, object, propertyName); > return true; > } > >Index: Source/JavaScriptCore/runtime/PutPropertySlot.h >=================================================================== >--- Source/JavaScriptCore/runtime/PutPropertySlot.h (revision 182498) >+++ 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 182498) >+++ 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,21 +59,14 @@ void SymbolTableEntry::freeFatEntrySlow( > delete fatEntry(); > } > >-JSValue SymbolTableEntry::inferredValue() >-{ >- if (!isFat()) >- return JSValue(); >- return fatEntry()->m_watchpoints->inferredValue(); >-} >- >-void SymbolTableEntry::prepareToWatch(SymbolTable* symbolTable) >+void SymbolTableEntry::prepareToWatch() > { > if (!isWatchable()) > return; > 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,48 +84,29 @@ SymbolTableEntry::FatEntry* SymbolTableE > SymbolTable::SymbolTable(VM& vm) > : JSCell(vm, vm.symbolTableStructure.get()) > , m_usesNonStrictEval(false) >- , m_functionEnteredOnce(ClearWatchpoint) > { > } > > SymbolTable::~SymbolTable() { } > >+void SymbolTable::finishCreation(VM& vm) >+{ >+ Base::finishCreation(vm); >+ m_singletonScope.set(vm, this, InferredValue::create(vm)); >+} >+ > void SymbolTable::visitChildren(JSCell* thisCell, SlotVisitor& visitor) > { > SymbolTable* thisSymbolTable = jsCast<SymbolTable*>(thisCell); > > visitor.append(&thisSymbolTable->m_arguments); >- >- if (!thisSymbolTable->m_watchpointCleanup) { >- thisSymbolTable->m_watchpointCleanup = >- std::make_unique<WatchpointCleanup>(thisSymbolTable); >- } >- >- visitor.addUnconditionalFinalizer(thisSymbolTable->m_watchpointCleanup.get()); >+ visitor.append(&thisSymbolTable->m_singletonScope); > > // 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 182498) >+++ Source/JavaScriptCore/runtime/SymbolTable.h (working copy) >@@ -31,17 +31,20 @@ > > #include "ConcurrentJITLock.h" > #include "ConstantMode.h" >+#include "InferredValue.h" > #include "JSObject.h" > #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 +66,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,32 +263,44 @@ 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()); > } > >- void prepareToWatch(SymbolTable*); >+ void prepareToWatch(); > > void addWatchpoint(Watchpoint*); > >- VariableWatchpointSet* watchpointSet() >+ // This watchpoint set is initialized clear, and goes through the following state transitions: >+ // >+ // First write to this var, in any scope that has this symbol table: Clear->IsWatched. >+ // >+ // Second write to this var, in any scope that has this symbol table: IsWatched->IsInvalidated. >+ // >+ // We ensure that we touch the set (i.e. trigger its state transition) after we do the write. This >+ // means that if you're in the compiler thread, and you: >+ // >+ // 1) Observe that the set IsWatched and commit to adding your watchpoint. >+ // 2) Load a value from any scope that has this watchpoint set. >+ // >+ // Then you can be sure that that value is either going to be the correct value for that var forever, >+ // or the watchpoint set will invalidate and you'll get fired. >+ // >+ // It's possible to write a program that first creates multiple scopes with the same var, and then >+ // initializes that var in just one of them. This means that a compilation could constant-fold to one >+ // of the scopes that still has an undefined value for this variable. That's fine, because at that >+ // point any write to any of the instances of that variable would fire the watchpoint. >+ 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 +323,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&); >@@ -637,6 +652,8 @@ public: > SymbolTable* cloneScopePart(VM&); > > void prepareForTypeProfiling(const ConcurrentJITLocker&); >+ >+ InferredValue* singletonScope() { return m_singletonScope.get(); } > > static void visitChildren(JSCell*, SlotVisitor&); > >@@ -646,20 +663,10 @@ 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(); >+ >+ JS_EXPORT_PRIVATE void finishCreation(VM&); > > Map m_map; > ScopeOffset m_maxScopeOffset; >@@ -674,13 +681,11 @@ private: > bool m_usesNonStrictEval; > > WriteBarrier<ScopedArgumentsTable> m_arguments; >+ WriteBarrier<InferredValue> m_singletonScope; > >- 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 182498) >+++ Source/JavaScriptCore/runtime/TypeProfiler.cpp (working copy) >@@ -28,6 +28,7 @@ > > #include "InspectorProtocolObjects.h" > #include "TypeLocation.h" >+#include <wtf/text/StringBuilder.h> > > namespace JSC { > >Index: Source/JavaScriptCore/runtime/VM.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/VM.cpp (revision 182498) >+++ Source/JavaScriptCore/runtime/VM.cpp (working copy) >@@ -237,6 +237,7 @@ VM::VM(VMType vmType, HeapType heapType) > unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); > propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); > weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull())); >+ inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull())); > #if ENABLE(PROMISES) > promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull())); > promiseReactionStructure.set(*this, JSPromiseReaction::createStructure(*this, 0, jsNull())); >Index: Source/JavaScriptCore/runtime/VM.h >=================================================================== >--- Source/JavaScriptCore/runtime/VM.h (revision 182498) >+++ Source/JavaScriptCore/runtime/VM.h (working copy) >@@ -270,6 +270,7 @@ public: > Strong<Structure> unlinkedFunctionCodeBlockStructure; > Strong<Structure> propertyTableStructure; > Strong<Structure> weakMapDataStructure; >+ Strong<Structure> inferredValueStructure; > #if ENABLE(PROMISES) > Strong<Structure> promiseDeferredStructure; > Strong<Structure> promiseReactionStructure; >Index: Source/JavaScriptCore/tests/stress/infer-uninitialized-closure-var.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/infer-uninitialized-closure-var.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/infer-uninitialized-closure-var.js (working copy) >@@ -0,0 +1,26 @@ >+function foo(p) { >+ var x; >+ >+ noInline(f); >+ >+ if (p) { >+ var f = function() { return x; } >+ >+ foo(false); >+ >+ for (var i = 0; i < 10000; ++i) { >+ var result = f(); >+ if (result !== void 0) >+ throw "Error: bad result (1): " + result; >+ } >+ >+ x = 43; >+ >+ var result = f(); >+ if (result != 43) >+ throw "Error: bad result (2): " + result; >+ } else >+ x = 42; >+} >+ >+foo(true); >Index: Source/JavaScriptCore/tests/stress/singleton-scope-then-overwrite.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/singleton-scope-then-overwrite.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/singleton-scope-then-overwrite.js (working copy) >@@ -0,0 +1,20 @@ >+function foo(a) { >+ var x = a + 1; >+ var f = function(a) { >+ return x + a; >+ }; >+ noInline(f); >+ for (var i = 0; i < 10000; ++i) { >+ var result = f(i); >+ if (result != a + 1 + i) >+ throw "Error: bad result: " + result; >+ } >+ x = 999; >+ var result = f(1); >+ if (result != 999 + 1) >+ throw "Error: bad result: " + result; >+} >+ >+noInline(foo); >+for (var i = 0; i < 3; ++i) >+ foo(42 + i); >Index: Source/JavaScriptCore/tests/stress/singleton-scope-then-realloc-and-overwrite.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/singleton-scope-then-realloc-and-overwrite.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/singleton-scope-then-realloc-and-overwrite.js (working copy) >@@ -0,0 +1,20 @@ >+function foo(a) { >+ var x = a + 1; >+ return function(a) { >+ return x + a; >+ }; >+} >+ >+var f = foo(42); >+noInline(f); >+ >+for (var i = 0; i < 10000; ++i) { >+ var result = f(i); >+ if (result != 42 + 1 + i) >+ throw "Error: bad result: " + result; >+} >+ >+var f = foo(43); >+var result = f(1); >+if (result != 43 + 1 + 1) >+ throw "Error: bad result: " + result; >Index: Source/JavaScriptCore/tests/stress/singleton-scope-then-realloc.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/singleton-scope-then-realloc.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/singleton-scope-then-realloc.js (working copy) >@@ -0,0 +1,20 @@ >+function foo(a) { >+ var x = a + 1; >+ return function(a) { >+ return x += a; >+ }; >+} >+ >+var f = foo(42); >+noInline(f); >+ >+for (var i = 0; i < 10000; ++i) { >+ var result = f(1); >+ if (result != 42 + 1 + i + 1) >+ throw "Error: bad result: " + result; >+} >+ >+var f = foo(43); >+var result = f(1); >+if (result != 43 + 1 + 1) >+ throw "Error: bad result: " + result; >Index: LayoutTests/ChangeLog >=================================================================== >--- LayoutTests/ChangeLog (revision 182498) >+++ LayoutTests/ChangeLog (working copy) >@@ -1,3 +1,20 @@ >+2015-04-07 Filip Pizlo <fpizlo@apple.com> >+ >+ JSC should detect singleton functions >+ https://bugs.webkit.org/show_bug.cgi?id=143232 >+ >+ Reviewed by Michael Saboff. >+ >+ * js/regress/create-lots-of-functions-expected.txt: Added. >+ * js/regress/create-lots-of-functions.html: Added. >+ * js/regress/no-inline-constructor-expected.txt: Added. >+ * js/regress/no-inline-constructor.html: Added. >+ * js/regress/script-tests/create-lots-of-functions.js: Added. >+ * js/regress/script-tests/no-inline-constructor.js: Added. >+ * js/regress/script-tests/singleton-scope.js: Added. >+ * js/regress/singleton-scope-expected.txt: Added. >+ * js/regress/singleton-scope.html: Added. >+ > 2015-04-07 Matthew Mirman <mmirman@apple.com> > > Source and stack information should get appended only to native errors >Index: LayoutTests/js/regress/create-lots-of-functions-expected.txt >=================================================================== >--- LayoutTests/js/regress/create-lots-of-functions-expected.txt (revision 0) >+++ LayoutTests/js/regress/create-lots-of-functions-expected.txt (working copy) >@@ -0,0 +1,10 @@ >+JSRegress/create-lots-of-functions >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS no exception thrown >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >Index: LayoutTests/js/regress/create-lots-of-functions.html >=================================================================== >--- LayoutTests/js/regress/create-lots-of-functions.html (revision 0) >+++ LayoutTests/js/regress/create-lots-of-functions.html (working copy) >@@ -0,0 +1,12 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="../../resources/regress-pre.js"></script> >+<script src="script-tests/create-lots-of-functions.js"></script> >+<script src="../../resources/regress-post.js"></script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >Index: LayoutTests/js/regress/no-inline-constructor-expected.txt >=================================================================== >--- LayoutTests/js/regress/no-inline-constructor-expected.txt (revision 0) >+++ LayoutTests/js/regress/no-inline-constructor-expected.txt (working copy) >@@ -0,0 +1,10 @@ >+JSRegress/no-inline-constructor >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS no exception thrown >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >Index: LayoutTests/js/regress/no-inline-constructor.html >=================================================================== >--- LayoutTests/js/regress/no-inline-constructor.html (revision 0) >+++ LayoutTests/js/regress/no-inline-constructor.html (working copy) >@@ -0,0 +1,12 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="../../resources/regress-pre.js"></script> >+<script src="script-tests/no-inline-constructor.js"></script> >+<script src="../../resources/regress-post.js"></script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >Index: LayoutTests/js/regress/singleton-scope-expected.txt >=================================================================== >--- LayoutTests/js/regress/singleton-scope-expected.txt (revision 0) >+++ LayoutTests/js/regress/singleton-scope-expected.txt (working copy) >@@ -0,0 +1,10 @@ >+JSRegress/singleton-scope >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS no exception thrown >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >Index: LayoutTests/js/regress/singleton-scope.html >=================================================================== >--- LayoutTests/js/regress/singleton-scope.html (revision 0) >+++ LayoutTests/js/regress/singleton-scope.html (working copy) >@@ -0,0 +1,12 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="../../resources/regress-pre.js"></script> >+<script src="script-tests/singleton-scope.js"></script> >+<script src="../../resources/regress-post.js"></script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >Index: LayoutTests/js/regress/script-tests/create-lots-of-functions.js >=================================================================== >--- LayoutTests/js/regress/script-tests/create-lots-of-functions.js (revision 0) >+++ LayoutTests/js/regress/script-tests/create-lots-of-functions.js (working copy) >@@ -0,0 +1,12 @@ >+function foo() { >+ var result = 0; >+ for (var i = 0; i < 100; ++i) >+ result += (function() { return i })(); >+ return result; >+} >+ >+for (var i = 0; i < 10000; ++i) { >+ var result = foo(); >+ if (result != 4950) >+ throw "Error: bad result: " + result; >+} >Index: LayoutTests/js/regress/script-tests/no-inline-constructor.js >=================================================================== >--- LayoutTests/js/regress/script-tests/no-inline-constructor.js (revision 0) >+++ LayoutTests/js/regress/script-tests/no-inline-constructor.js (working copy) >@@ -0,0 +1,13 @@ >+function Foo() { >+ var o = {f:{f:{f:{f:42}}}}; >+ this.f = 42; >+} >+ >+noInline(Foo); >+ >+for (var i = 0; i < 3000000; ++i) { >+ var result = new Foo(); >+ if (result.f != 42) >+ throw "Error: bad result: " + result.f; >+} >+ >Index: LayoutTests/js/regress/script-tests/singleton-scope.js >=================================================================== >--- LayoutTests/js/regress/script-tests/singleton-scope.js (revision 0) >+++ LayoutTests/js/regress/script-tests/singleton-scope.js (working copy) >@@ -0,0 +1,16 @@ >+function foo() { >+ var x = 42; >+ var y = 43; >+ return function(z) { >+ var result = x + y; >+ x += z; >+ y += z; >+ return result; >+ } >+} >+ >+var f = foo(); >+noInline(f); >+ >+for (var i = 0; i < 10000000; ++i) >+ f(1);
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