Changeset 201605 in webkit
- Timestamp:
- Jun 2, 2016, 11:41:16 AM (10 years ago)
- Location:
- trunk/Source
- Files:
-
- 5 edited
-
JavaScriptCore/ChangeLog (modified) (1 diff)
-
JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (modified) (27 diffs)
-
JavaScriptCore/runtime/ConcurrentJITLock.h (modified) (3 diffs)
-
WTF/ChangeLog (modified) (1 diff)
-
WTF/wtf/Locker.h (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r201590 r201605 1 2016-06-02 Filip Pizlo <fpizlo@apple.com> 2 3 Make it easier to use NoLockingNecessary 4 https://bugs.webkit.org/show_bug.cgi?id=158306 5 6 Reviewed by Keith Miller. 7 8 Adapt to the new NoLockingNecessary API. More details in the WTF ChangeLog. 9 10 * bytecompiler/BytecodeGenerator.cpp: 11 (JSC::BytecodeGenerator::BytecodeGenerator): 12 (JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded): 13 (JSC::BytecodeGenerator::instantiateLexicalVariables): 14 (JSC::BytecodeGenerator::emitPrefillStackTDZVariables): 15 (JSC::BytecodeGenerator::initializeBlockScopedFunctions): 16 (JSC::BytecodeGenerator::hoistSloppyModeFunctionIfNecessary): 17 (JSC::BytecodeGenerator::popLexicalScopeInternal): 18 (JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration): 19 (JSC::BytecodeGenerator::variable): 20 (JSC::BytecodeGenerator::createVariable): 21 (JSC::BytecodeGenerator::emitResolveScope): 22 (JSC::BytecodeGenerator::emitPushFunctionNameScope): 23 * runtime/ConcurrentJITLock.h: 24 (JSC::ConcurrentJITLockerBase::ConcurrentJITLockerBase): 25 (JSC::ConcurrentJITLocker::ConcurrentJITLocker): 26 1 27 2016-06-01 Filip Pizlo <fpizlo@apple.com> 2 28 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r201542 r201605 369 369 // activation. 370 370 371 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);372 371 if (capturesAnyArgumentByName) { 373 372 functionSymbolTable->setArgumentsLength(vm, parameters.size()); … … 378 377 // way we lift the value into the scope. 379 378 for (unsigned i = 0; i < parameters.size(); ++i) { 380 ScopeOffset offset = functionSymbolTable->takeNextScopeOffset( locker);379 ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary); 381 380 functionSymbolTable->setArgumentOffset(vm, i, offset); 382 381 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first)) { … … 388 387 // So, we just disable it. 389 388 entry.disableWatching(); 390 functionSymbolTable->set( locker, name, entry);389 functionSymbolTable->set(NoLockingNecessary, name, entry); 391 390 } 392 391 emitOpcode(op_put_to_scope); … … 409 408 for (unsigned i = 0; i < parameters.size(); ++i) { 410 409 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first)) 411 functionSymbolTable->set( locker, name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i))));410 functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i)))); 412 411 } 413 412 … … 420 419 // because when default parameter expressions exist, they belong in their own lexical environment 421 420 // separate from the "var" lexical environment. 422 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);423 421 for (unsigned i = 0; i < parameters.size(); ++i) { 424 422 UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first); … … 429 427 // This is the easy case - just tell the symbol table about the argument. It will 430 428 // be accessed directly. 431 functionSymbolTable->set( locker, name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i))));429 functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i)))); 432 430 continue; 433 431 } 434 432 435 ScopeOffset offset = functionSymbolTable->takeNextScopeOffset( locker);433 ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary); 436 434 const Identifier& ident = 437 435 static_cast<const BindingNode*>(parameters.at(i).first)->boundProperty(); 438 functionSymbolTable->set( locker, name, SymbolTableEntry(VarOffset(offset)));436 functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(offset))); 439 437 440 438 emitOpcode(op_put_to_scope); … … 906 904 ScopeOffset offset; 907 905 908 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);909 906 if (isThisUsedInInnerArrowFunction()) { 910 offset = functionSymbolTable->takeNextScopeOffset( locker);911 functionSymbolTable->set( locker, propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset)));907 offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary); 908 functionSymbolTable->set(NoLockingNecessary, propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset))); 912 909 } 913 910 914 911 if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) { 915 912 offset = functionSymbolTable->takeNextScopeOffset(); 916 functionSymbolTable->set( locker, propertyNames().newTargetLocalPrivateName.impl(), SymbolTableEntry(VarOffset(offset)));913 functionSymbolTable->set(NoLockingNecessary, propertyNames().newTargetLocalPrivateName.impl(), SymbolTableEntry(VarOffset(offset))); 917 914 } 918 915 919 916 if (isConstructor() && constructorKind() == ConstructorKind::Derived && isSuperUsedInInnerArrowFunction()) { 920 offset = functionSymbolTable->takeNextScopeOffset( locker);921 functionSymbolTable->set( locker, propertyNames().derivedConstructorPrivateName.impl(), SymbolTableEntry(VarOffset(offset)));917 offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary); 918 functionSymbolTable->set(NoLockingNecessary, propertyNames().derivedConstructorPrivateName.impl(), SymbolTableEntry(VarOffset(offset))); 922 919 } 923 920 … … 1765 1762 bool hasCapturedVariables = false; 1766 1763 { 1767 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);1768 1764 for (auto& entry : lexicalVariables) { 1769 1765 ASSERT(entry.value.isLet() || entry.value.isConst() || entry.value.isFunction()); 1770 1766 ASSERT(!entry.value.isVar()); 1771 SymbolTableEntry symbolTableEntry = symbolTable->get( locker, entry.key.get());1767 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get()); 1772 1768 ASSERT(symbolTableEntry.isNull()); 1773 1769 … … 1782 1778 VarOffset varOffset; 1783 1779 if (varKind == VarKind::Scope) { 1784 varOffset = VarOffset(symbolTable->takeNextScopeOffset( locker));1780 varOffset = VarOffset(symbolTable->takeNextScopeOffset(NoLockingNecessary)); 1785 1781 hasCapturedVariables = true; 1786 1782 } else { … … 1796 1792 1797 1793 SymbolTableEntry newEntry(varOffset, entry.value.isConst() ? ReadOnly : 0); 1798 symbolTable->add( locker, entry.key.get(), newEntry);1794 symbolTable->add(NoLockingNecessary, entry.key.get(), newEntry); 1799 1795 } 1800 1796 } … … 1806 1802 // Prefill stack variables with the TDZ empty value. 1807 1803 // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated. 1808 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);1809 1804 for (auto& entry : lexicalVariables) { 1810 1805 // Imported bindings which are not the namespace bindings are not allocated … … 1818 1813 continue; 1819 1814 1820 SymbolTableEntry symbolTableEntry = symbolTable->get( locker, entry.key.get());1815 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get()); 1821 1816 ASSERT(!symbolTableEntry.isNull()); 1822 1817 VarOffset offset = symbolTableEntry.varOffset(); … … 1954 1949 RefPtr<RegisterID> temp = newTemporary(); 1955 1950 int symbolTableIndex = constantSymbolTable ? constantSymbolTable->index() : 0; 1956 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);1957 1951 for (FunctionMetadataNode* function : functionStack) { 1958 1952 const Identifier& name = function->ident(); … … 1961 1955 RELEASE_ASSERT(iter->value.isFunction()); 1962 1956 // We purposefully don't hold the symbol table lock around this loop because emitNewFunctionExpressionCommon may GC. 1963 SymbolTableEntry entry = symbolTable->get( locker, name.impl());1957 SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, name.impl()); 1964 1958 RELEASE_ASSERT(!entry.isNull()); 1965 1959 emitNewFunctionExpressionCommon(temp.get(), function); … … 1986 1980 SymbolTable* varSymbolTable = varScope.m_symbolTable; 1987 1981 ASSERT(varSymbolTable->scopeType() == SymbolTable::ScopeType::VarScope); 1988 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary); 1989 SymbolTableEntry entry = varSymbolTable->get(locker, functionName.impl()); 1982 SymbolTableEntry entry = varSymbolTable->get(NoLockingNecessary, functionName.impl()); 1990 1983 ASSERT(!entry.isNull()); 1991 1984 bool isLexicallyScoped = false; … … 2013 2006 SymbolTable* symbolTable = stackEntry.m_symbolTable; 2014 2007 bool hasCapturedVariables = false; 2015 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);2016 2008 for (auto& entry : environment) { 2017 2009 if (entry.value.isCaptured()) { … … 2019 2011 continue; 2020 2012 } 2021 SymbolTableEntry symbolTableEntry = symbolTable->get( locker, entry.key.get());2013 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get()); 2022 2014 ASSERT(!symbolTableEntry.isNull()); 2023 2015 VarOffset offset = symbolTableEntry.varOffset(); … … 2067 2059 activationValuesToCopyOver.reserveInitialCapacity(symbolTable->scopeSize()); 2068 2060 2069 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary); 2070 for (auto end = symbolTable->end(locker), ptr = symbolTable->begin(locker); ptr != end; ++ptr) { 2061 for (auto end = symbolTable->end(NoLockingNecessary), ptr = symbolTable->begin(NoLockingNecessary); ptr != end; ++ptr) { 2071 2062 if (!ptr->value.varOffset().isScope()) 2072 2063 continue; … … 2100 2091 2101 2092 { 2102 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);2103 2093 for (auto pair : activationValuesToCopyOver) { 2104 2094 const Identifier& identifier = pair.second; 2105 SymbolTableEntry entry = symbolTable->get( locker, identifier.impl());2095 SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, identifier.impl()); 2106 2096 RELEASE_ASSERT(!entry.isNull()); 2107 2097 RegisterID* transitionValue = pair.first; … … 2138 2128 // } 2139 2129 // } 2140 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);2141 2130 for (unsigned i = m_symbolTableStack.size(); i--; ) { 2142 2131 SymbolTableStackEntry& stackEntry = m_symbolTableStack[i]; … … 2144 2133 return Variable(property); 2145 2134 SymbolTable* symbolTable = stackEntry.m_symbolTable; 2146 SymbolTableEntry symbolTableEntry = symbolTable->get( locker, property.impl());2135 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, property.impl()); 2147 2136 if (symbolTableEntry.isNull()) 2148 2137 continue; … … 2184 2173 { 2185 2174 ASSERT(property != propertyNames().thisIdentifier); 2186 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary); 2187 SymbolTableEntry entry = symbolTable->get(locker, property.impl()); 2175 SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, property.impl()); 2188 2176 2189 2177 if (!entry.isNull()) { … … 2209 2197 VarOffset varOffset; 2210 2198 if (varKind == VarKind::Scope) 2211 varOffset = VarOffset(symbolTable->takeNextScopeOffset( locker));2199 varOffset = VarOffset(symbolTable->takeNextScopeOffset(NoLockingNecessary)); 2212 2200 else { 2213 2201 ASSERT(varKind == VarKind::Stack); … … 2215 2203 } 2216 2204 SymbolTableEntry newEntry(varOffset, 0); 2217 symbolTable->add( locker, property.impl(), newEntry);2205 symbolTable->add(NoLockingNecessary, property.impl(), newEntry); 2218 2206 2219 2207 if (varKind == VarKind::Stack) { … … 2268 2256 // requires weird things because it is a shameful pile of nonsense, but block scoping would make 2269 2257 // that code sensible and obviate the need for us to do bad things. 2270 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);2271 2258 for (unsigned i = m_symbolTableStack.size(); i--; ) { 2272 2259 SymbolTableStackEntry& stackEntry = m_symbolTableStack[i]; … … 2275 2262 RELEASE_ASSERT(!stackEntry.m_isWithScope); 2276 2263 2277 if (stackEntry.m_symbolTable->get( locker, variable.ident().impl()).isNull())2264 if (stackEntry.m_symbolTable->get(NoLockingNecessary, variable.ident().impl()).isNull()) 2278 2265 continue; 2279 2266 … … 3785 3772 ASSERT_UNUSED(numVars, m_codeBlock->m_numVars == static_cast<int>(numVars + 1)); // Should have only created one new "var" for the function name scope. 3786 3773 bool shouldTreatAsLexicalVariable = isStrictMode(); 3787 ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary); 3788 Variable functionVar = variableForLocalEntry(property, m_symbolTableStack.last().m_symbolTable->get(locker, property.impl()), m_symbolTableStack.last().m_symbolTableConstantIndex, shouldTreatAsLexicalVariable); 3774 Variable functionVar = variableForLocalEntry(property, m_symbolTableStack.last().m_symbolTable->get(NoLockingNecessary, property.impl()), m_symbolTableStack.last().m_symbolTableConstantIndex, shouldTreatAsLexicalVariable); 3789 3775 emitPutToScope(m_symbolTableStack.last().m_scope, functionVar, callee, ThrowIfNotFound, InitializationMode::NotInitialization); 3790 3776 } -
trunk/Source/JavaScriptCore/runtime/ConcurrentJITLock.h
r199848 r201605 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 54 54 } 55 55 56 enum NoLockingNecessaryTag { NoLockingNecessary };57 56 explicit ConcurrentJITLockerBase(NoLockingNecessaryTag) 58 : m_locker( ConcurrentJITLockerImpl::NoLockingNecessary)57 : m_locker(NoLockingNecessary) 59 58 { 60 59 } … … 126 125 } 127 126 128 ConcurrentJITLocker( ConcurrentJITLockerBase::NoLockingNecessaryTag)129 : ConcurrentJITLockerBase( ConcurrentJITLockerBase::NoLockingNecessary)127 ConcurrentJITLocker(NoLockingNecessaryTag) 128 : ConcurrentJITLockerBase(NoLockingNecessary) 130 129 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG) 131 130 , m_disallowGC(Nullopt) -
trunk/Source/WTF/ChangeLog
r201594 r201605 1 2016-06-02 Filip Pizlo <fpizlo@apple.com> 2 3 Make it easier to use NoLockingNecessary 4 https://bugs.webkit.org/show_bug.cgi?id=158306 5 6 Reviewed by Keith Miller. 7 8 An idiom that we borrowed from LLVM is that if a function requires a lock to be held, we 9 have it take a const Locker& as its first argument. This may not communicate which lock is 10 to be held, but it does help us to remember that some lock must be held. So far, it's been 11 relatively easy to then figure out which lock. We've had bugs where we forgot to hold a 12 lock but I don't remember the last time we had a bug where we grabbed the wrong lock. 13 14 But sometimes, we know at the point where we call such a method that we actually don't 15 need to hold any lock. This usually happens during object construction. If we're 16 constructing some object then we usually know that we have not escaped it yet, so we don't 17 need to waste time acquiring its lock. We could solve this by having a separate set of 18 methods that don't do or require locking. This would be cumbersome, since usually for 19 every variant that takes const Locker&, there is already one that doesn't, and that one 20 will grab the lock for you. So this means having a third variant, that also doesn't take a 21 const Locker&, but does no locking. That's pretty weird. 22 23 So, we introduced NoLockingNecessary for situations like this. The idiom went like so: 24 25 Locker<Whatever> locker(Locker<Whatever>::NoLockingNecessary) 26 stuff->foo(locker); 27 28 Usually though, there would be some distance between where the locker is defined and where 29 it's used, so when you just look at stuff->foo(locker) in isolation you don't know if this 30 is a real locker or a NoLockingNecessary cast. Also, requiring two lines for this just 31 adds code. 32 33 This change makes this easier. Now you can just do: 34 35 stuff->foo(NoLockingNecessary). 36 37 This is because NoLockingNecessary has been pulled out into the WTF namespace (and is 38 usinged from the global namespace) and the Locker<> constructor that takes 39 NoLockingNecessaryTag is now implicit. 40 41 The only possible downside of this change is that people might use this idiom more 42 frequently now that it's easier to use. I don't think that's a bad thing. I'm now 43 convinced that this is not a bad idiom. When I was fixing an unrelated bug, I almost went 44 the way of adding more locking to some core JSC data structures, and in the process, I 45 needed to use NoLockingNecessary. It's clear that this is a general-purpose idiom and we 46 should not impose artificial constraints on its use. 47 48 * wtf/Locker.h: 49 (WTF::Locker::Locker): 50 (WTF::Locker::~Locker): 51 1 52 2016-06-01 Brady Eidson <beidson@apple.com> 2 53 -
trunk/Source/WTF/wtf/Locker.h
r199848 r201605 1 1 /* 2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2013, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 namespace WTF { 34 34 35 enum NoLockingNecessaryTag { NoLockingNecessary }; 36 35 37 template <typename T> class Locker { 36 38 WTF_MAKE_NONCOPYABLE(Locker); … … 39 41 explicit Locker(T* lockable) : m_lockable(lockable) { lock(); } 40 42 41 enum NoLockingNecessaryTag { NoLockingNecessary };42 43 // You should be wary of using this constructor. It's only applicable 43 44 // in places where there is a locking protocol for a particular object … … 45 46 // this often happens when an object is newly allocated and it can not 46 47 // be accessed concurrently. 47 explicitLocker(NoLockingNecessaryTag) : m_lockable(nullptr) { }48 Locker(NoLockingNecessaryTag) : m_lockable(nullptr) { } 48 49 49 50 ~Locker() … … 71 72 72 73 using WTF::Locker; 74 using WTF::NoLockingNecessaryTag; 75 using WTF::NoLockingNecessary; 73 76 74 77 #endif
Note:
See TracChangeset
for help on using the changeset viewer.