Changeset 221110 in webkit
- Timestamp:
- Aug 23, 2017 3:19:13 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 56 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r221084 r221110 1 2017-08-23 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Optimize Map iteration with intrinsic 4 https://bugs.webkit.org/show_bug.cgi?id=174355 5 6 Reviewed by Saam Barati. 7 8 * stress/map-iterator-result-should-have-expected-shape.js: Added. 9 (shouldBe): 10 (throw.new.Error): 11 * stress/set-iterator-result-should-have-expected-shape.js: Added. 12 (shouldBe): 13 (throw.new.Error.let.iterator.set Symbol): 14 (throw.new.Error.set add): 15 (let.iterator.set Symbol): 16 1 17 2017-08-23 Robin Morisset <rmorisset@apple.com> 2 18 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r221080 r221110 1477 1477 ${JAVASCRIPTCORE_DIR}/builtins/IteratorHelpers.js 1478 1478 ${JAVASCRIPTCORE_DIR}/builtins/IteratorPrototype.js 1479 ${JAVASCRIPTCORE_DIR}/builtins/MapIteratorPrototype.js 1479 1480 ${JAVASCRIPTCORE_DIR}/builtins/MapPrototype.js 1480 1481 ${JAVASCRIPTCORE_DIR}/builtins/ModuleLoaderPrototype.js … … 1487 1488 ${JAVASCRIPTCORE_DIR}/builtins/ReflectObject.js 1488 1489 ${JAVASCRIPTCORE_DIR}/builtins/RegExpPrototype.js 1490 ${JAVASCRIPTCORE_DIR}/builtins/SetIteratorPrototype.js 1489 1491 ${JAVASCRIPTCORE_DIR}/builtins/SetPrototype.js 1490 1492 ${JAVASCRIPTCORE_DIR}/builtins/StringConstructor.js -
trunk/Source/JavaScriptCore/ChangeLog
r221097 r221110 1 2017-08-23 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Optimize Map iteration with intrinsic 4 https://bugs.webkit.org/show_bug.cgi?id=174355 5 6 Reviewed by Saam Barati. 7 8 This patch optimizes Map/Set iteration by taking the approach similar to Array iteration. 9 We create a simple iterator object instead of JSMapIterator and JSSetIterator. And we 10 directly handles Map/Set buckets in JS builtins. We carefully create mapIteratorNext and 11 setIteratorNext functions which should be inlined. This leads significant performance boost 12 when they are inlined in for-of iteration. 13 14 This patch changes how DFG and FTL handles MapBucket if the bucket is not found. 15 Previously, we use nullptr for that, and DFG and FTL specially handle this nullptr as bucket. 16 Instead, this patch introduces sentinel buckets. They are marked as deleted, and not linked 17 to any hash maps. And its key and value fields are filled with Undefined. By returning this 18 sentinel bucket instead of returning nullptr, we simplify DFG and FTL's LoadXXXFromMapBucket 19 code. 20 21 We still keep JSMapIterator and JSSetIterator because they are useful to serialize Map and Set 22 in WebCore. So they are not used in user observable JS. We change them from JS objects to JS cells. 23 24 Existing microbenchmarks shows performance improvements. 25 26 large-map-iteration 164.1622+-4.1618 ^ 56.6284+-1.5355 ^ definitely 2.8989x faster 27 set-for-of 15.4369+-1.0631 ^ 9.2955+-0.5979 ^ definitely 1.6607x faster 28 map-for-each 7.5889+-0.5792 ^ 6.3011+-0.4816 ^ definitely 1.2044x faster 29 map-for-of 32.3904+-1.3003 ^ 12.6907+-0.6118 ^ definitely 2.5523x faster 30 map-rehash 13.9275+-0.9187 ^ 11.5367+-0.6430 ^ definitely 1.2072x faster 31 32 * CMakeLists.txt: 33 * DerivedSources.make: 34 * builtins/ArrayPrototype.js: 35 (globalPrivate.createArrayIterator): 36 * builtins/BuiltinNames.h: 37 * builtins/MapIteratorPrototype.js: Copied from Source/JavaScriptCore/builtins/MapPrototype.js. 38 (globalPrivate.mapIteratorNext): 39 (next): 40 * builtins/MapPrototype.js: 41 (globalPrivate.createMapIterator): 42 (values): 43 (keys): 44 (entries): 45 (forEach): 46 * builtins/SetIteratorPrototype.js: Copied from Source/JavaScriptCore/builtins/MapPrototype.js. 47 (globalPrivate.setIteratorNext): 48 (next): 49 * builtins/SetPrototype.js: 50 (globalPrivate.createSetIterator): 51 (values): 52 (entries): 53 (forEach): 54 * bytecode/BytecodeIntrinsicRegistry.cpp: 55 (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry): 56 * bytecode/BytecodeIntrinsicRegistry.h: 57 * bytecode/SpeculatedType.h: 58 * dfg/DFGAbstractInterpreterInlines.h: 59 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 60 * dfg/DFGByteCodeParser.cpp: 61 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 62 * dfg/DFGClobberize.h: 63 (JSC::DFG::clobberize): 64 * dfg/DFGDoesGC.cpp: 65 (JSC::DFG::doesGC): 66 * dfg/DFGFixupPhase.cpp: 67 (JSC::DFG::FixupPhase::fixupNode): 68 * dfg/DFGHeapLocation.cpp: 69 (WTF::printInternal): 70 * dfg/DFGHeapLocation.h: 71 * dfg/DFGNode.h: 72 (JSC::DFG::Node::hasHeapPrediction): 73 (JSC::DFG::Node::hasBucketOwnerType): 74 (JSC::DFG::Node::bucketOwnerType): 75 (JSC::DFG::Node::OpInfoWrapper::as const): 76 * dfg/DFGNodeType.h: 77 * dfg/DFGOperations.cpp: 78 * dfg/DFGPredictionPropagationPhase.cpp: 79 * dfg/DFGSafeToExecute.h: 80 (JSC::DFG::safeToExecute): 81 * dfg/DFGSpeculativeJIT.cpp: 82 (JSC::DFG::SpeculativeJIT::compileGetMapBucketHead): 83 (JSC::DFG::SpeculativeJIT::compileGetMapBucketNext): 84 (JSC::DFG::SpeculativeJIT::compileLoadKeyFromMapBucket): 85 (JSC::DFG::SpeculativeJIT::compileLoadValueFromMapBucket): 86 (JSC::DFG::SpeculativeJIT::compileCompareEqPtr): Deleted. 87 * dfg/DFGSpeculativeJIT.h: 88 * dfg/DFGSpeculativeJIT32_64.cpp: 89 (JSC::DFG::SpeculativeJIT::compileCompareEqPtr): 90 (JSC::DFG::SpeculativeJIT::compile): 91 * dfg/DFGSpeculativeJIT64.cpp: 92 (JSC::DFG::SpeculativeJIT::compileCompareEqPtr): 93 (JSC::DFG::SpeculativeJIT::compile): 94 * ftl/FTLAbstractHeapRepository.h: 95 * ftl/FTLCapabilities.cpp: 96 (JSC::FTL::canCompile): 97 * ftl/FTLLowerDFGToB3.cpp: 98 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 99 (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket): 100 (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketHead): 101 (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketNext): 102 (JSC::FTL::DFG::LowerDFGToB3::compileLoadValueFromMapBucket): 103 (JSC::FTL::DFG::LowerDFGToB3::compileLoadKeyFromMapBucket): 104 (JSC::FTL::DFG::LowerDFGToB3::setStorage): 105 (JSC::FTL::DFG::LowerDFGToB3::compileLoadFromJSMapBucket): Deleted. 106 (JSC::FTL::DFG::LowerDFGToB3::compileIsNonEmptyMapBucket): Deleted. 107 (JSC::FTL::DFG::LowerDFGToB3::lowMapBucket): Deleted. 108 (JSC::FTL::DFG::LowerDFGToB3::setMapBucket): Deleted. 109 * inspector/JSInjectedScriptHost.cpp: 110 (Inspector::JSInjectedScriptHost::subtype): 111 (Inspector::JSInjectedScriptHost::getInternalProperties): 112 (Inspector::cloneMapIteratorObject): 113 (Inspector::cloneSetIteratorObject): 114 (Inspector::JSInjectedScriptHost::iteratorEntries): 115 * runtime/HashMapImpl.h: 116 (JSC::HashMapBucket::createSentinel): 117 (JSC::HashMapBucket::offsetOfNext): 118 (JSC::HashMapBucket::offsetOfDeleted): 119 (JSC::HashMapImpl::offsetOfHead): 120 * runtime/Intrinsic.cpp: 121 (JSC::intrinsicName): 122 * runtime/Intrinsic.h: 123 * runtime/JSGlobalObject.cpp: 124 (JSC::JSGlobalObject::init): 125 * runtime/JSGlobalObject.h: 126 * runtime/JSMap.h: 127 * runtime/JSMapIterator.cpp: 128 (JSC::JSMapIterator::clone): Deleted. 129 * runtime/JSMapIterator.h: 130 (JSC::JSMapIterator::iteratedValue const): 131 * runtime/JSSet.h: 132 * runtime/JSSetIterator.cpp: 133 (JSC::JSSetIterator::clone): Deleted. 134 * runtime/JSSetIterator.h: 135 (JSC::JSSetIterator::iteratedValue const): 136 * runtime/MapConstructor.cpp: 137 (JSC::mapPrivateFuncMapBucketHead): 138 (JSC::mapPrivateFuncMapBucketNext): 139 (JSC::mapPrivateFuncMapBucketKey): 140 (JSC::mapPrivateFuncMapBucketValue): 141 * runtime/MapConstructor.h: 142 * runtime/MapIteratorPrototype.cpp: 143 (JSC::MapIteratorPrototype::finishCreation): 144 (JSC::MapIteratorPrototypeFuncNext): Deleted. 145 * runtime/MapPrototype.cpp: 146 (JSC::MapPrototype::finishCreation): 147 (JSC::mapProtoFuncValues): Deleted. 148 (JSC::mapProtoFuncEntries): Deleted. 149 (JSC::mapProtoFuncKeys): Deleted. 150 (JSC::privateFuncMapIterator): Deleted. 151 (JSC::privateFuncMapIteratorNext): Deleted. 152 * runtime/MapPrototype.h: 153 * runtime/SetConstructor.cpp: 154 (JSC::setPrivateFuncSetBucketHead): 155 (JSC::setPrivateFuncSetBucketNext): 156 (JSC::setPrivateFuncSetBucketKey): 157 * runtime/SetConstructor.h: 158 * runtime/SetIteratorPrototype.cpp: 159 (JSC::SetIteratorPrototype::finishCreation): 160 (JSC::SetIteratorPrototypeFuncNext): Deleted. 161 * runtime/SetPrototype.cpp: 162 (JSC::SetPrototype::finishCreation): 163 (JSC::setProtoFuncSize): 164 (JSC::setProtoFuncValues): Deleted. 165 (JSC::setProtoFuncEntries): Deleted. 166 (JSC::privateFuncSetIterator): Deleted. 167 (JSC::privateFuncSetIteratorNext): Deleted. 168 * runtime/SetPrototype.h: 169 * runtime/VM.cpp: 170 (JSC::VM::VM): 171 * runtime/VM.h: 172 1 173 2017-08-23 David Kilzer <ddkilzer@apple.com> 2 174 -
trunk/Source/JavaScriptCore/DerivedSources.make
r221080 r221110 106 106 $(JavaScriptCore)/builtins/IteratorHelpers.js \ 107 107 $(JavaScriptCore)/builtins/IteratorPrototype.js \ 108 $(JavaScriptCore)/builtins/MapIteratorPrototype.js \ 108 109 $(JavaScriptCore)/builtins/MapPrototype.js \ 109 110 $(JavaScriptCore)/builtins/ModuleLoaderPrototype.js \ … … 116 117 $(JavaScriptCore)/builtins/ReflectObject.js \ 117 118 $(JavaScriptCore)/builtins/RegExpPrototype.js \ 119 $(JavaScriptCore)/builtins/SetIteratorPrototype.js \ 118 120 $(JavaScriptCore)/builtins/SetPrototype.js \ 119 121 $(JavaScriptCore)/builtins/StringConstructor.js \ -
trunk/Source/JavaScriptCore/builtins/ArrayPrototype.js
r218674 r221110 29 29 function createArrayIterator(iteratedObject, kind, iterationFunction) 30 30 { 31 "use strict"; 32 31 33 this.@iteratedObject = iteratedObject; 32 34 this.@arrayIteratorKind = kind; -
trunk/Source/JavaScriptCore/builtins/BuiltinNames.h
r221080 r221110 148 148 macro(print) \ 149 149 macro(regExpCreate) \ 150 macro(SetIterator) \151 macro(setIteratorNext) \152 150 macro(replaceUsingRegExp) \ 153 151 macro(replaceUsingStringSearch) \ 154 macro(MapIterator) \ 155 macro(mapIteratorNext) \ 152 macro(mapBucket) \ 153 macro(mapBucketHead) \ 154 macro(mapBucketNext) \ 155 macro(mapBucketKey) \ 156 macro(mapBucketValue) \ 157 macro(mapIteratorKind) \ 158 macro(setBucket) \ 159 macro(setBucketHead) \ 160 macro(setBucketNext) \ 161 macro(setBucketKey) \ 162 macro(setIteratorKind) \ 156 163 macro(regExpBuiltinExec) \ 157 164 macro(regExpMatchFast) \ -
trunk/Source/JavaScriptCore/builtins/MapIteratorPrototype.js
r221109 r221110 1 1 /* 2 * Copyright (C) 201 6Yusuke Suzuki <utatane.tea@gmail.com>.2 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 function forEach(callback /*, thisArg */) 26 // We keep this function small very carefully to encourage inlining. 27 @globalPrivate 28 function mapIteratorNext(bucket, kind) 29 { 30 "use strict"; 31 var value; 32 33 bucket = @mapBucketNext(bucket); 34 this.@mapBucket = bucket; 35 var done = bucket === @sentinelMapBucket; 36 if (!done) { 37 var key = @mapBucketKey(bucket); 38 value = @mapBucketValue(bucket); 39 if (kind === @iterationKindKeyValue) 40 value = [ key, value ] 41 else if (kind === @iterationKindKey) 42 value = key; 43 } 44 return { done, value }; 45 } 46 47 function next() 27 48 { 28 49 "use strict"; 29 50 30 if ( !@isMap(this))31 @throwTypeError(" Map operation called on non-Map object");51 if (this == null) 52 @throwTypeError("%MapIteratorPrototype%.next requires that |this| not be null or undefined"); 32 53 33 if (typeof callback !== 'function') 34 @throwTypeError("Map.prototype.forEach callback must be a function"); 35 36 var thisArg = @argument(1); 37 var iterator = @MapIterator(this); 38 39 // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results. 40 var value = [ @undefined, @undefined ]; 41 for (;;) { 42 if (@mapIteratorNext.@call(iterator, value)) 43 break; 44 callback.@call(thisArg, value[1], value[0], this); 45 } 54 var bucket = this.@mapBucket; 55 if (bucket === @undefined) 56 @throwTypeError("%MapIteratorPrototype%.next requires that |this| be a Map Iterator instance"); 57 return @mapIteratorNext.@call(this, bucket, this.@mapIteratorKind); 46 58 } -
trunk/Source/JavaScriptCore/builtins/MapPrototype.js
r208524 r221110 1 1 /* 2 * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>.2 * Copyright (C) 2016-2017 Yusuke Suzuki <utatane.tea@gmail.com>. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 @constructor 27 @globalPrivate 28 function createMapIterator(iteratedObject, kind) 29 { 30 "use strict"; 31 32 @assert(@isMap(iteratedObject)); 33 this.@iteratedObject = iteratedObject; 34 this.@mapIteratorKind = kind; 35 this.@mapBucket = @mapBucketHead(iteratedObject); 36 } 37 38 function values() 39 { 40 "use strict"; 41 42 if (!@isMap(this)) 43 @throwTypeError("Map.prototype.values requires that |this| be Map"); 44 45 return new @createMapIterator(this, @iterationKindValue); 46 } 47 48 function keys() 49 { 50 "use strict"; 51 52 if (!@isMap(this)) 53 @throwTypeError("Map.prototype.keys requires that |this| be Map"); 54 55 return new @createMapIterator(this, @iterationKindKey); 56 } 57 58 function entries() 59 { 60 "use strict"; 61 62 if (!@isMap(this)) 63 @throwTypeError("Map.prototype.entries requires that |this| be Map"); 64 65 return new @createMapIterator(this, @iterationKindKeyValue); 66 } 67 26 68 function forEach(callback /*, thisArg */) 27 69 { … … 35 77 36 78 var thisArg = @argument(1); 37 var iterator = @MapIterator(this);79 var bucket = @mapBucketHead(this); 38 80 39 // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results. 40 var value = [ @undefined, @undefined ]; 41 for (;;) { 42 if (@mapIteratorNext.@call(iterator, value)) 81 do { 82 bucket = @mapBucketNext(bucket); 83 if (bucket === @sentinelMapBucket) 43 84 break; 44 callback.@call(thisArg, value[1], value[0], this);45 } 85 callback.@call(thisArg, @mapBucketValue(bucket), @mapBucketKey(bucket), this); 86 } while (true); 46 87 } -
trunk/Source/JavaScriptCore/builtins/SetIteratorPrototype.js
r221109 r221110 1 1 /* 2 * Copyright (C) 201 6Yusuke Suzuki <utatane.tea@gmail.com>.2 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 function forEach(callback /*, thisArg */) 26 // We keep this function small very carefully to encourage inlining. 27 @globalPrivate 28 function setIteratorNext(bucket, kind) 29 { 30 "use strict"; 31 var value; 32 33 bucket = @setBucketNext(bucket); 34 this.@setBucket = bucket; 35 var done = bucket === @sentinelSetBucket; 36 if (!done) { 37 value = @setBucketKey(bucket); 38 if (kind === @iterationKindKeyValue) 39 value = [ value, value ] 40 } 41 return { done, value }; 42 } 43 44 function next() 27 45 { 28 46 "use strict"; 29 47 30 if ( !@isMap(this))31 @throwTypeError(" Map operation called on non-Map object");48 if (this == null) 49 @throwTypeError("%SetIteratorPrototype%.next requires that |this| not be null or undefined"); 32 50 33 if (typeof callback !== 'function') 34 @throwTypeError("Map.prototype.forEach callback must be a function"); 35 36 var thisArg = @argument(1); 37 var iterator = @MapIterator(this); 38 39 // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results. 40 var value = [ @undefined, @undefined ]; 41 for (;;) { 42 if (@mapIteratorNext.@call(iterator, value)) 43 break; 44 callback.@call(thisArg, value[1], value[0], this); 45 } 51 var bucket = this.@setBucket; 52 if (bucket === @undefined) 53 @throwTypeError("%SetIteratorPrototype%.next requires that |this| be a Set Iterator instance"); 54 return @setIteratorNext.@call(this, bucket, this.@setIteratorKind); 46 55 } -
trunk/Source/JavaScriptCore/builtins/SetPrototype.js
r208524 r221110 24 24 */ 25 25 26 @constructor 27 @globalPrivate 28 function createSetIterator(iteratedObject, kind) 29 { 30 "use strict"; 31 32 @assert(@isSet(iteratedObject)); 33 this.@iteratedObject = iteratedObject; 34 this.@setIteratorKind = kind; 35 this.@setBucket = @setBucketHead(iteratedObject); 36 } 37 38 function values() 39 { 40 "use strict"; 41 42 if (!@isSet(this)) 43 @throwTypeError("Set.prototype.values requires that |this| be Set"); 44 45 return new @createSetIterator(this, @iterationKindValue); 46 } 47 48 function entries() 49 { 50 "use strict"; 51 52 if (!@isSet(this)) 53 @throwTypeError("Set.prototype.entries requires that |this| be Set"); 54 55 return new @createSetIterator(this, @iterationKindKeyValue); 56 } 57 26 58 function forEach(callback /*, thisArg */) 27 59 { … … 35 67 36 68 var thisArg = @argument(1); 37 var iterator = @SetIterator(this);69 var bucket = @setBucketHead(this); 38 70 39 // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results. 40 var value = [ @undefined ]; 41 for (;;) { 42 if (@setIteratorNext.@call(iterator, value)) 71 do { 72 bucket = @setBucketNext(bucket); 73 if (bucket === @sentinelSetBucket) 43 74 break; 44 callback.@call(thisArg, value[0], value[0], this); 45 } 75 var key = @setBucketKey(bucket); 76 callback.@call(thisArg, key, key, this); 77 } while (true); 46 78 } -
trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
r221080 r221110 70 70 m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Fulfilled))); 71 71 m_promiseStateRejected.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Rejected))); 72 m_sentinelMapBucket.set(m_vm, m_vm.sentinelMapBucket.get()); 73 m_sentinelSetBucket.set(m_vm, m_vm.sentinelSetBucket.get()); 72 74 m_GeneratorResumeModeNormal.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))); 73 75 m_GeneratorResumeModeThrow.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))); -
trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
r221080 r221110 81 81 macro(promiseStateFulfilled) \ 82 82 macro(promiseStateRejected) \ 83 macro(sentinelMapBucket) \ 84 macro(sentinelSetBucket) \ 83 85 macro(GeneratorResumeModeNormal) \ 84 86 macro(GeneratorResumeModeThrow) \ -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h
r220735 r221110 67 67 static const SpeculatedType SpecString = SpecStringIdent | SpecStringVar; // It's definitely a JSString. 68 68 static const SpeculatedType SpecSymbol = 1ull << 23; // It's definitely a Symbol. 69 static const SpeculatedType SpecCellOther = 1ull << 24; // 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=13307869 static const SpeculatedType SpecCellOther = 1ull << 24; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. 70 70 static const SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell. 71 71 static const SpeculatedType SpecBoolInt32 = 1ull << 25; // It's definitely an Int32 with value 0 or 1. -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r221080 r221110 1049 1049 } 1050 1050 1051 case LoadFromJSMapBucket: 1051 case LoadKeyFromMapBucket: 1052 case LoadValueFromMapBucket: 1052 1053 forNode(node).makeHeapTop(); 1053 1054 break; 1054 1055 1055 1056 case GetMapBucket: 1056 forNode(node).setType(m_graph, SpecCellOther); 1057 break; 1058 1059 case IsNonEmptyMapBucket: 1060 forNode(node).setType(SpecBoolean); 1057 case GetMapBucketHead: 1058 if (node->child1().useKind() == MapObjectUse) 1059 forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get()); 1060 else { 1061 ASSERT(node->child1().useKind() == SetObjectUse); 1062 forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get()); 1063 } 1064 break; 1065 1066 case GetMapBucketNext: 1067 if (node->bucketOwnerType() == BucketOwnerType::Map) 1068 forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get()); 1069 else { 1070 ASSERT(node->bucketOwnerType() == BucketOwnerType::Set); 1071 forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get()); 1072 } 1061 1073 break; 1062 1074 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r221084 r221110 2869 2869 Node* hash = addToGraph(MapHash, key); 2870 2870 Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(key), Edge(hash)); 2871 Node* result = addToGraph(Load FromJSMapBucket, OpInfo(), OpInfo(prediction), bucket);2871 Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket); 2872 2872 set(VirtualRegister(resultOperand), result); 2873 2873 return true; … … 2885 2885 UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse; 2886 2886 Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(key), Edge(hash)); 2887 Node* result = addToGraph(IsNonEmptyMapBucket, bucket); 2887 JSCell* sentinel = nullptr; 2888 if (intrinsic == JSMapHasIntrinsic) 2889 sentinel = m_vm->sentinelMapBucket.get(); 2890 else 2891 sentinel = m_vm->sentinelSetBucket.get(); 2892 2893 FrozenValue* frozenPointer = m_graph.freeze(sentinel); 2894 Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket); 2895 Node* result = addToGraph(LogicalNot, invertedResult); 2896 set(VirtualRegister(resultOperand), result); 2897 return true; 2898 } 2899 2900 case JSSetBucketHeadIntrinsic: 2901 case JSMapBucketHeadIntrinsic: { 2902 ASSERT(argumentCountIncludingThis == 2); 2903 2904 insertChecks(); 2905 Node* map = get(virtualRegisterForArgument(1, registerOffset)); 2906 UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse; 2907 Node* result = addToGraph(GetMapBucketHead, Edge(map, useKind)); 2908 set(VirtualRegister(resultOperand), result); 2909 return true; 2910 } 2911 2912 case JSSetBucketNextIntrinsic: 2913 case JSMapBucketNextIntrinsic: { 2914 ASSERT(argumentCountIncludingThis == 2); 2915 2916 insertChecks(); 2917 Node* bucket = get(virtualRegisterForArgument(1, registerOffset)); 2918 BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map; 2919 Node* result = addToGraph(GetMapBucketNext, OpInfo(type), bucket); 2920 set(VirtualRegister(resultOperand), result); 2921 return true; 2922 } 2923 2924 case JSSetBucketKeyIntrinsic: 2925 case JSMapBucketKeyIntrinsic: { 2926 ASSERT(argumentCountIncludingThis == 2); 2927 2928 insertChecks(); 2929 Node* bucket = get(virtualRegisterForArgument(1, registerOffset)); 2930 Node* result = addToGraph(LoadKeyFromMapBucket, OpInfo(), OpInfo(prediction), bucket); 2931 set(VirtualRegister(resultOperand), result); 2932 return true; 2933 } 2934 2935 case JSMapBucketValueIntrinsic: { 2936 ASSERT(argumentCountIncludingThis == 2); 2937 2938 insertChecks(); 2939 Node* bucket = get(virtualRegisterForArgument(1, registerOffset)); 2940 Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket); 2888 2941 set(VirtualRegister(resultOperand), result); 2889 2942 return true; -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r221080 r221110 149 149 // more bits than we currently have in PureValue. 150 150 return; 151 152 case CompareEqPtr: 153 def(PureValue(node, node->cellOperand()->cell())); 154 return; 151 155 152 156 case ArithIMul: … … 159 163 case StringCharCodeAt: 160 164 case CompareStrictEq: 161 case CompareEqPtr:162 165 case IsEmpty: 163 166 case IsUndefined: … … 1552 1555 return; 1553 1556 } 1554 case LoadFromJSMapBucket: { 1557 case GetMapBucketHead: { 1558 read(MiscFields); 1559 Edge& mapEdge = node->child1(); 1560 def(HeapLocation(MapBucketHeadLoc, MiscFields, mapEdge), LazyNode(node)); 1561 return; 1562 } 1563 case GetMapBucketNext: { 1564 read(MiscFields); 1565 LocationKind locationKind = MapBucketMapNextLoc; 1566 if (node->bucketOwnerType() == BucketOwnerType::Set) 1567 locationKind = MapBucketSetNextLoc; 1568 Edge& bucketEdge = node->child1(); 1569 def(HeapLocation(locationKind, MiscFields, bucketEdge), LazyNode(node)); 1570 return; 1571 } 1572 case LoadKeyFromMapBucket: { 1555 1573 read(MiscFields); 1556 1574 Edge& bucketEdge = node->child1(); 1557 def(HeapLocation( JSMapGetLoc, MiscFields, bucketEdge), LazyNode(node));1558 return; 1559 } 1560 case IsNonEmptyMapBucket:1575 def(HeapLocation(MapBucketKeyLoc, MiscFields, bucketEdge), LazyNode(node)); 1576 return; 1577 } 1578 case LoadValueFromMapBucket: { 1561 1579 read(MiscFields); 1562 def(HeapLocation(MapHasLoc, MiscFields, node->child1()), LazyNode(node)); 1563 return; 1580 Edge& bucketEdge = node->child1(); 1581 def(HeapLocation(MapBucketValueLoc, MiscFields, bucketEdge), LazyNode(node)); 1582 return; 1583 } 1564 1584 1565 1585 case ToLowerCase: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r221080 r221110 195 195 case MapHash: 196 196 case GetMapBucket: 197 case LoadFromJSMapBucket: 198 case IsNonEmptyMapBucket: 197 case GetMapBucketHead: 198 case GetMapBucketNext: 199 case LoadKeyFromMapBucket: 200 case LoadValueFromMapBucket: 199 201 case Unreachable: 200 202 case ExtractOSREntryLocal: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r221080 r221110 1796 1796 break; 1797 1797 1798 case LoadFromJSMapBucket: 1799 fixEdge<KnownCellUse>(node->child1()); 1800 break; 1801 1802 case IsNonEmptyMapBucket: 1803 fixEdge<KnownCellUse>(node->child1()); 1798 case GetMapBucketHead: 1799 if (node->child1().useKind() == MapObjectUse) 1800 fixEdge<MapObjectUse>(node->child1()); 1801 else if (node->child1().useKind() == SetObjectUse) 1802 fixEdge<SetObjectUse>(node->child1()); 1803 else 1804 RELEASE_ASSERT_NOT_REACHED(); 1805 break; 1806 1807 case GetMapBucketNext: 1808 case LoadKeyFromMapBucket: 1809 case LoadValueFromMapBucket: 1810 fixEdge<CellUse>(node->child1()); 1804 1811 break; 1805 1812 -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp
r220118 r221110 163 163 out.print("MapBucketLoc"); 164 164 return; 165 case JSMapGetLoc:166 out.print(" JSMapGetLoc");165 case MapBucketHeadLoc: 166 out.print("MapBucketHeadLoc"); 167 167 return; 168 case MapHasLoc: 169 out.print("MapHasLoc"); 168 case MapBucketKeyLoc: 169 out.print("MapBucketKeyLoc"); 170 return; 171 case MapBucketValueLoc: 172 out.print("MapBucketValueLoc"); 173 return; 174 case MapBucketMapNextLoc: 175 out.print("MapBucketMapNextLoc"); 176 return; 177 case MapBucketSetNextLoc: 178 out.print("MapBucketSetNextLoc"); 170 179 return; 171 180 case DOMStateLoc: -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h
r220118 r221110 64 64 StackPayloadLoc, 65 65 MapBucketLoc, 66 JSMapGetLoc, 67 MapHasLoc, 66 MapBucketHeadLoc, 67 MapBucketValueLoc, 68 MapBucketKeyLoc, 69 MapBucketMapNextLoc, 70 MapBucketSetNextLoc, 68 71 DOMStateLoc, 69 72 }; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r221084 r221110 242 242 DOMJIT::CallDOMGetterSnippet* snippet { nullptr }; 243 243 unsigned identifierNumber { 0 }; 244 }; 245 246 enum class BucketOwnerType : uint32_t { 247 Map, 248 Set 244 249 }; 245 250 … … 1516 1521 case StringReplaceRegExp: 1517 1522 case ToNumber: 1518 case LoadFromJSMapBucket: 1523 case LoadKeyFromMapBucket: 1524 case LoadValueFromMapBucket: 1519 1525 case CallDOMGetter: 1520 1526 case CallDOM: … … 2545 2551 } 2546 2552 2553 bool hasBucketOwnerType() 2554 { 2555 return op() == GetMapBucketNext; 2556 } 2557 2558 BucketOwnerType bucketOwnerType() 2559 { 2560 ASSERT(hasBucketOwnerType()); 2561 return m_opInfo.as<BucketOwnerType>(); 2562 } 2563 2547 2564 void dumpChildren(PrintStream& out) 2548 2565 { … … 2653 2670 } 2654 2671 template <typename T> 2655 ALWAYS_INLINE auto as() const -> typename std::enable_if< std::is_integral<T>::value&& sizeof(T) == 4, T>::type2672 ALWAYS_INLINE auto as() const -> typename std::enable_if<(std::is_integral<T>::value || std::is_enum<T>::value) && sizeof(T) == 4, T>::type 2656 2673 { 2657 return u.int32;2674 return static_cast<T>(u.int32); 2658 2675 } 2659 2676 template <typename T> 2660 ALWAYS_INLINE auto as() const -> typename std::enable_if< std::is_integral<T>::value&& sizeof(T) == 8, T>::type2677 ALWAYS_INLINE auto as() const -> typename std::enable_if<(std::is_integral<T>::value || std::is_enum<T>::value) && sizeof(T) == 8, T>::type 2661 2678 { 2662 return u.int64;2679 return static_cast<T>(u.int64); 2663 2680 } 2664 2681 ALWAYS_INLINE RegisteredStructure asRegisteredStructure() const -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r221080 r221110 432 432 macro(MapHash, NodeResultInt32) \ 433 433 macro(GetMapBucket, NodeResultJS) \ 434 macro(LoadFromJSMapBucket, NodeResultJS) \ 435 macro(IsNonEmptyMapBucket, NodeResultBoolean) \ 434 macro(GetMapBucketHead, NodeResultJS) \ 435 macro(GetMapBucketNext, NodeResultJS) \ 436 macro(LoadKeyFromMapBucket, NodeResultJS) \ 437 macro(LoadValueFromMapBucket, NodeResultJS) \ 436 438 \ 437 439 macro(ToLowerCase, NodeResultJS) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r220306 r221110 2300 2300 JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash); 2301 2301 if (!bucket) 2302 return nullptr;2302 return vm.sentinelMapBucket.get(); 2303 2303 return *bucket; 2304 2304 } … … 2310 2310 JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash); 2311 2311 if (!bucket) 2312 return nullptr;2312 return vm.sentinelSetBucket.get(); 2313 2313 return *bucket; 2314 2314 } -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r221084 r221110 718 718 case GetClosureVar: 719 719 case GetFromArguments: 720 case LoadFromJSMapBucket: 720 case LoadKeyFromMapBucket: 721 case LoadValueFromMapBucket: 721 722 case ToNumber: 722 723 case GetArgument: … … 757 758 setPrediction(SpecInt32Only); 758 759 break; 760 759 761 case GetMapBucket: 762 case GetMapBucketHead: 763 case GetMapBucketNext: 760 764 setPrediction(SpecCellOther); 761 break;762 case IsNonEmptyMapBucket:763 setPrediction(SpecBoolean);764 765 break; 765 766 -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r221080 r221110 384 384 case ToLowerCase: 385 385 case GetMapBucket: 386 case LoadFromJSMapBucket: 387 case IsNonEmptyMapBucket: 386 case GetMapBucketHead: 387 case GetMapBucketNext: 388 case LoadKeyFromMapBucket: 389 case LoadValueFromMapBucket: 388 390 case AtomicsAdd: 389 391 case AtomicsAnd: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r221080 r221110 10009 10009 } 10010 10010 10011 void SpeculativeJIT::compileCompareEqPtr(Node* node)10012 {10013 JSValueOperand operand(this, node->child1());10014 GPRTemporary result(this);10015 JSValueRegs regs = operand.jsValueRegs();10016 GPRReg resultGPR = result.gpr();10017 m_jit.boxBooleanPayload(false, resultGPR);10018 JITCompiler::JumpList notEqual = m_jit.branchIfNotEqual(regs, node->cellOperand()->value());10019 m_jit.boxBooleanPayload(true, resultGPR);10020 notEqual.link(&m_jit);10021 blessedBooleanResult(resultGPR, node);10022 }10023 10024 10011 void SpeculativeJIT::compileDefineDataProperty(Node* node) 10025 10012 { … … 10196 10183 } 10197 10184 10185 void SpeculativeJIT::compileGetMapBucketHead(Node* node) 10186 { 10187 SpeculateCellOperand map(this, node->child1()); 10188 GPRTemporary bucket(this); 10189 10190 GPRReg mapGPR = map.gpr(); 10191 GPRReg bucketGPR = bucket.gpr(); 10192 10193 if (node->child1().useKind() == MapObjectUse) 10194 speculateMapObject(node->child1(), mapGPR); 10195 else if (node->child1().useKind() == SetObjectUse) 10196 speculateSetObject(node->child1(), mapGPR); 10197 else 10198 RELEASE_ASSERT_NOT_REACHED(); 10199 10200 ASSERT(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead() == HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>::offsetOfHead()); 10201 m_jit.loadPtr(MacroAssembler::Address(mapGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead()), bucketGPR); 10202 cellResult(bucketGPR, node); 10203 } 10204 10205 void SpeculativeJIT::compileGetMapBucketNext(Node* node) 10206 { 10207 SpeculateCellOperand bucket(this, node->child1()); 10208 GPRTemporary result(this); 10209 10210 GPRReg bucketGPR = bucket.gpr(); 10211 GPRReg resultGPR = result.gpr(); 10212 10213 ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfNext() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()); 10214 ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfDeleted() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted()); 10215 m_jit.loadPtr(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()), resultGPR); 10216 10217 MacroAssembler::Label loop = m_jit.label(); 10218 auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR); 10219 auto done = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(resultGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted())); 10220 m_jit.loadPtr(MacroAssembler::Address(resultGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()), resultGPR); 10221 m_jit.jump().linkTo(loop, &m_jit); 10222 10223 notBucket.link(&m_jit); 10224 JSCell* sentinel = nullptr; 10225 if (node->bucketOwnerType() == BucketOwnerType::Map) 10226 sentinel = m_jit.vm()->sentinelMapBucket.get(); 10227 else { 10228 ASSERT(node->bucketOwnerType() == BucketOwnerType::Set); 10229 sentinel = m_jit.vm()->sentinelSetBucket.get(); 10230 } 10231 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), sentinel), resultGPR); 10232 done.link(&m_jit); 10233 10234 cellResult(resultGPR, node); 10235 } 10236 10237 void SpeculativeJIT::compileLoadKeyFromMapBucket(Node* node) 10238 { 10239 SpeculateCellOperand bucket(this, node->child1()); 10240 JSValueRegsTemporary result(this); 10241 10242 GPRReg bucketGPR = bucket.gpr(); 10243 JSValueRegs resultRegs = result.regs(); 10244 10245 m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey()), resultRegs); 10246 jsValueResult(resultRegs, node); 10247 } 10248 10249 void SpeculativeJIT::compileLoadValueFromMapBucket(Node* node) 10250 { 10251 SpeculateCellOperand bucket(this, node->child1()); 10252 JSValueRegsTemporary result(this); 10253 10254 GPRReg bucketGPR = bucket.gpr(); 10255 JSValueRegs resultRegs = result.regs(); 10256 10257 m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), resultRegs); 10258 jsValueResult(resultRegs, node); 10259 } 10260 10198 10261 } } // namespace JSC::DFG 10199 10262 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r220890 r221110 2780 2780 void compileCallDOM(Node*); 2781 2781 void compileCheckSubClass(Node*); 2782 void compileGetMapBucketHead(Node*); 2783 void compileGetMapBucketNext(Node*); 2784 void compileLoadKeyFromMapBucket(Node*); 2785 void compileLoadValueFromMapBucket(Node*); 2782 2786 2783 2787 #if USE(JSVALUE32_64) -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r221080 r221110 691 691 notEqual.link(&m_jit); 692 692 booleanResult(result.gpr(), node); 693 } 694 695 void SpeculativeJIT::compileCompareEqPtr(Node* node) 696 { 697 JSValueOperand operand(this, node->child1()); 698 GPRTemporary result(this); 699 JSValueRegs regs = operand.jsValueRegs(); 700 GPRReg resultGPR = result.gpr(); 701 m_jit.boxBooleanPayload(false, resultGPR); 702 JITCompiler::JumpList notEqual = m_jit.branchIfNotEqual(regs, node->cellOperand()->value()); 703 m_jit.boxBooleanPayload(true, resultGPR); 704 notEqual.link(&m_jit); 705 blessedBooleanResult(resultGPR, node); 693 706 } 694 707 … … 4903 4916 } 4904 4917 4905 case LoadFromJSMapBucket: { 4906 SpeculateCellOperand bucket(this, node->child1()); 4907 GPRTemporary resultPayload(this); 4908 GPRTemporary resultTag(this); 4909 4910 GPRReg bucketGPR = bucket.gpr(); 4911 GPRReg resultPayloadGPR = resultPayload.gpr(); 4912 GPRReg resultTagGPR = resultTag.gpr(); 4913 4914 auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR); 4915 m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), JSValueRegs(resultTagGPR, resultPayloadGPR)); 4916 auto done = m_jit.jump(); 4917 4918 notBucket.link(&m_jit); 4919 m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTagGPR); 4920 m_jit.move(TrustedImm32(0), resultPayloadGPR); 4921 done.link(&m_jit); 4922 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4923 break; 4924 } 4925 4926 case IsNonEmptyMapBucket: { 4927 SpeculateCellOperand bucket(this, node->child1()); 4928 GPRTemporary result(this); 4929 4930 GPRReg bucketGPR = bucket.gpr(); 4931 GPRReg resultGPR = result.gpr(); 4932 4933 m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR); 4934 booleanResult(resultGPR, node); 4935 break; 4936 } 4918 case GetMapBucketHead: 4919 compileGetMapBucketHead(node); 4920 break; 4921 4922 case GetMapBucketNext: 4923 compileGetMapBucketNext(node); 4924 break; 4925 4926 case LoadKeyFromMapBucket: 4927 compileLoadKeyFromMapBucket(node); 4928 break; 4929 4930 case LoadValueFromMapBucket: 4931 compileLoadValueFromMapBucket(node); 4932 break; 4937 4933 4938 4934 case Flush: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r221080 r221110 1835 1835 1836 1836 jsValueResult(result.gpr(), node, DataFormatJSBoolean); 1837 } 1838 1839 void SpeculativeJIT::compileCompareEqPtr(Node* node) 1840 { 1841 JSValueOperand value(this, node->child1()); 1842 GPRTemporary result(this); 1843 GPRReg valueGPR = value.gpr(); 1844 GPRReg resultGPR = result.gpr(); 1845 1846 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), node->cellOperand()->cell()), resultGPR); 1847 m_jit.compare64(MacroAssembler::Equal, valueGPR, resultGPR, resultGPR); 1848 unblessedBooleanResult(resultGPR, node); 1837 1849 } 1838 1850 … … 5255 5267 5256 5268 notPresentInTable.link(&m_jit); 5257 m_jit.move(TrustedImmPtr(nullptr), resultGPR); 5269 if (node->child1().useKind() == MapObjectUse) 5270 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelMapBucket.get()), resultGPR); 5271 else 5272 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelSetBucket.get()), resultGPR); 5258 5273 done.link(&m_jit); 5259 5274 cellResult(resultGPR, node); … … 5261 5276 } 5262 5277 5263 case LoadFromJSMapBucket: { 5264 SpeculateCellOperand bucket(this, node->child1()); 5265 GPRTemporary result(this); 5266 5267 GPRReg bucketGPR = bucket.gpr(); 5268 GPRReg resultGPR = result.gpr(); 5269 5270 auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR); 5271 m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), resultGPR); 5272 auto done = m_jit.jump(); 5273 5274 notBucket.link(&m_jit); 5275 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), resultGPR); 5276 done.link(&m_jit); 5277 jsValueResult(resultGPR, node); 5278 break; 5279 } 5280 5281 case IsNonEmptyMapBucket: { 5282 SpeculateCellOperand bucket(this, node->child1()); 5283 GPRTemporary result(this); 5284 5285 GPRReg bucketGPR = bucket.gpr(); 5286 GPRReg resultGPR = result.gpr(); 5287 5288 m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR); 5289 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 5290 jsValueResult(resultGPR, node, DataFormatJSBoolean); 5291 break; 5292 } 5278 case GetMapBucketHead: 5279 compileGetMapBucketHead(node); 5280 break; 5281 5282 case GetMapBucketNext: 5283 compileGetMapBucketNext(node); 5284 break; 5285 5286 case LoadKeyFromMapBucket: 5287 compileLoadKeyFromMapBucket(node); 5288 break; 5289 5290 case LoadValueFromMapBucket: 5291 compileLoadValueFromMapBucket(node); 5292 break; 5293 5293 5294 5294 case ToLowerCase: { -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r217202 r221110 114 114 macro(HashMapImpl_capacity, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()) \ 115 115 macro(HashMapImpl_buffer, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()) \ 116 macro(HashMapImpl_head, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead()) \ 116 117 macro(HashMapBucket_value, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()) \ 117 118 macro(HashMapBucket_key, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey()) \ 119 macro(HashMapBucket_next, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()) \ 120 macro(HashMapBucket_deleted, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted()) \ 118 121 macro(Symbol_symbolImpl, Symbol::offsetOfSymbolImpl()) \ 119 122 macro(JSFixedArray_size, JSFixedArray::offsetOfSize()) \ -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r221080 r221110 196 196 case MapHash: 197 197 case GetMapBucket: 198 case LoadFromJSMapBucket: 199 case IsNonEmptyMapBucket: 198 case GetMapBucketHead: 199 case GetMapBucketNext: 200 case LoadKeyFromMapBucket: 201 case LoadValueFromMapBucket: 200 202 case IsEmpty: 201 203 case IsUndefined: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r221080 r221110 972 972 compileGetMapBucket(); 973 973 break; 974 case LoadFromJSMapBucket: 975 compileLoadFromJSMapBucket(); 976 break; 977 case IsNonEmptyMapBucket: 978 compileIsNonEmptyMapBucket(); 974 case GetMapBucketHead: 975 compileGetMapBucketHead(); 976 break; 977 case GetMapBucketNext: 978 compileGetMapBucketNext(); 979 break; 980 case LoadKeyFromMapBucket: 981 compileLoadKeyFromMapBucket(); 982 break; 983 case LoadValueFromMapBucket: 984 compileLoadValueFromMapBucket(); 979 985 break; 980 986 case IsObject: … … 8237 8243 8238 8244 m_out.appendTo(notPresentInTable, continuation); 8239 ValueFromBlock notPresentResult = m_out.anchor(m_out.constIntPtr(0)); 8245 ValueFromBlock notPresentResult; 8246 if (m_node->child1().useKind() == MapObjectUse) 8247 notPresentResult = m_out.anchor(weakPointer(vm().sentinelMapBucket.get())); 8248 else if (m_node->child1().useKind() == SetObjectUse) 8249 notPresentResult = m_out.anchor(weakPointer(vm().sentinelSetBucket.get())); 8250 else 8251 RELEASE_ASSERT_NOT_REACHED(); 8240 8252 m_out.jump(continuation); 8241 8253 8242 8254 m_out.appendTo(continuation, lastNext); 8243 setMapBucket(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult)); 8244 } 8245 8246 void compileLoadFromJSMapBucket() 8247 { 8248 LValue mapBucket = lowMapBucket(m_node->child1()); 8249 8255 setJSValue(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult)); 8256 } 8257 8258 void compileGetMapBucketHead() 8259 { 8260 LValue map; 8261 if (m_node->child1().useKind() == MapObjectUse) 8262 map = lowMapObject(m_node->child1()); 8263 else if (m_node->child1().useKind() == SetObjectUse) 8264 map = lowSetObject(m_node->child1()); 8265 else 8266 RELEASE_ASSERT_NOT_REACHED(); 8267 8268 ASSERT(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead() == HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>::offsetOfHead()); 8269 setJSValue(m_out.loadPtr(map, m_heaps.HashMapImpl_head)); 8270 } 8271 8272 void compileGetMapBucketNext() 8273 { 8274 LBasicBlock loopStart = m_out.newBlock(); 8250 8275 LBasicBlock continuation = m_out.newBlock(); 8276 LBasicBlock noBucket = m_out.newBlock(); 8251 8277 LBasicBlock hasBucket = m_out.newBlock(); 8252 8253 ValueFromBlock noBucketResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))); 8254 8255 m_out.branch(m_out.equal(mapBucket, m_out.constIntPtr(0)), 8256 unsure(continuation), unsure(hasBucket)); 8257 8258 LBasicBlock lastNext = m_out.appendTo(hasBucket, continuation); 8259 ValueFromBlock bucketResult = m_out.anchor(m_out.load64(mapBucket, m_heaps.HashMapBucket_value)); 8278 LBasicBlock nextBucket = m_out.newBlock(); 8279 8280 LBasicBlock lastNext = m_out.insertNewBlocksBefore(loopStart); 8281 8282 ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfNext() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()); 8283 ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfDeleted() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted()); 8284 LValue mapBucketPrev = lowCell(m_node->child1()); 8285 ValueFromBlock mapBucketStart = m_out.anchor(m_out.loadPtr(mapBucketPrev, m_heaps.HashMapBucket_next)); 8286 m_out.jump(loopStart); 8287 8288 m_out.appendTo(loopStart, noBucket); 8289 LValue mapBucket = m_out.phi(pointerType(), mapBucketStart); 8290 m_out.branch(m_out.isNull(mapBucket), unsure(noBucket), unsure(hasBucket)); 8291 8292 m_out.appendTo(noBucket, hasBucket); 8293 ValueFromBlock noBucketResult; 8294 if (m_node->bucketOwnerType() == BucketOwnerType::Map) 8295 noBucketResult = m_out.anchor(weakPointer(vm().sentinelMapBucket.get())); 8296 else { 8297 ASSERT(node->bucketOwnerType() == BucketOwnerType::Set); 8298 noBucketResult = m_out.anchor(weakPointer(vm().sentinelSetBucket.get())); 8299 } 8260 8300 m_out.jump(continuation); 8261 8301 8302 m_out.appendTo(hasBucket, nextBucket); 8303 ValueFromBlock bucketResult = m_out.anchor(mapBucket); 8304 m_out.branch(m_out.isZero32(m_out.load32(mapBucket, m_heaps.HashMapBucket_deleted)), unsure(continuation), unsure(nextBucket)); 8305 8306 m_out.appendTo(nextBucket, continuation); 8307 m_out.addIncomingToPhi(mapBucket, m_out.anchor(m_out.loadPtr(mapBucket, m_heaps.HashMapBucket_next))); 8308 m_out.jump(loopStart); 8309 8262 8310 m_out.appendTo(continuation, lastNext); 8263 setJSValue(m_out.phi(Int64, noBucketResult, bucketResult)); 8264 } 8265 8266 void compileIsNonEmptyMapBucket() 8267 { 8268 LValue bucket = lowMapBucket(m_node->child1()); 8269 LValue result = m_out.notEqual(bucket, m_out.constIntPtr(0)); 8270 setBoolean(result); 8311 setJSValue(m_out.phi(pointerType(), noBucketResult, bucketResult)); 8312 } 8313 8314 void compileLoadValueFromMapBucket() 8315 { 8316 LValue mapBucket = lowCell(m_node->child1()); 8317 setJSValue(m_out.load64(mapBucket, m_heaps.HashMapBucket_value)); 8318 } 8319 8320 void compileLoadKeyFromMapBucket() 8321 { 8322 LValue mapBucket = lowCell(m_node->child1()); 8323 setJSValue(m_out.load64(mapBucket, m_heaps.HashMapBucket_key)); 8271 8324 } 8272 8325 … … 12865 12918 } 12866 12919 12867 LValue lowMapBucket(Edge edge)12868 {12869 LoweredNodeValue value = m_mapBucketValues.get(edge.node());12870 if (isValid(value))12871 return value.value();12872 12873 LValue result = lowCell(edge);12874 setStorage(edge.node(), result);12875 return result;12876 }12877 12878 12920 LValue strictInt52ToInt32(Edge edge, LValue value) 12879 12921 { … … 14389 14431 m_storageValues.set(node, LoweredNodeValue(value, m_highBlock)); 14390 14432 } 14391 void setMapBucket(Node* node, LValue value)14392 {14393 m_mapBucketValues.set(node, LoweredNodeValue(value, m_highBlock));14394 }14395 14433 void setDouble(Node* node, LValue value) 14396 14434 { … … 14425 14463 { 14426 14464 setStorage(m_node, value); 14427 }14428 void setMapBucket(LValue value)14429 {14430 setMapBucket(m_node, value);14431 14465 } 14432 14466 void setDouble(LValue value) … … 14619 14653 HashMap<Node*, LoweredNodeValue> m_booleanValues; 14620 14654 HashMap<Node*, LoweredNodeValue> m_storageValues; 14621 HashMap<Node*, LoweredNodeValue> m_mapBucketValues;14622 14655 HashMap<Node*, LoweredNodeValue> m_doubleValues; 14623 14656 -
trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
r218836 r221110 34 34 #include "Error.h" 35 35 #include "InjectedScriptHost.h" 36 #include "IterationKind.h" 36 37 #include "IteratorOperations.h" 37 38 #include "IteratorPrototype.h" … … 43 44 #include "JSInjectedScriptHostPrototype.h" 44 45 #include "JSMap.h" 45 #include "JSMapIterator.h"46 46 #include "JSPromise.h" 47 47 #include "JSSet.h" 48 #include "JSSetIterator.h"49 48 #include "JSStringIterator.h" 50 49 #include "JSTypedArrays.h" … … 52 51 #include "JSWeakSet.h" 53 52 #include "JSWithScope.h" 53 #include "MapIteratorPrototype.h" 54 54 #include "ObjectConstructor.h" 55 55 #include "ProxyObject.h" 56 56 #include "RegExpObject.h" 57 57 #include "ScopedArguments.h" 58 #include "SetIteratorPrototype.h" 58 59 #include "SourceCode.h" 59 60 #include "TypedArrayInlines.h" … … 183 184 return jsNontrivialString(exec, ASCIILiteral("weakset")); 184 185 185 if (value.inherits(vm, JSMapIterator::info()) 186 || value.inherits(vm, JSSetIterator::info()) 187 || value.inherits(vm, JSStringIterator::info())) 186 if (value.inherits(vm, JSStringIterator::info())) 188 187 return jsNontrivialString(exec, ASCIILiteral("iterator")); 189 188 190 if (object && object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) 191 return jsNontrivialString(exec, ASCIILiteral("iterator")); 189 if (object) { 190 if (object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorNextIndexPrivateName()) 191 || object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().mapBucketPrivateName()) 192 || object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().setBucketPrivateName())) 193 return jsNontrivialString(exec, ASCIILiteral("iterator")); 194 } 192 195 193 196 if (value.inherits(vm, JSInt8Array::info()) … … 336 339 return array; 337 340 } 338 } 339 340 if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(vm, value)) { 341 String kind; 342 switch (mapIterator->kind()) { 343 case IterateKey: 344 kind = ASCIILiteral("key"); 345 break; 346 case IterateValue: 347 kind = ASCIILiteral("value"); 348 break; 349 case IterateKeyValue: 350 kind = ASCIILiteral("key+value"); 351 break; 341 342 if (iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().mapBucketPrivateName())) { 343 JSValue iteratedValue = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().iteratedObjectPrivateName()); 344 String kind; 345 switch (static_cast<IterationKind>(iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().mapIteratorKindPrivateName()).asInt32())) { 346 case IterateKey: 347 kind = ASCIILiteral("key"); 348 break; 349 case IterateValue: 350 kind = ASCIILiteral("value"); 351 break; 352 case IterateKeyValue: 353 kind = ASCIILiteral("key+value"); 354 break; 355 } 356 unsigned index = 0; 357 JSArray* array = constructEmptyArray(exec, nullptr, 2); 358 RETURN_IF_EXCEPTION(scope, JSValue()); 359 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", iteratedValue)); 360 RETURN_IF_EXCEPTION(scope, JSValue()); 361 scope.release(); 362 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); 363 return array; 352 364 } 353 unsigned index = 0; 354 JSArray* array = constructEmptyArray(exec, nullptr, 2); 355 RETURN_IF_EXCEPTION(scope, JSValue()); 356 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", mapIterator->iteratedValue())); 357 RETURN_IF_EXCEPTION(scope, JSValue()); 358 scope.release(); 359 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); 360 return array; 361 } 362 363 if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(vm, value)) { 364 String kind; 365 switch (setIterator->kind()) { 366 case IterateKey: 367 kind = ASCIILiteral("key"); 368 break; 369 case IterateValue: 370 kind = ASCIILiteral("value"); 371 break; 372 case IterateKeyValue: 373 kind = ASCIILiteral("key+value"); 374 break; 365 366 if (iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().setBucketPrivateName())) { 367 JSValue iteratedValue = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().iteratedObjectPrivateName()); 368 String kind; 369 switch (static_cast<IterationKind>(iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().setIteratorKindPrivateName()).asInt32())) { 370 case IterateKey: 371 kind = ASCIILiteral("key"); 372 break; 373 case IterateValue: 374 kind = ASCIILiteral("value"); 375 break; 376 case IterateKeyValue: 377 kind = ASCIILiteral("key+value"); 378 break; 379 } 380 unsigned index = 0; 381 JSArray* array = constructEmptyArray(exec, nullptr, 2); 382 RETURN_IF_EXCEPTION(scope, JSValue()); 383 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", iteratedValue)); 384 RETURN_IF_EXCEPTION(scope, JSValue()); 385 scope.release(); 386 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); 387 return array; 375 388 } 376 unsigned index = 0;377 JSArray* array = constructEmptyArray(exec, nullptr, 2);378 RETURN_IF_EXCEPTION(scope, JSValue());379 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", setIterator->iteratedValue()));380 RETURN_IF_EXCEPTION(scope, JSValue());381 scope.release();382 array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));383 return array;384 389 } 385 390 … … 523 528 } 524 529 530 static JSObject* cloneMapIteratorObject(ExecState* exec, VM& vm, JSObject* iteratorObject, JSGlobalObject* globalObject, JSValue mapBucket, JSValue iteratedObject) 531 { 532 ASSERT(iteratorObject->type() == FinalObjectType); 533 JSObject* clone = constructEmptyObject(exec, MapIteratorPrototype::create(vm, globalObject, MapIteratorPrototype::createStructure(vm, globalObject, globalObject->iteratorPrototype()))); 534 clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratedObject); 535 clone->putDirect(vm, vm.propertyNames->builtinNames().mapIteratorKindPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapIteratorKindPrivateName())); 536 clone->putDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName(), mapBucket); 537 return clone; 538 } 539 540 static JSObject* cloneSetIteratorObject(ExecState* exec, VM& vm, JSObject* iteratorObject, JSGlobalObject* globalObject, JSValue setBucket, JSValue iteratedObject) 541 { 542 ASSERT(iteratorObject->type() == FinalObjectType); 543 JSObject* clone = constructEmptyObject(exec, SetIteratorPrototype::create(vm, globalObject, SetIteratorPrototype::createStructure(vm, globalObject, globalObject->iteratorPrototype()))); 544 clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratedObject); 545 clone->putDirect(vm, vm.propertyNames->builtinNames().setIteratorKindPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setIteratorKindPrivateName())); 546 clone->putDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName(), setBucket); 547 return clone; 548 } 549 525 550 JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec) 526 551 { … … 534 559 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 535 560 JSValue value = exec->uncheckedArgument(0); 536 if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(vm, value)) { 537 if (jsCast<JSMap*>(mapIterator->iteratedValue())->isIteratorProtocolFastAndNonObservable()) 538 iterator = mapIterator->clone(exec); 539 } else if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(vm, value)) { 540 if (jsCast<JSSet*>(setIterator->iteratedValue())->isIteratorProtocolFastAndNonObservable()) 541 iterator = setIterator->clone(exec); 542 } else if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(vm, value)) { 561 if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(vm, value)) { 543 562 if (globalObject->isStringPrototypeIteratorProtocolFastAndNonObservable()) 544 563 iterator = stringIterator->clone(exec); 545 564 } else if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(vm, value)) { 546 565 // Detect an ArrayIterator by checking for one of its unique private properties. 566 JSValue iteratedObject = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName()); 547 567 if (JSValue nextIndex = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) { 548 JSValue iteratedObject = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());549 568 if (isJSArray(iteratedObject)) { 550 569 JSArray* array = jsCast<JSArray*>(iteratedObject); … … 555 574 iterator = cloneArrayIteratorObject(exec, vm, iteratorObject, globalObject, nextIndex, iteratedObject); 556 575 } 576 } else if (JSValue mapBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName())) { 577 if (jsCast<JSMap*>(iteratedObject)->isIteratorProtocolFastAndNonObservable()) 578 iterator = cloneMapIteratorObject(exec, vm, iteratorObject, globalObject, mapBucket, iteratedObject); 579 } else if (JSValue setBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName())) { 580 if (jsCast<JSSet*>(iteratedObject)->isIteratorProtocolFastAndNonObservable()) 581 iterator = cloneSetIteratorObject(exec, vm, iteratorObject, globalObject, setBucket, iteratedObject); 557 582 } 558 583 } -
trunk/Source/JavaScriptCore/runtime/HashMapImpl.h
r220500 r221110 98 98 } 99 99 100 static HashMapBucket* createSentinel(VM& vm) 101 { 102 auto* bucket = create(vm); 103 bucket->setDeleted(true); 104 bucket->setKey(vm, jsUndefined()); 105 bucket->setValue(vm, jsUndefined()); 106 return bucket; 107 } 108 100 109 HashMapBucket(VM& vm, Structure* structure) 101 110 : Base(vm, structure) … … 151 160 } 152 161 162 static ptrdiff_t offsetOfNext() 163 { 164 return OBJECT_OFFSETOF(HashMapBucket, m_next); 165 } 166 167 static ptrdiff_t offsetOfDeleted() 168 { 169 return OBJECT_OFFSETOF(HashMapBucket, m_deleted); 170 } 171 153 172 template <typename T = Data> 154 173 ALWAYS_INLINE static typename std::enable_if<std::is_same<T, HashMapBucketDataKeyValue>::value, JSValue>::type extractValue(const HashMapBucket& bucket) … … 164 183 165 184 private: 166 Data m_data;167 185 WriteBarrier<HashMapBucket> m_next; 168 186 WriteBarrier<HashMapBucket> m_prev; 169 bool m_deleted { false }; 187 uint32_t m_deleted { false }; 188 Data m_data; 170 189 }; 171 190 … … 468 487 { 469 488 return m_capacity * sizeof(HashMapBucketType*); 489 } 490 491 static ptrdiff_t offsetOfHead() 492 { 493 return OBJECT_OFFSETOF(HashMapImpl<HashMapBucketType>, m_head); 470 494 } 471 495 -
trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp
r218084 r221110 138 138 case JSMapHasIntrinsic: 139 139 return "JSMapHasIntrinsic"; 140 case JSMapBucketHeadIntrinsic: 141 return "JSMapBucketHeadIntrinsic"; 142 case JSMapBucketNextIntrinsic: 143 return "JSMapBucketNextIntrinsic"; 144 case JSMapBucketKeyIntrinsic: 145 return "JSMapBucketKeyIntrinsic"; 146 case JSMapBucketValueIntrinsic: 147 return "JSMapBucketValueIntrinsic"; 140 148 case JSSetHasIntrinsic: 141 149 return "JSSetHasIntrinsic"; 150 case JSSetBucketHeadIntrinsic: 151 return "JSSetBucketHeadIntrinsic"; 152 case JSSetBucketNextIntrinsic: 153 return "JSSetBucketNextIntrinsic"; 154 case JSSetBucketKeyIntrinsic: 155 return "JSSetBucketKeyIntrinsic"; 142 156 case HasOwnPropertyIntrinsic: 143 157 return "HasOwnPropertyIntrinsic"; -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r218084 r221110 82 82 JSMapGetIntrinsic, 83 83 JSMapHasIntrinsic, 84 JSMapBucketHeadIntrinsic, 85 JSMapBucketNextIntrinsic, 86 JSMapBucketKeyIntrinsic, 87 JSMapBucketValueIntrinsic, 84 88 JSSetHasIntrinsic, 89 JSSetBucketHeadIntrinsic, 90 JSSetBucketNextIntrinsic, 91 JSSetBucketKeyIntrinsic, 85 92 HasOwnPropertyIntrinsic, 86 93 AtomicsAddIntrinsic, -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r221080 r221110 100 100 #include "JSLock.h" 101 101 #include "JSMap.h" 102 #include "JSMapIterator.h"103 102 #include "JSModuleEnvironment.h" 104 103 #include "JSModuleLoader.h" … … 111 110 #include "JSPromisePrototype.h" 112 111 #include "JSSet.h" 113 #include "JSSetIterator.h"114 112 #include "JSStringIterator.h" 115 113 #include "JSTemplateRegistryKey.h" … … 753 751 JSFunction* privateFuncConcatMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncConcatMemcpy); 754 752 JSFunction* privateFuncAppendMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncAppendMemcpy); 753 JSFunction* privateFuncMapBucketHead = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketHead, JSMapBucketHeadIntrinsic); 754 JSFunction* privateFuncMapBucketNext = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketNext, JSMapBucketNextIntrinsic); 755 JSFunction* privateFuncMapBucketKey = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketKey, JSMapBucketKeyIntrinsic); 756 JSFunction* privateFuncMapBucketValue = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketValue, JSMapBucketValueIntrinsic); 757 JSFunction* privateFuncSetBucketHead = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketHead, JSSetBucketHeadIntrinsic); 758 JSFunction* privateFuncSetBucketNext = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketNext, JSSetBucketNextIntrinsic); 759 JSFunction* privateFuncSetBucketKey = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketKey, JSSetBucketKeyIntrinsic); 755 760 756 761 JSObject* regExpProtoFlagsGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->flags); … … 784 789 JSObject* asyncFromSyncIteratorPrototype = AsyncFromSyncIteratorPrototype::create(vm, this, AsyncFromSyncIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get())); 785 790 AsyncFromSyncIteratorConstructorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, asyncFromSyncIteratorPrototype); 791 792 JSObject* mapIteratorPrototype = MapIteratorPrototype::create(vm, this, MapIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get())); 793 createMapIteratorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, mapIteratorPrototype); 794 795 JSObject* setIteratorPrototype = SetIteratorPrototype::create(vm, this, SetIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get())); 796 createSetIteratorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, setIteratorPrototype); 786 797 787 798 GlobalPropertyInfo staticGlobals[] = { … … 819 830 820 831 GlobalPropertyInfo(vm.propertyNames->builtinNames().repeatCharacterPrivateName(), JSFunction::create(vm, this, 2, String(), stringProtoFuncRepeatCharacter), DontEnum | DontDelete | ReadOnly), 821 GlobalPropertyInfo(vm.propertyNames->builtinNames().SetIteratorPrivateName(), JSFunction::create(vm, this, 1, String(), privateFuncSetIterator), DontEnum | DontDelete | ReadOnly),822 GlobalPropertyInfo(vm.propertyNames->builtinNames().setIteratorNextPrivateName(), JSFunction::create(vm, this, 0, String(), privateFuncSetIteratorNext), DontEnum | DontDelete | ReadOnly),823 832 GlobalPropertyInfo(vm.propertyNames->builtinNames().isArrayPrivateName(), arrayConstructor->getDirect(vm, vm.propertyNames->isArray), DontEnum | DontDelete | ReadOnly), 824 833 GlobalPropertyInfo(vm.propertyNames->builtinNames().isArraySlowPrivateName(), privateFuncIsArraySlow, DontEnum | DontDelete | ReadOnly), … … 826 835 GlobalPropertyInfo(vm.propertyNames->builtinNames().concatMemcpyPrivateName(), privateFuncConcatMemcpy, DontEnum | DontDelete | ReadOnly), 827 836 GlobalPropertyInfo(vm.propertyNames->builtinNames().appendMemcpyPrivateName(), privateFuncAppendMemcpy, DontEnum | DontDelete | ReadOnly), 828 GlobalPropertyInfo(vm.propertyNames->builtinNames().MapIteratorPrivateName(), JSFunction::create(vm, this, 1, String(), privateFuncMapIterator), DontEnum | DontDelete | ReadOnly),829 GlobalPropertyInfo(vm.propertyNames->builtinNames().mapIteratorNextPrivateName(), JSFunction::create(vm, this, 0, String(), privateFuncMapIteratorNext), DontEnum | DontDelete | ReadOnly),830 837 831 838 GlobalPropertyInfo(vm.propertyNames->builtinNames().hostPromiseRejectionTrackerPrivateName(), JSFunction::create(vm, this, 2, String(), globalFuncHostPromiseRejectionTracker), DontEnum | DontDelete | ReadOnly), … … 868 875 GlobalPropertyInfo(vm.propertyNames->builtinNames().makeBoundFunctionPrivateName(), JSFunction::create(vm, this, 5, String(), makeBoundFunction), DontEnum | DontDelete | ReadOnly), 869 876 GlobalPropertyInfo(vm.propertyNames->builtinNames().hasOwnLengthPropertyPrivateName(), JSFunction::create(vm, this, 1, String(), hasOwnLengthProperty), DontEnum | DontDelete | ReadOnly), 877 878 // Map and Set helpers. 879 GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketHeadPrivateName(), privateFuncMapBucketHead, DontEnum | DontDelete | ReadOnly), 880 GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketNextPrivateName(), privateFuncMapBucketNext, DontEnum | DontDelete | ReadOnly), 881 GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketKeyPrivateName(), privateFuncMapBucketKey, DontEnum | DontDelete | ReadOnly), 882 GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketValuePrivateName(), privateFuncMapBucketValue, DontEnum | DontDelete | ReadOnly), 883 GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketHeadPrivateName(), privateFuncSetBucketHead, DontEnum | DontDelete | ReadOnly), 884 GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketNextPrivateName(), privateFuncSetBucketNext, DontEnum | DontDelete | ReadOnly), 885 GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketKeyPrivateName(), privateFuncSetBucketKey, DontEnum | DontDelete | ReadOnly), 870 886 }; 871 887 addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); … … 957 973 958 974 { 959 ObjectPropertyCondition condition = setupAdaptiveWatchpoint(m _mapIteratorPrototype.get(), m_vm.propertyNames->next);975 ObjectPropertyCondition condition = setupAdaptiveWatchpoint(mapIteratorPrototype, m_vm.propertyNames->next); 960 976 m_mapIteratorPrototypeNextWatchpoint = std::make_unique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(vm, condition, m_mapIteratorProtocolWatchpoint); 961 977 m_mapIteratorPrototypeNextWatchpoint->install(); … … 968 984 969 985 { 970 ObjectPropertyCondition condition = setupAdaptiveWatchpoint( m_setIteratorPrototype.get(), m_vm.propertyNames->next);986 ObjectPropertyCondition condition = setupAdaptiveWatchpoint(setIteratorPrototype, m_vm.propertyNames->next); 971 987 m_setIteratorPrototypeNextWatchpoint = std::make_unique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(vm, condition, m_setIteratorProtocolWatchpoint); 972 988 m_setIteratorPrototypeNextWatchpoint->install(); -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r221080 r221110 127 127 128 128 #define FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(macro) \ 129 macro(MapIterator, mapIterator, mapIterator, JSMapIterator, MapIterator, iterator) \130 macro(SetIterator, setIterator, setIterator, JSSetIterator, SetIterator, iterator) \131 129 macro(StringIterator, stringIterator, stringIterator, JSStringIterator, StringIterator, iterator) \ 132 130 -
trunk/Source/JavaScriptCore/runtime/JSMap.h
r218836 r221110 31 31 namespace JSC { 32 32 33 class JSMapIterator;34 35 33 class JSMap final : public HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>> { 36 34 using Base = HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>; 37 35 public: 38 friend class JSMapIterator;39 36 40 37 DECLARE_EXPORT_INFO; -
trunk/Source/JavaScriptCore/runtime/JSMapIterator.cpp
r217192 r221110 32 32 namespace JSC { 33 33 34 const ClassInfo JSMapIterator::s_info = { "Map Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMapIterator) };34 const ClassInfo JSMapIterator::s_info = { "Map Iterator", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSMapIterator) }; 35 35 36 36 void JSMapIterator::finishCreation(VM& vm, JSMap* iteratedObject) … … 59 59 } 60 60 61 JSMapIterator* JSMapIterator::clone(ExecState* exec)62 {63 VM& vm = exec->vm();64 auto clone = JSMapIterator::create(vm, exec->jsCallee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind);65 clone->setIterator(vm, m_iter.get());66 return clone;67 61 } 68 69 } -
trunk/Source/JavaScriptCore/runtime/JSMapIterator.h
r211675 r221110 32 32 namespace JSC { 33 33 34 class JSMapIterator : public JSNonFinalObject { 34 // Now, it is only used for serialization. 35 class JSMapIterator : public JSCell { 35 36 typedef HashMapBucket<HashMapBucketDataKeyValue> HashMapBucketType; 36 37 public: 37 typedef JSNonFinalObject Base;38 using Base = JSCell; 38 39 39 40 DECLARE_EXPORT_INFO; … … 94 95 IterationKind kind() const { return m_kind; } 95 96 JSValue iteratedValue() const { return m_map.get(); } 96 JSMapIterator* clone(ExecState*);97 97 98 98 private: -
trunk/Source/JavaScriptCore/runtime/JSSet.h
r220500 r221110 31 31 namespace JSC { 32 32 33 class JSSetIterator;34 35 33 class JSSet final : public HashMapImpl<HashMapBucket<HashMapBucketDataKey>> { 36 34 using Base = HashMapImpl<HashMapBucket<HashMapBucketDataKey>>; 37 35 public: 38 39 friend class JSSetIterator;40 36 41 37 DECLARE_EXPORT_INFO; -
trunk/Source/JavaScriptCore/runtime/JSSetIterator.cpp
r217192 r221110 32 32 namespace JSC { 33 33 34 const ClassInfo JSSetIterator::s_info = { "Set Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSetIterator) };34 const ClassInfo JSSetIterator::s_info = { "Set Iterator", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSSetIterator) }; 35 35 36 36 void JSSetIterator::finishCreation(VM& vm, JSSet* iteratedObject) … … 59 59 } 60 60 61 JSSetIterator* JSSetIterator::clone(ExecState* exec)62 {63 VM& vm = exec->vm();64 auto clone = JSSetIterator::create(vm, exec->jsCallee()->globalObject()->setIteratorStructure(), m_set.get(), m_kind);65 clone->setIterator(vm, m_iter.get());66 return clone;67 61 } 68 69 } -
trunk/Source/JavaScriptCore/runtime/JSSetIterator.h
r211675 r221110 32 32 namespace JSC { 33 33 34 class JSSetIterator : public JSNonFinalObject { 34 // Now, it is only used for serialization. 35 class JSSetIterator : public JSCell { 35 36 typedef HashMapBucket<HashMapBucketDataKey> HashMapBucketType; 36 37 public: 37 typedef JSNonFinalObject Base;38 using Base = JSCell; 38 39 39 40 DECLARE_EXPORT_INFO; … … 82 83 IterationKind kind() const { return m_kind; } 83 84 JSValue iteratedValue() const { return m_set.get(); } 84 JSSetIterator* clone(ExecState*);85 85 86 86 private: -
trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp
r217527 r221110 121 121 } 122 122 123 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketHead(ExecState* exec) 124 { 125 ASSERT(isJSMap(exec->argument(0))); 126 JSMap* map = jsCast<JSMap*>(exec->uncheckedArgument(0)); 127 auto* head = map->head(); 128 ASSERT(head); 129 return JSValue::encode(head); 123 130 } 131 132 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketNext(ExecState* exec) 133 { 134 ASSERT(jsDynamicCast<JSMap::BucketType*>(exec->vm(), exec->argument(0))); 135 auto* bucket = jsCast<JSMap::BucketType*>(exec->uncheckedArgument(0)); 136 ASSERT(bucket); 137 bucket = bucket->next(); 138 while (bucket) { 139 if (!bucket->deleted()) 140 return JSValue::encode(bucket); 141 bucket = bucket->next(); 142 } 143 return JSValue::encode(exec->vm().sentinelMapBucket.get()); 144 } 145 146 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketKey(ExecState* exec) 147 { 148 ASSERT(jsDynamicCast<JSMap::BucketType*>(exec->vm(), exec->argument(0))); 149 auto* bucket = jsCast<JSMap::BucketType*>(exec->uncheckedArgument(0)); 150 ASSERT(bucket); 151 return JSValue::encode(bucket->key()); 152 } 153 154 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketValue(ExecState* exec) 155 { 156 ASSERT(jsDynamicCast<JSMap::BucketType*>(exec->vm(), exec->argument(0))); 157 auto* bucket = jsCast<JSMap::BucketType*>(exec->uncheckedArgument(0)); 158 ASSERT(bucket); 159 return JSValue::encode(bucket->value()); 160 } 161 162 } -
trunk/Source/JavaScriptCore/runtime/MapConstructor.h
r206525 r221110 61 61 }; 62 62 63 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketHead(ExecState*); 64 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketNext(ExecState*); 65 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketKey(ExecState*); 66 EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketValue(ExecState*); 67 63 68 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/MapIteratorPrototype.cpp
r217108 r221110 27 27 #include "MapIteratorPrototype.h" 28 28 29 #include " IteratorOperations.h"29 #include "JSCBuiltins.h" 30 30 #include "JSCInlines.h" 31 #include "JSMapIterator.h"32 31 33 32 namespace JSC { 34 33 35 34 const ClassInfo MapIteratorPrototype::s_info = { "Map Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(MapIteratorPrototype) }; 36 37 static EncodedJSValue JSC_HOST_CALL MapIteratorPrototypeFuncNext(ExecState*);38 35 39 36 void MapIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) … … 43 40 vm.prototypeMap.addPrototype(this); 44 41 45 JSC_ NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, MapIteratorPrototypeFuncNext, DontEnum, 0);42 JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", mapIteratorPrototypeNextCodeGenerator, DontEnum); 46 43 putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Map Iterator"), DontEnum | ReadOnly); 47 44 } 48 45 49 EncodedJSValue JSC_HOST_CALL MapIteratorPrototypeFuncNext(CallFrame* callFrame)50 {51 VM& vm = callFrame->vm();52 auto scope = DECLARE_THROW_SCOPE(vm);53 54 JSMapIterator* iterator = jsDynamicCast<JSMapIterator*>(vm, callFrame->thisValue());55 if (!iterator)56 return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot call MapIterator.next() on a non-MapIterator object")));57 58 JSValue result;59 if (iterator->next(callFrame, result)) {60 scope.release();61 return JSValue::encode(createIteratorResultObject(callFrame, result, false));62 }63 scope.release();64 return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true));65 46 } 66 67 68 } -
trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp
r217192 r221110 33 33 #include "JSCInlines.h" 34 34 #include "JSMap.h" 35 #include "JSMapIterator.h"36 35 #include "Lookup.h" 37 36 … … 45 44 @begin mapPrototypeTable 46 45 forEach JSBuiltin DontEnum|Function 0 46 values JSBuiltin DontEnum|Function 0 47 keys JSBuiltin DontEnum|Function 0 47 48 @end 48 49 */ … … 53 54 static EncodedJSValue JSC_HOST_CALL mapProtoFuncHas(ExecState*); 54 55 static EncodedJSValue JSC_HOST_CALL mapProtoFuncSet(ExecState*); 55 static EncodedJSValue JSC_HOST_CALL mapProtoFuncKeys(ExecState*);56 static EncodedJSValue JSC_HOST_CALL mapProtoFuncValues(ExecState*);57 static EncodedJSValue JSC_HOST_CALL mapProtoFuncEntries(ExecState*);58 56 59 57 static EncodedJSValue JSC_HOST_CALL mapProtoFuncSize(ExecState*); … … 70 68 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, mapProtoFuncHas, DontEnum, 1, JSMapHasIntrinsic); 71 69 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, mapProtoFuncSet, DontEnum, 2); 72 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), mapProtoFuncKeys, DontEnum, 0);73 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().valuesPublicName(), mapProtoFuncValues, DontEnum, 0);74 70 75 71 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, DontEnum, 1, JSMapGetIntrinsic); 76 72 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().setPrivateName(), mapProtoFuncSet, DontEnum, 2); 77 73 78 JSFunction* entries = JSFunction::create(vm, globalObject, 0, vm.propertyNames->builtinNames().entriesPublicName().string(), mapProtoFuncEntries);74 JSFunction* entries = JSFunction::create(vm, mapPrototypeEntriesCodeGenerator(vm), globalObject); 79 75 putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().entriesPublicName(), entries, DontEnum); 80 76 putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, entries, DontEnum); … … 151 147 } 152 148 153 EncodedJSValue JSC_HOST_CALL mapProtoFuncValues(CallFrame* callFrame)154 {155 VM& vm = callFrame->vm();156 auto scope = DECLARE_THROW_SCOPE(vm);157 158 JSMap* thisObj = jsDynamicCast<JSMap*>(vm, callFrame->thisValue());159 if (!thisObj)160 return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Map value iterator for a non-Map object.")));161 return JSValue::encode(JSMapIterator::create(vm, callFrame->jsCallee()->globalObject()->mapIteratorStructure(), thisObj, IterateValue));162 149 } 163 164 EncodedJSValue JSC_HOST_CALL mapProtoFuncEntries(CallFrame* callFrame)165 {166 VM& vm = callFrame->vm();167 auto scope = DECLARE_THROW_SCOPE(vm);168 169 JSMap* thisObj = jsDynamicCast<JSMap*>(vm, callFrame->thisValue());170 if (!thisObj)171 return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Map entry iterator for a non-Map object.")));172 return JSValue::encode(JSMapIterator::create(vm, callFrame->jsCallee()->globalObject()->mapIteratorStructure(), thisObj, IterateKeyValue));173 }174 175 EncodedJSValue JSC_HOST_CALL mapProtoFuncKeys(CallFrame* callFrame)176 {177 VM& vm = callFrame->vm();178 auto scope = DECLARE_THROW_SCOPE(vm);179 180 JSMap* thisObj = jsDynamicCast<JSMap*>(vm, callFrame->thisValue());181 if (!thisObj)182 return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Map key iterator for a non-Map object.")));183 return JSValue::encode(JSMapIterator::create(vm, callFrame->jsCallee()->globalObject()->mapIteratorStructure(), thisObj, IterateKey));184 }185 186 EncodedJSValue JSC_HOST_CALL privateFuncMapIterator(ExecState* exec)187 {188 ASSERT(jsDynamicCast<JSMap*>(exec->vm(), exec->uncheckedArgument(0)));189 JSMap* map = jsCast<JSMap*>(exec->uncheckedArgument(0));190 return JSValue::encode(JSMapIterator::create(exec->vm(), exec->jsCallee()->globalObject()->mapIteratorStructure(), map, IterateKeyValue));191 }192 193 EncodedJSValue JSC_HOST_CALL privateFuncMapIteratorNext(ExecState* exec)194 {195 VM& vm = exec->vm();196 auto scope = DECLARE_THROW_SCOPE(vm);197 ASSERT(jsDynamicCast<JSMapIterator*>(vm, exec->thisValue()));198 JSMapIterator* iterator = jsCast<JSMapIterator*>(exec->thisValue());199 JSValue key, value;200 if (iterator->nextKeyValue(exec, key, value)) {201 JSArray* resultArray = jsCast<JSArray*>(exec->uncheckedArgument(0));202 resultArray->putDirectIndex(exec, 0, key);203 RETURN_IF_EXCEPTION(scope, encodedJSValue());204 scope.release();205 resultArray->putDirectIndex(exec, 1, value);206 return JSValue::encode(jsBoolean(false));207 }208 return JSValue::encode(jsBoolean(true));209 }210 211 } -
trunk/Source/JavaScriptCore/runtime/MapPrototype.h
r206525 r221110 58 58 }; 59 59 60 EncodedJSValue JSC_HOST_CALL privateFuncMapIterator(ExecState*);61 EncodedJSValue JSC_HOST_CALL privateFuncMapIteratorNext(ExecState*);62 63 60 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/SetConstructor.cpp
r217527 r221110 107 107 } 108 108 109 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketHead(ExecState* exec) 110 { 111 ASSERT(isJSSet(exec->argument(0))); 112 JSSet* set = jsCast<JSSet*>(exec->uncheckedArgument(0)); 113 auto* head = set->head(); 114 ASSERT(head); 115 return JSValue::encode(head); 109 116 } 117 118 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketNext(ExecState* exec) 119 { 120 ASSERT(jsDynamicCast<JSSet::BucketType*>(exec->vm(), exec->argument(0))); 121 auto* bucket = jsCast<JSSet::BucketType*>(exec->uncheckedArgument(0)); 122 ASSERT(bucket); 123 bucket = bucket->next(); 124 while (bucket) { 125 if (!bucket->deleted()) 126 return JSValue::encode(bucket); 127 bucket = bucket->next(); 128 } 129 return JSValue::encode(exec->vm().sentinelSetBucket.get()); 130 } 131 132 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketKey(ExecState* exec) 133 { 134 ASSERT(jsDynamicCast<JSSet::BucketType*>(exec->vm(), exec->argument(0))); 135 auto* bucket = jsCast<JSSet::BucketType*>(exec->uncheckedArgument(0)); 136 ASSERT(bucket); 137 return JSValue::encode(bucket->key()); 138 } 139 140 } -
trunk/Source/JavaScriptCore/runtime/SetConstructor.h
r206525 r221110 61 61 }; 62 62 63 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketHead(ExecState*); 64 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketNext(ExecState*); 65 EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketKey(ExecState*); 66 63 67 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/SetIteratorPrototype.cpp
r217108 r221110 27 27 #include "SetIteratorPrototype.h" 28 28 29 #include " IteratorOperations.h"29 #include "JSCBuiltins.h" 30 30 #include "JSCInlines.h" 31 #include "JSSetIterator.h"32 31 33 32 namespace JSC { 34 33 35 34 const ClassInfo SetIteratorPrototype::s_info = { "Set Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(SetIteratorPrototype) }; 36 37 static EncodedJSValue JSC_HOST_CALL SetIteratorPrototypeFuncNext(ExecState*);38 35 39 36 void SetIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) … … 43 40 vm.prototypeMap.addPrototype(this); 44 41 45 JSC_ NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, SetIteratorPrototypeFuncNext, DontEnum, 0);42 JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", setIteratorPrototypeNextCodeGenerator, DontEnum); 46 43 putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Set Iterator"), DontEnum | ReadOnly); 47 44 } 48 45 49 EncodedJSValue JSC_HOST_CALL SetIteratorPrototypeFuncNext(CallFrame* callFrame)50 {51 VM& vm = callFrame->vm();52 auto scope = DECLARE_THROW_SCOPE(vm);53 54 JSValue result;55 JSSetIterator* iterator = jsDynamicCast<JSSetIterator*>(vm, callFrame->thisValue());56 if (!iterator)57 return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot call SetIterator.next() on a non-SetIterator object")));58 59 if (iterator->next(callFrame, result)) {60 scope.release();61 return JSValue::encode(createIteratorResultObject(callFrame, result, false));62 }63 scope.release();64 return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true));65 46 } 66 67 } -
trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp
r218861 r221110 33 33 #include "JSCInlines.h" 34 34 #include "JSSet.h" 35 #include "JSSetIterator.h"36 35 #include "Lookup.h" 37 36 … … 45 44 @begin setPrototypeTable 46 45 forEach JSBuiltin DontEnum|Function 0 46 entries JSBuiltin DontEnum|Function 0 47 47 @end 48 48 */ … … 52 52 static EncodedJSValue JSC_HOST_CALL setProtoFuncDelete(ExecState*); 53 53 static EncodedJSValue JSC_HOST_CALL setProtoFuncHas(ExecState*); 54 static EncodedJSValue JSC_HOST_CALL setProtoFuncValues(ExecState*);55 static EncodedJSValue JSC_HOST_CALL setProtoFuncEntries(ExecState*);56 54 57 55 … … 70 68 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().hasPrivateName(), setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic); 71 69 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().addPrivateName(), setProtoFuncAdd, DontEnum, 1); 72 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0);73 70 74 JSFunction* values = JSFunction::create(vm, globalObject, 0, vm.propertyNames->builtinNames().valuesPublicName().string(), setProtoFuncValues);71 JSFunction* values = JSFunction::create(vm, setPrototypeValuesCodeGenerator(vm), globalObject); 75 72 putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), values, DontEnum); 76 73 putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().keysPublicName(), values, DontEnum); … … 138 135 return JSValue::encode(jsNumber(set->size())); 139 136 } 140 141 EncodedJSValue JSC_HOST_CALL setProtoFuncValues(CallFrame* callFrame)142 {143 VM& vm = callFrame->vm();144 auto scope = DECLARE_THROW_SCOPE(vm);145 146 JSSet* thisObj = jsDynamicCast<JSSet*>(vm, callFrame->thisValue());147 if (!thisObj)148 return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Set value iterator for a non-Set object.")));149 return JSValue::encode(JSSetIterator::create(vm, callFrame->jsCallee()->globalObject()->setIteratorStructure(), thisObj, IterateValue));150 }151 152 EncodedJSValue JSC_HOST_CALL setProtoFuncEntries(CallFrame* callFrame)153 {154 VM& vm = callFrame->vm();155 auto scope = DECLARE_THROW_SCOPE(vm);156 157 JSSet* thisObj = jsDynamicCast<JSSet*>(vm, callFrame->thisValue());158 if (!thisObj)159 return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Set entry iterator for a non-Set object.")));160 return JSValue::encode(JSSetIterator::create(vm, callFrame->jsCallee()->globalObject()->setIteratorStructure(), thisObj, IterateKeyValue));161 }162 163 EncodedJSValue JSC_HOST_CALL privateFuncSetIterator(ExecState* exec)164 {165 166 ASSERT(jsDynamicCast<JSSet*>(exec->vm(), exec->uncheckedArgument(0)));167 JSSet* set = jsCast<JSSet*>(exec->uncheckedArgument(0));168 return JSValue::encode(JSSetIterator::create(exec->vm(), exec->jsCallee()->globalObject()->setIteratorStructure(), set, IterateKey));169 }170 171 EncodedJSValue JSC_HOST_CALL privateFuncSetIteratorNext(ExecState* exec)172 {173 ASSERT(jsDynamicCast<JSSetIterator*>(exec->vm(), exec->thisValue()));174 JSSetIterator* iterator = jsCast<JSSetIterator*>(exec->thisValue());175 JSValue result;176 if (iterator->next(exec, result)) {177 JSArray* resultArray = jsCast<JSArray*>(exec->uncheckedArgument(0));178 resultArray->putDirectIndex(exec, 0, result);179 return JSValue::encode(jsBoolean(false));180 }181 return JSValue::encode(jsBoolean(true));182 }183 137 184 138 } -
trunk/Source/JavaScriptCore/runtime/SetPrototype.h
r206525 r221110 58 58 }; 59 59 60 EncodedJSValue JSC_HOST_CALL privateFuncSetIterator(ExecState*);61 EncodedJSValue JSC_HOST_CALL privateFuncSetIteratorNext(ExecState*);62 63 60 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r220777 r221110 71 71 #include "JSLock.h" 72 72 #include "JSMap.h" 73 #include "JSMapIterator.h" 73 74 #include "JSPromiseDeferred.h" 74 75 #include "JSPropertyNameEnumerator.h" 75 76 #include "JSScriptFetcher.h" 77 #include "JSSet.h" 78 #include "JSSetIterator.h" 76 79 #include "JSSourceCode.h" 77 80 #include "JSTemplateRegistryKey.h" … … 276 279 hashMapBucketSetStructure.set(*this, HashMapBucket<HashMapBucketDataKey>::createStructure(*this, 0, jsNull())); 277 280 hashMapBucketMapStructure.set(*this, HashMapBucket<HashMapBucketDataKeyValue>::createStructure(*this, 0, jsNull())); 281 setIteratorStructure.set(*this, JSSetIterator::createStructure(*this, 0, jsNull())); 282 mapIteratorStructure.set(*this, JSMapIterator::createStructure(*this, 0, jsNull())); 283 284 sentinelSetBucket.set(*this, JSSet::BucketType::createSentinel(*this)); 285 sentinelMapBucket.set(*this, JSMap::BucketType::createSentinel(*this)); 278 286 279 287 nativeStdFunctionCellStructure.set(*this, NativeStdFunctionCell::createStructure(*this, 0, jsNull())); -
trunk/Source/JavaScriptCore/runtime/VM.h
r220777 r221110 385 385 Strong<Structure> hashMapBucketSetStructure; 386 386 Strong<Structure> hashMapBucketMapStructure; 387 Strong<Structure> setIteratorStructure; 388 Strong<Structure> mapIteratorStructure; 387 389 388 390 Strong<JSCell> emptyPropertyNameEnumerator; 391 Strong<JSCell> sentinelSetBucket; 392 Strong<JSCell> sentinelMapBucket; 389 393 390 394 std::unique_ptr<PromiseDeferredTimer> promiseDeferredTimer; -
trunk/Source/WebCore/ChangeLog
r221109 r221110 1 2017-08-23 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Optimize Map iteration with intrinsic 4 https://bugs.webkit.org/show_bug.cgi?id=174355 5 6 Reviewed by Saam Barati. 7 8 * bindings/js/SerializedScriptValue.cpp: 9 (WebCore::CloneSerializer::serialize): 10 1 11 2017-08-23 Alex Christensen <achristensen@webkit.org> 2 12 -
trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp
r220949 r221110 1594 1594 if (!startMap(inMap)) 1595 1595 break; 1596 JSMapIterator* iterator = JSMapIterator::create(vm, m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, IterateKeyValue);1596 JSMapIterator* iterator = JSMapIterator::create(vm, vm.mapIteratorStructure.get(), inMap, IterateKeyValue); 1597 1597 m_gcBuffer.append(inMap); 1598 1598 m_gcBuffer.append(iterator); … … 1638 1638 if (!startSet(inSet)) 1639 1639 break; 1640 JSSetIterator* iterator = JSSetIterator::create(vm, m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, IterateKey);1640 JSSetIterator* iterator = JSSetIterator::create(vm, vm.setIteratorStructure.get(), inSet, IterateKey); 1641 1641 m_gcBuffer.append(inSet); 1642 1642 m_gcBuffer.append(iterator);
Note: See TracChangeset
for help on using the changeset viewer.