Changeset 174789 in webkit
- Timestamp:
- Oct 16, 2014 12:55:14 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r174762 r174789 1 2014-10-16 Saam Barati <saambarati1@gmail.com> 2 3 Have the ProfileType node in the DFG convert to a structure check where it can 4 https://bugs.webkit.org/show_bug.cgi?id=137596 5 6 Reviewed by Filip Pizlo. 7 8 TypeSet now keeps track of the live set of Structures it has seen. 9 It no longer nukes everything during GC. It now only removes unmarked 10 structures during GC. This modification allows the ProfileType node 11 to convert into a CheckStructure node safely in the DFG. 12 13 This change brings up the conversion rate from ProfileType to Check 14 or CheckStructrue from ~45% to ~65%. This change also speeds the 15 type profiler up significantly: consistently between 2x-20x faster. 16 17 This patch also does some slight refactoring: a few type profiler 18 related fields are moved from VM to TypeProfiler. 19 20 * bytecode/CodeBlock.cpp: 21 (JSC::CodeBlock::CodeBlock): 22 * dfg/DFGFixupPhase.cpp: 23 (JSC::DFG::FixupPhase::fixupNode): 24 * dfg/DFGNode.h: 25 (JSC::DFG::Node::convertToCheckStructure): 26 * heap/Heap.cpp: 27 (JSC::Heap::collect): 28 * runtime/SymbolTable.cpp: 29 (JSC::SymbolTable::uniqueIDForVariable): 30 * runtime/SymbolTable.h: 31 * runtime/TypeLocationCache.cpp: 32 (JSC::TypeLocationCache::getTypeLocation): 33 * runtime/TypeProfiler.cpp: 34 (JSC::TypeProfiler::TypeProfiler): 35 (JSC::TypeProfiler::nextTypeLocation): 36 (JSC::TypeProfiler::invalidateTypeSetCache): 37 (JSC::TypeProfiler::dumpTypeProfilerData): 38 * runtime/TypeProfiler.h: 39 (JSC::TypeProfiler::getNextUniqueVariableID): 40 * runtime/TypeProfilerLog.cpp: 41 (JSC::TypeProfilerLog::processLogEntries): 42 * runtime/TypeSet.cpp: 43 (JSC::TypeSet::addTypeInformation): 44 (JSC::TypeSet::invalidateCache): 45 * runtime/TypeSet.h: 46 (JSC::TypeSet::structureSet): 47 * runtime/VM.cpp: 48 (JSC::VM::VM): 49 (JSC::VM::enableTypeProfiler): 50 (JSC::VM::disableTypeProfiler): 51 (JSC::VM::dumpTypeProfilerData): 52 (JSC::VM::nextTypeLocation): Deleted. 53 (JSC::VM::invalidateTypeSetCache): Deleted. 54 * runtime/VM.h: 55 (JSC::VM::typeProfiler): 56 (JSC::VM::getNextUniqueVariableID): Deleted. 57 * tests/typeProfiler/dfg-jit-optimizations.js: 58 1 59 2014-10-16 Adrien Destugues <pulkomandy@gmail.com> 2 60 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r174610 r174789 2006 2006 2007 2007 case op_profile_type: { 2008 RELEASE_ASSERT(vm()->typeProfiler()); 2008 2009 // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType? 2009 2010 size_t instructionOffset = i + opLength - 1; -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r174749 r174789 1136 1136 node->convertToCheck(); 1137 1137 fixEdge<OtherUse>(node->child1()); 1138 } else if (typeSet->doesTypeConformTo(TypeObject)) { 1139 StructureSet set = typeSet->structureSet(); 1140 if (!set.isEmpty()) { 1141 node->convertToCheckStructure(m_graph.addStructureSet(set)); 1142 fixEdge<CellUse>(node->child1()); 1143 } 1138 1144 } 1139 1145 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r174167 r174789 381 381 setOpAndDefaultFlags(Check); 382 382 } 383 384 void convertToCheckStructure(StructureSet* set) 385 { 386 setOpAndDefaultFlags(CheckStructure); 387 m_opInfo = bitwise_cast<uintptr_t>(set); 388 } 383 389 384 390 void replaceWith(Node* other) -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r173069 r174789 983 983 DeferGCForAWhile awhile(*this); 984 984 vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC")); 985 vm()->invalidateTypeSetCache();986 985 } 987 986 … … 1012 1011 1013 1012 JAVASCRIPTCORE_GC_MARKED(); 1013 1014 if (vm()->typeProfiler()) 1015 vm()->typeProfiler()->invalidateTypeSetCache(); 1014 1016 1015 1017 reapWeakHandles(); -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r172820 r174789 33 33 #include "JSCInlines.h" 34 34 #include "SlotVisitorInlines.h" 35 #include "TypeProfiler.h" 35 36 #include "VariableWatchpointSetInlines.h" 36 37 … … 212 213 GlobalVariableID id = iter->value; 213 214 if (id == TypeProfilerNeedsUniqueIDGeneration) { 214 id = vm. getNextUniqueVariableID();215 id = vm.typeProfiler()->getNextUniqueVariableID(); 215 216 m_typeProfilingRareData->m_uniqueIDMap.set(key, id); 216 217 m_typeProfilingRareData->m_uniqueTypeSetMap.set(key, TypeSet::create()); // Make a new global typeset for this corresponding ID. -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r172820 r174789 32 32 #include "ConcurrentJITLock.h" 33 33 #include "JSObject.h" 34 #include "Type Set.h"34 #include "TypeLocation.h" 35 35 #include "VariableWatchpointSet.h" 36 36 #include <memory> -
trunk/Source/JavaScriptCore/runtime/TypeLocationCache.cpp
r172614 r174789 28 28 #include "TypeLocationCache.h" 29 29 30 #include "TypeProfiler.h" 30 31 #include "VM.h" 31 32 … … 42 43 bool isNewLocation = false; 43 44 if (m_locationMap.find(key) == m_locationMap.end()) { 44 TypeLocation* location = vm->nextTypeLocation(); 45 ASSERT(vm->typeProfiler()); 46 TypeLocation* location = vm->typeProfiler()->nextTypeLocation(); 45 47 location->m_globalVariableID = globalVariableID; 46 48 location->m_sourceID = sourceID; -
trunk/Source/JavaScriptCore/runtime/TypeProfiler.cpp
r174167 r174789 33 33 34 34 static const bool verbose = false; 35 36 TypeProfiler::TypeProfiler() 37 : m_nextUniqueVariableID(1) 38 { 39 } 35 40 36 41 void TypeProfiler::logTypesForTypeLocation(TypeLocation* location) … … 137 142 } 138 143 144 TypeLocation* TypeProfiler::nextTypeLocation() 145 { 146 return m_typeLocationInfo.add(); 147 } 148 149 void TypeProfiler::invalidateTypeSetCache() 150 { 151 for (Bag<TypeLocation>::iterator iter = m_typeLocationInfo.begin(); !!iter; ++iter) { 152 TypeLocation* location = *iter; 153 location->m_instructionTypeSet->invalidateCache(); 154 if (location->m_globalTypeSet) 155 location->m_globalTypeSet->invalidateCache(); 156 } 157 } 158 159 void TypeProfiler::dumpTypeProfilerData() 160 { 161 for (Bag<TypeLocation>::iterator iter = m_typeLocationInfo.begin(); !!iter; ++iter) { 162 TypeLocation* location = *iter; 163 logTypesForTypeLocation(location); 164 } 165 } 166 139 167 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/TypeProfiler.h
r173505 r174789 29 29 #include "CodeBlock.h" 30 30 #include "FunctionHasExecutedCache.h" 31 #include "TypeLocation.h" 31 32 #include "TypeLocationCache.h" 33 #include <wtf/Bag.h> 32 34 #include <wtf/HashMap.h> 33 35 #include <wtf/Vector.h> … … 39 41 40 42 namespace JSC { 41 42 class TypeLocation;43 43 44 44 struct QueryKey { … … 95 95 class TypeProfiler { 96 96 public: 97 TypeProfiler(); 97 98 void logTypesForTypeLocation(TypeLocation*); 98 99 JS_EXPORT_PRIVATE String typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptor, unsigned offset, intptr_t sourceID); … … 101 102 TypeLocationCache* typeLocationCache() { return &m_typeLocationCache; } 102 103 TypeLocation* findLocation(unsigned divot, intptr_t sourceID, TypeProfilerSearchDescriptor); 104 GlobalVariableID getNextUniqueVariableID() { return m_nextUniqueVariableID++; } 105 TypeLocation* nextTypeLocation(); 106 void invalidateTypeSetCache(); 107 void dumpTypeProfilerData(); 103 108 104 109 private: … … 109 114 typedef HashMap<QueryKey, TypeLocation*> TypeLocationQueryCache; 110 115 TypeLocationQueryCache m_queryCache; 116 GlobalVariableID m_nextUniqueVariableID; 117 Bag<TypeLocation> m_typeLocationInfo; 111 118 }; 112 119 -
trunk/Source/JavaScriptCore/runtime/TypeProfilerLog.cpp
r172820 r174789 60 60 double before = currentTimeMS(); 61 61 LogEntry* entry = m_logStartPtr; 62 HashMap<Structure ID, RefPtr<StructureShape>> seenShapes;62 HashMap<Structure*, RefPtr<StructureShape>> seenShapes; 63 63 while (entry != m_currentLogEntryPtr) { 64 64 StructureID id = entry->structureID; 65 65 RefPtr<StructureShape> shape; 66 66 JSValue value = entry->value; 67 Structure* structure = 0; 67 68 if (id) { 68 auto iter = seenShapes.find(id); 69 structure = Heap::heap(value.asCell())->structureIDTable().get(id); 70 auto iter = seenShapes.find(structure); 69 71 if (iter == seenShapes.end()) { 70 shape = Heap::heap(value.asCell())->structureIDTable().get(entry->structureID)->toStructureShape(value);71 seenShapes.set( id, shape);72 shape = structure->toStructureShape(value); 73 seenShapes.set(structure, shape); 72 74 } else 73 75 shape = iter->value; … … 78 80 location->m_lastSeenType = type; 79 81 if (location->m_globalTypeSet) 80 location->m_globalTypeSet->addTypeInformation(type, shape, id);81 location->m_instructionTypeSet->addTypeInformation(type, shape, id);82 location->m_globalTypeSet->addTypeInformation(type, shape, structure); 83 location->m_instructionTypeSet->addTypeInformation(type, shape, structure); 82 84 83 85 entry++; -
trunk/Source/JavaScriptCore/runtime/TypeSet.cpp
r174292 r174789 68 68 } 69 69 70 void TypeSet::addTypeInformation(RuntimeType type, PassRefPtr<StructureShape> prpNewShape, Structure ID id)70 void TypeSet::addTypeInformation(RuntimeType type, PassRefPtr<StructureShape> prpNewShape, Structure* structure) 71 71 { 72 72 RefPtr<StructureShape> newShape = prpNewShape; 73 73 m_seenTypes = m_seenTypes | type; 74 74 75 if (id && newShape && type != TypeString) { 76 ASSERT(m_structureIDCache.isValidValue(id)); 77 auto addResult = m_structureIDCache.add(id); 78 if (addResult.isNewEntry) { 75 if (structure && newShape && type != TypeString) { 76 if (!m_structureSet.contains(structure)) { 77 m_structureSet.add(structure); 79 78 // Make one more pass making sure that: 80 // - We don't have two instances of the same shape. (Same shapes may have different Structure IDs).79 // - We don't have two instances of the same shape. (Same shapes may have different Structures). 81 80 // - We don't have two shapes that share the same prototype chain. If these shapes share the same 82 81 // prototype chain, they will be merged into one shape. … … 108 107 void TypeSet::invalidateCache() 109 108 { 110 m_structureIDCache.clear(); 109 auto keepMarkedStructuresFilter = [] (Structure* structure) -> bool { return Heap::isMarked(structure); }; 110 m_structureSet.genericFilter(keepMarkedStructuresFilter); 111 111 } 112 112 -
trunk/Source/JavaScriptCore/runtime/TypeSet.h
r174292 r174789 27 27 #define TypeSet_h 28 28 29 #include "Structure IDTable.h"29 #include "StructureSet.h" 30 30 #include <wtf/HashSet.h> 31 31 #include <wtf/RefCounted.h> … … 98 98 static PassRefPtr<TypeSet> create() { return adoptRef(new TypeSet); } 99 99 TypeSet(); 100 void addTypeInformation(RuntimeType, PassRefPtr<StructureShape>, Structure ID);100 void addTypeInformation(RuntimeType, PassRefPtr<StructureShape>, Structure*); 101 101 static RuntimeType getRuntimeTypeForValue(JSValue); 102 102 void invalidateCache(); … … 111 111 bool doesTypeConformTo(uint32_t test) const; 112 112 uint32_t seenTypes() const { return m_seenTypes; } 113 StructureSet structureSet() const { return m_structureSet; }; 113 114 114 115 private: 115 116 116 uint32_t m_seenTypes; 117 117 bool m_isOverflown; 118 118 Vector<RefPtr<StructureShape>> m_structureHistory; 119 HashSet<StructureID> m_structureIDCache;119 StructureSet m_structureSet; 120 120 }; 121 121 -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r173949 r174789 192 192 , m_enabledProfiler(nullptr) 193 193 , m_builtinExecutables(BuiltinExecutables::create(*this)) 194 , m_nextUniqueVariableID(1)195 194 , m_typeProfilerEnabledCount(0) 196 195 { … … 899 898 } 900 899 901 TypeLocation* VM::nextTypeLocation()902 {903 RELEASE_ASSERT(!!m_typeLocationInfo);904 905 return m_typeLocationInfo->add();906 }907 908 900 bool VM::enableTypeProfiler() 909 901 { … … 912 904 m_typeProfiler = std::make_unique<TypeProfiler>(); 913 905 m_typeProfilerLog = std::make_unique<TypeProfilerLog>(); 914 m_typeLocationInfo = std::make_unique<Bag<TypeLocation>>();915 906 needsToRecompile = true; 916 907 } … … 929 920 m_typeProfiler.reset(nullptr); 930 921 m_typeProfilerLog.reset(nullptr); 931 m_typeLocationInfo.reset(nullptr);932 922 needsToRecompile = true; 933 923 } … … 942 932 943 933 typeProfilerLog()->processLogEntries(ASCIILiteral("VM Dump Types")); 944 TypeProfiler* profiler = m_typeProfiler.get(); 945 for (Bag<TypeLocation>::iterator iter = m_typeLocationInfo->begin(); !!iter; ++iter) { 946 TypeLocation* location = *iter; 947 profiler->logTypesForTypeLocation(location); 948 } 949 } 950 951 void VM::invalidateTypeSetCache() 952 { 953 RELEASE_ASSERT(typeProfiler()); 954 955 for (Bag<TypeLocation>::iterator iter = m_typeLocationInfo->begin(); !!iter; ++iter) { 956 TypeLocation* location = *iter; 957 location->m_instructionTypeSet->invalidateCache(); 958 if (location->m_globalTypeSet) 959 location->m_globalTypeSet->invalidateCache(); 960 } 934 typeProfiler()->dumpTypeProfilerData(); 961 935 } 962 936 -
trunk/Source/JavaScriptCore/runtime/VM.h
r173304 r174789 47 47 #include "ThunkGenerators.h" 48 48 #include "TypedArrayController.h" 49 #include "TypeLocation.h"50 49 #include "VMEntryRecord.h" 51 50 #include "Watchdog.h" … … 516 515 TypeProfilerLog* typeProfilerLog() { return m_typeProfilerLog.get(); } 517 516 TypeProfiler* typeProfiler() { return m_typeProfiler.get(); } 518 TypeLocation* nextTypeLocation();519 517 JS_EXPORT_PRIVATE void dumpTypeProfilerData(); 520 void invalidateTypeSetCache();521 GlobalVariableID getNextUniqueVariableID() { return m_nextUniqueVariableID++; }522 518 523 519 private: … … 571 567 std::unique_ptr<TypeProfiler> m_typeProfiler; 572 568 std::unique_ptr<TypeProfilerLog> m_typeProfilerLog; 573 GlobalVariableID m_nextUniqueVariableID;574 569 unsigned m_typeProfilerEnabledCount; 575 std::unique_ptr<Bag<TypeLocation>> m_typeLocationInfo;576 570 }; 577 571 -
trunk/Source/JavaScriptCore/tests/typeProfiler/dfg-jit-optimizations.js
r174167 r174789 37 37 } 38 38 } 39 40 function testStrucure(obj) { return obj; } 41 var obj = {x: 20}; 42 tierUpToDFG(testStrucure, obj); 43 var types = findTypeForExpression(testStrucure, "obj"); 44 assert(types.instructionTypeSet.structures.length === 1, "variable 'test' should have exactly structure"); 45 assert(types.instructionTypeSet.structures[0].fields.length === 1, "variable 'test' should have exactly ONE field"); 46 assert(types.instructionTypeSet.structures[0].fields.indexOf("x") !== -1, "variable 'test' should have field 'x'"); 47 48 testStrucure({x:20, y: 40}) 49 types = findTypeForExpression(testStrucure, "obj"); 50 assert(types.instructionTypeSet.structures.length === 1, "variable 'test' should have still have exactly one structure"); 51 assert(types.instructionTypeSet.structures[0].fields.indexOf("x") !== -1, "variable 'test' should have field 'x'"); 52 assert(types.instructionTypeSet.structures[0].optionalFields.indexOf("y") !== -1, "variable 'test' should have field optional field 'y'");
Note: See TracChangeset
for help on using the changeset viewer.