WebKit Bugzilla
Attachment 339653 Details for
Bug 185329
: Make a compact version of VariableEnvironment that UnlinkedFunctionExecutable stores and hash-cons these compact environments as we make them
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
c-backup.diff (text/plain), 13.54 KB, created by
Saam Barati
on 2018-05-05 11:29:03 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2018-05-05 11:29:03 PDT
Size:
13.54 KB
patch
obsolete
>Index: Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp (revision 231355) >+++ Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp (working copy) >@@ -68,7 +68,8 @@ static UnlinkedFunctionCodeBlock* genera > > UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext), debuggerMode); > >- error = BytecodeGenerator::generate(vm, function.get(), source, result, debuggerMode, executable->parentScopeTDZVariables()); >+ VariableEnvironment parentScopeTDZVariables = executable->parentScopeTDZVariables(); >+ error = BytecodeGenerator::generate(vm, function.get(), source, result, debuggerMode, &parentScopeTDZVariables); > > if (error.isValid()) > return nullptr; >@@ -104,6 +105,7 @@ UnlinkedFunctionExecutable::UnlinkedFunc > , m_inferredName(node->inferredName()) > , m_parentSourceOverride(WTFMove(parentSourceOverride)) > , m_classSource(node->classSource()) >+ , m_parentScopeTDZVariables(vm->m_compactVariableMap->get(parentScopeTDZVariables)) > { > // Make sure these bitfields are adequately wide. > ASSERT(m_constructAbility == static_cast<unsigned>(constructAbility)); >@@ -112,8 +114,6 @@ UnlinkedFunctionExecutable::UnlinkedFunc > ASSERT(m_scriptMode == static_cast<unsigned>(scriptMode)); > ASSERT(m_superBinding == static_cast<unsigned>(node->superBinding())); > ASSERT(m_derivedContextType == static_cast<unsigned>(derivedContextType)); >- >- m_parentScopeTDZVariables.swap(parentScopeTDZVariables); > } > > void UnlinkedFunctionExecutable::destroy(JSCell* cell) >Index: Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >=================================================================== >--- Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h (revision 231355) >+++ Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h (working copy) >@@ -127,7 +127,7 @@ public: > ConstructAbility constructAbility() const { return static_cast<ConstructAbility>(m_constructAbility); } > JSParserScriptMode scriptMode() const { return static_cast<JSParserScriptMode>(m_scriptMode); } > bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; } >- const VariableEnvironment* parentScopeTDZVariables() const { return &m_parentScopeTDZVariables; } >+ VariableEnvironment parentScopeTDZVariables() const { return m_parentScopeTDZVariables.environment().toVariableEnvironment(); } > > bool isArrowFunction() const { return isArrowFunctionParseMode(parseMode()); } > >@@ -176,7 +176,7 @@ private: > String m_sourceURLDirective; > String m_sourceMappingURLDirective; > >- VariableEnvironment m_parentScopeTDZVariables; >+ CompactVariableMap::Handle m_parentScopeTDZVariables; > > protected: > static void visitChildren(JSCell*, SlotVisitor&); >Index: Source/JavaScriptCore/parser/VariableEnvironment.cpp >=================================================================== >--- Source/JavaScriptCore/parser/VariableEnvironment.cpp (revision 231355) >+++ Source/JavaScriptCore/parser/VariableEnvironment.cpp (working copy) >@@ -96,4 +96,83 @@ void VariableEnvironment::markVariableAs > findResult->value.setIsExported(); > } > >+CompactVariableEnvironment::CompactVariableEnvironment(const VariableEnvironment& env) >+{ >+ m_isEverythingCaptured = env.isEverythingCaptured(); >+ m_variables.reserveInitialCapacity(env.size()); >+ m_variableMetadata.reserveInitialCapacity(env.size()); >+ m_hash = 0; >+ for (auto& pair : env) { >+ m_variables.append(pair.key); >+ m_hash ^= pair.key->hash(); >+ m_variableMetadata.append(pair.value); >+ m_hash += pair.value.bits(); >+ } >+ >+ // OOPS: sort this vector. >+ >+ if (m_isEverythingCaptured) >+ m_hash *= 2; >+} >+ >+bool CompactVariableEnvironment::operator==(const CompactVariableEnvironment& other) const >+{ >+ if (m_isEverythingCaptured != other.m_isEverythingCaptured) >+ return false; >+ if (m_variables != other.m_variables) >+ return false; >+ // OOPS: add == for VariableEnvironmentEntry >+ if (m_variableMetadata.size() != other.m_variableMetadata.size()) >+ return false; >+ for (unsigned i = 0; i < m_variableMetadata.size(); ++i) { >+ if (m_variableMetadata[i].bits() != other.m_variableMetadata[i].bits()) >+ return false; >+ } >+ return true; >+} >+ >+VariableEnvironment CompactVariableEnvironment::toVariableEnvironment() const >+{ >+ VariableEnvironment result; >+ for (size_t i = 0; i < m_variables.size(); ++i) >+ result.add(m_variables[i]).iterator->value = m_variableMetadata[i]; >+ >+ if (m_isEverythingCaptured) >+ result.markAllVariablesAsCaptured(); >+ >+ return result; >+} >+ >+CompactVariableMap::Handle CompactVariableMap::get(const VariableEnvironment& env) >+{ >+ auto* environment = new CompactVariableEnvironment(env); >+ CompactVariableMapKey key { *environment }; >+ auto addResult = m_map.add(key, 1); >+ if (addResult.isNewEntry) >+ return CompactVariableMap::Handle(*environment, *this); >+ >+ delete environment; >+ ++addResult.iterator->value; >+ return CompactVariableMap::Handle(addResult.iterator->key.environment(), *this); >+} >+ >+CompactVariableMap::Handle::~Handle() >+{ >+ if (!m_map) { >+ ASSERT(!m_environment); >+ // This happens if we were moved. >+ return; >+ } >+ >+ RELEASE_ASSERT(m_environment); >+ auto iter = m_map->m_map.find(CompactVariableMapKey(*m_environment)); >+ RELEASE_ASSERT(iter != m_map->m_map.end()); >+ --iter->value; >+ if (!iter->value) { >+ CompactVariableEnvironment* environment = &iter->key.environment(); >+ m_map->m_map.remove(iter); >+ fastFree(environment); >+ } >+} >+ > } // namespace JSC >Index: Source/JavaScriptCore/parser/VariableEnvironment.h >=================================================================== >--- Source/JavaScriptCore/parser/VariableEnvironment.h (revision 231355) >+++ Source/JavaScriptCore/parser/VariableEnvironment.h (working copy) >@@ -56,6 +56,8 @@ public: > > ALWAYS_INLINE void clearIsVar() { m_bits &= ~IsVar; } > >+ uint16_t bits() const { return m_bits; } >+ > private: > enum Traits : uint16_t { > IsCaptured = 1 << 0, >@@ -80,14 +82,11 @@ class VariableEnvironment { > private: > typedef HashMap<RefPtr<UniquedStringImpl>, VariableEnvironmentEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, VariableEnvironmentEntryHashTraits> Map; > public: >- VariableEnvironment() >- { } >- VariableEnvironment(VariableEnvironment&& other) >- : m_map(WTFMove(other.m_map)) >- , m_isEverythingCaptured(other.m_isEverythingCaptured) >- { } >- VariableEnvironment(const VariableEnvironment&) = default; >+ VariableEnvironment() = default; >+ VariableEnvironment(VariableEnvironment&& other) = default; >+ VariableEnvironment(const VariableEnvironment&) = default; // OOPS: try to remove this if possible. > VariableEnvironment& operator=(const VariableEnvironment&) = default; >+ VariableEnvironment& operator=(VariableEnvironment&&) = default; > > ALWAYS_INLINE Map::iterator begin() { return m_map.begin(); } > ALWAYS_INLINE Map::iterator end() { return m_map.end(); } >@@ -109,9 +108,119 @@ public: > void markVariableAsImported(const RefPtr<UniquedStringImpl>& identifier); > void markVariableAsExported(const RefPtr<UniquedStringImpl>& identifier); > >+ bool isEverythingCaptured() const { return m_isEverythingCaptured; } >+ > private: > Map m_map; > bool m_isEverythingCaptured { false }; > }; > >+class CompactVariableEnvironment { >+ WTF_MAKE_FAST_ALLOCATED; >+ WTF_MAKE_NONCOPYABLE(CompactVariableEnvironment); >+public: >+ CompactVariableEnvironment(const VariableEnvironment&); >+ VariableEnvironment toVariableEnvironment() const; >+ >+ bool operator==(const CompactVariableEnvironment&) const; >+ unsigned hash() const { return m_hash; } >+ >+private: >+ Vector<RefPtr<UniquedStringImpl>> m_variables; >+ Vector<VariableEnvironmentEntry> m_variableMetadata; >+ unsigned m_hash; >+ bool m_isEverythingCaptured; >+}; >+ >+struct CompactVariableMapKey { >+ CompactVariableMapKey(CompactVariableEnvironment& environment) >+ : m_environment(&environment) >+ { } >+ >+ static unsigned hash(const CompactVariableMapKey& key) { return key.m_environment->hash(); } >+ static bool equal(const CompactVariableMapKey& a, const CompactVariableMapKey& b) { return *a.m_environment == *b.m_environment; } >+ static const bool safeToCompareToEmptyOrDeleted = false; >+ static void makeDeletedValue(CompactVariableMapKey& handle) >+ { >+ handle.m_environment = reinterpret_cast<CompactVariableEnvironment*>(1); >+ } >+ bool isHashTableDeletedValue() const >+ { >+ return m_environment == reinterpret_cast<CompactVariableEnvironment*>(1); >+ } >+ bool isHashTableEmptyValue() const >+ { >+ return !m_environment; >+ } >+ >+ CompactVariableEnvironment& environment() >+ { >+ RELEASE_ASSERT(!isHashTableDeletedValue()); >+ RELEASE_ASSERT(!isHashTableEmptyValue()); >+ return *m_environment; >+ } >+ >+private: >+ CompactVariableEnvironment* m_environment; >+}; >+ >+} // namespace JSC >+ >+namespace WTF { >+ >+template<typename T> struct DefaultHash; >+template<> struct DefaultHash<JSC::CompactVariableMapKey> { >+ using Hash = JSC::CompactVariableMapKey; >+}; >+ >+template<> struct HashTraits<JSC::CompactVariableMapKey> : GenericHashTraits<JSC::CompactVariableMapKey> { >+ static const bool emptyValueIsZero = true; >+ >+ static void constructDeletedValue(JSC::CompactVariableMapKey& key) { JSC::CompactVariableMapKey::makeDeletedValue(key); } >+ static bool isDeletedValue(JSC::CompactVariableMapKey key) { return key.isHashTableDeletedValue(); } >+ >+ static const bool hasIsEmptyValueFunction = true; >+ static bool isEmptyValue(JSC::CompactVariableMapKey key) { return key.isHashTableEmptyValue(); } >+}; >+ >+} // namespace WTF >+ >+namespace JSC { >+ >+class CompactVariableMap : public RefCounted<CompactVariableMap> { >+public: >+ class Handle { >+ WTF_MAKE_NONCOPYABLE(Handle); // If we wanted this, we'd need to do a hashtable lookup and bump the refcount. >+ public: >+ Handle(CompactVariableEnvironment& environment, CompactVariableMap& map) >+ : m_environment(&environment) >+ , m_map(&map) >+ { } >+ Handle(Handle&& other) >+ : m_environment(other.m_environment) >+ , m_map(WTFMove(other.m_map)) >+ { >+ RELEASE_ASSERT(!!m_environment == !!m_map); >+ RELEASE_ASSERT(!other.m_map); >+ other.m_environment = nullptr; >+ } >+ ~Handle(); >+ >+ const CompactVariableEnvironment& environment() const >+ { >+ return *m_environment; >+ } >+ >+ private: >+ CompactVariableEnvironment* m_environment; >+ RefPtr<CompactVariableMap> m_map; >+ }; >+public: >+ Handle get(const VariableEnvironment&); >+ >+private: >+ friend class Handle; >+ HashMap<CompactVariableMapKey, unsigned> m_map; >+}; >+ > } // namespace JSC >Index: Source/JavaScriptCore/runtime/VM.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/VM.cpp (revision 231355) >+++ Source/JavaScriptCore/runtime/VM.cpp (working copy) >@@ -142,6 +142,7 @@ > #include "TypeProfiler.h" > #include "TypeProfilerLog.h" > #include "UnlinkedCodeBlock.h" >+#include "VariableEnvironment.h" > #include "VMEntryScope.h" > #include "VMInspector.h" > #include "WasmWorklist.h" >@@ -333,6 +334,7 @@ VM::VM(VMType vmType, HeapType heapType) > , interpreter(0) > , entryScope(0) > , m_regExpCache(new RegExpCache(this)) >+ , m_compactVariableMap(adoptRef(*(new CompactVariableMap))) > #if ENABLE(REGEXP_TRACING) > , m_rtTraceList(new RTTraceList()) > #endif >Index: Source/JavaScriptCore/runtime/VM.h >=================================================================== >--- Source/JavaScriptCore/runtime/VM.h (revision 231355) >+++ Source/JavaScriptCore/runtime/VM.h (working copy) >@@ -102,6 +102,7 @@ class BytecodeIntrinsicRegistry; > class CodeBlock; > class CodeCache; > class CommonIdentifiers; >+class CompactVariableMap; > class CustomGetterSetter; > class DOMAttributeGetterSetter; > class ExecState; >@@ -709,6 +710,7 @@ public: > void releaseRegExpPatternContexBuffer(); > #endif > >+ Ref<CompactVariableMap> m_compactVariableMap; > > std::unique_ptr<HasOwnPropertyCache> m_hasOwnPropertyCache; > ALWAYS_INLINE HasOwnPropertyCache* hasOwnPropertyCache() { return m_hasOwnPropertyCache.get(); } >Index: Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm >=================================================================== >--- Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (revision 231355) >+++ Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (working copy) >@@ -3220,7 +3220,10 @@ void MediaPlayerPrivateAVFoundationObjC: > void MediaPlayerPrivateAVFoundationObjC::setShouldDisableSleep(bool flag) > { > #if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR) && !ENABLE(MINIMAL_SIMULATOR) >+#pragma clang diagnostic push >+#pragma clang diagnostic ignored "-Wdeprecated-declarations" > [m_avPlayer _setPreventsSleepDuringVideoPlayback:flag]; >+#pragma clang diagnostic pop > #else > UNUSED_PARAM(flag); > #endif
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 185329
:
339653
|
339765
|
339788