Changeset 205520 in webkit
- Timestamp:
- Sep 6, 2016 4:22:01 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 14 added
- 65 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r205511 r205520 1 2016-09-06 Saam Barati <sbarati@apple.com> 2 3 Make JSMap and JSSet faster 4 https://bugs.webkit.org/show_bug.cgi?id=160989 5 6 Reviewed by Filip Pizlo. 7 8 * microbenchmarks/dense-set.js: Added. 9 (bench): 10 * microbenchmarks/large-map-iteration-with-additions.js: Added. 11 (bar): 12 (foo): 13 * microbenchmarks/large-map-iteration-with-mutation.js: Added. 14 (bar): 15 (foo): 16 * microbenchmarks/large-map-iteration.js: Added. 17 (bar): 18 (foo): 19 * microbenchmarks/map-get-get-cse.js: Added. 20 (bar): 21 (foo): 22 * microbenchmarks/map-has-get-cse-opportunity.js: Added. 23 (bar): 24 (foo): 25 * microbenchmarks/sparse-set.js: Added. 26 (bench): 27 * stress/map-cse-correctness.js: Added. 28 (assert): 29 (testHas): 30 (testGet): 31 (foo): 32 * stress/map-iteration.js: Added. 33 (assert): 34 (test1): 35 (test2): 36 (test3): 37 (test4): 38 (test5): 39 (test6): 40 (test7): 41 (test8): 42 (test9): 43 (test10): 44 (test11): 45 (test12): 46 (test13): 47 (test14): 48 (test15): 49 (test16): 50 (test17): 51 (test18): 52 1 53 2016-09-06 Benjamin Poulain <bpoulain@apple.com> 2 54 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r205507 r205520 673 673 runtime/GeneratorPrototype.cpp 674 674 runtime/GetterSetter.cpp 675 runtime/HashMapImpl.cpp 675 676 runtime/Identifier.cpp 676 677 runtime/IndexingType.cpp … … 758 759 runtime/LiteralParser.cpp 759 760 runtime/Lookup.cpp 761 runtime/MapBase.cpp 760 762 runtime/MapConstructor.cpp 761 763 runtime/MapIteratorPrototype.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r205511 r205520 1 2016-09-06 Saam Barati <sbarati@apple.com> 2 3 Make JSMap and JSSet faster 4 https://bugs.webkit.org/show_bug.cgi?id=160989 5 6 Reviewed by Filip Pizlo. 7 8 This patch revamps how we implement Map and Set. It uses 9 a new hash map implementation. The hash map uses linear 10 probing and it uses Wang's 64 bit hash function for JSValues 11 that aren't strings. Strings use StringImpl's hash function. 12 The reason I wanted to roll our own HashTable is twofold: 13 I didn't want to inline WTF::HashMap's implementation into our 14 JIT, since that seems error prone and unmaintainable. Also, I wanted 15 a different structure for hash map buckets where buckets also exist in 16 a linked list. 17 18 The reason for making buckets part of a linked list is that iteration 19 is now simple. Iteration works by just traversing a linked list. 20 This design also allows for a simple implementation when doing iteration 21 while the hash table is mutating. Whenever we remove a bucket from 22 the hash table, it is removed from the list, meaning items in the 23 list don't point to it. However, the removed bucket will still point 24 to things that are either in the list, or have also been removed. 25 e.g, from a removed bucket, you can always follow pointers until you 26 either find an item in the list, or you find the tail of the list. 27 This is a really nice property because it means that a Map or Set 28 does not need to reason about the all the iterators that point 29 into its list. Also, whenever we add items to the Map or Set, we 30 hijack the tail as the new item, and make the new item point to a newly 31 created tail. This means that any iterator that pointed to the "tail" now 32 points to non-tail items. This makes the implementation of adding things 33 to the Map/Set while iterating easy. 34 35 I also made Map.prototype.get, Map.prototype.has, and Set.prototype.has 36 into intrinsics in the DFG. The IR can now reason about hash map 37 operations and can even do CSE over Wang's hash function, hash map 38 bucket lookups, hash map bucket loads, and testing if a key is in 39 the hash table. This makes code patterns for Map like so, super fast 40 in the FTL, since we will only be doing a single hash and hash bucket lookup: 41 42 ``` 43 function getKeyIfPresent(map, key) { 44 if (map.has(key)) 45 return map.get(key); 46 } 47 ``` 48 49 This patch is roughly an 8% speedup on ES6SampleBench. 50 51 52 * CMakeLists.txt: 53 * JavaScriptCore.xcodeproj/project.pbxproj: 54 * assembler/MacroAssemblerARM64.h: 55 (JSC::MacroAssemblerARM64::not64): 56 * bytecode/SpeculatedType.cpp: 57 (JSC::speculationFromClassInfo): 58 * bytecode/SpeculatedType.h: 59 * dfg/DFGAbstractInterpreterInlines.h: 60 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 61 (JSC::DFG::AbstractInterpreter<AbstractStateType>::execute): 62 * dfg/DFGByteCodeParser.cpp: 63 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 64 * dfg/DFGClobberize.h: 65 (JSC::DFG::clobberize): 66 * dfg/DFGDoesGC.cpp: 67 (JSC::DFG::doesGC): 68 * dfg/DFGEdge.h: 69 (JSC::DFG::Edge::shift): 70 (JSC::DFG::Edge::makeWord): 71 * dfg/DFGFixupPhase.cpp: 72 (JSC::DFG::FixupPhase::fixupNode): 73 * dfg/DFGHeapLocation.cpp: 74 (WTF::printInternal): 75 * dfg/DFGHeapLocation.h: 76 * dfg/DFGNode.h: 77 (JSC::DFG::Node::hasHeapPrediction): 78 * dfg/DFGNodeType.h: 79 * dfg/DFGOperations.cpp: 80 * dfg/DFGOperations.h: 81 * dfg/DFGPredictionPropagationPhase.cpp: 82 * dfg/DFGSafeToExecute.h: 83 (JSC::DFG::SafeToExecuteEdge::operator()): 84 (JSC::DFG::safeToExecute): 85 * dfg/DFGSpeculativeJIT.cpp: 86 (JSC::DFG::SpeculativeJIT::speculateMapObject): 87 (JSC::DFG::SpeculativeJIT::speculateSetObject): 88 (JSC::DFG::SpeculativeJIT::speculate): 89 * dfg/DFGSpeculativeJIT.h: 90 (JSC::DFG::SpeculativeJIT::callOperation): 91 * dfg/DFGSpeculativeJIT32_64.cpp: 92 (JSC::DFG::SpeculativeJIT::compile): 93 * dfg/DFGSpeculativeJIT64.cpp: 94 (JSC::DFG::SpeculativeJIT::compile): 95 * dfg/DFGUseKind.cpp: 96 (WTF::printInternal): 97 * dfg/DFGUseKind.h: 98 (JSC::DFG::typeFilterFor): 99 (JSC::DFG::isCell): 100 * ftl/FTLAbstractHeapRepository.h: 101 * ftl/FTLCapabilities.cpp: 102 (JSC::FTL::canCompile): 103 * ftl/FTLLowerDFGToB3.cpp: 104 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 105 (JSC::FTL::DFG::LowerDFGToB3::compileMapHash): 106 (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket): 107 (JSC::FTL::DFG::LowerDFGToB3::compileLoadFromJSMapBucket): 108 (JSC::FTL::DFG::LowerDFGToB3::compileIsNonEmptyMapBucket): 109 (JSC::FTL::DFG::LowerDFGToB3::lowMapObject): 110 (JSC::FTL::DFG::LowerDFGToB3::lowSetObject): 111 (JSC::FTL::DFG::LowerDFGToB3::lowMapBucket): 112 (JSC::FTL::DFG::LowerDFGToB3::speculate): 113 (JSC::FTL::DFG::LowerDFGToB3::speculateMapObject): 114 (JSC::FTL::DFG::LowerDFGToB3::speculateSetObject): 115 (JSC::FTL::DFG::LowerDFGToB3::setMapBucket): 116 (JSC::FTL::DFG::LowerDFGToB3::lowRegExpObject): Deleted. 117 (JSC::FTL::DFG::LowerDFGToB3::lowStorage): Deleted. 118 (JSC::FTL::DFG::LowerDFGToB3::speculateRegExpObject): Deleted. 119 (JSC::FTL::DFG::LowerDFGToB3::setStorage): Deleted. 120 * jit/AssemblyHelpers.cpp: 121 (JSC::AssemblyHelpers::wangsInt64Hash): 122 * jit/AssemblyHelpers.h: 123 (JSC::AssemblyHelpers::emitAllocateDestructibleObject): Deleted. 124 * jit/JITOperations.h: 125 * parser/ModuleAnalyzer.cpp: 126 (JSC::ModuleAnalyzer::ModuleAnalyzer): 127 * runtime/HashMapImpl.cpp: Added. 128 (JSC::HashMapBucket<Data>::visitChildren): 129 (JSC::HashMapImpl<HashMapBucket>::visitChildren): 130 (JSC::HashMapImpl<HashMapBucket>::copyBackingStore): 131 * runtime/HashMapImpl.h: Added. 132 (JSC::HashMapBucket::selectStructure): 133 (JSC::HashMapBucket::createStructure): 134 (JSC::HashMapBucket::create): 135 (JSC::HashMapBucket::HashMapBucket): 136 (JSC::HashMapBucket::setNext): 137 (JSC::HashMapBucket::setPrev): 138 (JSC::HashMapBucket::setKey): 139 (JSC::HashMapBucket::setValue): 140 (JSC::HashMapBucket::key): 141 (JSC::HashMapBucket::value): 142 (JSC::HashMapBucket::next): 143 (JSC::HashMapBucket::prev): 144 (JSC::HashMapBucket::deleted): 145 (JSC::HashMapBucket::setDeleted): 146 (JSC::HashMapBucket::offsetOfKey): 147 (JSC::HashMapBucket::offsetOfValue): 148 (JSC::HashMapBuffer::allocationSize): 149 (JSC::HashMapBuffer::buffer): 150 (JSC::HashMapBuffer::create): 151 (JSC::areKeysEqual): 152 (JSC::normalizeMapKey): 153 (JSC::jsMapHash): 154 (JSC::HashMapImpl::selectStructure): 155 (JSC::HashMapImpl::createStructure): 156 (JSC::HashMapImpl::create): 157 (JSC::HashMapImpl::HashMapImpl): 158 (JSC::HashMapImpl::buffer): 159 (JSC::HashMapImpl::finishCreation): 160 (JSC::HashMapImpl::emptyValue): 161 (JSC::HashMapImpl::isEmpty): 162 (JSC::HashMapImpl::deletedValue): 163 (JSC::HashMapImpl::isDeleted): 164 (JSC::HashMapImpl::findBucket): 165 (JSC::HashMapImpl::get): 166 (JSC::HashMapImpl::has): 167 (JSC::HashMapImpl::add): 168 (JSC::HashMapImpl::remove): 169 (JSC::HashMapImpl::size): 170 (JSC::HashMapImpl::clear): 171 (JSC::HashMapImpl::bufferSizeInBytes): 172 (JSC::HashMapImpl::offsetOfBuffer): 173 (JSC::HashMapImpl::offsetOfCapacity): 174 (JSC::HashMapImpl::head): 175 (JSC::HashMapImpl::tail): 176 (JSC::HashMapImpl::approximateSize): 177 (JSC::HashMapImpl::findBucketAlreadyHashedAndNormalized): 178 (JSC::HashMapImpl::rehash): 179 (JSC::HashMapImpl::makeAndSetNewBuffer): 180 * runtime/Intrinsic.h: 181 * runtime/JSCJSValue.h: 182 * runtime/JSCJSValueInlines.h: 183 (JSC::sameValue): 184 * runtime/JSGlobalObject.cpp: 185 (JSC::JSGlobalObject::init): 186 * runtime/JSMap.cpp: 187 (JSC::JSMap::destroy): Deleted. 188 (JSC::JSMap::estimatedSize): Deleted. 189 (JSC::JSMap::visitChildren): Deleted. 190 (JSC::JSMap::copyBackingStore): Deleted. 191 (JSC::JSMap::has): Deleted. 192 (JSC::JSMap::size): Deleted. 193 (JSC::JSMap::get): Deleted. 194 (JSC::JSMap::set): Deleted. 195 (JSC::JSMap::clear): Deleted. 196 (JSC::JSMap::remove): Deleted. 197 * runtime/JSMap.h: 198 (JSC::JSMap::createStructure): 199 (JSC::JSMap::create): 200 (JSC::JSMap::get): 201 (JSC::JSMap::set): 202 (JSC::JSMap::JSMap): 203 (JSC::JSMap::Entry::key): Deleted. 204 (JSC::JSMap::Entry::value): Deleted. 205 (JSC::JSMap::Entry::visitChildren): Deleted. 206 (JSC::JSMap::Entry::setKey): Deleted. 207 (JSC::JSMap::Entry::setKeyWithoutWriteBarrier): Deleted. 208 (JSC::JSMap::Entry::setValue): Deleted. 209 (JSC::JSMap::Entry::clear): Deleted. 210 * runtime/JSMapIterator.cpp: 211 (JSC::JSMapIterator::finishCreation): 212 (JSC::JSMapIterator::visitChildren): 213 (JSC::JSMapIterator::clone): 214 * runtime/JSMapIterator.h: 215 (JSC::JSMapIterator::advanceIter): 216 (JSC::JSMapIterator::next): 217 (JSC::JSMapIterator::nextKeyValue): 218 (JSC::JSMapIterator::JSMapIterator): 219 (JSC::JSMapIterator::setIterator): 220 (JSC::JSMapIterator::finish): Deleted. 221 (JSC::JSMapIterator::iteratorData): Deleted. 222 * runtime/JSModuleLoader.cpp: 223 (JSC::JSModuleLoader::finishCreation): 224 * runtime/JSModuleLoader.h: 225 (JSC::JSModuleLoader::create): 226 * runtime/JSModuleRecord.cpp: 227 (JSC::JSModuleRecord::finishCreation): 228 * runtime/JSModuleRecord.h: 229 (JSC::JSModuleRecord::create): 230 * runtime/JSSet.cpp: 231 (JSC::JSSet::destroy): Deleted. 232 (JSC::JSSet::estimatedSize): Deleted. 233 (JSC::JSSet::visitChildren): Deleted. 234 (JSC::JSSet::copyBackingStore): Deleted. 235 (JSC::JSSet::has): Deleted. 236 (JSC::JSSet::size): Deleted. 237 (JSC::JSSet::add): Deleted. 238 (JSC::JSSet::clear): Deleted. 239 (JSC::JSSet::remove): Deleted. 240 * runtime/JSSet.h: 241 (JSC::JSSet::createStructure): 242 (JSC::JSSet::create): 243 (JSC::JSSet::add): 244 (JSC::JSSet::JSSet): 245 (JSC::JSSet::Entry::key): Deleted. 246 (JSC::JSSet::Entry::value): Deleted. 247 (JSC::JSSet::Entry::visitChildren): Deleted. 248 (JSC::JSSet::Entry::setKey): Deleted. 249 (JSC::JSSet::Entry::setKeyWithoutWriteBarrier): Deleted. 250 (JSC::JSSet::Entry::setValue): Deleted. 251 (JSC::JSSet::Entry::clear): Deleted. 252 * runtime/JSSetIterator.cpp: 253 (JSC::JSSetIterator::finishCreation): 254 (JSC::JSSetIterator::visitChildren): 255 (JSC::JSSetIterator::clone): 256 * runtime/JSSetIterator.h: 257 (JSC::JSSetIterator::advanceIter): 258 (JSC::JSSetIterator::next): 259 (JSC::JSSetIterator::JSSetIterator): 260 (JSC::JSSetIterator::setIterator): 261 (JSC::JSSetIterator::finish): Deleted. 262 (JSC::JSSetIterator::iteratorData): Deleted. 263 * runtime/JSType.h: 264 * runtime/MapBase.cpp: Added. 265 (JSC::MapBase<HashMapBucketType>::visitChildren): 266 (JSC::MapBase<HashMapBucketType>::estimatedSize): 267 * runtime/MapBase.h: Added. 268 (JSC::MapBase::size): 269 (JSC::MapBase::has): 270 (JSC::MapBase::clear): 271 (JSC::MapBase::remove): 272 (JSC::MapBase::findBucket): 273 (JSC::MapBase::offsetOfHashMapImpl): 274 (JSC::MapBase::impl): 275 (JSC::MapBase::finishCreation): 276 (JSC::MapBase::MapBase): 277 * runtime/MapConstructor.cpp: 278 (JSC::constructMap): 279 * runtime/MapIteratorPrototype.cpp: 280 (JSC::MapIteratorPrototypeFuncNext): 281 * runtime/MapPrototype.cpp: 282 (JSC::MapPrototype::finishCreation): 283 (JSC::getMap): 284 (JSC::privateFuncIsMap): 285 (JSC::privateFuncMapIteratorNext): 286 * runtime/PropertyDescriptor.cpp: 287 (JSC::sameValue): Deleted. 288 * runtime/PropertyDescriptor.h: 289 * runtime/SetConstructor.cpp: 290 (JSC::constructSet): 291 * runtime/SetIteratorPrototype.cpp: 292 (JSC::SetIteratorPrototypeFuncNext): 293 * runtime/SetPrototype.cpp: 294 (JSC::SetPrototype::finishCreation): 295 (JSC::getSet): 296 (JSC::privateFuncSetIteratorNext): 297 * runtime/VM.cpp: 298 (JSC::VM::VM): 299 * runtime/VM.h: 300 1 301 2016-09-06 Benjamin Poulain <bpoulain@apple.com> 2 302 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r205507 r205520 1319 1319 792CB3491C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */; }; 1320 1320 792CB34A1C4EED5C00D13AF3 /* PCToCodeOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1321 795B19971D78BE3500262FA0 /* MapBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 795B19951D78BE3500262FA0 /* MapBase.cpp */; }; 1322 795B19981D78BE3500262FA0 /* MapBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 795B19961D78BE3500262FA0 /* MapBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1321 1323 7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 796465681B952FF0003059EE /* GetPutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1322 1324 797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */; }; 1323 1325 797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1324 1326 799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1327 79A0907F1D768465008B889B /* HashMapImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A0907D1D768465008B889B /* HashMapImpl.cpp */; }; 1328 79A090801D768465008B889B /* HashMapImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A0907E1D768465008B889B /* HashMapImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1325 1329 79A228351D35D71E00D8E067 /* ArithProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A228331D35D71E00D8E067 /* ArithProfile.cpp */; }; 1326 1330 79A228361D35D71F00D8E067 /* ArithProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A228341D35D71E00D8E067 /* ArithProfile.h */; }; … … 3570 3574 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCToCodeOriginMap.cpp; sourceTree = "<group>"; }; 3571 3575 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCToCodeOriginMap.h; sourceTree = "<group>"; }; 3576 795B19951D78BE3500262FA0 /* MapBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MapBase.cpp; sourceTree = "<group>"; }; 3577 795B19961D78BE3500262FA0 /* MapBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapBase.h; sourceTree = "<group>"; }; 3572 3578 796465681B952FF0003059EE /* GetPutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetPutInfo.h; sourceTree = "<group>"; }; 3573 3579 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalLexicalEnvironment.cpp; sourceTree = "<group>"; }; 3574 3580 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalLexicalEnvironment.h; sourceTree = "<group>"; }; 3575 3581 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PCToOriginMap.h; path = b3/B3PCToOriginMap.h; sourceTree = "<group>"; }; 3582 79A0907D1D768465008B889B /* HashMapImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashMapImpl.cpp; sourceTree = "<group>"; }; 3583 79A0907E1D768465008B889B /* HashMapImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashMapImpl.h; sourceTree = "<group>"; }; 3576 3584 79A228331D35D71E00D8E067 /* ArithProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArithProfile.cpp; sourceTree = "<group>"; }; 3577 3585 79A228341D35D71E00D8E067 /* ArithProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArithProfile.h; sourceTree = "<group>"; }; … … 5826 5834 BC02E9B80E184545000F9297 /* GetterSetter.cpp */, 5827 5835 BC337BDE0E1AF0B80076918A /* GetterSetter.h */, 5836 79A0907D1D768465008B889B /* HashMapImpl.cpp */, 5837 79A0907E1D768465008B889B /* HashMapImpl.h */, 5828 5838 933A349D038AE80F008635CE /* Identifier.cpp */, 5829 5839 933A349A038AE7C6008635CE /* Identifier.h */, … … 6036 6046 F692A8680255597D01FF60F7 /* Lookup.cpp */, 6037 6047 F692A8690255597D01FF60F7 /* Lookup.h */, 6048 795B19951D78BE3500262FA0 /* MapBase.cpp */, 6049 795B19961D78BE3500262FA0 /* MapBase.h */, 6038 6050 A700873717CBE85300C3E643 /* MapConstructor.cpp */, 6039 6051 A700873817CBE85300C3E643 /* MapConstructor.h */, … … 7327 7339 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */, 7328 7340 62EC9BB71B7EB07C00303AD1 /* CallFrameShuffleData.h in Headers */, 7341 795B19981D78BE3500262FA0 /* MapBase.h in Headers */, 7329 7342 62D755D71B84FB4A001801FA /* CallFrameShuffler.h in Headers */, 7330 7343 0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */, … … 7494 7507 A7D89CF817A0B8CC00773AD8 /* DFGFlushFormat.h in Headers */, 7495 7508 0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */, 7509 79A090801D768465008B889B /* HashMapImpl.h in Headers */, 7496 7510 0F69CC89193AC60A0045759E /* DFGFrozenValue.h in Headers */, 7497 7511 86EC9DC61328DF82002B2AD7 /* DFGGenerationInfo.h in Headers */, … … 9226 9240 0FB105851675480F00F8AB6E /* ExitKind.cpp in Sources */, 9227 9241 0FEA0A1C1708B00700BB722C /* FTLAbstractHeap.cpp in Sources */, 9242 79A0907F1D768465008B889B /* HashMapImpl.cpp in Sources */, 9228 9243 0FEA0A1E1708B00700BB722C /* FTLAbstractHeapRepository.cpp in Sources */, 9229 9244 0F93274D1C1F66AA00CF6564 /* GPRInfo.cpp in Sources */, … … 9270 9285 FE4BFF2B1AD476E700088F87 /* FunctionOverrides.cpp in Sources */, 9271 9286 147F39CC107EC37600427A48 /* FunctionPrototype.cpp in Sources */, 9287 795B19971D78BE3500262FA0 /* MapBase.cpp in Sources */, 9272 9288 62D2D38F1ADF103F000206C1 /* FunctionRareData.cpp in Sources */, 9273 9289 2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */, -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
r205462 r205520 944 944 } 945 945 946 void not64(RegisterID srcDst) 947 { 948 m_assembler.mvn<64>(srcDst, srcDst); 949 } 950 946 951 // Memory access operations: 947 952 -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
r205507 r205520 31 31 32 32 #include "DirectArguments.h" 33 #include "JSCInlines.h" 33 34 #include "JSArray.h" 34 35 #include "JSFunction.h" 35 #include "JSCInlines.h" 36 #include "JSMap.h" 37 #include "JSSet.h" 36 38 #include "ScopedArguments.h" 37 39 #include "StringObject.h" … … 347 349 if (classInfo == RegExpObject::info()) 348 350 return SpecRegExpObject; 351 352 if (classInfo == JSMap::info()) 353 return SpecMapObject; 354 355 if (classInfo == JSSet::info()) 356 return SpecSetObject; 349 357 350 358 if (classInfo->isSubClassOf(JSFunction::info())) -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h
r205507 r205520 40 40 typedef uint64_t SpeculatedType; 41 41 static const SpeculatedType SpecNone = 0; // We don't know anything yet. 42 static const SpeculatedType SpecFinalObject = 1u << 0; // It's definitely a JSFinalObject.43 static const SpeculatedType SpecArray = 1u << 1; // It's definitely a JSArray.44 static const SpeculatedType SpecFunction = 1u << 2; // It's definitely a JSFunction.45 static const SpeculatedType SpecInt8Array = 1u << 3; // It's definitely an Int8Array or one of its subclasses.46 static const SpeculatedType SpecInt16Array = 1u << 4; // It's definitely an Int16Array or one of its subclasses.47 static const SpeculatedType SpecInt32Array = 1u << 5; // It's definitely an Int32Array or one of its subclasses.48 static const SpeculatedType SpecUint8Array = 1u << 6; // It's definitely an Uint8Array or one of its subclasses.49 static const SpeculatedType SpecUint8ClampedArray = 1u << 7; // It's definitely an Uint8ClampedArray or one of its subclasses.50 static const SpeculatedType SpecUint16Array = 1u << 8; // It's definitely an Uint16Array or one of its subclasses.51 static const SpeculatedType SpecUint32Array = 1u << 9; // It's definitely an Uint32Array or one of its subclasses.52 static const SpeculatedType SpecFloat32Array = 1u << 10; // It's definitely an Uint16Array or one of its subclasses.53 static const SpeculatedType SpecFloat64Array = 1u << 11; // It's definitely an Uint16Array or one of its subclasses.42 static const SpeculatedType SpecFinalObject = 1ull << 0; // It's definitely a JSFinalObject. 43 static const SpeculatedType SpecArray = 1ull << 1; // It's definitely a JSArray. 44 static const SpeculatedType SpecFunction = 1ull << 2; // It's definitely a JSFunction. 45 static const SpeculatedType SpecInt8Array = 1ull << 3; // It's definitely an Int8Array or one of its subclasses. 46 static const SpeculatedType SpecInt16Array = 1ull << 4; // It's definitely an Int16Array or one of its subclasses. 47 static const SpeculatedType SpecInt32Array = 1ull << 5; // It's definitely an Int32Array or one of its subclasses. 48 static const SpeculatedType SpecUint8Array = 1ull << 6; // It's definitely an Uint8Array or one of its subclasses. 49 static const SpeculatedType SpecUint8ClampedArray = 1ull << 7; // It's definitely an Uint8ClampedArray or one of its subclasses. 50 static const SpeculatedType SpecUint16Array = 1ull << 8; // It's definitely an Uint16Array or one of its subclasses. 51 static const SpeculatedType SpecUint32Array = 1ull << 9; // It's definitely an Uint32Array or one of its subclasses. 52 static const SpeculatedType SpecFloat32Array = 1ull << 10; // It's definitely an Uint16Array or one of its subclasses. 53 static const SpeculatedType SpecFloat64Array = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses. 54 54 static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array; 55 static const SpeculatedType SpecDirectArguments = 1u << 12; // It's definitely a DirectArguments object. 56 static const SpeculatedType SpecScopedArguments = 1u << 13; // It's definitely a ScopedArguments object. 57 static const SpeculatedType SpecStringObject = 1u << 14; // It's definitely a StringObject. 58 static const SpeculatedType SpecRegExpObject = 1u << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject). 59 static const SpeculatedType SpecObjectOther = 1u << 16; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. 60 static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecObjectOther; // Bitmask used for testing for any kind of object prediction. 61 static const SpeculatedType SpecStringIdent = 1u << 17; // It's definitely a JSString, and it's an identifier. 62 static const SpeculatedType SpecStringVar = 1u << 18; // It's definitely a JSString, and it's not an identifier. 55 static const SpeculatedType SpecDirectArguments = 1ull << 12; // It's definitely a DirectArguments object. 56 static const SpeculatedType SpecScopedArguments = 1ull << 13; // It's definitely a ScopedArguments object. 57 static const SpeculatedType SpecStringObject = 1ull << 14; // It's definitely a StringObject. 58 static const SpeculatedType SpecRegExpObject = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject). 59 static const SpeculatedType SpecMapObject = 1ull << 16; // It's definitely Map object (can it be a subclass? FIXME). 60 static const SpeculatedType SpecSetObject = 1ull << 17; // It's definitely s Set object (can it be a subclass? FIXME). 61 static const SpeculatedType SpecObjectOther = 1ull << 18; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. 62 static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecObjectOther; // Bitmask used for testing for any kind of object prediction. 63 static const SpeculatedType SpecStringIdent = 1ull << 19; // It's definitely a JSString, and it's an identifier. 64 static const SpeculatedType SpecStringVar = 1ull << 20; // It's definitely a JSString, and it's not an identifier. 63 65 static const SpeculatedType SpecString = SpecStringIdent | SpecStringVar; // It's definitely a JSString. 64 static const SpeculatedType SpecSymbol = 1u << 19; // It's definitely a Symbol.65 static const SpeculatedType SpecCellOther = 1u << 20; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=13307866 static const SpeculatedType SpecSymbol = 1ull << 21; // It's definitely a Symbol. 67 static const SpeculatedType SpecCellOther = 1ull << 22; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078 66 68 static const SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell. 67 static const SpeculatedType SpecBoolInt32 = 1u << 21; // It's definitely an Int32 with value 0 or 1.68 static const SpeculatedType SpecNonBoolInt32 = 1u << 22; // It's definitely an Int32 with value other than 0 or 1.69 static const SpeculatedType SpecBoolInt32 = 1ull << 23; // It's definitely an Int32 with value 0 or 1. 70 static const SpeculatedType SpecNonBoolInt32 = 1ull << 24; // It's definitely an Int32 with value other than 0 or 1. 69 71 static const SpeculatedType SpecInt32Only = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32. 70 static const SpeculatedType SpecInt52Only = 1u << 23; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.72 static const SpeculatedType SpecInt52Only = 1ull << 25; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32. 71 73 static const SpeculatedType SpecAnyInt = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on. 72 static const SpeculatedType SpecAnyIntAsDouble = 1u << 24; // It's definitely an Int52 and it's inside a double.73 static const SpeculatedType SpecNonIntAsDouble = 1u << 25; // It's definitely not an Int52 but it's a real number and it's a double.74 static const SpeculatedType SpecAnyIntAsDouble = 1ull << 26; // It's definitely an Int52 and it's inside a double. 75 static const SpeculatedType SpecNonIntAsDouble = 1ull << 27; // It's definitely not an Int52 but it's a real number and it's a double. 74 76 static const SpeculatedType SpecDoubleReal = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double. 75 static const SpeculatedType SpecDoublePureNaN = 1u << 26; // It's definitely a NaN that is sae to tag (i.e. pure).76 static const SpeculatedType SpecDoubleImpureNaN = 1u << 27; // It's definitely a NaN that is unsafe to tag (i.e. impure).77 static const SpeculatedType SpecDoublePureNaN = 1ull << 28; // It's definitely a NaN that is sae to tag (i.e. pure). 78 static const SpeculatedType SpecDoubleImpureNaN = 1ull << 29; // It's definitely a NaN that is unsafe to tag (i.e. impure). 77 79 static const SpeculatedType SpecDoubleNaN = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN. 78 80 static const SpeculatedType SpecBytecodeDouble = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN. … … 82 84 static const SpeculatedType SpecBytecodeNumber = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN. 83 85 static const SpeculatedType SpecFullNumber = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN. 84 static const SpeculatedType SpecBoolean = 1u << 28; // It's definitely a Boolean.85 static const SpeculatedType SpecOther = 1u << 29; // It's definitely either Null or Undefined.86 static const SpeculatedType SpecBoolean = 1ull << 30; // It's definitely a Boolean. 87 static const SpeculatedType SpecOther = 1ull << 31; // It's definitely either Null or Undefined. 86 88 static const SpeculatedType SpecMisc = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined. 87 89 static const SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. 88 90 static const SpeculatedType SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc; // It's any non-Object JSValue. 89 static const SpeculatedType SpecEmpty = 1u << 30; // It's definitely an empty value marker.91 static const SpeculatedType SpecEmpty = 1ull << 32; // It's definitely an empty value marker. 90 92 static const SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local. 91 93 static const SpeculatedType SpecFullTop = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers. -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r205511 r205520 977 977 break; 978 978 } 979 980 case MapHash: 981 forNode(node).setType(SpecInt32Only); 982 break; 983 984 case LoadFromJSMapBucket: 985 forNode(node).makeHeapTop(); 986 break; 987 988 case GetMapBucket: 989 forNode(node).setType(m_graph, SpecCellOther); 990 break; 991 992 case IsNonEmptyMapBucket: 993 forNode(node).setType(SpecBoolean); 994 break; 979 995 980 996 case IsEmpty: … … 2884 2900 { 2885 2901 Node* node = m_state.block()->at(indexInBlock); 2886 2902 2887 2903 startExecuting(); 2888 2904 executeEdges(node); -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r205507 r205520 2539 2539 return true; 2540 2540 } 2541 2541 2542 case JSMapGetIntrinsic: { 2543 if (argumentCountIncludingThis != 2) 2544 return false; 2545 2546 insertChecks(); 2547 Node* map = get(virtualRegisterForArgument(0, registerOffset)); 2548 Node* key = get(virtualRegisterForArgument(1, registerOffset)); 2549 Node* hash = addToGraph(MapHash, key); 2550 Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(key), Edge(hash)); 2551 Node* result = addToGraph(LoadFromJSMapBucket, OpInfo(), OpInfo(prediction), bucket); 2552 set(VirtualRegister(resultOperand), result); 2553 return true; 2554 } 2555 2556 case JSSetHasIntrinsic: 2557 case JSMapHasIntrinsic: { 2558 if (argumentCountIncludingThis != 2) 2559 return false; 2560 2561 insertChecks(); 2562 Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset)); 2563 Node* key = get(virtualRegisterForArgument(1, registerOffset)); 2564 Node* hash = addToGraph(MapHash, key); 2565 UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse; 2566 Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(key), Edge(hash)); 2567 Node* result = addToGraph(IsNonEmptyMapBucket, bucket); 2568 set(VirtualRegister(resultOperand), result); 2569 return true; 2570 } 2571 2542 2572 default: 2543 2573 return false; -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r205511 r205520 1252 1252 write(SideState); 1253 1253 return; 1254 1255 case MapHash: 1256 def(PureValue(node)); 1257 return; 1258 case GetMapBucket: { 1259 read(MiscFields); 1260 Edge& mapEdge = node->child1(); 1261 Edge& keyEdge = node->child2(); 1262 def(HeapLocation(MapBucketLoc, MiscFields, mapEdge, keyEdge), LazyNode(node)); 1263 return; 1264 } 1265 case LoadFromJSMapBucket: { 1266 read(MiscFields); 1267 Edge& bucketEdge = node->child1(); 1268 def(HeapLocation(JSMapGetLoc, MiscFields, bucketEdge), LazyNode(node)); 1269 return; 1270 } 1271 case IsNonEmptyMapBucket: 1272 read(MiscFields); 1273 def(HeapLocation(MapHasLoc, MiscFields, node->child1()), LazyNode(node)); 1274 return; 1254 1275 1255 1276 case LastNodeType: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r205507 r205520 186 186 case CheckWatchdogTimer: 187 187 case StringFromCharCode: 188 case MapHash: 189 case GetMapBucket: 190 case LoadFromJSMapBucket: 191 case IsNonEmptyMapBucket: 188 192 case Unreachable: 189 193 case ExtractOSREntryLocal: -
trunk/Source/JavaScriptCore/dfg/DFGEdge.h
r205507 r205520 190 190 191 191 #if USE(JSVALUE64) 192 static uint32_t shift() { return 7; }192 static constexpr uint32_t shift() { return 8; } 193 193 194 194 static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus, KillStatus killStatus) … … 198 198 ASSERT((shiftedValue >> shift()) == bitwise_cast<uintptr_t>(node)); 199 199 ASSERT(useKind >= 0 && useKind < LastUseKind); 200 ASSERT((static_cast<uintptr_t>(LastUseKind) << 2) <= (static_cast<uintptr_t>(2) << shift())); 201 return shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | static_cast<uintptr_t>(DFG::isProved(proofStatus)); 200 static_assert((static_cast<uintptr_t>(LastUseKind) << 2) < (static_cast<uintptr_t>(1) << shift()), "We rely on this being true to not clobber the node pointer."); 201 uintptr_t result = shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | static_cast<uintptr_t>(DFG::isProved(proofStatus)); 202 if (!ASSERT_DISABLED) { 203 union U { 204 U() { word = 0; } 205 uintptr_t word; 206 Edge edge; 207 } u; 208 u.word = result; 209 ASSERT(u.edge.useKindUnchecked() == useKind); 210 ASSERT(u.edge.node() == node); 211 ASSERT(u.edge.proofStatusUnchecked() == proofStatus); 212 ASSERT(u.edge.killStatusUnchecked() == killStatus); 213 } 214 return result; 202 215 } 203 216 -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r205511 r205520 1548 1548 break; 1549 1549 } 1550 1551 case GetMapBucket: 1552 if (node->child1().useKind() == MapObjectUse) 1553 fixEdge<MapObjectUse>(node->child1()); 1554 else if (node->child1().useKind() == SetObjectUse) 1555 fixEdge<SetObjectUse>(node->child1()); 1556 else 1557 RELEASE_ASSERT_NOT_REACHED(); 1558 fixEdge<UntypedUse>(node->child2()); 1559 fixEdge<Int32Use>(node->child3()); 1560 break; 1561 1562 case LoadFromJSMapBucket: 1563 fixEdge<KnownCellUse>(node->child1()); 1564 break; 1565 1566 case IsNonEmptyMapBucket: 1567 fixEdge<KnownCellUse>(node->child1()); 1568 break; 1569 1570 case MapHash: 1571 fixEdge<UntypedUse>(node->child1()); 1572 break; 1550 1573 1551 1574 #if !ASSERT_DISABLED -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp
r205507 r205520 144 144 out.print("RegExpObjectLastIndexLoc"); 145 145 return; 146 case MapBucketLoc: 147 out.print("MapBucketLoc"); 148 return; 149 case JSMapGetLoc: 150 out.print("JSMapGetLoc"); 151 return; 152 case MapHasLoc: 153 out.print("MapHasLoc"); 154 return; 146 155 } 147 156 -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h
r205507 r205520 59 59 TypedArrayByteOffsetLoc, 60 60 StackLoc, 61 StackPayloadLoc 61 StackPayloadLoc, 62 MapBucketLoc, 63 JSMapGetLoc, 64 MapHasLoc 62 65 }; 63 66 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r205507 r205520 1422 1422 case StringReplaceRegExp: 1423 1423 case ToNumber: 1424 case LoadFromJSMapBucket: 1424 1425 return true; 1425 1426 default: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r205511 r205520 389 389 macro(GetEnumeratorStructurePname, NodeMustGenerate | NodeResultJS) \ 390 390 macro(GetEnumeratorGenericPname, NodeMustGenerate | NodeResultJS) \ 391 macro(ToIndexString, NodeResultJS) 391 macro(ToIndexString, NodeResultJS) \ 392 /* Nodes for JSMap and JSSet */ \ 393 macro(MapHash, NodeResultInt32) \ 394 macro(GetMapBucket, NodeResultJS) \ 395 macro(LoadFromJSMapBucket, NodeResultJS) \ 396 macro(IsNonEmptyMapBucket, NodeResultBoolean) \ 392 397 393 398 // This enum generates a monotonically increasing id for all Node types, -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r205511 r205520 51 51 #include "JSGenericTypedArrayViewConstructorInlines.h" 52 52 #include "JSLexicalEnvironment.h" 53 #include "JSMap.h" 54 #include "JSSet.h" 53 55 #include "ObjectConstructor.h" 54 56 #include "Repatch.h" … … 1824 1826 } 1825 1827 1828 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input) 1829 { 1830 VM& vm = exec->vm(); 1831 NativeCallFrameTracer tracer(&vm, exec); 1832 1833 return jsMapHash(exec, vm, normalizeMapKey(JSValue::decode(input))); 1834 } 1835 1836 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash) 1837 { 1838 VM& vm = exec->vm(); 1839 NativeCallFrameTracer tracer(&vm, exec); 1840 JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash); 1841 if (!bucket) 1842 return nullptr; 1843 return *bucket; 1844 } 1845 1846 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash) 1847 { 1848 VM& vm = exec->vm(); 1849 NativeCallFrameTracer tracer(&vm, exec); 1850 JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash); 1851 if (!bucket) 1852 return nullptr; 1853 return *bucket; 1854 } 1855 1826 1856 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit) 1827 1857 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r205511 r205520 144 144 JSString* JIT_OPERATION operationSingleCharacterString(ExecState*, int32_t); 145 145 146 int32_t JIT_OPERATION operationMapHash(ExecState*, EncodedJSValue input); 147 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t); 148 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t); 149 146 150 JSCell* JIT_OPERATION operationNewStringObject(ExecState*, JSString*, Structure*); 147 151 JSCell* JIT_OPERATION operationToStringOnCell(ExecState*, JSCell*); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r205507 r205520 709 709 case GetClosureVar: 710 710 case GetFromArguments: 711 case LoadFromJSMapBucket: 711 712 case ToNumber: { 712 713 setPrediction(m_currentNode->getHeapPrediction()); … … 738 739 break; 739 740 } 741 742 case MapHash: 743 setPrediction(SpecInt32Only); 744 break; 745 case GetMapBucket: 746 setPrediction(SpecCellOther); 747 break; 748 case IsNonEmptyMapBucket: 749 setPrediction(SpecBoolean); 750 break; 740 751 741 752 case GetRestLength: { -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r205507 r205520 59 59 case FinalObjectUse: 60 60 case RegExpObjectUse: 61 case MapObjectUse: 62 case SetObjectUse: 61 63 case ObjectOrOtherUse: 62 64 case StringIdentUse: … … 356 358 case PutDynamicVar: 357 359 case ResolveScope: 360 case MapHash: 361 case GetMapBucket: 362 case LoadFromJSMapBucket: 363 case IsNonEmptyMapBucket: 358 364 return true; 359 365 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r205511 r205520 7419 7419 } 7420 7420 7421 void SpeculativeJIT::speculateMapObject(Edge edge, GPRReg cell) 7422 { 7423 speculateCellType(edge, cell, SpecMapObject, JSMapType); 7424 } 7425 7426 void SpeculativeJIT::speculateMapObject(Edge edge) 7427 { 7428 if (!needsTypeCheck(edge, SpecMapObject)) 7429 return; 7430 7431 SpeculateCellOperand operand(this, edge); 7432 speculateMapObject(edge, operand.gpr()); 7433 } 7434 7435 void SpeculativeJIT::speculateSetObject(Edge edge, GPRReg cell) 7436 { 7437 speculateCellType(edge, cell, SpecSetObject, JSSetType); 7438 } 7439 7440 void SpeculativeJIT::speculateSetObject(Edge edge) 7441 { 7442 if (!needsTypeCheck(edge, SpecSetObject)) 7443 return; 7444 7445 SpeculateCellOperand operand(this, edge); 7446 speculateSetObject(edge, operand.gpr()); 7447 } 7448 7421 7449 void SpeculativeJIT::speculateObjectOrOther(Edge edge) 7422 7450 { … … 7705 7733 case RegExpObjectUse: 7706 7734 speculateRegExpObject(edge); 7735 break; 7736 case MapObjectUse: 7737 speculateMapObject(edge); 7738 break; 7739 case SetObjectUse: 7740 speculateSetObject(edge); 7707 7741 break; 7708 7742 case ObjectOrOtherUse: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r205511 r205520 1312 1312 #if USE(JSVALUE64) 1313 1313 1314 JITCompiler::Call callOperation(C_JITOperation_ECJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1315 { 1316 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1317 return appendCallSetResult(operation, result); 1318 } 1319 1314 1320 JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC) 1315 1321 { … … 1745 1751 } 1746 1752 #else // USE(JSVALUE32_64) 1753 1754 JITCompiler::Call callOperation(C_JITOperation_ECJZ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2, GPRReg arg3) 1755 { 1756 m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3); 1757 return appendCallSetResult(operation, result); 1758 } 1759 1760 JITCompiler::Call callOperation(Z_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1) 1761 { 1762 m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR()); 1763 return appendCallSetResult(operation, result); 1764 } 1747 1765 1748 1766 JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC) … … 2690 2708 void speculateRegExpObject(Edge, GPRReg cell); 2691 2709 void speculateRegExpObject(Edge); 2710 void speculateMapObject(Edge); 2711 void speculateMapObject(Edge, GPRReg cell); 2712 void speculateSetObject(Edge); 2713 void speculateSetObject(Edge, GPRReg cell); 2692 2714 void speculateObjectOrOther(Edge); 2693 2715 void speculateString(Edge edge, GPRReg cell); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r205507 r205520 38 38 #include "DirectArguments.h" 39 39 #include "GetterSetter.h" 40 #include "HashMapImpl.h" 40 41 #include "JSEnvironmentRecord.h" 41 42 #include "JSLexicalEnvironment.h" … … 4720 4721 } 4721 4722 4723 case MapHash: { 4724 JSValueOperand input(this, node->child1()); 4725 4726 JSValueRegs inputRegs = input.jsValueRegs(); 4727 4728 GPRFlushedCallResult result(this); 4729 GPRReg resultGPR = result.gpr(); 4730 4731 flushRegisters(); 4732 callOperation(operationMapHash, resultGPR, inputRegs); 4733 m_jit.exceptionCheck(); 4734 int32Result(resultGPR, node); 4735 break; 4736 } 4737 4738 case GetMapBucket: { 4739 SpeculateCellOperand map(this, node->child1()); 4740 JSValueOperand key(this, node->child2()); 4741 SpeculateInt32Operand hash(this, node->child3()); 4742 GPRFlushedCallResult result(this); 4743 4744 GPRReg mapGPR = map.gpr(); 4745 JSValueRegs keyRegs = key.jsValueRegs(); 4746 GPRReg hashGPR = hash.gpr(); 4747 GPRReg resultGPR = result.gpr(); 4748 4749 if (node->child1().useKind() == MapObjectUse) 4750 speculateMapObject(node->child1(), mapGPR); 4751 else if (node->child1().useKind() == SetObjectUse) 4752 speculateSetObject(node->child1(), mapGPR); 4753 else 4754 RELEASE_ASSERT_NOT_REACHED(); 4755 4756 flushRegisters(); 4757 if (node->child1().useKind() == MapObjectUse) 4758 callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyRegs, hashGPR); 4759 else 4760 callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyRegs, hashGPR); 4761 m_jit.exceptionCheck(); 4762 cellResult(resultGPR, node); 4763 break; 4764 } 4765 4766 case LoadFromJSMapBucket: { 4767 SpeculateCellOperand bucket(this, node->child1()); 4768 GPRTemporary resultPayload(this); 4769 GPRTemporary resultTag(this); 4770 4771 GPRReg bucketGPR = bucket.gpr(); 4772 GPRReg resultPayloadGPR = resultPayload.gpr(); 4773 GPRReg resultTagGPR = resultTag.gpr(); 4774 4775 auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR); 4776 m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), JSValueRegs(resultTagGPR, resultPayloadGPR)); 4777 auto done = m_jit.jump(); 4778 4779 notBucket.link(&m_jit); 4780 m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTagGPR); 4781 m_jit.move(TrustedImm32(0), resultPayloadGPR); 4782 done.link(&m_jit); 4783 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4784 break; 4785 } 4786 4787 case IsNonEmptyMapBucket: { 4788 SpeculateCellOperand bucket(this, node->child1()); 4789 GPRTemporary result(this); 4790 4791 GPRReg bucketGPR = bucket.gpr(); 4792 GPRReg resultGPR = result.gpr(); 4793 4794 m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR); 4795 booleanResult(resultGPR, node); 4796 break; 4797 } 4798 4722 4799 case Flush: 4723 4800 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r205507 r205520 40 40 #include "JSEnvironmentRecord.h" 41 41 #include "JSLexicalEnvironment.h" 42 #include "JSMap.h" 42 43 #include "JSPropertyNameEnumerator.h" 44 #include "JSSet.h" 43 45 #include "ObjectPrototype.h" 44 46 #include "SetupVarargsFrame.h" … … 4616 4618 } 4617 4619 4620 case MapHash: { 4621 JSValueOperand input(this, node->child1()); 4622 GPRTemporary temp(this); 4623 GPRTemporary result(this); 4624 4625 GPRReg inputGPR = input.gpr(); 4626 GPRReg resultGPR = result.gpr(); 4627 GPRReg tempGPR = temp.gpr(); 4628 4629 MacroAssembler::JumpList straightHash; 4630 MacroAssembler::JumpList done; 4631 auto isNotCell = m_jit.branchIfNotCell(inputGPR); 4632 MacroAssembler::JumpList slowPath; 4633 straightHash.append(m_jit.branch8(MacroAssembler::NotEqual, MacroAssembler::Address(inputGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType))); 4634 m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR); 4635 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR)); 4636 m_jit.load32(MacroAssembler::Address(resultGPR, StringImpl::flagsOffset()), resultGPR); 4637 m_jit.urshift64(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR); 4638 slowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR)); 4639 done.append(m_jit.jump()); 4640 4641 isNotCell.link(&m_jit); 4642 straightHash.append(m_jit.branchIfNotNumber(inputGPR)); 4643 straightHash.append(m_jit.branchIfInt32(JSValueRegs(inputGPR))); 4644 slowPath.append(m_jit.jump()); 4645 4646 straightHash.link(&m_jit); 4647 m_jit.move(inputGPR, resultGPR); 4648 m_jit.wangsInt64Hash(resultGPR, tempGPR); 4649 done.append(m_jit.jump()); 4650 4651 slowPath.link(&m_jit); 4652 silentSpillAllRegisters(resultGPR); 4653 callOperation(operationMapHash, resultGPR, JSValueRegs(inputGPR)); 4654 silentFillAllRegisters(resultGPR); 4655 m_jit.exceptionCheck(); 4656 4657 done.link(&m_jit); 4658 int32Result(resultGPR, node); 4659 break; 4660 } 4661 case GetMapBucket: { 4662 SpeculateCellOperand map(this, node->child1()); 4663 JSValueOperand key(this, node->child2()); 4664 SpeculateInt32Operand hash(this, node->child3()); 4665 GPRTemporary mask(this); 4666 GPRTemporary index(this); 4667 GPRTemporary buffer(this); 4668 GPRTemporary bucket(this); 4669 GPRTemporary result(this); 4670 4671 GPRReg hashGPR = hash.gpr(); 4672 GPRReg mapGPR = map.gpr(); 4673 GPRReg maskGPR = mask.gpr(); 4674 GPRReg indexGPR = index.gpr(); 4675 GPRReg bufferGPR = buffer.gpr(); 4676 GPRReg bucketGPR = bucket.gpr(); 4677 GPRReg keyGPR = key.gpr(); 4678 GPRReg resultGPR = result.gpr(); 4679 4680 if (node->child1().useKind() == MapObjectUse) 4681 speculateMapObject(node->child1(), mapGPR); 4682 else if (node->child1().useKind() == SetObjectUse) 4683 speculateSetObject(node->child1(), mapGPR); 4684 else 4685 RELEASE_ASSERT_NOT_REACHED(); 4686 4687 m_jit.loadPtr(MacroAssembler::Address(mapGPR, node->child1().useKind() == MapObjectUse ? JSMap::offsetOfHashMapImpl() : JSSet::offsetOfHashMapImpl()), bufferGPR); 4688 m_jit.load32(MacroAssembler::Address(bufferGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()), maskGPR); 4689 m_jit.loadPtr(MacroAssembler::Address(bufferGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()), bufferGPR); 4690 m_jit.sub32(TrustedImm32(1), maskGPR); 4691 m_jit.move(hashGPR, indexGPR); 4692 4693 MacroAssembler::Label loop = m_jit.label(); 4694 MacroAssembler::JumpList done; 4695 MacroAssembler::JumpList slowPathCases; 4696 MacroAssembler::JumpList loopAround; 4697 4698 m_jit.and32(maskGPR, indexGPR); 4699 m_jit.loadPtr(MacroAssembler::BaseIndex(bufferGPR, indexGPR, MacroAssembler::TimesEight), bucketGPR); 4700 m_jit.move(bucketGPR, resultGPR); 4701 auto notPresentInTable = m_jit.branchPtr(MacroAssembler::Equal, 4702 bucketGPR, TrustedImmPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())); 4703 loopAround.append(m_jit.branchPtr(MacroAssembler::Equal, 4704 bucketGPR, TrustedImmPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue()))); 4705 4706 m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKey>::offsetOfKey()), bucketGPR); 4707 4708 // Perform Object.is() 4709 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for! 4710 auto oneIsntCell = m_jit.branchIfNotCell(JSValueRegs(bucketGPR)); 4711 // first is a cell here. 4712 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR))); 4713 // Both are cells here. 4714 loopAround.append(m_jit.branch8(JITCompiler::NotEqual, 4715 JITCompiler::Address(bucketGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType))); 4716 // The first is a string here. 4717 slowPathCases.append(m_jit.branch8(JITCompiler::Equal, 4718 JITCompiler::Address(keyGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType))); 4719 // The first is a string, but the second is not, we continue to loop around. 4720 loopAround.append(m_jit.jump()); 4721 4722 oneIsntCell.link(&m_jit); 4723 // We've already done a 64-bit compare at this point, so if one is not a number, they're definitely not equal. 4724 loopAround.append(m_jit.branchIfNotNumber(bucketGPR)); 4725 loopAround.append(m_jit.branchIfNotNumber(keyGPR)); 4726 // Both are definitely numbers. If we see a double, we go to the slow path. 4727 slowPathCases.append(m_jit.branchIfNotInt32(bucketGPR)); 4728 slowPathCases.append(m_jit.branchIfNotInt32(keyGPR)); 4729 4730 loopAround.link(&m_jit); 4731 m_jit.add32(TrustedImm32(1), indexGPR); 4732 m_jit.jump().linkTo(loop, &m_jit); 4733 4734 slowPathCases.link(&m_jit); 4735 silentSpillAllRegisters(indexGPR); 4736 if (node->child1().useKind() == MapObjectUse) 4737 callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyGPR, hashGPR); 4738 else 4739 callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyGPR, hashGPR); 4740 silentFillAllRegisters(indexGPR); 4741 m_jit.exceptionCheck(); 4742 done.append(m_jit.jump()); 4743 4744 notPresentInTable.link(&m_jit); 4745 m_jit.move(TrustedImmPtr(nullptr), resultGPR); 4746 done.link(&m_jit); 4747 cellResult(resultGPR, node); 4748 break; 4749 } 4750 4751 case LoadFromJSMapBucket: { 4752 SpeculateCellOperand bucket(this, node->child1()); 4753 GPRTemporary result(this); 4754 4755 GPRReg bucketGPR = bucket.gpr(); 4756 GPRReg resultGPR = result.gpr(); 4757 4758 auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR); 4759 m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), resultGPR); 4760 auto done = m_jit.jump(); 4761 4762 notBucket.link(&m_jit); 4763 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), resultGPR); 4764 done.link(&m_jit); 4765 jsValueResult(resultGPR, node); 4766 break; 4767 } 4768 4769 case IsNonEmptyMapBucket: { 4770 SpeculateCellOperand bucket(this, node->child1()); 4771 GPRTemporary result(this); 4772 4773 GPRReg bucketGPR = bucket.gpr(); 4774 GPRReg resultGPR = result.gpr(); 4775 4776 m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR); 4777 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 4778 jsValueResult(resultGPR, node, DataFormatJSBoolean); 4779 break; 4780 } 4781 4618 4782 case IsObject: { 4619 4783 JSValueOperand value(this, node->child1()); -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp
r205507 r205520 95 95 out.print("RegExpObject"); 96 96 return; 97 case MapObjectUse: 98 out.print("MapObjectUse"); 99 return; 100 case SetObjectUse: 101 out.print("SetObjectUse"); 102 return; 97 103 case ObjectOrOtherUse: 98 104 out.print("ObjectOrOther"); -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.h
r205507 r205520 64 64 KnownPrimitiveUse, // This bizarre type arises for op_strcat, which has a bytecode guarantee that it will only see primitives (i.e. not objects). 65 65 SymbolUse, 66 MapObjectUse, 67 SetObjectUse, 66 68 StringObjectUse, 67 69 StringOrStringObjectUse, … … 135 137 case SymbolUse: 136 138 return SpecSymbol; 139 case MapObjectUse: 140 return SpecMapObject; 141 case SetObjectUse: 142 return SpecSetObject; 137 143 case StringObjectUse: 138 144 return SpecStringObject; … … 222 228 case StringObjectUse: 223 229 case StringOrStringObjectUse: 230 case MapObjectUse: 231 case SetObjectUse: 224 232 return true; 225 233 default: -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r205507 r205520 33 33 #include "FTLAbstractHeap.h" 34 34 #include "IndexingType.h" 35 #include "JSMap.h" 36 #include "JSSet.h" 35 37 36 38 namespace JSC { namespace FTL { … … 102 104 macro(Structure_globalObject, Structure::globalObjectOffset()) \ 103 105 macro(Structure_prototype, Structure::prototypeOffset()) \ 104 macro(Structure_structureID, Structure::structureIDOffset()) 106 macro(Structure_structureID, Structure::structureIDOffset()) \ 107 macro(JSMap_hashMapImpl, JSMap::offsetOfHashMapImpl()) \ 108 macro(JSSet_hashMapImpl, JSSet::offsetOfHashMapImpl()) \ 109 macro(HashMapImpl_capacity, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()) \ 110 macro(HashMapImpl_buffer, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()) \ 111 macro(HashMapBucket_value, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()) \ 112 macro(HashMapBucket_key, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey()) \ 105 113 106 114 #define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \ -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r205507 r205520 182 182 case In: 183 183 case IsJSArray: 184 case MapHash: 185 case GetMapBucket: 186 case LoadFromJSMapBucket: 187 case IsNonEmptyMapBucket: 184 188 case IsEmpty: 185 189 case IsUndefined: … … 426 430 case StringOrStringObjectUse: 427 431 case SymbolUse: 432 case MapObjectUse: 433 case SetObjectUse: 428 434 case FinalObjectUse: 429 435 case RegExpObjectUse: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r205511 r205520 71 71 #include "JSGeneratorFunction.h" 72 72 #include "JSLexicalEnvironment.h" 73 #include "JSMap.h" 73 74 #include "OperandsInlines.h" 74 75 #include "ScopedArguments.h" … … 898 899 case IsJSArray: 899 900 compileIsJSArray(); 901 break; 902 case MapHash: 903 compileMapHash(); 904 break; 905 case GetMapBucket: 906 compileGetMapBucket(); 907 break; 908 case LoadFromJSMapBucket: 909 compileLoadFromJSMapBucket(); 910 break; 911 case IsNonEmptyMapBucket: 912 compileIsNonEmptyMapBucket(); 900 913 break; 901 914 case IsObject: … … 6280 6293 m_out.appendTo(continuation, lastNext); 6281 6294 setBoolean(m_out.phi(Int32, notCellResult, cellResult)); 6295 } 6296 6297 void compileMapHash() 6298 { 6299 LValue value = lowJSValue(m_node->child1()); 6300 6301 LBasicBlock isCellCase = m_out.newBlock(); 6302 LBasicBlock notCell = m_out.newBlock(); 6303 LBasicBlock slowCase = m_out.newBlock(); 6304 LBasicBlock straightHash = m_out.newBlock(); 6305 LBasicBlock isNumberCase = m_out.newBlock(); 6306 LBasicBlock isStringCase = m_out.newBlock(); 6307 LBasicBlock nonEmptyStringCase = m_out.newBlock(); 6308 LBasicBlock continuation = m_out.newBlock(); 6309 6310 m_out.branch( 6311 isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(notCell)); 6312 6313 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase); 6314 LValue isString = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType)); 6315 m_out.branch( 6316 isString, unsure(isStringCase), unsure(straightHash)); 6317 6318 m_out.appendTo(isStringCase, nonEmptyStringCase); 6319 LValue stringImpl = m_out.loadPtr(value, m_heaps.JSString_value); 6320 m_out.branch( 6321 m_out.equal(stringImpl, m_out.constIntPtr(0)), rarely(slowCase), usually(nonEmptyStringCase)); 6322 6323 m_out.appendTo(nonEmptyStringCase, notCell); 6324 LValue hash = m_out.lShr(m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount)); 6325 ValueFromBlock nonEmptyStringHashResult = m_out.anchor(hash); 6326 m_out.branch(m_out.equal(hash, m_out.constInt32(0)), 6327 rarely(slowCase), usually(continuation)); 6328 6329 m_out.appendTo(notCell, isNumberCase); 6330 m_out.branch( 6331 isNumber(value), unsure(isNumberCase), unsure(straightHash)); 6332 6333 m_out.appendTo(isNumberCase, straightHash); 6334 m_out.branch( 6335 isInt32(value), unsure(straightHash), unsure(slowCase)); 6336 6337 m_out.appendTo(straightHash, slowCase); 6338 // key += ~(key << 32); 6339 LValue key = value; 6340 LValue temp = key; 6341 temp = m_out.shl(temp, m_out.constInt32(32)); 6342 temp = m_out.bitNot(temp); 6343 key = m_out.add(key, temp); 6344 // key ^= (key >> 22); 6345 temp = key; 6346 temp = m_out.lShr(temp, m_out.constInt32(22)); 6347 key = m_out.bitXor(key, temp); 6348 // key += ~(key << 13); 6349 temp = key; 6350 temp = m_out.shl(temp, m_out.constInt32(13)); 6351 temp = m_out.bitNot(temp); 6352 key = m_out.add(key, temp); 6353 // key ^= (key >> 8); 6354 temp = key; 6355 temp = m_out.lShr(temp, m_out.constInt32(8)); 6356 key = m_out.bitXor(key, temp); 6357 // key += (key << 3); 6358 temp = key; 6359 temp = m_out.shl(temp, m_out.constInt32(3)); 6360 key = m_out.add(key, temp); 6361 // key ^= (key >> 15); 6362 temp = key; 6363 temp = m_out.lShr(temp, m_out.constInt32(15)); 6364 key = m_out.bitXor(key, temp); 6365 // key += ~(key << 27); 6366 temp = key; 6367 temp = m_out.shl(temp, m_out.constInt32(27)); 6368 temp = m_out.bitNot(temp); 6369 key = m_out.add(key, temp); 6370 // key ^= (key >> 31); 6371 temp = key; 6372 temp = m_out.lShr(temp, m_out.constInt32(31)); 6373 key = m_out.bitXor(key, temp); 6374 key = m_out.castToInt32(key); 6375 6376 ValueFromBlock fastResult = m_out.anchor(key); 6377 m_out.jump(continuation); 6378 6379 m_out.appendTo(slowCase, continuation); 6380 ValueFromBlock slowResult = m_out.anchor( 6381 vmCall(Int32, m_out.operation(operationMapHash), m_callFrame, value)); 6382 m_out.jump(continuation); 6383 6384 m_out.appendTo(continuation, lastNext); 6385 setInt32(m_out.phi(Int32, fastResult, slowResult, nonEmptyStringHashResult)); 6386 } 6387 6388 void compileGetMapBucket() 6389 { 6390 LBasicBlock loopStart = m_out.newBlock(); 6391 LBasicBlock loopAround = m_out.newBlock(); 6392 LBasicBlock slowPath = m_out.newBlock(); 6393 LBasicBlock notPresentInTable = m_out.newBlock(); 6394 LBasicBlock notEmptyValue = m_out.newBlock(); 6395 LBasicBlock notDeletedValue = m_out.newBlock(); 6396 LBasicBlock notBitEqual = m_out.newBlock(); 6397 LBasicBlock bucketKeyNotCell = m_out.newBlock(); 6398 LBasicBlock bucketKeyIsCell = m_out.newBlock(); 6399 LBasicBlock bothAreCells = m_out.newBlock(); 6400 LBasicBlock bucketKeyIsString = m_out.newBlock(); 6401 LBasicBlock bucketKeyIsNumber = m_out.newBlock(); 6402 LBasicBlock bothAreNumbers = m_out.newBlock(); 6403 LBasicBlock bucketKeyIsInt32 = m_out.newBlock(); 6404 LBasicBlock continuation = m_out.newBlock(); 6405 6406 LBasicBlock lastNext = m_out.insertNewBlocksBefore(loopStart); 6407 6408 LValue map; 6409 if (m_node->child1().useKind() == MapObjectUse) 6410 map = lowMapObject(m_node->child1()); 6411 else if (m_node->child1().useKind() == SetObjectUse) 6412 map = lowSetObject(m_node->child1()); 6413 else 6414 RELEASE_ASSERT_NOT_REACHED(); 6415 6416 LValue key = lowJSValue(m_node->child2()); 6417 LValue hash = lowInt32(m_node->child3()); 6418 6419 LValue hashMapImpl = m_out.loadPtr(map, m_node->child1().useKind() == MapObjectUse ? m_heaps.JSMap_hashMapImpl : m_heaps.JSSet_hashMapImpl); 6420 LValue buffer = m_out.loadPtr(hashMapImpl, m_heaps.HashMapImpl_buffer); 6421 LValue mask = m_out.sub(m_out.load32(hashMapImpl, m_heaps.HashMapImpl_capacity), m_out.int32One); 6422 6423 ValueFromBlock indexStart = m_out.anchor(hash); 6424 m_out.jump(loopStart); 6425 6426 m_out.appendTo(loopStart, notEmptyValue); 6427 LValue unmaskedIndex = m_out.phi(Int32, indexStart); 6428 LValue index = m_out.bitAnd(mask, unmaskedIndex); 6429 LValue hashMapBucket = m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), buffer, m_out.zeroExt(index, Int64), ScaleEight)); 6430 ValueFromBlock bucketResult = m_out.anchor(hashMapBucket); 6431 m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())), 6432 unsure(notPresentInTable), unsure(notEmptyValue)); 6433 6434 m_out.appendTo(notEmptyValue, notDeletedValue); 6435 m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue())), 6436 unsure(loopAround), unsure(notDeletedValue)); 6437 6438 m_out.appendTo(notDeletedValue, notBitEqual); 6439 LValue bucketKey = m_out.load64(hashMapBucket, m_heaps.HashMapBucket_key); 6440 // Perform Object.is() 6441 m_out.branch(m_out.equal(key, bucketKey), 6442 unsure(continuation), unsure(notBitEqual)); 6443 6444 m_out.appendTo(notBitEqual, bucketKeyIsCell); 6445 m_out.branch(isCell(bucketKey), 6446 unsure(bucketKeyIsCell), unsure(bucketKeyNotCell)); 6447 6448 m_out.appendTo(bucketKeyIsCell, bothAreCells); 6449 m_out.branch(isCell(key), 6450 unsure(bothAreCells), unsure(loopAround)); 6451 6452 m_out.appendTo(bothAreCells, bucketKeyIsString); 6453 m_out.branch(isString(bucketKey), 6454 unsure(bucketKeyIsString), unsure(loopAround)); 6455 6456 m_out.appendTo(bucketKeyIsString, bucketKeyNotCell); 6457 m_out.branch(isString(key), 6458 unsure(slowPath), unsure(loopAround)); 6459 6460 m_out.appendTo(bucketKeyNotCell, bucketKeyIsNumber); 6461 m_out.branch(isNotNumber(bucketKey), 6462 unsure(loopAround), unsure(bucketKeyIsNumber)); 6463 6464 m_out.appendTo(bucketKeyIsNumber, bothAreNumbers); 6465 m_out.branch(isNotNumber(key), 6466 unsure(loopAround), unsure(bothAreNumbers)); 6467 6468 m_out.appendTo(bothAreNumbers, bucketKeyIsInt32); 6469 m_out.branch(isNotInt32(bucketKey), 6470 unsure(slowPath), unsure(bucketKeyIsInt32)); 6471 6472 m_out.appendTo(bucketKeyIsInt32, loopAround); 6473 m_out.branch(isNotInt32(key), 6474 unsure(slowPath), unsure(loopAround)); 6475 6476 m_out.appendTo(loopAround, slowPath); 6477 m_out.addIncomingToPhi(unmaskedIndex, m_out.anchor(m_out.add(index, m_out.int32One))); 6478 m_out.jump(loopStart); 6479 6480 m_out.appendTo(slowPath, notPresentInTable); 6481 ValueFromBlock slowPathResult = m_out.anchor(vmCall(pointerType(), 6482 m_out.operation(m_node->child1().useKind() == MapObjectUse ? operationJSMapFindBucket : operationJSSetFindBucket), m_callFrame, map, key, hash)); 6483 m_out.jump(continuation); 6484 6485 m_out.appendTo(notPresentInTable, continuation); 6486 ValueFromBlock notPresentResult = m_out.anchor(m_out.constIntPtr(0)); 6487 m_out.jump(continuation); 6488 6489 m_out.appendTo(continuation, lastNext); 6490 setMapBucket(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult)); 6491 } 6492 6493 void compileLoadFromJSMapBucket() 6494 { 6495 LValue mapBucket = lowMapBucket(m_node->child1()); 6496 6497 LBasicBlock continuation = m_out.newBlock(); 6498 LBasicBlock hasBucket = m_out.newBlock(); 6499 6500 ValueFromBlock noBucketResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))); 6501 6502 m_out.branch(m_out.equal(mapBucket, m_out.constIntPtr(0)), 6503 unsure(continuation), unsure(hasBucket)); 6504 6505 LBasicBlock lastNext = m_out.appendTo(hasBucket, continuation); 6506 ValueFromBlock bucketResult = m_out.anchor(m_out.load64(mapBucket, m_heaps.HashMapBucket_value)); 6507 m_out.jump(continuation); 6508 6509 m_out.appendTo(continuation, lastNext); 6510 setJSValue(m_out.phi(Int64, noBucketResult, bucketResult)); 6511 } 6512 6513 void compileIsNonEmptyMapBucket() 6514 { 6515 LValue bucket = lowMapBucket(m_node->child1()); 6516 LValue result = m_out.notEqual(bucket, m_out.constIntPtr(0)); 6517 setBoolean(result); 6282 6518 } 6283 6519 … … 9990 10226 return result; 9991 10227 } 10228 10229 LValue lowMapObject(Edge edge) 10230 { 10231 LValue result = lowCell(edge); 10232 speculateMapObject(edge, result); 10233 return result; 10234 } 10235 10236 LValue lowSetObject(Edge edge) 10237 { 10238 LValue result = lowCell(edge); 10239 speculateSetObject(edge, result); 10240 return result; 10241 } 9992 10242 9993 10243 LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) … … 10113 10363 return result; 10114 10364 } 10365 10366 LValue lowMapBucket(Edge edge) 10367 { 10368 LoweredNodeValue value = m_mapBucketValues.get(edge.node()); 10369 if (isValid(value)) 10370 return value.value(); 10371 10372 LValue result = lowCell(edge); 10373 setStorage(edge.node(), result); 10374 return result; 10375 } 10115 10376 10116 10377 LValue strictInt52ToInt32(Edge edge, LValue value) … … 10415 10676 case RegExpObjectUse: 10416 10677 speculateRegExpObject(edge); 10678 break; 10679 case MapObjectUse: 10680 speculateMapObject(edge); 10681 break; 10682 case SetObjectUse: 10683 speculateSetObject(edge); 10417 10684 break; 10418 10685 case StringUse: … … 10744 11011 speculateRegExpObject(edge, lowCell(edge)); 10745 11012 } 11013 11014 void speculateMapObject(Edge edge, LValue cell) 11015 { 11016 FTL_TYPE_CHECK( 11017 jsValueValue(cell), edge, SpecMapObject, isNotType(cell, JSMapType)); 11018 } 11019 11020 void speculateMapObject(Edge edge) 11021 { 11022 speculateMapObject(edge, lowCell(edge)); 11023 } 11024 11025 void speculateSetObject(Edge edge, LValue cell) 11026 { 11027 FTL_TYPE_CHECK( 11028 jsValueValue(cell), edge, SpecSetObject, isNotType(cell, JSSetType)); 11029 } 11030 11031 void speculateSetObject(Edge edge) 11032 { 11033 speculateSetObject(edge, lowCell(edge)); 11034 } 10746 11035 10747 11036 void speculateString(Edge edge, LValue cell) … … 11512 11801 m_storageValues.set(node, LoweredNodeValue(value, m_highBlock)); 11513 11802 } 11803 void setMapBucket(Node* node, LValue value) 11804 { 11805 m_mapBucketValues.set(node, LoweredNodeValue(value, m_highBlock)); 11806 } 11514 11807 void setDouble(Node* node, LValue value) 11515 11808 { … … 11544 11837 { 11545 11838 setStorage(m_node, value); 11839 } 11840 void setMapBucket(LValue value) 11841 { 11842 setMapBucket(m_node, value); 11546 11843 } 11547 11844 void setDouble(LValue value) … … 11728 12025 HashMap<Node*, LoweredNodeValue> m_booleanValues; 11729 12026 HashMap<Node*, LoweredNodeValue> m_storageValues; 12027 HashMap<Node*, LoweredNodeValue> m_mapBucketValues; 11730 12028 HashMap<Node*, LoweredNodeValue> m_doubleValues; 11731 12029 -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp
r205507 r205520 627 627 } 628 628 629 #if USE(JSVALUE64) 630 void AssemblyHelpers::wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch) 631 { 632 GPRReg input = inputAndResult; 633 // key += ~(key << 32); 634 move(input, scratch); 635 lshift64(TrustedImm32(32), scratch); 636 not64(scratch); 637 add64(scratch, input); 638 // key ^= (key >> 22); 639 move(input, scratch); 640 urshift64(TrustedImm32(22), scratch); 641 xor64(scratch, input); 642 // key += ~(key << 13); 643 move(input, scratch); 644 lshift64(TrustedImm32(13), scratch); 645 not64(scratch); 646 add64(scratch, input); 647 // key ^= (key >> 8); 648 move(input, scratch); 649 urshift64(TrustedImm32(8), scratch); 650 xor64(scratch, input); 651 // key += (key << 3); 652 move(input, scratch); 653 lshift64(TrustedImm32(3), scratch); 654 add64(scratch, input); 655 // key ^= (key >> 15); 656 move(input, scratch); 657 urshift64(TrustedImm32(15), scratch); 658 xor64(scratch, input); 659 // key += ~(key << 27); 660 move(input, scratch); 661 lshift64(TrustedImm32(27), scratch); 662 not64(scratch); 663 add64(scratch, input); 664 // key ^= (key >> 31); 665 move(input, scratch); 666 urshift64(TrustedImm32(31), scratch); 667 xor64(scratch, input); 668 669 // return static_cast<unsigned>(result) 670 void* mask = bitwise_cast<void*>(static_cast<uintptr_t>(UINT_MAX)); 671 and64(TrustedImmPtr(mask), inputAndResult); 672 } 673 #endif // USE(JSVALUE64) 674 629 675 } // namespace JSC 630 676 -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r205507 r205520 62 62 } 63 63 } 64 64 65 65 CodeBlock* codeBlock() { return m_codeBlock; } 66 66 VM* vm() { return m_vm; } … … 1529 1529 storePtr(TrustedImmPtr(structure->classInfo()), Address(resultGPR, JSDestructibleObject::classInfoOffset())); 1530 1530 } 1531 1532 #if USE(JSVALUE64) 1533 void wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch); 1534 #endif 1531 1535 1532 1536 protected: -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r205508 r205520 206 206 typedef JSCell* (JIT_OPERATION *C_JITOperation_EZ)(ExecState*, int32_t); 207 207 typedef JSCell* (JIT_OPERATION *C_JITOperation_EJscI)(ExecState*, JSScope*, UniquedStringImpl*); 208 typedef JSCell* (JIT_OPERATION *C_JITOperation_ECJZ)(ExecState*, JSCell*, EncodedJSValue, int32_t); 208 209 typedef double (JIT_OPERATION *D_JITOperation_D)(double); 209 210 typedef double (JIT_OPERATION *D_JITOperation_G)(JSGlobalObject*); -
trunk/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp
r205507 r205520 38 38 ModuleAnalyzer::ModuleAnalyzer(ExecState* exec, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) 39 39 : m_vm(&exec->vm()) 40 , m_moduleRecord(exec->vm(), JSModuleRecord::create(exec ->vm(), exec->lexicalGlobalObject()->moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables))40 , m_moduleRecord(exec->vm(), JSModuleRecord::create(exec, exec->vm(), exec->lexicalGlobalObject()->moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables)) 41 41 { 42 42 } -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r205507 r205520 63 63 IsTypedArrayViewIntrinsic, 64 64 BoundThisNoArgsFunctionCallIntrinsic, 65 JSMapGetIntrinsic, 66 JSMapHasIntrinsic, 67 JSSetHasIntrinsic, 65 68 66 69 // Getter intrinsics. -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.h
r205507 r205520 607 607 bool isThisValueAltered(const PutPropertySlot&, JSObject* baseObject); 608 608 609 // See section 7.2.9: https://tc39.github.io/ecma262/#sec-samevalue 610 bool sameValue(ExecState*, JSValue a, JSValue b); 611 609 612 } // namespace JSC 610 613 -
trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
r205507 r205520 1059 1059 } 1060 1060 1061 // See section 7.2.9: https://tc39.github.io/ecma262/#sec-samevalue 1062 ALWAYS_INLINE bool sameValue(ExecState* exec, JSValue a, JSValue b) 1063 { 1064 if (!a.isNumber()) 1065 return JSValue::strictEqual(exec, a, b); 1066 if (!b.isNumber()) 1067 return false; 1068 double x = a.asNumber(); 1069 double y = b.asNumber(); 1070 bool xIsNaN = std::isnan(x); 1071 bool yIsNaN = std::isnan(y); 1072 if (xIsNaN || yIsNaN) 1073 return xIsNaN && yIsNaN; 1074 return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y); 1075 } 1076 1061 1077 } // namespace JSC 1062 1078 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r205507 r205520 642 642 643 643 m_moduleLoaderStructure.set(vm, this, JSModuleLoader::createStructure(vm, this, m_moduleLoaderPrototype.get())); 644 m_moduleLoader.set(vm, this, JSModuleLoader::create( vm, this, m_moduleLoaderStructure.get()));644 m_moduleLoader.set(vm, this, JSModuleLoader::create(globalExec(), vm, this, m_moduleLoaderStructure.get())); 645 645 if (Options::exposeInternalModuleLoader()) 646 646 putDirectWithoutTransition(vm, vm.propertyNames->Loader, m_moduleLoader.get(), DontEnum); -
trunk/Source/JavaScriptCore/runtime/JSMap.cpp
r205507 r205520 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 … … 27 27 #include "JSMap.h" 28 28 29 #include "CopiedBlockInlines.h" 30 #include "JSCJSValueInlines.h" 31 #include "JSMapIterator.h" 32 #include "MapDataInlines.h" 33 #include "SlotVisitorInlines.h" 34 #include "StructureInlines.h" 29 #include "JSCInlines.h" 35 30 36 31 namespace JSC { 37 32 38 33 const ClassInfo JSMap::s_info = { "Map", &Base::s_info, 0, CREATE_METHOD_TABLE(JSMap) }; 39 40 void JSMap::destroy(JSCell* cell)41 {42 JSMap* thisObject = jsCast<JSMap*>(cell);43 thisObject->JSMap::~JSMap();44 }45 46 size_t JSMap::estimatedSize(JSCell* cell)47 {48 JSMap* thisObject = jsCast<JSMap*>(cell);49 size_t mapDataSize = thisObject->m_mapData.capacityInBytes();50 return Base::estimatedSize(cell) + mapDataSize;51 }52 34 53 35 String JSMap::toStringName(const JSObject*, ExecState*) … … 56 38 } 57 39 58 void JSMap::visitChildren(JSCell* cell, SlotVisitor& visitor)59 {60 Base::visitChildren(cell, visitor);61 jsCast<JSMap*>(cell)->m_mapData.visitChildren(cell, visitor);62 40 } 63 64 void JSMap::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token)65 {66 Base::copyBackingStore(cell, visitor, token);67 jsCast<JSMap*>(cell)->m_mapData.copyBackingStore(visitor, token);68 }69 70 bool JSMap::has(ExecState* exec, JSValue key)71 {72 return m_mapData.contains(exec, key);73 }74 75 size_t JSMap::size(ExecState* exec)76 {77 return m_mapData.size(exec);78 }79 80 JSValue JSMap::get(ExecState* exec, JSValue key)81 {82 JSValue result = m_mapData.get(exec, key);83 if (!result)84 return jsUndefined();85 return result;86 }87 88 void JSMap::set(ExecState* exec, JSValue key, JSValue value)89 {90 m_mapData.set(exec, this, key, value);91 }92 93 void JSMap::clear(ExecState*)94 {95 m_mapData.clear();96 }97 98 bool JSMap::remove(ExecState* exec, JSValue key)99 {100 return m_mapData.remove(exec, key);101 }102 103 } -
trunk/Source/JavaScriptCore/runtime/JSMap.h
r205507 r205520 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 … … 27 27 #define JSMap_h 28 28 29 #include "JSDestructibleObject.h"30 29 #include "JSObject.h" 31 #include "Map Data.h"30 #include "MapBase.h" 32 31 33 32 namespace JSC { … … 35 34 class JSMapIterator; 36 35 37 class JSMap : public JSDestructibleObject { 36 class JSMap : public MapBase<HashMapBucket<HashMapBucketDataKeyValue>> { 37 typedef MapBase<HashMapBucket<HashMapBucketDataKeyValue>> Base; 38 38 public: 39 typedef JSDestructibleObject Base;40 41 39 friend class JSMapIterator; 42 43 // Our marking functions expect Entry to maintain this layout, and have all44 // fields be WriteBarrier<Unknown>45 class Entry {46 private:47 WriteBarrier<Unknown> m_key;48 WriteBarrier<Unknown> m_value;49 50 public:51 const WriteBarrier<Unknown>& key() const52 {53 return m_key;54 }55 56 const WriteBarrier<Unknown>& value() const57 {58 return m_value;59 }60 61 void visitChildren(SlotVisitor& visitor)62 {63 visitor.append(&m_key);64 visitor.append(&m_value);65 }66 67 void setKey(VM& vm, const JSCell* owner, JSValue key)68 {69 m_key.set(vm, owner, key);70 }71 72 void setKeyWithoutWriteBarrier(JSValue key)73 {74 m_key.setWithoutWriteBarrier(key);75 }76 77 void setValue(VM& vm, const JSCell* owner, JSValue value)78 {79 m_value.set(vm, owner, value);80 }81 82 void clear()83 {84 m_key.clear();85 m_value.clear();86 }87 };88 89 typedef MapDataImpl<Entry, JSMapIterator> MapData;90 40 91 41 DECLARE_EXPORT_INFO; … … 93 43 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 94 44 { 95 return Structure::create(vm, globalObject, prototype, TypeInfo( ObjectType, StructureFlags), info());45 return Structure::create(vm, globalObject, prototype, TypeInfo(JSMapType, StructureFlags), info()); 96 46 } 97 47 98 static JSMap* create( VM& vm, Structure* structure)48 static JSMap* create(ExecState* exec, VM& vm, Structure* structure) 99 49 { 100 50 JSMap* instance = new (NotNull, allocateCell<JSMap>(vm.heap)) JSMap(vm, structure); 101 instance->finishCreation( vm);51 instance->finishCreation(exec, vm); 102 52 return instance; 103 53 } 104 54 105 static JSMap* create(ExecState* exec, Structure* structure)55 ALWAYS_INLINE JSValue get(ExecState* exec, JSValue key) 106 56 { 107 return create(exec->vm(), structure);57 return m_map->get(exec, key); 108 58 } 109 59 110 bool has(ExecState*, JSValue); 111 size_t size(ExecState*); 112 JSValue get(ExecState*, JSValue); 113 JS_EXPORT_PRIVATE void set(ExecState*, JSValue key, JSValue value); 114 void clear(ExecState*); 115 bool remove(ExecState*, JSValue); 60 ALWAYS_INLINE void set(ExecState* exec, JSValue key, JSValue value) 61 { 62 m_map->add(exec, key, value); 63 } 116 64 117 65 private: 118 66 JSMap(VM& vm, Structure* structure) 119 67 : Base(vm, structure) 120 , m_mapData(vm, this)121 68 { 122 69 } 123 70 124 static void destroy(JSCell*);125 static size_t estimatedSize(JSCell*);126 static void visitChildren(JSCell*, SlotVisitor&);127 static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);128 71 static String toStringName(const JSObject*, ExecState*); 129 130 MapData m_mapData;131 72 }; 132 73 -
trunk/Source/JavaScriptCore/runtime/JSMapIterator.cpp
r205507 r205520 39 39 Base::finishCreation(vm); 40 40 m_map.set(vm, this, iteratedObject); 41 setIterator(vm, m_map->impl()->head()); 41 42 } 42 43 … … 47 48 Base::visitChildren(thisObject, visitor); 48 49 visitor.append(&thisObject->m_map); 50 visitor.append(&thisObject->m_iter); 49 51 } 50 52 … … 60 62 JSMapIterator* JSMapIterator::clone(ExecState* exec) 61 63 { 62 auto clone = JSMapIterator::create(exec->vm(), exec->callee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind); 63 clone->m_iterator = m_iterator; 64 VM& vm = exec->vm(); 65 auto clone = JSMapIterator::create(vm, exec->callee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind); 66 clone->setIterator(vm, m_iter.get()); 64 67 return clone; 65 68 } -
trunk/Source/JavaScriptCore/runtime/JSMapIterator.h
r205507 r205520 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 … … 35 35 36 36 class JSMapIterator : public JSNonFinalObject { 37 typedef HashMapBucket<HashMapBucketDataKeyValue> HashMapBucketType; 37 38 public: 38 39 typedef JSNonFinalObject Base; … … 52 53 } 53 54 54 bool next(CallFrame* callFrame, JSValue& value)55 ALWAYS_INLINE HashMapBucketType* advanceIter(ExecState* exec) 55 56 { 56 WTF::KeyValuePair<JSValue, JSValue> pair; 57 if (!m_iterator.next(pair)) 57 HashMapBucketType* prev = m_iter.get(); 58 if (!prev) 59 return nullptr; 60 HashMapBucketType* bucket = m_iter->next(); 61 while (bucket && bucket->deleted()) { 62 prev = bucket; 63 bucket = bucket->next(); 64 } 65 if (!bucket) { 66 setIterator(exec->vm(), nullptr); 67 return nullptr; 68 } 69 setIterator(exec->vm(), bucket); // We keep m_iter on the last value since the first thing we do in this function is call next(). 70 return bucket; 71 } 72 bool next(ExecState* exec, JSValue& value) 73 { 74 HashMapBucketType* bucket = advanceIter(exec); 75 if (!bucket) 58 76 return false; 59 77 60 78 if (m_kind == IterateValue) 61 value = pair.value;79 value = bucket->value(); 62 80 else if (m_kind == IterateKey) 63 value = pair.key;81 value = bucket->key(); 64 82 else 65 value = createPair( callFrame, pair.key, pair.value);83 value = createPair(exec, bucket->key(), bucket->value()); 66 84 return true; 67 85 } 68 86 69 bool nextKeyValue( JSValue& key, JSValue& value)87 bool nextKeyValue(ExecState* exec, JSValue& key, JSValue& value) 70 88 { 71 WTF::KeyValuePair<JSValue, JSValue> pair;72 if (! m_iterator.next(pair))89 HashMapBucketType* bucket = advanceIter(exec); 90 if (!bucket) 73 91 return false; 74 92 75 key = pair.key;76 value = pair.value;93 key = bucket->key(); 94 value = bucket->value(); 77 95 return true; 78 }79 80 void finish()81 {82 m_iterator.finish();83 96 } 84 97 … … 87 100 JSMapIterator* clone(ExecState*); 88 101 89 JSMap::MapData::IteratorData* iteratorData() 102 private: 103 JSMapIterator(VM& vm, Structure* structure, JSMap*, IterationKind kind) 104 : Base(vm, structure) 105 , m_kind(kind) 106 { } 107 108 void setIterator(VM& vm, HashMapBucketType* bucket) 90 109 { 91 return &m_iterator; 92 } 93 94 private: 95 JSMapIterator(VM& vm, Structure* structure, JSMap* iteratedObject, IterationKind kind) 96 : Base(vm, structure) 97 , m_iterator(iteratedObject->m_mapData.createIteratorData(this)) 98 , m_kind(kind) 99 { 110 m_iter.setMayBeNull(vm, this, bucket); 100 111 } 101 112 … … 105 116 106 117 WriteBarrier<JSMap> m_map; 107 JSMap::MapData::IteratorData m_iterator;118 WriteBarrier<HashMapBucketType> m_iter; 108 119 IterationKind m_kind; 109 120 }; -
trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp
r205507 r205520 56 56 } 57 57 58 void JSModuleLoader::finishCreation( VM& vm, JSGlobalObject* globalObject)58 void JSModuleLoader::finishCreation(ExecState* exec, VM& vm, JSGlobalObject* globalObject) 59 59 { 60 60 Base::finishCreation(vm); 61 61 ASSERT(inherits(info())); 62 putDirect(vm, Identifier::fromString(&vm, "registry"), JSMap::create(vm, globalObject->mapStructure())); 62 auto scope = DECLARE_THROW_SCOPE(vm); 63 JSMap* map = JSMap::create(exec, vm, globalObject->mapStructure()); 64 RELEASE_ASSERT(!scope.exception()); 65 putDirect(vm, Identifier::fromString(&vm, "registry"), map); 63 66 } 64 67 -
trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h
r205507 r205520 48 48 }; 49 49 50 static JSModuleLoader* create( VM& vm, JSGlobalObject* globalObject, Structure* structure)50 static JSModuleLoader* create(ExecState* exec, VM& vm, JSGlobalObject* globalObject, Structure* structure) 51 51 { 52 52 JSModuleLoader* object = new (NotNull, allocateCell<JSModuleLoader>(vm.heap)) JSModuleLoader(vm, structure); 53 object->finishCreation( vm, globalObject);53 object->finishCreation(exec, vm, globalObject); 54 54 return object; 55 55 } … … 78 78 79 79 protected: 80 void finishCreation( VM&, JSGlobalObject*);80 void finishCreation(ExecState*, VM&, JSGlobalObject*); 81 81 }; 82 82 -
trunk/Source/JavaScriptCore/runtime/JSModuleRecord.cpp
r205507 r205520 45 45 } 46 46 47 void JSModuleRecord::finishCreation( VM& vm)47 void JSModuleRecord::finishCreation(ExecState* exec, VM& vm) 48 48 { 49 49 Base::finishCreation(vm); … … 52 52 putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("evaluated")), jsBoolean(false)); 53 53 54 m_dependenciesMap.set(vm, this, JSMap::create(vm, globalObject()->mapStructure())); 54 auto scope = DECLARE_THROW_SCOPE(vm); 55 JSMap* map = JSMap::create(exec, vm, globalObject()->mapStructure()); 56 RELEASE_ASSERT(!scope.exception()); 57 m_dependenciesMap.set(vm, this, map); 55 58 putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("dependenciesMap")), m_dependenciesMap.get()); 56 59 } -
trunk/Source/JavaScriptCore/runtime/JSModuleRecord.h
r205507 r205520 88 88 } 89 89 90 static JSModuleRecord* create( VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)90 static JSModuleRecord* create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) 91 91 { 92 92 JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables); 93 instance->finishCreation( vm);93 instance->finishCreation(exec, vm); 94 94 return instance; 95 95 } … … 153 153 } 154 154 155 void finishCreation( VM&);155 void finishCreation(ExecState*, VM&); 156 156 157 157 JSModuleNamespaceObject* getModuleNamespace(ExecState*); -
trunk/Source/JavaScriptCore/runtime/JSSet.cpp
r205507 r205520 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 … … 27 27 #include "JSSet.h" 28 28 29 #include "CopiedBlockInlines.h" 30 #include "JSCJSValueInlines.h" 31 #include "JSSetIterator.h" 32 #include "MapDataInlines.h" 33 #include "SlotVisitorInlines.h" 34 #include "StructureInlines.h" 29 #include "JSCInlines.h" 35 30 36 31 namespace JSC { 37 32 38 33 const ClassInfo JSSet::s_info = { "Set", &Base::s_info, 0, CREATE_METHOD_TABLE(JSSet) }; 39 40 void JSSet::destroy(JSCell* cell)41 {42 JSSet* thisObject = jsCast<JSSet*>(cell);43 thisObject->JSSet::~JSSet();44 }45 34 46 35 String JSSet::toStringName(const JSObject*, ExecState*) … … 49 38 } 50 39 51 size_t JSSet::estimatedSize(JSCell* cell)52 {53 JSSet* thisObject = jsCast<JSSet*>(cell);54 size_t setDataSize = thisObject->m_setData.capacityInBytes();55 return Base::estimatedSize(cell) + setDataSize;56 40 } 57 58 void JSSet::visitChildren(JSCell* cell, SlotVisitor& visitor)59 {60 Base::visitChildren(cell, visitor);61 jsCast<JSSet*>(cell)->m_setData.visitChildren(cell, visitor);62 }63 64 void JSSet::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token)65 {66 Base::copyBackingStore(cell, visitor, token);67 jsCast<JSSet*>(cell)->m_setData.copyBackingStore(visitor, token);68 }69 70 bool JSSet::has(ExecState* exec, JSValue value)71 {72 return m_setData.contains(exec, value);73 }74 75 size_t JSSet::size(ExecState* exec)76 {77 return m_setData.size(exec);78 }79 80 void JSSet::add(ExecState* exec, JSValue value)81 {82 m_setData.set(exec, this, value, value);83 }84 85 void JSSet::clear(ExecState*)86 {87 m_setData.clear();88 }89 90 bool JSSet::remove(ExecState* exec, JSValue value)91 {92 return m_setData.remove(exec, value);93 }94 95 } -
trunk/Source/JavaScriptCore/runtime/JSSet.h
r205507 r205520 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 … … 27 27 #define JSSet_h 28 28 29 #include "JSDestructibleObject.h"30 29 #include "JSObject.h" 31 #include "Map Data.h"30 #include "MapBase.h" 32 31 33 32 namespace JSC { … … 35 34 class JSSetIterator; 36 35 37 class JSSet : public JSDestructibleObject { 36 class JSSet : public MapBase<HashMapBucket<HashMapBucketDataKey>> { 37 typedef MapBase<HashMapBucket<HashMapBucketDataKey>> Base; 38 38 public: 39 typedef JSDestructibleObject Base;40 39 41 40 friend class JSSetIterator; 42 43 // Our marking functions expect Entry to maintain this layout, and have all44 // fields be WriteBarrier<Unknown>45 class Entry {46 private:47 WriteBarrier<Unknown> m_key;48 49 public:50 const WriteBarrier<Unknown>& key() const51 {52 return m_key;53 }54 55 const WriteBarrier<Unknown>& value() const56 {57 return m_key;58 }59 60 void visitChildren(SlotVisitor& visitor)61 {62 visitor.append(&m_key);63 }64 65 void setKey(VM& vm, const JSCell* owner, JSValue key)66 {67 m_key.set(vm, owner, key);68 }69 70 void setKeyWithoutWriteBarrier(JSValue key)71 {72 m_key.setWithoutWriteBarrier(key);73 }74 75 void setValue(VM&, const JSCell*, JSValue)76 {77 }78 79 void clear()80 {81 m_key.clear();82 }83 };84 85 typedef MapDataImpl<Entry, JSSetIterator> SetData;86 41 87 42 DECLARE_EXPORT_INFO; … … 89 44 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 90 45 { 91 return Structure::create(vm, globalObject, prototype, TypeInfo( ObjectType, StructureFlags), info());46 return Structure::create(vm, globalObject, prototype, TypeInfo(JSSetType, StructureFlags), info()); 92 47 } 93 48 94 static JSSet* create( VM& vm, Structure* structure)49 static JSSet* create(ExecState* exec, VM& vm, Structure* structure) 95 50 { 96 51 JSSet* instance = new (NotNull, allocateCell<JSSet>(vm.heap)) JSSet(vm, structure); 97 instance->finishCreation( vm);52 instance->finishCreation(exec, vm); 98 53 return instance; 99 54 } 100 55 101 static JSSet* create(ExecState* exec, Structure* structure)56 ALWAYS_INLINE void add(ExecState* exec, JSValue key) 102 57 { 103 return create(exec->vm(), structure);58 m_map->add(exec, key); 104 59 } 105 106 bool has(ExecState*, JSValue);107 size_t size(ExecState*);108 JS_EXPORT_PRIVATE void add(ExecState*, JSValue);109 void clear(ExecState*);110 bool remove(ExecState*, JSValue);111 60 112 61 private: 113 62 JSSet(VM& vm, Structure* structure) 114 63 : Base(vm, structure) 115 , m_setData(vm, this)116 64 { 117 65 } 118 66 119 static void destroy(JSCell*);120 static size_t estimatedSize(JSCell*);121 static void visitChildren(JSCell*, SlotVisitor&);122 static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);123 67 static String toStringName(const JSObject*, ExecState*); 124 125 SetData m_setData;126 68 }; 127 69 -
trunk/Source/JavaScriptCore/runtime/JSSetIterator.cpp
r205507 r205520 39 39 Base::finishCreation(vm); 40 40 m_set.set(vm, this, iteratedObject); 41 setIterator(vm, m_set->impl()->head()); 41 42 } 42 43 … … 47 48 Base::visitChildren(thisObject, visitor); 48 49 visitor.append(&thisObject->m_set); 50 visitor.append(&thisObject->m_iter); 49 51 } 50 52 … … 60 62 JSSetIterator* JSSetIterator::clone(ExecState* exec) 61 63 { 62 auto clone = JSSetIterator::create(exec->vm(), exec->callee()->globalObject()->setIteratorStructure(), m_set.get(), m_kind); 63 clone->m_iterator = m_iterator; 64 VM& vm = exec->vm(); 65 auto clone = JSSetIterator::create(vm, exec->callee()->globalObject()->setIteratorStructure(), m_set.get(), m_kind); 66 clone->setIterator(vm, m_iter.get()); 64 67 return clone; 65 68 } -
trunk/Source/JavaScriptCore/runtime/JSSetIterator.h
r205507 r205520 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 … … 36 36 37 37 class JSSetIterator : public JSNonFinalObject { 38 typedef HashMapBucket<HashMapBucketDataKey> HashMapBucketType; 38 39 public: 39 40 typedef JSNonFinalObject Base; … … 53 54 } 54 55 55 bool next(CallFrame* callFrame, JSValue& value)56 ALWAYS_INLINE HashMapBucketType* advanceIter(ExecState* exec) 56 57 { 57 WTF::KeyValuePair<JSValue, JSValue> pair; 58 if (!m_iterator.next(pair)) 59 return false; 60 if (m_kind == IterateValue || m_kind == IterateKey) 61 value = pair.key; 62 else 63 value = createPair(callFrame, pair.key, pair.key); 64 return true; 58 HashMapBucketType* prev = m_iter.get(); 59 if (!prev) 60 return nullptr; 61 HashMapBucketType* bucket = m_iter->next(); 62 while (bucket && bucket->deleted()) { 63 prev = bucket; 64 bucket = bucket->next(); 65 } 66 if (!bucket) { 67 setIterator(exec->vm(), nullptr); 68 return nullptr; 69 } 70 setIterator(exec->vm(), bucket); // We keep m_iter on the last value since the first thing we do in this function is call next(). 71 return bucket; 65 72 } 66 73 67 void finish()74 bool next(ExecState* exec, JSValue& value) 68 75 { 69 m_iterator.finish(); 76 HashMapBucketType* bucket = advanceIter(exec); 77 if (!bucket) 78 return false; 79 80 if (m_kind == IterateValue || m_kind == IterateKey) 81 value = bucket->key(); 82 else 83 value = createPair(exec, bucket->key(), bucket->key()); 84 return true; 70 85 } 71 86 … … 74 89 JSSetIterator* clone(ExecState*); 75 90 76 JSSet::SetData::IteratorData* iteratorData() 91 private: 92 JSSetIterator(VM& vm, Structure* structure, JSSet*, IterationKind kind) 93 : Base(vm, structure) 94 , m_kind(kind) 77 95 { 78 return &m_iterator;79 96 } 80 97 81 private: 82 JSSetIterator(VM& vm, Structure* structure, JSSet* iteratedObject, IterationKind kind) 83 : Base(vm, structure) 84 , m_iterator(iteratedObject->m_setData.createIteratorData(this)) 85 , m_kind(kind) 98 void setIterator(VM& vm, HashMapBucketType* bucket) 86 99 { 100 m_iter.setMayBeNull(vm, this, bucket); 87 101 } 88 102 … … 92 106 93 107 WriteBarrier<JSSet> m_set; 94 JSSet::SetData::IteratorData m_iterator;108 WriteBarrier<HashMapBucketType> m_iter; 95 109 IterationKind m_kind; 96 110 }; -
trunk/Source/JavaScriptCore/runtime/JSType.h
r205507 r205520 83 83 RegExpObjectType, 84 84 ProxyObjectType, 85 JSMapType, 86 JSSetType, 85 87 86 LastJSCObjectType = ProxyObjectType,88 LastJSCObjectType = JSSetType, 87 89 }; 88 90 -
trunk/Source/JavaScriptCore/runtime/MapBase.cpp
r205519 r205520 1 1 /* 2 * Copyright (C) 201 3, 2016 Apple,Inc. All rights reserved.2 * Copyright (C) 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 25 25 26 26 #include "config.h" 27 #include " JSMapIterator.h"27 #include "MapBase.h" 28 28 29 #include "JSCInlines.h" 30 #include "JSMap.h" 31 #include "MapDataInlines.h" 29 #include "SlotVisitorInlines.h" 32 30 33 31 namespace JSC { 34 32 35 const ClassInfo JSMapIterator::s_info = { "Map Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(JSMapIterator) }; 36 37 void JSMapIterator::finishCreation(VM& vm, JSMap* iteratedObject) 33 template <typename HashMapBucketType> 34 void MapBase<HashMapBucketType>::visitChildren(JSCell* cell, SlotVisitor& visitor) 38 35 { 39 Base::finishCreation(vm); 40 m_map.set(vm, this, iteratedObject); 41 } 42 43 void JSMapIterator::visitChildren(JSCell* cell, SlotVisitor& visitor) 44 { 45 JSMapIterator* thisObject = jsCast<JSMapIterator*>(cell); 46 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 36 MapBase* thisObject = static_cast<MapBase*>(cell); 47 37 Base::visitChildren(thisObject, visitor); 48 38 visitor.append(&thisObject->m_map); 49 39 } 50 40 51 JSValue JSMapIterator::createPair(CallFrame* callFrame, JSValue key, JSValue value) 41 template <typename HashMapBucketType> 42 size_t MapBase<HashMapBucketType>::estimatedSize(JSCell* cell) 52 43 { 53 MarkedArgumentBuffer args; 54 args.append(key); 55 args.append(value); 56 JSGlobalObject* globalObject = callFrame->callee()->globalObject(); 57 return constructArray(callFrame, 0, globalObject, args); 44 return Base::estimatedSize(cell) + static_cast<MapBase*>(cell)->m_map->approximateSize(); 58 45 } 59 46 60 JSMapIterator* JSMapIterator::clone(ExecState* exec) 61 { 62 auto clone = JSMapIterator::create(exec->vm(), exec->callee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind); 63 clone->m_iterator = m_iterator; 64 return clone; 65 } 47 template class MapBase<HashMapBucket<HashMapBucketDataKeyValue>>; 48 template class MapBase<HashMapBucket<HashMapBucketDataKey>>; 66 49 67 } 50 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp
r205507 r205520 62 62 JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject(); 63 63 Structure* mapStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->mapStructure()); 64 if ( exec->hadException())64 if (UNLIKELY(scope.exception())) 65 65 return JSValue::encode(JSValue()); 66 JSMap* map = JSMap::create(exec, mapStructure); 66 JSMap* map = JSMap::create(exec, vm, mapStructure); 67 if (UNLIKELY(scope.exception())) 68 return JSValue::encode(JSValue()); 67 69 JSValue iterable = exec->argument(0); 68 70 if (iterable.isUndefinedOrNull()) -
trunk/Source/JavaScriptCore/runtime/MapIteratorPrototype.cpp
r205507 r205520 59 59 if (iterator->next(callFrame, result)) 60 60 return JSValue::encode(createIteratorResultObject(callFrame, result, false)); 61 iterator->finish();62 61 return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true)); 63 62 } -
trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp
r205507 r205520 69 69 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, mapProtoFuncClear, DontEnum, 0); 70 70 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, mapProtoFuncDelete, DontEnum, 1); 71 JSC_NATIVE_ FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, mapProtoFuncGet, DontEnum, 1);72 JSC_NATIVE_ FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, mapProtoFuncHas, DontEnum, 1);71 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, mapProtoFuncGet, DontEnum, 1, JSMapGetIntrinsic); 72 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, mapProtoFuncHas, DontEnum, 1, JSMapHasIntrinsic); 73 73 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, mapProtoFuncSet, DontEnum, 2); 74 74 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), mapProtoFuncKeys, DontEnum, 0); 75 75 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().valuesPublicName(), mapProtoFuncValues, DontEnum, 0); 76 76 77 // Private get / set operations. 78 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, DontEnum, 1); 77 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, DontEnum, 1, JSMapGetIntrinsic); 79 78 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().setPrivateName(), mapProtoFuncSet, DontEnum, 2); 80 79 … … 92 91 auto scope = DECLARE_THROW_SCOPE(vm); 93 92 94 if ( !thisValue.isObject()) {93 if (UNLIKELY(!thisValue.isCell())) { 95 94 throwVMError(callFrame, scope, createNotAnObjectError(callFrame, thisValue)); 96 95 return nullptr; 97 96 } 98 JSMap* map = jsDynamicCast<JSMap*>(thisValue); 99 if (!map) { 100 throwTypeError(callFrame, scope, ASCIILiteral("Map operation called on non-Map object")); 101 return nullptr; 102 } 103 return map; 97 98 if (LIKELY(thisValue.asCell()->type() == JSMapType)) 99 return jsCast<JSMap*>(thisValue); 100 throwTypeError(callFrame, scope, ASCIILiteral("Map operation called on non-Map object")); 101 return nullptr; 102 } 103 104 EncodedJSValue JSC_HOST_CALL privateFuncIsMap(ExecState* exec) 105 { 106 JSValue value = exec->uncheckedArgument(0); 107 return JSValue::encode(jsBoolean(value.isCell() && value.asCell()->type() == JSMapType)); 104 108 } 105 109 … … 188 192 } 189 193 190 EncodedJSValue JSC_HOST_CALL privateFuncIsMap(ExecState* exec)191 {192 return JSValue::encode(jsBoolean(jsDynamicCast<JSMap*>(exec->uncheckedArgument(0))));193 }194 195 194 EncodedJSValue JSC_HOST_CALL privateFuncMapIterator(ExecState* exec) 196 195 { … … 205 204 JSMapIterator* iterator = jsCast<JSMapIterator*>(exec->thisValue()); 206 205 JSValue key, value; 207 if (iterator->nextKeyValue( key, value)) {206 if (iterator->nextKeyValue(exec, key, value)) { 208 207 JSArray* resultArray = jsCast<JSArray*>(exec->uncheckedArgument(0)); 209 208 resultArray->putDirectIndex(exec, 0, key); … … 211 210 return JSValue::encode(jsBoolean(false)); 212 211 } 213 iterator->finish();214 212 return JSValue::encode(jsBoolean(true)); 215 213 } -
trunk/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
r205507 r205520 192 192 } 193 193 194 // See ES5.1 9.12195 bool sameValue(ExecState* exec, JSValue a, JSValue b)196 {197 if (!a.isNumber())198 return JSValue::strictEqual(exec, a, b);199 if (!b.isNumber())200 return false;201 double x = a.asNumber();202 double y = b.asNumber();203 bool xIsNaN = std::isnan(x);204 bool yIsNaN = std::isnan(y);205 if (xIsNaN || yIsNaN)206 return xIsNaN && yIsNaN;207 return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y);208 }209 210 194 bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const 211 195 { -
trunk/Source/JavaScriptCore/runtime/PropertyDescriptor.h
r205507 r205520 32 32 33 33 class GetterSetter; 34 35 // See ES5.1 9.1236 bool sameValue(ExecState*, JSValue, JSValue);37 34 38 35 class PropertyDescriptor { -
trunk/Source/JavaScriptCore/runtime/SetConstructor.cpp
r205507 r205520 63 63 JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject(); 64 64 Structure* setStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->setStructure()); 65 if ( exec->hadException())65 if (UNLIKELY(scope.exception())) 66 66 return JSValue::encode(JSValue()); 67 JSSet* set = JSSet::create(exec, setStructure); 67 JSSet* set = JSSet::create(exec, vm, setStructure); 68 if (UNLIKELY(scope.exception())) 69 return JSValue::encode(JSValue()); 68 70 JSValue iterable = exec->argument(0); 69 71 if (iterable.isUndefinedOrNull()) -
trunk/Source/JavaScriptCore/runtime/SetIteratorPrototype.cpp
r205507 r205520 59 59 if (iterator->next(callFrame, result)) 60 60 return JSValue::encode(createIteratorResultObject(callFrame, result, false)); 61 iterator->finish();62 61 return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true)); 63 62 } -
trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp
r205507 r205520 69 69 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, setProtoFuncClear, DontEnum, 0); 70 70 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, setProtoFuncDelete, DontEnum, 1); 71 JSC_NATIVE_ FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, DontEnum, 1);71 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic); 72 72 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0); 73 73 … … 86 86 auto scope = DECLARE_THROW_SCOPE(vm); 87 87 88 if ( !thisValue.isObject()) {88 if (UNLIKELY(!thisValue.isCell())) { 89 89 throwVMError(callFrame, scope, createNotAnObjectError(callFrame, thisValue)); 90 90 return nullptr; 91 91 } 92 JSSet* set = jsDynamicCast<JSSet*>(thisValue); 93 if (!set) { 94 throwTypeError(callFrame, scope, ASCIILiteral("Set operation called on non-Set object")); 95 return nullptr; 96 } 97 return set; 92 if (LIKELY(thisValue.asCell()->type() == JSSetType)) 93 return jsCast<JSSet*>(thisValue); 94 throwTypeError(callFrame, scope, ASCIILiteral("Set operation called on non-Set object")); 95 return nullptr; 98 96 } 99 97 … … 185 183 return JSValue::encode(jsBoolean(false)); 186 184 } 187 iterator->finish();188 185 return JSValue::encode(jsBoolean(true)); 189 186 } -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r205507 r205520 66 66 #include "JSLexicalEnvironment.h" 67 67 #include "JSLock.h" 68 #include "JSMap.h" 68 69 #include "JSPromiseDeferred.h" 69 70 #include "JSPropertyNameEnumerator.h" … … 254 255 webAssemblyCodeBlockStructure.set(*this, WebAssemblyCodeBlock::createStructure(*this, 0, jsNull())); 255 256 #endif 257 hashMapBucketSetStructure.set(*this, HashMapBucket<HashMapBucketDataKey>::createStructure(*this, 0, jsNull())); 258 hashMapBucketMapStructure.set(*this, HashMapBucket<HashMapBucketDataKeyValue>::createStructure(*this, 0, jsNull())); 259 hashMapImplSetStructure.set(*this, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::createStructure(*this, 0, jsNull())); 260 hashMapImplMapStructure.set(*this, HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>::createStructure(*this, 0, jsNull())); 256 261 257 262 iterationTerminator.set(*this, JSFinalObject::create(*this, JSFinalObject::createStructure(*this, 0, jsNull(), 1))); -
trunk/Source/JavaScriptCore/runtime/VM.h
r205507 r205520 335 335 Strong<Structure> functionCodeBlockStructure; 336 336 Strong<Structure> webAssemblyCodeBlockStructure; 337 Strong<Structure> hashMapBucketSetStructure; 338 Strong<Structure> hashMapBucketMapStructure; 339 Strong<Structure> hashMapImplSetStructure; 340 Strong<Structure> hashMapImplMapStructure; 337 341 338 342 Strong<JSCell> iterationTerminator; -
trunk/Source/WTF/ChangeLog
r205507 r205520 1 2016-09-06 Saam Barati <sbarati@apple.com> 2 3 Make JSMap and JSSet faster 4 https://bugs.webkit.org/show_bug.cgi?id=160989 5 6 Reviewed by Filip Pizlo. 7 8 I made s_flagCount public in StringImpl since JSC's JITs now use this field. 9 10 * wtf/text/StringImpl.h: 11 1 12 2016-09-06 Commit Queue <commit-queue@webkit.org> 2 13 -
trunk/Source/WTF/wtf/text/StringImpl.h
r205507 r205520 149 149 150 150 // The bottom 6 bits in the hash are flags. 151 public: 151 152 static const unsigned s_flagCount = 6; 153 private: 152 154 static const unsigned s_flagMask = (1u << s_flagCount) - 1; 153 155 COMPILE_ASSERT(s_flagCount <= StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags); -
trunk/Source/WebCore/ChangeLog
r205519 r205520 1 2016-09-06 Saam Barati <sbarati@apple.com> 2 3 Make JSMap and JSSet faster 4 https://bugs.webkit.org/show_bug.cgi?id=160989 5 6 Reviewed by Filip Pizlo. 7 8 * ForwardingHeaders/runtime/HashMapImpl.h: Added. 9 * ForwardingHeaders/runtime/MapBase.h: Added. 10 * bindings/js/SerializedScriptValue.cpp: 11 (WebCore::CloneSerializer::serialize): 12 (WebCore::CloneDeserializer::deserialize): 13 1 14 2016-09-06 Myles C. Maxfield <mmaxfield@apple.com> 2 15 -
trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp
r205507 r205520 1369 1369 JSMapIterator* iterator = mapIteratorStack.last(); 1370 1370 JSValue key, value; 1371 if (!iterator->nextKeyValue( key, value)) {1371 if (!iterator->nextKeyValue(m_exec, key, value)) { 1372 1372 mapIteratorStack.removeLast(); 1373 1373 JSObject* object = inputObjectStack.last(); … … 2546 2546 if (outputObjectStack.size() > maximumFilterRecursion) 2547 2547 return std::make_pair(JSValue(), StackOverflowError); 2548 JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure()); 2548 JSMap* map = JSMap::create(m_exec, m_exec->vm(), m_globalObject->mapStructure()); 2549 if (UNLIKELY(m_exec->hadException())) 2550 goto error; 2549 2551 m_gcBuffer.append(map); 2550 2552 outputObjectStack.append(map); … … 2575 2577 if (outputObjectStack.size() > maximumFilterRecursion) 2576 2578 return std::make_pair(JSValue(), StackOverflowError); 2577 JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure()); 2579 JSSet* set = JSSet::create(m_exec, m_exec->vm(), m_globalObject->setStructure()); 2580 if (UNLIKELY(m_exec->hadException())) 2581 goto error; 2578 2582 m_gcBuffer.append(set); 2579 2583 outputObjectStack.append(set);
Note: See TracChangeset
for help on using the changeset viewer.