Changeset 280760 in webkit
- Timestamp:
- Aug 7, 2021, 2:38:59 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 11 added
- 68 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/microbenchmarks/for-in-double-array-with-own-named.js (added)
-
JSTests/microbenchmarks/for-in-double-array.js (added)
-
JSTests/microbenchmarks/for-in-getters.js (added)
-
JSTests/microbenchmarks/for-in-int32-array-with-own-named.js (added)
-
JSTests/microbenchmarks/for-in-int32-array.js (added)
-
JSTests/microbenchmarks/for-in-int32-object-with-own-named-and-getters.js (added)
-
JSTests/microbenchmarks/for-in-int32-object-with-own-named.js (added)
-
JSTests/microbenchmarks/for-in-object-with-own-named.js (added)
-
JSTests/microbenchmarks/for-in-string-array.js (added)
-
JSTests/microbenchmarks/for-of-iterate-array-map-set.js (added)
-
JSTests/stress/for-in-array-mode.js (modified) (2 diffs)
-
JSTests/stress/for-in-base-reassigned-later.js (modified) (1 diff)
-
JSTests/stress/for-in-delete-during-iteration.js (modified) (2 diffs)
-
JSTests/stress/for-in-primitive-index-on-prototype.js (added)
-
JSTests/stress/for-in-tests.js (modified) (1 diff)
-
JSTests/stress/has-own-property-structure-for-in-loop-correctness.js (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (modified) (1 diff)
-
Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (modified) (2 diffs)
-
Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (modified) (2 diffs)
-
Source/JavaScriptCore/builtins/BuiltinNames.h (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/BytecodeList.rb (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/bytecode/CodeBlock.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/LinkTimeConstant.h (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/Opcode.h (modified) (4 diffs)
-
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (modified) (14 diffs)
-
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (modified) (7 diffs)
-
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGArrayMode.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGCFAPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGCapabilities.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGClobberize.h (modified) (6 diffs)
-
Source/JavaScriptCore/dfg/DFGDoesGC.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (modified) (8 diffs)
-
Source/JavaScriptCore/dfg/DFGGraph.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGMayExit.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGNode.h (modified) (7 diffs)
-
Source/JavaScriptCore/dfg/DFGNodeType.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGOpInfo.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGOperations.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGOperations.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGSafeToExecute.h (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (modified) (28 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (modified) (16 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLCapabilities.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (modified) (27 diffs)
-
Source/JavaScriptCore/ftl/FTLOutput.h (modified) (3 diffs)
-
Source/JavaScriptCore/generator/DSL.rb (modified) (1 diff)
-
Source/JavaScriptCore/interpreter/Register.h (modified) (1 diff)
-
Source/JavaScriptCore/interpreter/RegisterInlines.h (modified) (1 diff)
-
Source/JavaScriptCore/jit/AssemblyHelpers.h (modified) (2 diffs)
-
Source/JavaScriptCore/jit/JIT.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/jit/JIT.h (modified) (5 diffs)
-
Source/JavaScriptCore/jit/JITOpcodes.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/jit/JITPropertyAccess.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (modified) (1 diff)
-
Source/JavaScriptCore/llint/LowLevelInterpreter.asm (modified) (2 diffs)
-
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (modified) (1 diff)
-
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/CommonSlowPaths.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSGlobalObject.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h (modified) (7 diffs)
-
Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r280716 r280760 1 2021-08-07 Keith Miller <keith_miller@apple.com> 2 3 for-in should only emit one loop in bytecode 4 https://bugs.webkit.org/show_bug.cgi?id=227989 5 6 Reviewed by Yusuke Suzuki. 7 8 * microbenchmarks/for-in-double-array-with-own-named.js: Added. 9 (test): 10 * microbenchmarks/for-in-double-array.js: Added. 11 (test): 12 * microbenchmarks/for-in-getters.js: Added. 13 (test): 14 * microbenchmarks/for-in-int32-array-with-own-named.js: Added. 15 (test): 16 * microbenchmarks/for-in-int32-array.js: Added. 17 (test): 18 * microbenchmarks/for-in-int32-object-with-own-named-and-getters.js: Added. 19 (test): 20 * microbenchmarks/for-in-int32-object-with-own-named.js: Added. 21 (test): 22 * microbenchmarks/for-in-object-with-own-named.js: Added. 23 (sum): 24 (opaqueSet): 25 * microbenchmarks/for-in-string-array.js: Added. 26 (test): 27 * microbenchmarks/for-of-iterate-array-map-set.js: Added. 28 (sum): 29 (let.generator): 30 * stress/for-in-array-mode.js: 31 (test): 32 * stress/for-in-base-reassigned-later.js: 33 * stress/for-in-delete-during-iteration.js: 34 * stress/for-in-primitive-index-on-prototype.js: Added. 35 (test): 36 * stress/for-in-tests.js: 37 * stress/has-own-property-structure-for-in-loop-correctness.js: 38 (test5): 39 1 40 2021-08-05 Mikhail R. Gadelha <mikhail@igalia.com> 2 41 -
trunk/JSTests/stress/for-in-array-mode.js
r182444 r280760 27 27 "(arr) {" + "\n" + 28 28 " var sum = 0;" + "\n" + 29 " for (var i in arr) " + "\n" +29 " for (var i in arr) {" + "\n" + 30 30 " sum += arr[i];" + "\n" + 31 " } " + 31 32 " return sum;" + "\n" + 32 33 "}"; … … 76 77 if ((actual != expected) && (actual != previousResult)) { 77 78 print("FAIL: " + name + ": expected: " + expected + ", actual: " + actual + ", starting @ loop iteration " + i); 79 $vm.breakpoint(); 78 80 previousResult = actual; 79 81 failed = true; -
trunk/JSTests/stress/for-in-base-reassigned-later.js
r172794 r280760 15 15 var result = foo({0:0, 1:1, a:2, b:3}); 16 16 if (result != 7) 17 throw "Error: bad result: " + result;17 throw new Error("bad result: " + result); 18 18 } -
trunk/JSTests/stress/for-in-delete-during-iteration.js
r181891 r280760 13 13 noInline(foo); 14 14 for (var i = 0; i < 10000; ++i) { 15 if (foo() !== "1235") 16 throw new Error("bad result"); 15 var result = foo(); 16 if (result !== "1235") 17 throw new Error("bad result got: " + result); 17 18 } 18 19 foo(null); … … 37 38 noInline(foo); 38 39 for (var i = 0; i < 10000; ++i) { 39 if (foo() !== "xz") 40 throw new Error("bad result"); 40 var result = foo(); 41 if (result !== "xz") 42 throw new Error("bad result: " + result); 41 43 } 42 44 })(); -
trunk/JSTests/stress/for-in-tests.js
r271269 r280760 106 106 } 107 107 })(); 108 108 109 (function() { 109 110 var foo = function(a, b) { -
trunk/JSTests/stress/has-own-property-structure-for-in-loop-correctness.js
r262233 r280760 133 133 134 134 for (let i = 0; i < 1000; ++i) { 135 assert(count(o) === 0); 135 var c = count(o); 136 if (c) 137 print(c); 138 assert(c === 0); 136 139 } 137 140 } -
trunk/Source/JavaScriptCore/ChangeLog
r280745 r280760 1 2021-08-07 Keith Miller <keith_miller@apple.com> 2 3 for-in should only emit one loop in bytecode 4 https://bugs.webkit.org/show_bug.cgi?id=227989 5 6 Reviewed by Yusuke Suzuki. 7 8 This patch redesigns how we implement for-in loops. Before this patch we would emit three copies of the for-in loop body. One for the indexed properties, one for the named-own properties, and one for generic properties (anything else). This had a couple of problems. Firstly, it meant bytecode size grew exponentially to number of nested for-in loops. This in turn meant DFG/FTL compilation took much longer. 9 10 Going off our experience with fast for-of, this patch turns for-in loops specializations into 11 a "fused" opcode that internally switches on the enumeration mode it currently sees. For example, if we are enumerating an own-named property, the new enumerator_get_by_val bytecode will check the enumerator cell's cached structure matches the base's then load the property offset directly. 12 13 There are four new opcodes this patch adds, which replace the various operations we had for the specialized loops previously. The new opcodes are EnumeratorGetByVal, EnumeratorInByVal, EnumeratorHasOwnProperty, and EnumeratorNext. The first three correspond to GetByVal, InByVal, and HasOwnProperty respectively. The EnumeratorNext opcode has three results in bytecode, the next enumeration value's mode, the index of the property name, and the property name string itself. When enumeration is done EnumeratorNext returns JS null as the property name string. Since the DFG doesn't support tuples yet this opcode is spilt into four new nodes. The first computes the updated index and mode for the next enumeration key, which is encoded into a single JS number. Then there are two nodes that extract the mode and index. Finally, the last new node produces the property name string or null based on the extracted mode and index. 14 15 Since, in most benchmarks, any given enumeration opcode tends to profile exactly one enumeration mode. This patch focuses primarily on reimplementing all the optimizations we have for any one specific mode. This means there are still potential optimizations for the multi-mode flavors of each new opcode. 16 17 The main optimizations implemented for each new opcode are: 18 19 EnumeratorNext: 20 1) IndexedMode loops are loaded and checked for presence inline (DFG/FTL). 21 2) NamedMode is computed inline as long as the cached structure on the enumerator cell matches the base (Baseline+). This can only differ if there's a transition. 22 3) property names are extracted from the cached buffer inline (Baseline+). 23 24 EnumeratorGetByVal: 25 EnumeratorInByVal: 26 EnumeratorHasOwnProperty: 27 1) IndexedMode has all the optimizations of a normal XByVal on indexed properties (DFG/FTL). 28 2) NamedMode will extract the value directly from the inline/out-of-line offset if the structure matches the enumerator's (Baseline+). 29 30 There are also a few interesting changes worth mentioning here: 31 1) If a for-in loop would produce an empty enumerator we now always 32 return the VMs empty enumerator. This has two benefits, most importantly, it distingishes between an unprofiled for-in loop and empty enumeration, which prevents OSR exit loops. Also, it means that the various Enumerator opcodes no longer need to handle undefined/null when `toObject`ing the base value. 33 34 2) The enumerator now contains a bit set of all the modes it will produce. This removes a few extra branches when speculating on the modes we will see in EnumeratorNext. 35 36 3) In the DFG, enumerator GetByVal relies on compileGetByVal to set the result it also passes a prefix callback which emits code after the various cases set up their operands but before code is emitting to help satisfy the branch over register allocation validation. Also, the array mode branch in compileGetByVal passes the data format that it would prefer, which for normal GetByVal is returned. For EnumeratorGetByVal, that preference is completely ignored and it always returns DataFormatJS. 37 38 * assembler/MacroAssemblerARM64.h: 39 (JSC::MacroAssemblerARM64::or8): 40 * assembler/MacroAssemblerX86Common.h: 41 (JSC::MacroAssemblerX86Common::or8): 42 * assembler/MacroAssemblerX86_64.h: 43 (JSC::MacroAssemblerX86_64::rshift64): 44 (JSC::MacroAssemblerX86_64::or8): Deleted. 45 * builtins/BuiltinNames.h: 46 * bytecode/BytecodeList.rb: 47 * bytecode/BytecodeUseDef.cpp: 48 (JSC::computeUsesForBytecodeIndexImpl): 49 (JSC::computeDefsForBytecodeIndexImpl): 50 * bytecode/CodeBlock.cpp: 51 (JSC::CodeBlock::finishCreation): 52 * bytecode/LinkTimeConstant.h: 53 * bytecode/Opcode.h: 54 * bytecompiler/BytecodeGenerator.cpp: 55 (JSC::BytecodeGenerator::recordHasOwnPropertyInForInLoop): 56 (JSC::BytecodeGenerator::emitInByVal): 57 (JSC::BytecodeGenerator::emitGetByVal): 58 (JSC::BytecodeGenerator::emitEnumeratorNext): 59 (JSC::BytecodeGenerator::emitEnumeratorHasOwnProperty): 60 (JSC::BytecodeGenerator::pushForInScope): 61 (JSC::BytecodeGenerator::popForInScope): 62 (JSC::rewriteOp): 63 (JSC::ForInContext::finalize): 64 (JSC::BytecodeGenerator::findForInContext): 65 (JSC::BytecodeGenerator::recordHasOwnStructurePropertyInForInLoop): Deleted. 66 (JSC::BytecodeGenerator::emitGetEnumerableLength): Deleted. 67 (JSC::BytecodeGenerator::emitHasEnumerableIndexedProperty): Deleted. 68 (JSC::BytecodeGenerator::emitHasEnumerableStructureProperty): Deleted. 69 (JSC::BytecodeGenerator::emitHasEnumerableProperty): Deleted. 70 (JSC::BytecodeGenerator::emitHasOwnStructureProperty): Deleted. 71 (JSC::BytecodeGenerator::emitEnumeratorStructurePropertyName): Deleted. 72 (JSC::BytecodeGenerator::emitEnumeratorGenericPropertyName): Deleted. 73 (JSC::BytecodeGenerator::emitToIndexString): Deleted. 74 (JSC::BytecodeGenerator::pushIndexedForInScope): Deleted. 75 (JSC::BytecodeGenerator::popIndexedForInScope): Deleted. 76 (JSC::BytecodeGenerator::pushStructureForInScope): Deleted. 77 (JSC::BytecodeGenerator::popStructureForInScope): Deleted. 78 (JSC::StructureForInContext::finalize): Deleted. 79 (JSC::IndexedForInContext::finalize): Deleted. 80 (JSC::BytecodeGenerator::findStructureForInContext): Deleted. 81 * bytecompiler/BytecodeGenerator.h: 82 (JSC::ForInContext::isValid const): 83 (JSC::ForInContext::invalidate): 84 (JSC::ForInContext::local const): 85 (JSC::ForInContext::propertyName const): 86 (JSC::ForInContext::propertyOffset const): 87 (JSC::ForInContext::enumerator const): 88 (JSC::ForInContext::mode const): 89 (JSC::ForInContext::ForInContext): 90 (JSC::ForInContext::bodyBytecodeStartOffset const): 91 (JSC::ForInContext::type const): Deleted. 92 (JSC::ForInContext::isIndexedForInContext const): Deleted. 93 (JSC::ForInContext::isStructureForInContext const): Deleted. 94 (JSC::ForInContext::asIndexedForInContext): Deleted. 95 (JSC::ForInContext::asStructureForInContext): Deleted. 96 (JSC::StructureForInContext::StructureForInContext): Deleted. 97 (JSC::StructureForInContext::index const): Deleted. 98 (JSC::StructureForInContext::property const): Deleted. 99 (JSC::StructureForInContext::enumerator const): Deleted. 100 (JSC::StructureForInContext::baseVariable const): Deleted. 101 (JSC::StructureForInContext::addGetInst): Deleted. 102 (JSC::StructureForInContext::addInInst): Deleted. 103 (JSC::StructureForInContext::addHasOwnPropertyJump): Deleted. 104 (JSC::IndexedForInContext::IndexedForInContext): Deleted. 105 (JSC::IndexedForInContext::index const): Deleted. 106 (JSC::IndexedForInContext::addGetInst): Deleted. 107 * bytecompiler/NodesCodegen.cpp: 108 (JSC::HasOwnPropertyFunctionCallDotNode::emitBytecode): 109 (JSC::ForInNode::emitBytecode): 110 * dfg/DFGAbstractInterpreterInlines.h: 111 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 112 * dfg/DFGArrayMode.h: 113 (JSC::DFG::ArrayMode::isSaneChain const): 114 * dfg/DFGBackwardsPropagationPhase.cpp: 115 (JSC::DFG::BackwardsPropagationPhase::propagate): 116 * dfg/DFGByteCodeParser.cpp: 117 (JSC::DFG::ByteCodeParser::parseBlock): 118 * dfg/DFGCFAPhase.cpp: 119 (JSC::DFG::CFAPhase::injectOSR): 120 * dfg/DFGCapabilities.cpp: 121 (JSC::DFG::capabilityLevel): 122 * dfg/DFGClobberize.h: 123 (JSC::DFG::clobberize): 124 * dfg/DFGDoesGC.cpp: 125 (JSC::DFG::doesGC): 126 * dfg/DFGFixupPhase.cpp: 127 (JSC::DFG::FixupPhase::fixupNode): 128 (JSC::DFG::FixupPhase::setJSArraySaneChainIfPossible): 129 * dfg/DFGGraph.cpp: 130 (JSC::DFG::Graph::dump): 131 * dfg/DFGIntegerRangeOptimizationPhase.cpp: 132 * dfg/DFGMayExit.cpp: 133 * dfg/DFGNode.h: 134 (JSC::DFG::Node::hasHeapPrediction): 135 (JSC::DFG::Node::hasStorageChild const): 136 (JSC::DFG::Node::storageChildIndex): 137 (JSC::DFG::Node::hasArrayMode): 138 (JSC::DFG::Node::hasEnumeratorMetadata const): 139 (JSC::DFG::Node::enumeratorMetadata): 140 * dfg/DFGNodeType.h: 141 * dfg/DFGOpInfo.h: 142 (JSC::DFG::OpInfo::OpInfo): 143 * dfg/DFGOperations.cpp: 144 (JSC::DFG::JSC_DEFINE_JIT_OPERATION): 145 * dfg/DFGOperations.h: 146 * dfg/DFGPredictionPropagationPhase.cpp: 147 * dfg/DFGSSALoweringPhase.cpp: 148 (JSC::DFG::SSALoweringPhase::handleNode): 149 * dfg/DFGSafeToExecute.h: 150 (JSC::DFG::safeToExecute): 151 * dfg/DFGSpeculativeJIT.cpp: 152 (JSC::DFG::JSValueRegsTemporary::JSValueRegsTemporary): 153 (JSC::DFG::SpeculativeJIT::compileGetByValOnString): 154 (JSC::DFG::SpeculativeJIT::setIntTypedArrayLoadResult): 155 (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): 156 (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray): 157 (JSC::DFG::SpeculativeJIT::compileGetByValForObjectWithString): 158 (JSC::DFG::SpeculativeJIT::compileGetByValForObjectWithSymbol): 159 (JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments): 160 (JSC::DFG::SpeculativeJIT::compileGetByValOnScopedArguments): 161 (JSC::DFG::SpeculativeJIT::compileEnumeratorNextUpdateIndexAndMode): 162 (JSC::DFG::SpeculativeJIT::compileEnumeratorNextExtractIndex): 163 (JSC::DFG::SpeculativeJIT::compileEnumeratorNextExtractMode): 164 (JSC::DFG::SpeculativeJIT::compileEnumeratorNextUpdatePropertyName): 165 (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): 166 (JSC::DFG::SpeculativeJIT::compileEnumeratorHasProperty): 167 (JSC::DFG::SpeculativeJIT::compileEnumeratorInByVal): 168 (JSC::DFG::SpeculativeJIT::compileEnumeratorHasOwnProperty): 169 (JSC::DFG::SpeculativeJIT::compileHasIndexedProperty): 170 (JSC::DFG::SpeculativeJIT::compileGetEnumerableLength): Deleted. 171 (JSC::DFG::SpeculativeJIT::compileHasEnumerableProperty): Deleted. 172 (JSC::DFG::SpeculativeJIT::compileToIndexString): Deleted. 173 (JSC::DFG::SpeculativeJIT::compileHasEnumerableStructureProperty): Deleted. 174 (JSC::DFG::SpeculativeJIT::compileHasOwnStructurePropertyImpl): Deleted. 175 (JSC::DFG::SpeculativeJIT::compileHasOwnStructureProperty): Deleted. 176 (JSC::DFG::SpeculativeJIT::compileInStructureProperty): Deleted. 177 (JSC::DFG::SpeculativeJIT::compileGetEnumeratorPname): Deleted. 178 (JSC::DFG::SpeculativeJIT::compileGetDirectPname): Deleted. 179 * dfg/DFGSpeculativeJIT.h: 180 (JSC::DFG::SpeculativeJIT::allocate): 181 (JSC::DFG::JSValueOperand::regs): 182 (JSC::DFG::JSValueOperand::gpr): 183 (JSC::DFG::StorageOperand::StorageOperand): 184 (JSC::DFG::StorageOperand::~StorageOperand): 185 (JSC::DFG::StorageOperand::emplace): 186 (JSC::DFG::JSValueRegsTemporary::operator bool): 187 (JSC::DFG::JSValueRegsTemporary::JSValueRegsTemporary): 188 * dfg/DFGSpeculativeJIT32_64.cpp: 189 (JSC::DFG::SpeculativeJIT::compileGetByVal): 190 (JSC::DFG::SpeculativeJIT::compile): 191 * dfg/DFGSpeculativeJIT64.cpp: 192 (JSC::DFG::SpeculativeJIT::compileGetByVal): 193 (JSC::DFG::SpeculativeJIT::compile): 194 * dfg/DFGTypeCheckHoistingPhase.cpp: 195 (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks): 196 (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks): 197 * ftl/FTLAbstractHeapRepository.h: 198 * ftl/FTLCapabilities.cpp: 199 (JSC::FTL::canCompile): 200 * ftl/FTLLowerDFGToB3.cpp: 201 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 202 (JSC::FTL::DFG::LowerDFGToB3::compileGetByValImpl): 203 (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal): 204 (JSC::FTL::DFG::LowerDFGToB3::compileStringCharAtImpl): 205 (JSC::FTL::DFG::LowerDFGToB3::compileStringCharAt): 206 (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq): 207 * ftl/FTLOutput.h: 208 (JSC::FTL::Output::phi): 209 * generator/DSL.rb: 210 * interpreter/Register.h: 211 * interpreter/RegisterInlines.h: 212 (JSC::Register::operator=): 213 * jit/AssemblyHelpers.h: 214 * jit/JIT.cpp: 215 (JSC::JIT::privateCompileMainPass): 216 (JSC::JIT::privateCompileSlowCases): 217 * jit/JIT.h: 218 * jit/JITOpcodes.cpp: 219 (JSC::JIT::privateCompileHasIndexedProperty): 220 (JSC::JIT::emit_op_has_structure_propertyImpl): Deleted. 221 (JSC::JIT::emit_op_has_enumerable_structure_property): Deleted. 222 (JSC::JIT::emit_op_has_own_structure_property): Deleted. 223 (JSC::JIT::emit_op_in_structure_property): Deleted. 224 (JSC::JIT::emit_op_has_enumerable_indexed_property): Deleted. 225 (JSC::JIT::emitSlow_op_has_enumerable_indexed_property): Deleted. 226 (JSC::JIT::emit_op_get_direct_pname): Deleted. 227 (JSC::JIT::emit_op_enumerator_structure_pname): Deleted. 228 (JSC::JIT::emit_op_enumerator_generic_pname): Deleted. 229 * jit/JITOpcodes32_64.cpp: 230 (JSC::JIT::privateCompileHasIndexedProperty): 231 (JSC::JIT::emit_op_has_structure_propertyImpl): Deleted. 232 (JSC::JIT::emit_op_has_enumerable_structure_property): Deleted. 233 (JSC::JIT::emit_op_has_own_structure_property): Deleted. 234 (JSC::JIT::emit_op_in_structure_property): Deleted. 235 (JSC::JIT::emit_op_has_enumerable_indexed_property): Deleted. 236 (JSC::JIT::emitSlow_op_has_enumerable_indexed_property): Deleted. 237 (JSC::JIT::emit_op_get_direct_pname): Deleted. 238 (JSC::JIT::emit_op_enumerator_structure_pname): Deleted. 239 (JSC::JIT::emit_op_enumerator_generic_pname): Deleted. 240 * jit/JITPropertyAccess.cpp: 241 (JSC::JIT::generateGetByValSlowCase): 242 (JSC::JIT::emitSlow_op_get_by_val): 243 (JSC::JIT::emit_op_enumerator_next): 244 (JSC::JIT::emit_op_enumerator_get_by_val): 245 (JSC::JIT::emitSlow_op_enumerator_get_by_val): 246 (JSC::JIT::emit_enumerator_has_propertyImpl): 247 (JSC::JIT::emit_op_enumerator_in_by_val): 248 (JSC::JIT::emit_op_enumerator_has_own_property): 249 * jit/JITPropertyAccess32_64.cpp: 250 (JSC::JIT::emit_op_enumerator_next): 251 (JSC::JIT::emit_op_enumerator_get_by_val): 252 (JSC::JIT::emitSlow_op_enumerator_get_by_val): 253 (JSC::JIT::emit_op_enumerator_in_by_val): 254 (JSC::JIT::emit_op_enumerator_has_own_property): 255 * llint/LowLevelInterpreter.asm: 256 * llint/LowLevelInterpreter64.asm: 257 * runtime/CommonSlowPaths.cpp: 258 (JSC::JSC_DEFINE_COMMON_SLOW_PATH): 259 * runtime/CommonSlowPaths.h: 260 * runtime/FileBasedFuzzerAgent.cpp: 261 (JSC::FileBasedFuzzerAgent::getPredictionInternal): 262 * runtime/FileBasedFuzzerAgentBase.cpp: 263 (JSC::FileBasedFuzzerAgentBase::opcodeAliasForLookupKey): 264 * runtime/JSGlobalObject.cpp: 265 (JSC::JSGlobalObject::init): 266 * runtime/JSPropertyNameEnumerator.cpp: 267 (JSC::JSPropertyNameEnumerator::JSPropertyNameEnumerator): 268 (JSC::JSPropertyNameEnumerator::computeNext): 269 * runtime/JSPropertyNameEnumerator.h: 270 (JSC::propertyNameEnumerator): 271 * runtime/PredictionFileCreatingFuzzerAgent.cpp: 272 (JSC::PredictionFileCreatingFuzzerAgent::getPredictionInternal): 273 1 274 2021-08-06 Yusuke Suzuki <ysuzuki@apple.com> 2 275 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
r280583 r280760 1070 1070 } 1071 1071 1072 void or8(RegisterID src, AbsoluteAddress address) 1073 { 1074 load8(address.m_ptr, getCachedDataTempRegisterIDAndInvalidate()); 1075 or32(src, dataTempRegister, dataTempRegister); 1076 store8(dataTempRegister, address.m_ptr); 1077 } 1078 1072 1079 void or8(TrustedImm32 imm, AbsoluteAddress address) 1073 1080 { -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r280578 r280760 626 626 } 627 627 628 void or8(RegisterID src, AbsoluteAddress address) 629 { 630 move(TrustedImmPtr(address.m_ptr), scratchRegister()); 631 or8(src, Address(scratchRegister())); 632 } 633 628 634 void or32(Address src, RegisterID dest) 629 635 { … … 664 670 { 665 671 m_assembler.orb_im(static_cast<int8_t>(imm.m_value), address.offset, address.base, address.index, address.scale); 672 } 673 674 void or8(TrustedImm32 imm, AbsoluteAddress address) 675 { 676 move(TrustedImmPtr(address.m_ptr), scratchRegister()); 677 or8(imm, Address(scratchRegister())); 666 678 } 667 679 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
r279889 r280760 98 98 } 99 99 100 void or8(TrustedImm32 imm, AbsoluteAddress address)101 {102 move(TrustedImmPtr(address.m_ptr), scratchRegister());103 or8(imm, Address(scratchRegister()));104 }105 106 100 void sub32(TrustedImm32 imm, AbsoluteAddress address) 107 101 { … … 586 580 swap(src, X86Registers::ecx); 587 581 } 582 } 583 584 void rshift64(RegisterID src, TrustedImm32 imm, RegisterID dest) 585 { 586 move(src, dest); 587 rshift64(imm, dest); 588 588 } 589 589 -
trunk/Source/JavaScriptCore/builtins/BuiltinNames.h
r275439 r280760 182 182 macro(createPrivateSymbol) \ 183 183 macro(entries) \ 184 macro(outOfLineReactionCounts) 184 macro(outOfLineReactionCounts) \ 185 macro(emptyPropertyNameEnumerator) 185 186 186 187 -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb
r277926 r280760 30 30 :ECMAMode, 31 31 :ErrorTypeWithExtension, 32 :EnumeratorMetadata, 32 33 :GetByIdMode, 33 34 :GetByIdModeMetadata, … … 1155 1156 } 1156 1157 1157 op :get_enumerable_length, 1158 args: { 1159 dst: VirtualRegister, 1160 base: VirtualRegister, 1161 } 1162 1163 op :has_enumerable_indexed_property, 1164 args: { 1165 dst: VirtualRegister, 1166 base: VirtualRegister, 1167 property: VirtualRegister, 1158 op :get_property_enumerator, 1159 args: { 1160 dst: VirtualRegister, 1161 base: VirtualRegister, 1162 } 1163 1164 op :enumerator_next, 1165 args: { 1166 # out 1167 propertyName: VirtualRegister, 1168 # in/out 1169 mode: VirtualRegister, # Will always be a JS UInt32 representing a JSForInMode. 1170 index: VirtualRegister, # Gets reset to zero every time mode changes. 1171 # in 1172 base: VirtualRegister, 1173 enumerator: VirtualRegister, 1168 1174 }, 1169 1175 metadata: { 1170 1176 arrayProfile: ArrayProfile, 1171 } 1172 1173 op :has_enumerable_structure_property, 1174 args: { 1175 dst: VirtualRegister, 1176 base: VirtualRegister, 1177 property: VirtualRegister, 1178 enumerator: VirtualRegister, 1179 } 1180 1181 op :has_own_structure_property, 1182 args: { 1183 dst: VirtualRegister, 1184 base: VirtualRegister, 1185 property: VirtualRegister, 1186 enumerator: VirtualRegister, 1187 } 1188 1189 op :in_structure_property, 1190 args: { 1191 dst: VirtualRegister, 1192 base: VirtualRegister, 1193 property: VirtualRegister, 1194 enumerator: VirtualRegister, 1195 } 1196 1197 op :has_enumerable_property, 1198 args: { 1199 dst: VirtualRegister, 1200 base: VirtualRegister, 1201 property: VirtualRegister, 1202 } 1203 1204 op :get_direct_pname, 1205 args: { 1206 dst: VirtualRegister, 1207 base: VirtualRegister, 1208 property: VirtualRegister, 1177 enumeratorMetadata: EnumeratorMetadata, 1178 } 1179 1180 op :enumerator_get_by_val, 1181 args: { 1182 dst: VirtualRegister, 1183 base: VirtualRegister, 1184 mode: VirtualRegister, 1185 propertyName: VirtualRegister, 1209 1186 index: VirtualRegister, 1210 1187 enumerator: VirtualRegister, … … 1212 1189 metadata: { 1213 1190 profile: ValueProfile, 1214 }1215 1216 op :get_property_enumerator, 1217 args: { 1218 dst: VirtualRegister,1219 base: VirtualRegister,1220 }1221 1222 op :enumerator_structure_pname,1223 args: {1224 dst: VirtualRegister,1191 arrayProfile: ArrayProfile, 1192 enumeratorMetadata: EnumeratorMetadata, 1193 } 1194 1195 op :enumerator_in_by_val, 1196 args: { 1197 dst: VirtualRegister, 1198 base: VirtualRegister, 1199 mode: VirtualRegister, 1200 propertyName: VirtualRegister, 1201 index: VirtualRegister, 1225 1202 enumerator: VirtualRegister, 1203 }, 1204 metadata: { 1205 arrayProfile: ArrayProfile, 1206 enumeratorMetadata: EnumeratorMetadata, 1207 } 1208 1209 op :enumerator_has_own_property, 1210 args: { 1211 dst: VirtualRegister, 1212 base: VirtualRegister, 1213 mode: VirtualRegister, 1214 propertyName: VirtualRegister, 1226 1215 index: VirtualRegister, 1227 }1228 1229 op :enumerator_generic_pname,1230 args: {1231 dst: VirtualRegister,1232 1216 enumerator: VirtualRegister, 1233 index: VirtualRegister, 1234 } 1235 1236 op :to_index_string, 1237 args: { 1238 dst: VirtualRegister, 1239 index: VirtualRegister, 1217 }, 1218 metadata: { 1219 arrayProfile: ArrayProfile, 1220 enumeratorMetadata: EnumeratorMetadata, 1240 1221 } 1241 1222 -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp
r277926 r280760 164 164 USES(OpSpread, argument) 165 165 USES(OpGetPropertyEnumerator, base) 166 USES(OpGetEnumerableLength, base)167 166 USES(OpNewFuncExp, scope) 168 167 USES(OpNewGeneratorFuncExp, scope) 169 168 USES(OpNewAsyncFuncExp, scope) 170 USES(OpToIndexString, index)171 169 USES(OpCreateLexicalEnvironment, scope, symbolTable, initialValue) 172 170 USES(OpCreateGeneratorFrameEnvironment, scope, symbolTable, initialValue) … … 222 220 USES(OpNewArrayBuffer, immutableButterfly) 223 221 224 USES(OpHasEnumerableIndexedProperty, base, property)225 USES(OpHasEnumerableStructureProperty, base, property, enumerator)226 USES(OpHasEnumerableProperty, base, property)227 USES(OpEnumeratorStructurePname, enumerator, index)228 USES(OpEnumeratorGenericPname, enumerator, index)229 222 USES(OpGetByVal, base, property) 230 223 USES(OpGetPrivateName, base, property) … … 266 259 USES(OpGetByValWithThis, base, thisValue, property) 267 260 USES(OpInstanceofCustom, value, constructor, hasInstanceValue) 268 USES(OpHasOwnStructureProperty, base, property, enumerator)269 USES(OpInStructureProperty, base, property, enumerator)270 261 271 262 case op_call_varargs: { … … 285 276 } 286 277 287 USES(OpGetDirectPname, base, property, index, enumerator)288 289 278 USES(OpSwitchString, scrutinee) 290 279 USES(OpSwitchChar, scrutinee) … … 295 284 296 285 USES(OpYield, argument) 286 287 USES(OpEnumeratorNext, mode, index, base, enumerator) 288 USES(OpEnumeratorGetByVal, base, mode, propertyName, index, enumerator) 289 USES(OpEnumeratorInByVal, base, mode, propertyName, index, enumerator) 290 USES(OpEnumeratorHasOwnProperty, base, mode, propertyName, index, enumerator) 297 291 298 292 case op_iterator_open: { … … 425 419 // These all have a single destination for the first argument. 426 420 DEFS(OpArgumentCount, dst) 427 DEFS(OpToIndexString, dst)428 DEFS(OpGetEnumerableLength, dst)429 DEFS(OpHasEnumerableIndexedProperty, dst)430 DEFS(OpHasEnumerableStructureProperty, dst)431 DEFS(OpHasEnumerableProperty, dst)432 DEFS(OpHasOwnStructureProperty, dst)433 DEFS(OpInStructureProperty, dst)434 DEFS(OpGetDirectPname, dst)435 421 DEFS(OpGetPropertyEnumerator, dst) 436 DEFS(OpEnumeratorStructurePname, dst)437 DEFS(OpEnumeratorGenericPname, dst)438 422 DEFS(OpGetParentScope, dst) 439 423 DEFS(OpPushWithScope, dst) … … 568 552 DEFS(OpCatch, exception, thrownValue) 569 553 554 DEFS(OpEnumeratorNext, propertyName, mode, index) 555 DEFS(OpEnumeratorGetByVal, dst) 556 DEFS(OpEnumeratorInByVal, dst) 557 DEFS(OpEnumeratorHasOwnProperty, dst) 558 570 559 case op_iterator_open: { 571 560 auto bytecode = instruction->as<OpIteratorOpen>(); -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r280004 r280760 473 473 m_bytecodeCost += opcodeLengths[opcodeID]; 474 474 switch (opcodeID) { 475 LINK(OpHasEnumerableIndexedProperty)476 477 475 LINK(OpCallVarargs, profile) 478 476 LINK(OpTailCallVarargs, profile) … … 482 480 LINK(OpGetPrivateName, profile) 483 481 484 LINK(OpGetDirectPname, profile)485 482 LINK(OpGetByIdWithThis, profile) 486 483 LINK(OpTryGetById, profile) … … 503 500 504 501 LINK(OpGetById, profile) 502 503 LINK(OpEnumeratorNext, profile) 504 LINK(OpEnumeratorInByVal, profile) 505 LINK(OpEnumeratorHasOwnProperty, profile) 506 LINK(OpEnumeratorGetByVal, profile) 505 507 506 508 LINK(OpCall, profile) -
trunk/Source/JavaScriptCore/bytecode/LinkTimeConstant.h
r275439 r280760 112 112 v(hasOwnPropertyFunction, nullptr) \ 113 113 v(createPrivateSymbol, nullptr) \ 114 v(emptyPropertyNameEnumerator, nullptr) \ 114 115 115 116 -
trunk/Source/JavaScriptCore/bytecode/Opcode.h
r273972 r280760 1 1 /* 2 * Copyright (C) 2008 , 2009, 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2008-2021 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> 4 4 * … … 100 100 macro(OpConstructVarargs) \ 101 101 macro(OpGetByVal) \ 102 macro(Op GetDirectPname) \102 macro(OpEnumeratorGetByVal) \ 103 103 macro(OpGetById) \ 104 104 macro(OpGetByIdWithThis) \ … … 128 128 129 129 #define FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(macro) \ 130 macro(OpHasEnumerableIndexedProperty) \131 130 macro(OpCallVarargs) \ 132 131 macro(OpTailCallVarargs) \ … … 137 136 macro(OpPutByVal) \ 138 137 macro(OpPutByValDirect) \ 138 macro(OpEnumeratorNext) \ 139 macro(OpEnumeratorGetByVal) \ 140 macro(OpEnumeratorInByVal) \ 141 macro(OpEnumeratorHasOwnProperty) \ 139 142 140 143 #define FOR_EACH_OPCODE_WITH_ARRAY_ALLOCATION_PROFILE(macro) \ -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r279448 r280760 1504 1504 } 1505 1505 1506 void BytecodeGenerator::recordHasOwn StructurePropertyInForInLoop(StructureForInContext& structureContext, unsigned branchOffset, Label& genericPath)1506 void BytecodeGenerator::recordHasOwnPropertyInForInLoop(ForInContext& context, unsigned branchOffset, Label& genericPath) 1507 1507 { 1508 1508 RELEASE_ASSERT(genericPath.isBound()); 1509 1509 RELEASE_ASSERT(!genericPath.isForward()); 1510 structureContext.addHasOwnPropertyJump(branchOffset, genericPath.location());1510 context.addHasOwnPropertyJump(branchOffset, genericPath.location()); 1511 1511 } 1512 1512 … … 2582 2582 continue; 2583 2583 2584 if (!context.isStructureForInContext()) 2585 break; 2586 2587 StructureForInContext& structureContext = context.asStructureForInContext(); 2588 OpInStructureProperty::emit<OpcodeSize::Wide32>(this, dst, base, property, structureContext.enumerator()); 2589 structureContext.addInInst(m_lastInstruction.offset(), property->index()); 2584 OpEnumeratorInByVal::emit<OpcodeSize::Wide32>(this, dst, base, context.mode(), property, context.propertyOffset(), context.enumerator()); 2585 context.addInInst(m_lastInstruction.offset(), property->index()); 2590 2586 return dst; 2591 2587 } … … 2735 2731 continue; 2736 2732 2737 if (context.isIndexedForInContext()) { 2738 auto& indexedContext = context.asIndexedForInContext(); 2739 kill(dst); 2740 if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Narrow>(this, dst, base, property)) 2741 OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(this, dst, base, indexedContext.index()); 2742 else if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Wide16>(this, dst, base, property)) 2743 OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Wide16>(this, dst, base, indexedContext.index()); 2744 else 2745 OpGetByVal::emit<OpcodeSize::Wide32>(this, dst, base, indexedContext.index()); 2746 indexedContext.addGetInst(m_lastInstruction.offset(), property->index()); 2747 return dst; 2748 } 2749 2750 // We cannot do the above optimization here since OpGetDirectPname => OpGetByVal conversion involves different metadata ID allocation. 2751 StructureForInContext& structureContext = context.asStructureForInContext(); 2752 OpGetDirectPname::emit<OpcodeSize::Wide32>(this, kill(dst), base, property, structureContext.index(), structureContext.enumerator()); 2753 2754 structureContext.addGetInst(m_lastInstruction.offset(), property->index()); 2733 // FIXME: We should have a better bytecode rewriter that can resize chunks. 2734 OpEnumeratorGetByVal::emit<OpcodeSize::Wide32>(this, kill(dst), base, context.mode(), property, context.propertyOffset(), context.enumerator()); 2735 context.addGetInst(m_lastInstruction.offset(), property->index()); 2755 2736 return dst; 2756 2737 } … … 4553 4534 } 4554 4535 4555 RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base) 4556 { 4557 OpGetEnumerableLength::emit(this, dst, base); 4558 return dst; 4559 } 4560 4561 RegisterID* BytecodeGenerator::emitHasEnumerableIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName) 4562 { 4563 OpHasEnumerableIndexedProperty::emit(this, dst, base, propertyName); 4564 return dst; 4565 } 4566 4567 RegisterID* BytecodeGenerator::emitHasEnumerableStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator) 4568 { 4569 OpHasEnumerableStructureProperty::emit(this, dst, base, propertyName, enumerator); 4570 return dst; 4571 } 4572 4573 RegisterID* BytecodeGenerator::emitHasEnumerableProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName) 4574 { 4575 OpHasEnumerableProperty::emit(this, dst, base, propertyName); 4576 return dst; 4577 } 4578 4579 RegisterID* BytecodeGenerator::emitHasOwnStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator) 4580 { 4581 OpHasOwnStructureProperty::emit(this, dst, base, propertyName, enumerator); 4536 void BytecodeGenerator::emitEnumeratorNext(RegisterID* propertyName, RegisterID* mode, RegisterID* index, RegisterID* base, RegisterID* enumerator) 4537 { 4538 OpEnumeratorNext::emit(this, propertyName, mode, index, base, enumerator); 4539 } 4540 4541 RegisterID* BytecodeGenerator::emitEnumeratorHasOwnProperty(RegisterID* dst, RegisterID* base, RegisterID* mode, RegisterID* propertyName, RegisterID* index, RegisterID* enumerator) 4542 { 4543 OpEnumeratorHasOwnProperty::emit(this, dst, base, mode, propertyName, index, enumerator); 4582 4544 return dst; 4583 4545 } … … 4589 4551 } 4590 4552 4591 RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)4592 {4593 OpEnumeratorStructurePname::emit(this, dst, enumerator, index);4594 return dst;4595 }4596 4597 RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)4598 {4599 OpEnumeratorGenericPname::emit(this, dst, enumerator, index);4600 return dst;4601 }4602 4603 RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)4604 {4605 OpToIndexString::emit(this, dst, index);4606 return dst;4607 }4608 4609 4553 RegisterID* BytecodeGenerator::emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType type) 4610 4554 { … … 4647 4591 OpIsEmpty::emit(this, dst, src); 4648 4592 return dst; 4649 }4650 4651 void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)4652 {4653 if (!localRegister)4654 return;4655 unsigned bodyBytecodeStartOffset = instructions().size();4656 m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister, bodyBytecodeStartOffset)));4657 }4658 4659 void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)4660 {4661 if (!localRegister)4662 return;4663 unsigned bodyBytecodeEndOffset = instructions().size();4664 m_forInContextStack.last()->asIndexedForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);4665 m_forInContextStack.removeLast();4666 4593 } 4667 4594 … … 4769 4696 } 4770 4697 4771 void BytecodeGenerator::push StructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister, std::optional<Variable> baseVariable)4698 void BytecodeGenerator::pushForInScope(RegisterID* localRegister, RegisterID* propertyNameRegister, RegisterID* propertyOffsetRegister, RegisterID* enumeratorRegister, RegisterID* modeRegister, std::optional<Variable> baseVariable) 4772 4699 { 4773 4700 if (!localRegister) 4774 4701 return; 4775 4702 unsigned bodyBytecodeStartOffset = instructions().size(); 4776 m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister, baseVariable, bodyBytecodeStartOffset)));4777 } 4778 4779 void BytecodeGenerator::pop StructureForInScope(RegisterID* localRegister)4703 m_forInContextStack.append(adoptRef(*new ForInContext(localRegister, propertyNameRegister, propertyOffsetRegister, enumeratorRegister, modeRegister, baseVariable, bodyBytecodeStartOffset))); 4704 } 4705 4706 void BytecodeGenerator::popForInScope(RegisterID* localRegister) 4780 4707 { 4781 4708 if (!localRegister) 4782 4709 return; 4783 4710 unsigned bodyBytecodeEndOffset = instructions().size(); 4784 m_forInContextStack.last()-> asStructureForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);4711 m_forInContextStack.last()->finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset); 4785 4712 m_forInContextStack.removeLast(); 4786 4713 } … … 5385 5312 } 5386 5313 5314 template <typename OldOpType, typename NewOpType, typename TupleType> 5315 ALWAYS_INLINE void rewriteOp(BytecodeGenerator& generator, TupleType& instTuple) 5316 { 5317 unsigned instIndex = std::get<0>(instTuple); 5318 int propertyRegIndex = std::get<1>(instTuple); 5319 auto instruction = generator.m_writer.ref(instIndex); 5320 auto end = instIndex + instruction->size(); 5321 ASSERT(instruction->isWide32()); 5322 5323 generator.m_writer.seek(instIndex); 5324 5325 auto bytecode = instruction->as<OldOpType>(); 5326 5327 generator.disablePeepholeOptimization(); 5328 5329 // Change the opcode to get_by_val. 5330 // 1. dst stays the same. 5331 // 2. base stays the same. 5332 // 3. property gets switched to the original property. 5333 5334 static_assert(sizeof(NewOpType) <= sizeof(OldOpType)); 5335 NewOpType::emit(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex)); 5336 5337 // 4. nop out the remaining bytes 5338 while (generator.m_writer.position() < end) 5339 OpNop::emit<OpcodeSize::Narrow>(&generator); 5340 } 5341 5387 5342 void ForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlockGenerator* codeBlock, unsigned bodyBytecodeEndOffset) 5388 5343 { … … 5399 5354 // reassigned from its original value. 5400 5355 5401 for (unsigned offset = bodyBytecodeStartOffset(); isValid() && offset < bodyBytecodeEndOffset;) { 5356 bool escaped = false; 5357 for (unsigned offset = bodyBytecodeStartOffset(); !escaped && offset < bodyBytecodeEndOffset;) { 5402 5358 auto instruction = generator.instructions().at(offset); 5403 5359 ASSERT(!instruction->is<OpEnter>()); … … 5405 5361 computeDefsForBytecodeIndex(codeBlock, instruction.ptr(), checkpoint, [&] (VirtualRegister operand) { 5406 5362 if (local()->virtualRegister() == operand) 5407 invalidate();5363 escaped = true; 5408 5364 }); 5409 5365 } 5410 5366 offset += instruction->size(); 5411 5367 } 5412 } 5413 5414 template <typename OldOpType, typename TupleType> 5415 ALWAYS_INLINE void rewriteOp(BytecodeGenerator& generator, TupleType& instTuple) 5416 { 5417 unsigned instIndex = std::get<0>(instTuple); 5418 int propertyRegIndex = std::get<1>(instTuple); 5419 auto instruction = generator.m_writer.ref(instIndex); 5420 auto end = instIndex + instruction->size(); 5421 ASSERT(instruction->isWide32()); 5422 5423 generator.m_writer.seek(instIndex); 5424 5425 auto bytecode = instruction->as<OldOpType>(); 5426 5427 generator.disablePeepholeOptimization(); 5428 5429 // Change the opcode to get_by_val. 5430 // 1. dst stays the same. 5431 // 2. base stays the same. 5432 // 3. property gets switched to the original property. 5433 5434 if constexpr (std::is_same<OldOpType, OpGetDirectPname>::value) { 5435 static_assert(sizeof(OpGetByVal) <= sizeof(OpGetDirectPname)); 5436 OpGetByVal::emit<OpcodeSize::Wide32>(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex)); 5437 } else if constexpr (std::is_same<OldOpType, OpInStructureProperty>::value) { 5438 static_assert(sizeof(OpInByVal) <= sizeof(OpInStructureProperty)); 5439 OpInByVal::emit<OpcodeSize::Wide32>(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex)); 5440 } else 5441 RELEASE_ASSERT_NOT_REACHED(); 5442 5443 // 4. nop out the remaining bytes 5444 while (generator.m_writer.position() < end) 5445 OpNop::emit<OpcodeSize::Narrow>(&generator); 5446 } 5447 5448 void StructureForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlockGenerator* codeBlock, unsigned bodyBytecodeEndOffset) 5449 { 5450 Base::finalize(generator, codeBlock, bodyBytecodeEndOffset); 5451 if (isValid()) 5368 5369 if (!escaped) 5452 5370 return; 5453 5371 … … 5456 5374 5457 5375 for (const auto& instTuple : m_getInsts) 5458 rewriteOp<Op GetDirectPname>(generator, instTuple);5376 rewriteOp<OpEnumeratorGetByVal, OpGetByVal>(generator, instTuple); 5459 5377 5460 5378 for (const auto& instTuple : m_inInsts) 5461 rewriteOp<Op InStructureProperty>(generator, instTuple);5379 rewriteOp<OpEnumeratorInByVal, OpInByVal>(generator, instTuple); 5462 5380 5463 5381 for (const auto& hasOwnPropertyTuple : m_hasOwnPropertyJumpInsts) { … … 5485 5403 generator.m_lastOpcodeID = lastOpcodeID; 5486 5404 generator.m_lastInstruction = lastInstruction; 5487 }5488 }5489 5490 void IndexedForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlockGenerator* codeBlock, unsigned bodyBytecodeEndOffset)5491 {5492 Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);5493 if (isValid())5494 return;5495 5496 for (const auto& instPair : m_getInsts) {5497 unsigned instIndex = instPair.first;5498 int propertyRegIndex = instPair.second;5499 generator.m_writer.ref(instIndex)->cast<OpGetByVal>()->setProperty(VirtualRegister(propertyRegIndex), []() {5500 ASSERT_NOT_REACHED();5501 return VirtualRegister();5502 });5503 5405 } 5504 5406 } … … 5529 5431 } 5530 5432 5531 StructureForInContext* BytecodeGenerator::findStructureForInContext(RegisterID* property)5433 ForInContext* BytecodeGenerator::findForInContext(RegisterID* property) 5532 5434 { 5533 5435 for (size_t i = m_forInContextStack.size(); i--; ) { … … 5536 5438 continue; 5537 5439 5538 if (!context.isStructureForInContext()) 5539 break; 5540 5541 return &context.asStructureForInContext(); 5440 return &context; 5542 5441 } 5543 5442 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r279447 r280760 62 62 class JSImmutableButterfly; 63 63 class Identifier; 64 class IndexedForInContext; 65 class StructureForInContext; 64 class ForInContext; 66 65 67 66 enum ExpectedFunction { … … 257 256 WTF_MAKE_NONCOPYABLE(ForInContext); 258 257 public: 259 virtual ~ForInContext() = default;260 261 bool isValid() const { return m_isValid; }262 void invalidate() { m_isValid = false; }263 264 enum class Type : uint8_t {265 IndexedForIn,266 StructureForIn267 };268 269 Type type() const { return m_type; }270 bool isIndexedForInContext() const { return m_type == Type::IndexedForIn; }271 bool isStructureForInContext() const { return m_type == Type::StructureForIn; }272 273 IndexedForInContext& asIndexedForInContext()274 {275 ASSERT(isIndexedForInContext());276 return *reinterpret_cast<IndexedForInContext*>(this);277 }278 279 StructureForInContext& asStructureForInContext()280 {281 ASSERT(isStructureForInContext());282 return *reinterpret_cast<StructureForInContext*>(this);283 }284 285 RegisterID* local() const { return m_localRegister.get(); }286 287 protected:288 ForInContext(RegisterID* localRegister, Type type, unsigned bodyBytecodeStartOffset)289 : m_localRegister(localRegister)290 , m_type(type)291 , m_bodyBytecodeStartOffset(bodyBytecodeStartOffset)292 { }293 294 unsigned bodyBytecodeStartOffset() const { return m_bodyBytecodeStartOffset; }295 296 void finalize(BytecodeGenerator&, UnlinkedCodeBlockGenerator*, unsigned bodyBytecodeEndOffset);297 298 private:299 RefPtr<RegisterID> m_localRegister;300 bool m_isValid { true };301 Type m_type;302 unsigned m_bodyBytecodeStartOffset;303 };304 305 class StructureForInContext : public ForInContext {306 using Base = ForInContext;307 public:308 258 using GetInst = std::tuple<unsigned, int>; 309 259 using InInst = GetInst; 310 260 using HasOwnPropertyJumpInst = std::tuple<unsigned, unsigned>; 311 261 312 StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister, std::optional<Variable> baseVariable, unsigned bodyBytecodeStartOffset) 313 : ForInContext(localRegister, Type::StructureForIn, bodyBytecodeStartOffset) 314 , m_indexRegister(indexRegister) 315 , m_propertyRegister(propertyRegister) 316 , m_enumeratorRegister(enumeratorRegister) 262 bool isValid() const { return m_isValid; } 263 void invalidate() { m_isValid = false; } 264 265 RegisterID* local() const { return m_localRegister.get(); } 266 RegisterID* propertyName() const { return m_propertyName.get(); } 267 RegisterID* propertyOffset() const { return m_propertyOffset.get(); } 268 RegisterID* enumerator() const { return m_enumerator.get(); } 269 RegisterID* mode() const { return m_mode.get(); } 270 const std::optional<Variable>& baseVariable() const { return m_baseVariable; } 271 272 void addGetInst(unsigned instIndex, int propertyRegIndex) 273 { 274 m_getInsts.append(GetInst { instIndex, propertyRegIndex }); 275 } 276 277 void addInInst(unsigned instIndex, int propertyRegIndex) 278 { 279 m_inInsts.append(InInst { instIndex, propertyRegIndex }); 280 } 281 282 void addHasOwnPropertyJump(unsigned branchInstIndex, unsigned genericPathTarget) 283 { 284 m_hasOwnPropertyJumpInsts.append(HasOwnPropertyJumpInst { branchInstIndex, genericPathTarget }); 285 } 286 287 ForInContext(RegisterID* localRegister, RegisterID* propertyName, RegisterID* propertyOffset, RegisterID* enumerator, RegisterID* mode, std::optional<Variable> baseVariable, unsigned bodyBytecodeStartOffset) 288 : m_localRegister(localRegister) 289 , m_propertyName(propertyName) 290 , m_propertyOffset(propertyOffset) 291 , m_enumerator(enumerator) 292 , m_mode(mode) 317 293 , m_baseVariable(baseVariable) 318 { 319 } 320 321 RegisterID* index() const { return m_indexRegister.get(); } 322 RegisterID* property() const { return m_propertyRegister.get(); } 323 RegisterID* enumerator() const { return m_enumeratorRegister.get(); } 324 const std::optional<Variable>& baseVariable() const { return m_baseVariable; } 325 326 void addGetInst(unsigned instIndex, int propertyRegIndex) 327 { 328 m_getInsts.append(GetInst { instIndex, propertyRegIndex }); 329 } 330 331 void addInInst(unsigned instIndex, int propertyRegIndex) 332 { 333 m_inInsts.append(InInst { instIndex, propertyRegIndex }); 334 } 335 336 void addHasOwnPropertyJump(unsigned branchInstIndex, unsigned genericPathTarget) 337 { 338 m_hasOwnPropertyJumpInsts.append(HasOwnPropertyJumpInst { branchInstIndex, genericPathTarget }); 339 } 294 , m_bodyBytecodeStartOffset(bodyBytecodeStartOffset) 295 { } 296 297 unsigned bodyBytecodeStartOffset() const { return m_bodyBytecodeStartOffset; } 340 298 341 299 void finalize(BytecodeGenerator&, UnlinkedCodeBlockGenerator*, unsigned bodyBytecodeEndOffset); 342 300 343 301 private: 344 RefPtr<RegisterID> m_indexRegister; 345 RefPtr<RegisterID> m_propertyRegister; 346 RefPtr<RegisterID> m_enumeratorRegister; 302 RefPtr<RegisterID> m_localRegister; 303 RefPtr<RegisterID> m_propertyName; 304 RefPtr<RegisterID> m_propertyOffset; 305 RefPtr<RegisterID> m_enumerator; 306 RefPtr<RegisterID> m_mode; 347 307 std::optional<Variable> m_baseVariable; 308 bool m_isValid { true }; 309 unsigned m_bodyBytecodeStartOffset; 310 Vector<InInst> m_inInsts; 348 311 Vector<GetInst> m_getInsts; 349 Vector<InInst> m_inInsts;350 312 Vector<HasOwnPropertyJumpInst> m_hasOwnPropertyJumpInsts; 351 };352 353 class IndexedForInContext : public ForInContext {354 using Base = ForInContext;355 public:356 IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister, unsigned bodyBytecodeStartOffset)357 : ForInContext(localRegister, Type::IndexedForIn, bodyBytecodeStartOffset)358 , m_indexRegister(indexRegister)359 {360 }361 362 RegisterID* index() const { return m_indexRegister.get(); }363 364 void finalize(BytecodeGenerator&, UnlinkedCodeBlockGenerator*, unsigned bodyBytecodeEndOffset);365 void addGetInst(unsigned instIndex, int propertyIndex) { m_getInsts.append({ instIndex, propertyIndex }); }366 367 private:368 RefPtr<RegisterID> m_indexRegister;369 Vector<std::pair<unsigned, int>> m_getInsts;370 313 }; 371 314 … … 400 343 401 344 friend class FinallyContext; 402 friend class IndexedForInContext; 403 friend class StructureForInContext; 345 friend class ForInContext; 404 346 friend class StrictModeScope; 405 347 406 template <typename OldOpType, typename TupleType>348 template <typename OldOpType, typename NewOpType, typename TupleType> 407 349 friend void rewriteOp(BytecodeGenerator&, TupleType&); 408 350 … … 682 624 void hoistSloppyModeFunctionIfNecessary(const Identifier& functionName); 683 625 684 StructureForInContext* findStructureForInContext(RegisterID* property);626 ForInContext* findForInContext(RegisterID* property); 685 627 686 628 private: … … 918 860 void emitJumpIfNotFunctionApply(RegisterID* cond, Label& target); 919 861 unsigned emitWideJumpIfNotFunctionHasOwnProperty(RegisterID* cond, Label& target); 920 void recordHasOwn StructurePropertyInForInLoop(StructureForInContext&, unsigned branchOffset, Label& genericPath);862 void recordHasOwnPropertyInForInLoop(ForInContext&, unsigned branchOffset, Label& genericPath); 921 863 922 864 template<typename BinOp, typename JmpOp> … … 929 871 void emitCheckTraps(); 930 872 931 RegisterID* emitHasEnumerableIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);932 RegisterID* emitHasEnumerableStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);933 RegisterID* emitHasEnumerableProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);934 RegisterID* emitHasOwnStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);935 873 RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base); 936 RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base); 937 RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length); 938 RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator); 939 RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index); 940 RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index); 941 RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index); 874 void emitEnumeratorNext(RegisterID* propertyName, RegisterID* mode, RegisterID* index, RegisterID* base, RegisterID* enumerator); 875 RegisterID* emitEnumeratorHasOwnProperty(RegisterID* dst, RegisterID* base, RegisterID* mode, RegisterID* propertyName, RegisterID* index, RegisterID* enumerator); 942 876 943 877 RegisterID* emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType); … … 1058 992 void emitOptionalCheck(RegisterID* src); 1059 993 1060 void pushIndexedForInScope(RegisterID* local, RegisterID* index); 1061 void popIndexedForInScope(RegisterID* local); 1062 void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator, std::optional<Variable> base); 1063 void popStructureForInScope(RegisterID* local); 994 void pushForInScope(RegisterID* local, RegisterID* propertyName, RegisterID* propertyOffset, RegisterID* enumerator, RegisterID* mode, std::optional<Variable> base); 995 void popForInScope(RegisterID* local); 1064 996 1065 997 LabelScope* breakTarget(const Identifier&); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r279447 r280760 2132 2132 ExpressionNode* argument = m_args->m_listNode->m_expr; 2133 2133 RELEASE_ASSERT(argument->isResolveNode()); 2134 StructureForInContext* structureContext = nullptr;2134 ForInContext* context = nullptr; 2135 2135 Variable argumentVariable = generator.variable(static_cast<ResolveNode*>(argument)->identifier()); 2136 2136 if (argumentVariable.isLocal()) { 2137 2137 RegisterID* property = argumentVariable.local(); 2138 structureContext = generator.findStructureForInContext(property);2138 context = generator.findForInContext(property); 2139 2139 } 2140 2140 2141 2141 auto canUseFastHasOwnProperty = [&] { 2142 if (! structureContext)2142 if (!context) 2143 2143 return false; 2144 if (! structureContext->baseVariable())2144 if (!context->baseVariable()) 2145 2145 return false; 2146 2146 if (m_base->isResolveNode()) 2147 return generator.variable(static_cast<ResolveNode*>(m_base)->identifier()) == structureContext->baseVariable().value();2147 return generator.variable(static_cast<ResolveNode*>(m_base)->identifier()) == context->baseVariable().value(); 2148 2148 if (m_base->isThisNode()) { 2149 2149 // After generator.ensureThis (which must be invoked in |base|'s materialization), we can ensure that |this| is in local this-register. 2150 2150 ASSERT(base); 2151 return generator.variable(generator.propertyNames().builtinNames().thisPrivateName(), ThisResolutionType::Local) == structureContext->baseVariable().value();2151 return generator.variable(generator.propertyNames().builtinNames().thisPrivateName(), ThisResolutionType::Local) == context->baseVariable().value(); 2152 2152 } 2153 2153 return false; … … 2161 2161 2162 2162 unsigned branchInsnOffset = generator.emitWideJumpIfNotFunctionHasOwnProperty(function.get(), realCall.get()); 2163 generator.emit HasOwnStructureProperty(returnValue.get(), base.get(), generator.emitNode(argument), structureContext->enumerator());2163 generator.emitEnumeratorHasOwnProperty(returnValue.get(), base.get(), context->mode(), generator.emitNode(argument), context->propertyOffset(), context->enumerator()); 2164 2164 generator.emitJump(end.get()); 2165 2165 … … 2173 2173 generator.emitLabel(end.get()); 2174 2174 2175 generator.recordHasOwn StructurePropertyInForInLoop(*structureContext, branchInsnOffset, realCall);2175 generator.recordHasOwnPropertyInForInLoop(*context, branchInsnOffset, realCall); 2176 2176 } else { 2177 2177 CallArguments callArguments(generator, m_args); … … 4185 4185 generator.emitLoad(dst, jsUndefined()); 4186 4186 4187 Ref<Label> end = generator.newLabel();4188 4189 4187 RegisterID* forLoopSymbolTable = nullptr; 4190 4188 generator.pushLexicalScope(this, BytecodeGenerator::ScopeType::LetConstScope, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable); … … 4194 4192 4195 4193 RefPtr<RegisterID> base = generator.newTemporary(); 4196 RefPtr<RegisterID> length;4197 RefPtr<RegisterID> enumerator;4198 4194 4199 4195 generator.emitNode(base.get(), m_expr); 4200 4196 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator); 4201 RefPtr<RegisterID> enumeratorIndex; 4197 4202 4198 4203 4199 std::optional<Variable> baseVariable; … … 4210 4206 } 4211 4207 4212 // Pause at the assignment expression for each for..in iteration.4213 generator.emitDebugHook(m_lexpr);4214 4215 4208 int profilerStartOffset = m_statement->startOffset(); 4216 4209 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0); 4217 4210 4218 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());4219 4220 BytecodeGenerator::PreservedTDZStack preservedTDZStack;4221 generator.preserveTDZStack(preservedTDZStack);4222 4223 // Indexed property loop.4224 4211 { 4212 RefPtr<RegisterID> enumerator = generator.newTemporary(); 4213 RefPtr<RegisterID> mode = generator.emitLoad(generator.newTemporary(), jsNumber(static_cast<unsigned>(JSPropertyNameEnumerator::InitMode))); 4214 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0)); 4215 RefPtr<RegisterID> propertyName = generator.newTemporary(); 4225 4216 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); 4226 Ref<Label> loopStart = generator.newLabel(); 4227 Ref<Label> loopEnd = generator.newLabel(); 4228 4229 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get()); 4230 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0)); 4231 RefPtr<RegisterID> propertyName = generator.newTemporary(); 4232 4233 generator.emitLabel(loopStart.get()); 4217 4218 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get()); 4219 generator.moveLinkTimeConstant(propertyName.get(), LinkTimeConstant::emptyPropertyNameEnumerator); 4220 generator.emitEqualityOp<OpStricteq>(propertyName.get(), enumerator.get(), propertyName.get()); 4221 generator.emitJumpIfTrue(propertyName.get(), scope->breakTarget()); 4222 4223 generator.emitLabel(*scope->continueTarget()); 4234 4224 generator.emitLoopHint(); 4235 4236 RefPtr<RegisterID> result = generator.emitBinaryOp<OpLess>(generator.newTemporary(), i.get(), length.get()); 4237 generator.emitJumpIfFalse(result.get(), loopEnd.get()); 4238 generator.emitHasEnumerableIndexedProperty(result.get(), base.get(), i.get()); 4239 generator.emitJumpIfFalse(result.get(), *scope->continueTarget()); 4240 4241 generator.emitToIndexString(propertyName.get(), i.get()); 4225 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable); 4226 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration. 4227 4228 // FIXME: We should have a way to see if anyone is actually using the propertyName for something other than a get_by_val. If not, we could eliminate the toString in this opcode. 4229 generator.emitEnumeratorNext(propertyName.get(), mode.get(), index.get(), base.get(), enumerator.get()); 4230 4231 // Note, choosing undefined or null helps please DFG's Abstract Interpreter as it doesn't distinguish null and undefined as types (via SpecOther). 4232 generator.emitJumpIfTrue(generator.emitIsUndefinedOrNull(generator.newTemporary(), propertyName.get()), scope->breakTarget()); 4233 4242 4234 this->emitLoopHeader(generator, propertyName.get()); 4243 4235 4244 4236 generator.emitProfileControlFlow(profilerStartOffset); 4245 4237 4246 generator.push IndexedForInScope(local.get(), i.get());4238 generator.pushForInScope(local.get(), propertyName.get(), index.get(), enumerator.get(), mode.get(), baseVariable); 4247 4239 generator.emitNode(dst, m_statement); 4248 generator.pop IndexedForInScope(local.get());4240 generator.popForInScope(local.get()); 4249 4241 4250 4242 generator.emitProfileControlFlow(profilerEndOffset); 4251 4252 generator.emitLabel(*scope->continueTarget()); 4253 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable); 4254 generator.emitInc(i.get()); 4255 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration. 4256 generator.emitJump(loopStart.get()); 4243 generator.emitJump(*scope->continueTarget()); 4257 4244 4258 4245 generator.emitLabel(scope->breakTarget()); 4259 generator.emitJump(end.get()); 4260 generator.emitLabel(loopEnd.get()); 4261 } 4262 generator.restoreTDZStack(preservedTDZStack); 4263 4264 // Structure property loop. 4265 { 4266 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); 4267 Ref<Label> loopStart = generator.newLabel(); 4268 Ref<Label> loopEnd = generator.newLabel(); 4269 4270 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0)); 4271 RefPtr<RegisterID> propertyName = generator.newTemporary(); 4272 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get()); 4273 4274 generator.emitLabel(loopStart.get()); 4275 generator.emitLoopHint(); 4276 4277 RefPtr<RegisterID> result = generator.emitIsNull(generator.newTemporary(), propertyName.get()); 4278 generator.emitJumpIfTrue(result.get(), loopEnd.get()); 4279 generator.emitHasEnumerableStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get()); 4280 generator.emitJumpIfFalse(result.get(), *scope->continueTarget()); 4281 4282 this->emitLoopHeader(generator, propertyName.get()); 4283 4284 generator.emitProfileControlFlow(profilerStartOffset); 4285 4286 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get(), baseVariable); 4287 generator.emitNode(dst, m_statement); 4288 generator.popStructureForInScope(local.get()); 4289 4290 generator.emitProfileControlFlow(profilerEndOffset); 4291 4292 generator.emitLabel(*scope->continueTarget()); 4293 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable); 4294 generator.emitInc(enumeratorIndex.get()); 4295 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get()); 4296 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration. 4297 generator.emitJump(loopStart.get()); 4298 4299 generator.emitLabel(scope->breakTarget()); 4300 generator.emitJump(end.get()); 4301 generator.emitLabel(loopEnd.get()); 4302 } 4303 generator.restoreTDZStack(preservedTDZStack); 4304 4305 // Generic property loop. 4306 { 4307 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); 4308 Ref<Label> loopStart = generator.newLabel(); 4309 Ref<Label> loopEnd = generator.newLabel(); 4310 4311 RefPtr<RegisterID> propertyName = generator.newTemporary(); 4312 4313 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get()); 4314 4315 generator.emitLabel(loopStart.get()); 4316 generator.emitLoopHint(); 4317 4318 RefPtr<RegisterID> result = generator.emitIsNull(generator.newTemporary(), propertyName.get()); 4319 generator.emitJumpIfTrue(result.get(), loopEnd.get()); 4320 4321 generator.emitHasEnumerableProperty(result.get(), base.get(), propertyName.get()); 4322 generator.emitJumpIfFalse(result.get(), *scope->continueTarget()); 4323 4324 this->emitLoopHeader(generator, propertyName.get()); 4325 4326 generator.emitProfileControlFlow(profilerStartOffset); 4327 4328 generator.emitNode(dst, m_statement); 4329 4330 generator.emitLabel(*scope->continueTarget()); 4331 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable); 4332 generator.emitInc(enumeratorIndex.get()); 4333 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get()); 4334 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration. 4335 generator.emitJump(loopStart.get()); 4336 4337 generator.emitLabel(scope->breakTarget()); 4338 generator.emitJump(end.get()); 4339 generator.emitLabel(loopEnd.get()); 4340 } 4341 4342 generator.emitLabel(end.get()); 4246 } 4247 4343 4248 generator.popLexicalScope(this); 4344 4249 generator.emitProfileControlFlow(profilerEndOffset); -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r279604 r280760 2152 2152 setForNode(node, m_vm.stringStructure.get()); 2153 2153 break; 2154 2154 2155 case EnumeratorGetByVal: { 2156 // FIXME: This should be able to do code motion for OwnStructureMode but we'd need to teach AI about the enumerator's cached structure for that to be profitable. 2157 clobberWorld(); 2158 makeHeapTopForNode(node); 2159 break; 2160 } 2161 2155 2162 case GetByVal: 2156 2163 case AtomicsAdd: … … 4245 4252 break; 4246 4253 } 4247 4248 case GetEnumerableLength: { 4249 setNonCellTypeForNode(node, SpecInt32Only); 4250 break; 4251 } 4252 case HasEnumerableProperty: { 4253 setNonCellTypeForNode(node, SpecBoolean); 4254 clobberWorld(); 4255 break; 4256 } 4257 case InStructureProperty: 4258 case HasOwnStructureProperty: 4259 case HasEnumerableStructureProperty: { 4260 setNonCellTypeForNode(node, SpecBoolean); 4261 clobberWorld(); 4262 break; 4263 } 4264 case HasIndexedProperty: 4265 case HasEnumerableIndexedProperty: { 4254 4255 case HasIndexedProperty: { 4266 4256 ArrayMode mode = node->arrayMode(); 4267 4257 switch (mode.type()) { … … 4282 4272 break; 4283 4273 } 4284 case GetDirectPname: { 4285 clobberWorld(); 4286 makeHeapTopForNode(node); 4287 break; 4288 } 4274 4289 4275 case GetPropertyEnumerator: { 4290 4276 setTypeForNode(node, SpecCell); … … 4292 4278 break; 4293 4279 } 4294 case GetEnumeratorStructurePname: { 4280 4281 case EnumeratorNextUpdateIndexAndMode: { 4282 ArrayMode arrayMode = node->arrayMode(); 4283 if (arrayMode.isSaneChain()) 4284 ASSERT(node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode); 4285 else if (node->enumeratorMetadata() != JSPropertyNameEnumerator::OwnStructureMode || m_graph.varArgChild(node, 0).useKind() != CellUse) 4286 clobberWorld(); 4287 4288 setNonCellTypeForNode(node, SpecBytecodeNumber); 4289 break; 4290 } 4291 4292 case EnumeratorNextExtractMode: { 4293 if (node->child1()->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) { 4294 setConstant(node, jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::IndexedMode))); 4295 break; 4296 } 4297 4298 if (node->child1()->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && m_graph.varArgChild(node->child1().node(), 0).useKind() == CellUse) { 4299 setConstant(node, jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::OwnStructureMode))); 4300 break; 4301 } 4302 4303 FALLTHROUGH; 4304 } 4305 case EnumeratorNextExtractIndex: { 4306 setNonCellTypeForNode(node, SpecInt32Only); 4307 break; 4308 } 4309 4310 case EnumeratorNextUpdatePropertyName: { 4295 4311 setTypeForNode(node, SpecString | SpecOther); 4296 4312 break; 4297 4313 } 4298 case GetEnumeratorGenericPname: { 4299 setTypeForNode(node, SpecString | SpecOther); 4300 break; 4301 } 4302 case ToIndexString: { 4303 setTypeForNode(node, SpecString); 4314 4315 case EnumeratorInByVal: 4316 case EnumeratorHasOwnProperty: { 4317 // FIXME: We can determine when the property definitely exists based on abstract 4318 // value information. 4319 clobberWorld(); 4320 setNonCellTypeForNode(node, SpecBoolean); 4304 4321 break; 4305 4322 } -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h
r272170 r280760 288 288 { 289 289 return speculation() == Array::OutOfBoundsSaneChain; 290 } 291 292 bool isSaneChain() const 293 { 294 return isInBoundsSaneChain() || isOutOfBoundsSaneChain(); 290 295 } 291 296 -
trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
r261895 r280760 391 391 break; 392 392 } 393 393 394 case EnumeratorGetByVal: 394 395 case GetByVal: { 395 396 m_graph.varArgChild(node, 0)->mergeFlags(NodeBytecodeUsesAsValue); -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r279690 r280760 8388 8388 } 8389 8389 8390 case op_get_enumerable_length: {8391 auto bytecode = currentInstruction->as<OpGetEnumerableLength>();8392 set(bytecode.m_dst, addToGraph(GetEnumerableLength, get(bytecode.m_base)));8393 NEXT_OPCODE(op_get_enumerable_length);8394 }8395 8396 case op_has_enumerable_structure_property: {8397 auto bytecode = currentInstruction->as<OpHasEnumerableStructureProperty>();8398 set(bytecode.m_dst, addToGraph(HasEnumerableStructureProperty,8399 get(bytecode.m_base),8400 get(bytecode.m_property),8401 get(bytecode.m_enumerator)));8402 NEXT_OPCODE(op_has_enumerable_structure_property);8403 }8404 8405 case op_has_enumerable_property: {8406 auto bytecode = currentInstruction->as<OpHasEnumerableProperty>();8407 set(bytecode.m_dst, addToGraph(HasEnumerableProperty, get(bytecode.m_base), get(bytecode.m_property)));8408 NEXT_OPCODE(op_has_enumerable_property);8409 }8410 8411 case op_has_own_structure_property: {8412 auto bytecode = currentInstruction->as<OpHasOwnStructureProperty>();8413 set(bytecode.m_dst, addToGraph(HasOwnStructureProperty,8414 get(bytecode.m_base),8415 get(bytecode.m_property),8416 get(bytecode.m_enumerator)));8417 NEXT_OPCODE(op_has_own_structure_property);8418 }8419 8420 case op_in_structure_property: {8421 auto bytecode = currentInstruction->as<OpInStructureProperty>();8422 set(bytecode.m_dst, addToGraph(InStructureProperty,8423 get(bytecode.m_base),8424 get(bytecode.m_property),8425 get(bytecode.m_enumerator)));8426 NEXT_OPCODE(op_in_structure_property);8427 }8428 8429 case op_has_enumerable_indexed_property: {8430 auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();8431 Node* base = get(bytecode.m_base);8432 ArrayMode arrayMode = getArrayMode(bytecode.metadata(codeBlock).m_arrayProfile, Array::Read);8433 Node* property = get(bytecode.m_property);8434 addVarArgChild(base);8435 addVarArgChild(property);8436 addVarArgChild(nullptr);8437 Node* hasIterableProperty = addToGraph(Node::VarArg, HasEnumerableIndexedProperty, OpInfo(arrayMode.asWord()));8438 m_exitOK = false; // HasIndexedProperty must be treated as if it clobbers exit state, since FixupPhase may make it generic.8439 set(bytecode.m_dst, hasIterableProperty);8440 NEXT_OPCODE(op_has_enumerable_indexed_property);8441 }8442 8443 case op_get_direct_pname: {8444 auto bytecode = currentInstruction->as<OpGetDirectPname>();8445 SpeculatedType prediction = getPredictionWithoutOSRExit();8446 8447 Node* base = get(bytecode.m_base);8448 Node* property = get(bytecode.m_property);8449 Node* index = get(bytecode.m_index);8450 Node* enumerator = get(bytecode.m_enumerator);8451 8452 addVarArgChild(base);8453 addVarArgChild(property);8454 addVarArgChild(index);8455 addVarArgChild(enumerator);8456 set(bytecode.m_dst, addToGraph(Node::VarArg, GetDirectPname, OpInfo(0), OpInfo(prediction)));8457 8458 NEXT_OPCODE(op_get_direct_pname);8459 }8460 8461 8390 case op_get_property_enumerator: { 8462 8391 auto bytecode = currentInstruction->as<OpGetPropertyEnumerator>(); … … 8465 8394 } 8466 8395 8467 case op_enumerator_structure_pname: { 8468 auto bytecode = currentInstruction->as<OpEnumeratorStructurePname>(); 8469 set(bytecode.m_dst, addToGraph(GetEnumeratorStructurePname, 8470 get(bytecode.m_enumerator), 8471 get(bytecode.m_index))); 8472 NEXT_OPCODE(op_enumerator_structure_pname); 8473 } 8474 8475 case op_enumerator_generic_pname: { 8476 auto bytecode = currentInstruction->as<OpEnumeratorGenericPname>(); 8477 set(bytecode.m_dst, addToGraph(GetEnumeratorGenericPname, 8478 get(bytecode.m_enumerator), 8479 get(bytecode.m_index))); 8480 NEXT_OPCODE(op_enumerator_generic_pname); 8481 } 8482 8483 case op_to_index_string: { 8484 auto bytecode = currentInstruction->as<OpToIndexString>(); 8485 set(bytecode.m_dst, addToGraph(ToIndexString, get(bytecode.m_index))); 8486 NEXT_OPCODE(op_to_index_string); 8396 case op_enumerator_next: { 8397 auto bytecode = currentInstruction->as<OpEnumeratorNext>(); 8398 auto& metadata = bytecode.metadata(codeBlock); 8399 ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read); 8400 Node* base = get(bytecode.m_base); 8401 Node* index = get(bytecode.m_index); 8402 Node* enumerator = get(bytecode.m_enumerator); 8403 Node* mode = get(bytecode.m_mode); 8404 8405 auto seenModes = OptionSet<JSPropertyNameEnumerator::Mode>::fromRaw(metadata.m_enumeratorMetadata); 8406 8407 if (!seenModes) 8408 addToGraph(ForceOSRExit); 8409 8410 addVarArgChild(base); 8411 addVarArgChild(index); 8412 addVarArgChild(mode); 8413 addVarArgChild(enumerator); 8414 addVarArgChild(nullptr); // storage for IndexedMode only. 8415 Node* updatedIndexAndMode = addToGraph(Node::VarArg, EnumeratorNextUpdateIndexAndMode, OpInfo(arrayMode.asWord()), OpInfo(seenModes)); 8416 8417 Node* updatedMode = addToGraph(EnumeratorNextExtractMode, updatedIndexAndMode); 8418 set(bytecode.m_mode, updatedMode); 8419 8420 Node* updatedIndex = addToGraph(EnumeratorNextExtractIndex, updatedIndexAndMode); 8421 set(bytecode.m_index, updatedIndex); 8422 8423 set(bytecode.m_propertyName, addToGraph(EnumeratorNextUpdatePropertyName, OpInfo(), OpInfo(seenModes), updatedIndex, updatedMode, enumerator)); 8424 8425 NEXT_OPCODE(op_enumerator_next); 8426 } 8427 8428 case op_enumerator_get_by_val: { 8429 auto bytecode = currentInstruction->as<OpEnumeratorGetByVal>(); 8430 auto& metadata = bytecode.metadata(codeBlock); 8431 ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read); 8432 SpeculatedType speculation = getPredictionWithoutOSRExit(); 8433 8434 Node* base = get(bytecode.m_base); 8435 Node* propertyName = get(bytecode.m_propertyName); 8436 Node* index = get(bytecode.m_index); 8437 Node* mode = get(bytecode.m_mode); 8438 Node* enumerator = get(bytecode.m_enumerator); 8439 8440 auto seenModes = OptionSet<JSPropertyNameEnumerator::Mode>::fromRaw(metadata.m_enumeratorMetadata); 8441 if (!seenModes) 8442 addToGraph(ForceOSRExit); 8443 8444 if (seenModes == JSPropertyNameEnumerator::IndexedMode) { 8445 Node* badMode = addToGraph(ArithBitAnd, mode, jsConstant(jsNumber(JSPropertyNameEnumerator::GenericMode | JSPropertyNameEnumerator::OwnStructureMode))); 8446 8447 // We know the ArithBitAnd cannot have effects so it's ok to exit here. 8448 m_exitOK = true; 8449 addToGraph(ExitOK); 8450 8451 addToGraph(CheckIsConstant, OpInfo(m_graph.freezeStrong(jsNumber(0))), badMode); 8452 8453 addVarArgChild(base); 8454 addVarArgChild(index); // Use index so we'll use the normal indexed optimizations. 8455 addVarArgChild(nullptr); // For property storage to match GetByVal. 8456 set(bytecode.m_dst, addToGraph(Node::VarArg, GetByVal, OpInfo(arrayMode.asWord()), OpInfo(speculation))); 8457 8458 addToGraph(Phantom, propertyName); 8459 addToGraph(Phantom, enumerator); 8460 NEXT_OPCODE(op_enumerator_get_by_val); 8461 } 8462 8463 // FIXME: Checking for a BadConstantValue causes us to always use the Generic variant if we switched from IndexedMode -> IndexedMode + OwnStructureMode even though that might be fine. 8464 if (!seenModes.containsAny({ JSPropertyNameEnumerator::GenericMode, JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch }) 8465 && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantValue)) { 8466 Node* modeTest = addToGraph(SameValue, mode, jsConstant(jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::GenericMode)))); 8467 addToGraph(CheckIsConstant, OpInfo(m_graph.freezeStrong(jsBoolean(false))), modeTest); 8468 8469 addVarArgChild(base); 8470 addVarArgChild(index); // Use index so we'll use the normal indexed optimizations. 8471 addVarArgChild(nullptr); // For property storage to match GetByVal. 8472 addVarArgChild(index); 8473 addVarArgChild(mode); 8474 addVarArgChild(enumerator); 8475 set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorGetByVal, OpInfo(arrayMode.asWord()), OpInfo(speculation))); 8476 8477 addToGraph(Phantom, propertyName); 8478 NEXT_OPCODE(op_enumerator_get_by_val); 8479 } 8480 8481 addVarArgChild(base); 8482 addVarArgChild(propertyName); 8483 addVarArgChild(nullptr); // For property storage to match GetByVal. 8484 addVarArgChild(index); 8485 addVarArgChild(mode); 8486 addVarArgChild(enumerator); 8487 set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorGetByVal, OpInfo(arrayMode.asWord()), OpInfo(speculation))); 8488 8489 NEXT_OPCODE(op_enumerator_get_by_val); 8490 } 8491 8492 case op_enumerator_in_by_val: { 8493 auto bytecode = currentInstruction->as<OpEnumeratorInByVal>(); 8494 auto& metadata = bytecode.metadata(codeBlock); 8495 ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read); 8496 8497 addVarArgChild(get(bytecode.m_base)); 8498 addVarArgChild(get(bytecode.m_propertyName)); 8499 addVarArgChild(get(bytecode.m_index)); 8500 addVarArgChild(get(bytecode.m_mode)); 8501 addVarArgChild(get(bytecode.m_enumerator)); 8502 set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorInByVal, OpInfo(arrayMode.asWord()), OpInfo(metadata.m_enumeratorMetadata))); 8503 8504 NEXT_OPCODE(op_enumerator_in_by_val); 8505 } 8506 8507 case op_enumerator_has_own_property: { 8508 auto bytecode = currentInstruction->as<OpEnumeratorHasOwnProperty>(); 8509 auto& metadata = bytecode.metadata(codeBlock); 8510 ArrayMode arrayMode = getArrayMode(metadata.m_arrayProfile, Array::Read); 8511 8512 addVarArgChild(get(bytecode.m_base)); 8513 addVarArgChild(get(bytecode.m_propertyName)); 8514 addVarArgChild(get(bytecode.m_index)); 8515 addVarArgChild(get(bytecode.m_mode)); 8516 addVarArgChild(get(bytecode.m_enumerator)); 8517 set(bytecode.m_dst, addToGraph(Node::VarArg, EnumeratorHasOwnProperty, OpInfo(arrayMode.asWord()), OpInfo(metadata.m_enumeratorMetadata))); 8518 8519 NEXT_OPCODE(op_enumerator_has_own_property); 8487 8520 } 8488 8521 -
trunk/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
r278253 r280760 165 165 166 166 // This merges snapshot of stack values while CFA phase want to have proven types and values. This is somewhat tricky. 167 // But this is OK as long as DFG OSR entry validates the inputs with *proven* Abstrac Value values. And it turns out that this167 // But this is OK as long as DFG OSR entry validates the inputs with *proven* AbstractValue values. And it turns out that this 168 168 // type widening is critical to navier-stokes. Without it, navier-stokes has more strict constraint on OSR entry and 169 169 // fails OSR entry repeatedly. -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r277926 r280760 255 255 case op_get_scope: 256 256 case op_get_from_scope: 257 case op_get_enumerable_length:258 case op_has_enumerable_indexed_property:259 case op_has_enumerable_structure_property:260 case op_has_enumerable_property:261 case op_has_own_structure_property:262 case op_in_structure_property:263 case op_get_direct_pname:264 257 case op_get_property_enumerator: 265 case op_enumerator_structure_pname:266 case op_enumerator_generic_pname:267 case op_to_index_string:268 258 case op_new_func: 269 259 case op_new_func_exp: … … 300 290 case op_check_private_brand: 301 291 case op_switch_string: 292 case op_enumerator_next: 293 case op_enumerator_get_by_val: 294 case op_enumerator_in_by_val: 295 case op_enumerator_has_own_property: 302 296 return CanCompileAndInline; 303 297 -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r279604 r280760 148 148 case CheckArrayOrEmpty: 149 149 break; 150 case EnumeratorNextUpdateIndexAndMode: 151 case EnumeratorGetByVal: 152 case EnumeratorInByVal: 153 case EnumeratorHasOwnProperty: 150 154 case GetIndexedPropertyStorage: 151 155 case GetArrayLength: … … 165 169 case ArrayIndexOf: 166 170 case HasIndexedProperty: 167 case HasEnumerableIndexedProperty:168 171 case AtomicsAdd: 169 172 case AtomicsAnd: … … 338 341 return; 339 342 340 case GetEnumerableLength: { 341 read(Heap); 342 write(SideState); 343 return; 344 } 345 346 case ToIndexString: 347 case GetEnumeratorStructurePname: 348 case GetEnumeratorGenericPname: { 343 case EnumeratorNextUpdatePropertyName: { 344 def(PureValue(node, node->enumeratorMetadata().toRaw())); 345 return; 346 } 347 348 case EnumeratorNextExtractMode: 349 case EnumeratorNextExtractIndex: { 349 350 def(PureValue(node)); 350 351 return; 351 352 } 352 353 353 case HasIndexedProperty: 354 case HasEnumerableIndexedProperty: { 354 case EnumeratorNextUpdateIndexAndMode: { 355 read(JSObject_butterfly); 356 if (node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && graph.varArgChild(node, 0).useKind() == CellUse) { 357 read(NamedProperties); 358 read(JSCell_structureID); 359 return; 360 } 361 362 if (node->enumeratorMetadata() != JSPropertyNameEnumerator::IndexedMode) { 363 clobberTop(); 364 return; 365 } 366 367 ArrayMode mode = node->arrayMode(); 368 switch (mode.type()) { 369 case Array::ForceExit: { 370 write(SideState); 371 return; 372 } 373 case Array::Int32: { 374 if (mode.isSaneChain()) { 375 read(Butterfly_publicLength); 376 read(IndexedInt32Properties); 377 def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node)); 378 return; 379 } 380 break; 381 } 382 383 case Array::Double: { 384 if (mode.isSaneChain()) { 385 read(Butterfly_publicLength); 386 read(IndexedDoubleProperties); 387 def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node)); 388 return; 389 } 390 break; 391 } 392 393 case Array::Contiguous: { 394 if (mode.isSaneChain()) { 395 read(Butterfly_publicLength); 396 read(IndexedContiguousProperties); 397 def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, graph.varArgChild(node, 0), graph.varArgChild(node, 1)), LazyNode(node)); 398 return; 399 } 400 break; 401 } 402 403 case Array::ArrayStorage: { 404 if (mode.isInBounds()) { 405 read(Butterfly_vectorLength); 406 read(IndexedArrayStorageProperties); 407 return; 408 } 409 break; 410 } 411 412 default: 413 break; 414 } 415 416 clobberTop(); 417 return; 418 } 419 420 case HasIndexedProperty: { 355 421 read(JSObject_butterfly); 356 422 ArrayMode mode = node->arrayMode(); … … 706 772 case ToPropertyKey: 707 773 case InByVal: 774 case EnumeratorInByVal: 775 case EnumeratorHasOwnProperty: 708 776 case InById: 709 777 case HasPrivateName: … … 717 785 case ResolveScope: 718 786 case ToObject: 719 case HasEnumerableStructureProperty:720 case HasEnumerableProperty:721 case HasOwnStructureProperty:722 case InStructureProperty:723 787 case GetPropertyEnumerator: 724 case GetDirectPname:725 788 case InstanceOfCustom: 726 789 case ToNumber: … … 905 968 for (unsigned i = data->limit; i--;) 906 969 write(AbstractHeap(Stack, data->start + static_cast<int>(i))); 970 return; 971 } 972 973 case EnumeratorGetByVal: { 974 clobberTop(); 907 975 return; 908 976 } -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r279604 r280760 206 206 case GetByOffset: 207 207 case GetGetterSetterByOffset: 208 case GetEnumerableLength:209 208 case FiatInt52: 210 209 case BooleanToNumber: … … 298 297 case GetByIdWithThis: 299 298 case GetByValWithThis: 300 case GetDirectPname:301 299 case GetDynamicVar: 302 300 case GetMapBucket: 303 301 case HasIndexedProperty: 304 case HasEnumerableIndexedProperty:305 case HasEnumerableStructureProperty:306 case HasEnumerableProperty:307 302 case HasOwnProperty: 308 case HasOwnStructureProperty:309 case InStructureProperty:310 303 case InById: 311 304 case InByVal: … … 393 386 case ThrowStaticError: 394 387 case GetPropertyEnumerator: 395 case GetEnumeratorStructurePname: 396 case GetEnumeratorGenericPname: 397 case ToIndexString: 388 case EnumeratorInByVal: 389 case EnumeratorHasOwnProperty: 390 case EnumeratorNextUpdatePropertyName: 391 case EnumeratorNextUpdateIndexAndMode: 398 392 case MaterializeNewObject: 399 393 case MaterializeNewInternalFieldObject: … … 505 499 case GetIndexedPropertyStorage: 506 500 case GetByVal: 501 case EnumeratorGetByVal: 507 502 if (node->arrayMode().type() == Array::String) 508 503 return true; 504 return false; 505 506 case EnumeratorNextExtractMode: 507 case EnumeratorNextExtractIndex: 509 508 return false; 510 509 -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r279690 r280760 1025 1025 } 1026 1026 1027 case EnumeratorGetByVal: { 1028 fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 3)); 1029 fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 4)); 1030 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 5)); 1031 FALLTHROUGH; 1032 } 1033 1027 1034 case GetByVal: { 1028 1035 if (!node->prediction()) { … … 1063 1070 node->setArrayMode(ArrayMode(Array::Generic, node->arrayMode().action())); 1064 1071 break; 1072 1073 1074 case Array::ForceExit: { 1075 // Don't force OSR because we have only seen OwnStructureMode. 1076 // FIXME: WE should have a better way to do this... 1077 if (node->op() == EnumeratorGetByVal) 1078 node->setArrayMode(node->arrayMode().withType(Array::Generic)); 1079 break; 1080 } 1065 1081 default: 1066 1082 break; … … 1074 1090 case Array::Double: 1075 1091 case Array::Int32: { 1076 std::optional<Array::Speculation> saneChainSpeculation; 1077 if (arrayMode.isJSArrayWithOriginalStructure()) { 1078 // Check if InBoundsSaneChain will work on a per-type basis. Note that: 1079 // 1080 // 1) We don't want double arrays to sometimes return undefined, since 1081 // that would require a change to the return type and it would pessimise 1082 // things a lot. So, we'd only want to do that if we actually had 1083 // evidence that we could read from a hole. That's pretty annoying. 1084 // Likely the best way to handle that case is with an equivalent of 1085 // InBoundsSaneChain for OutOfBounds. For now we just detect when Undefined and 1086 // NaN are indistinguishable according to backwards propagation, and just 1087 // use InBoundsSaneChain in that case. This happens to catch a lot of cases. 1088 // 1089 // 2) We don't want int32 array loads to have to do a hole check just to 1090 // coerce to Undefined, since that would mean twice the checks. We want to 1091 // be able to say we always return Int32. FIXME: Maybe this should be profiling 1092 // based? 1093 // 1094 // This has two implications. First, we have to do more checks than we'd 1095 // like. It's unfortunate that we have to do the hole check. Second, 1096 // some accesses that hit a hole will now need to take the full-blown 1097 // out-of-bounds slow path. We can fix that with: 1098 // https://bugs.webkit.org/show_bug.cgi?id=144668 1099 1100 switch (arrayMode.type()) { 1101 case Array::Int32: 1102 if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex)) 1103 saneChainSpeculation = Array::OutOfBoundsSaneChain; 1104 break; 1105 case Array::Contiguous: 1106 // This is happens to be entirely natural. We already would have 1107 // returned any JSValue, and now we'll return Undefined. We still do 1108 // the check but it doesn't require taking any kind of slow path. 1109 if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex)) 1110 saneChainSpeculation = Array::OutOfBoundsSaneChain; 1111 else if (arrayMode.speculation() == Array::InBounds) 1112 saneChainSpeculation = Array::InBoundsSaneChain; 1113 break; 1114 1115 case Array::Double: 1116 if (!(node->flags() & NodeBytecodeUsesAsOther) && arrayMode.speculation() == Array::InBounds) { 1117 // Holes look like NaN already, so if the user doesn't care 1118 // about the difference between Undefined and NaN then we can 1119 // do this. 1120 saneChainSpeculation = Array::InBoundsSaneChain; 1121 } else if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex)) 1122 saneChainSpeculation = Array::OutOfBoundsSaneChain; 1123 break; 1124 1125 default: 1126 break; 1127 } 1128 } 1129 1130 if (saneChainSpeculation) 1131 setSaneChainIfPossible(node, *saneChainSpeculation); 1132 1092 setJSArraySaneChainIfPossible(node); 1133 1093 break; 1134 1094 } … … 1179 1139 break; 1180 1140 } 1181 1141 1142 // Don't set a non-JSValue result for EnumeratorGetByVal as the indexing mode doesn't tell us about the type of OwnStructure 1143 // properties. This isn't an issue for IndexedMode only as BytecodeParsing will emit a normal GetByVal if we've profiled that. 1144 if (node->op() == EnumeratorGetByVal) 1145 break; 1182 1146 switch (arrayMode.type()) { 1183 1147 case Array::Double: … … 2276 2240 } 2277 2241 2278 case GetEnumerableLength: { 2279 fixEdge<CellUse>(node->child1()); 2280 break; 2281 } 2282 case HasEnumerableProperty: { 2283 fixEdge<CellUse>(node->child2()); 2284 break; 2285 } 2286 case HasEnumerableStructureProperty: { 2287 fixEdge<StringUse>(node->child2()); 2288 fixEdge<KnownCellUse>(node->child3()); 2289 break; 2290 } 2291 case HasOwnStructureProperty: 2292 case InStructureProperty: { 2293 fixEdge<CellUse>(node->child1()); 2294 fixEdge<KnownStringUse>(node->child2()); 2295 fixEdge<KnownCellUse>(node->child3()); 2296 break; 2297 } 2298 case HasIndexedProperty: 2299 case HasEnumerableIndexedProperty: { 2242 case HasIndexedProperty: { 2300 2243 node->setArrayMode( 2301 2244 node->arrayMode().refine( … … 2316 2259 break; 2317 2260 } 2318 case GetDirectPname: { 2319 Edge& base = m_graph.varArgChild(node, 0); 2320 Edge& property = m_graph.varArgChild(node, 1); 2321 Edge& index = m_graph.varArgChild(node, 2); 2322 Edge& enumerator = m_graph.varArgChild(node, 3); 2323 fixEdge<CellUse>(base); 2324 fixEdge<KnownCellUse>(property); 2325 fixEdge<Int32Use>(index); 2326 fixEdge<KnownCellUse>(enumerator); 2327 break; 2328 } 2261 2329 2262 case GetPropertyEnumerator: { 2330 2263 if (node->child1()->shouldSpeculateCell()) … … 2332 2265 break; 2333 2266 } 2334 case GetEnumeratorStructurePname: { 2335 fixEdge<KnownCellUse>(node->child1()); 2336 fixEdge<Int32Use>(node->child2()); 2337 break; 2338 } 2339 case GetEnumeratorGenericPname: { 2340 fixEdge<KnownCellUse>(node->child1()); 2341 fixEdge<Int32Use>(node->child2()); 2342 break; 2343 } 2344 case ToIndexString: { 2345 fixEdge<Int32Use>(node->child1()); 2346 break; 2347 } 2267 2268 case EnumeratorNextUpdateIndexAndMode: { 2269 Edge& base = m_graph.varArgChild(node, 0); 2270 Edge& index = m_graph.varArgChild(node, 1); 2271 Edge& storageEdge = m_graph.varArgChild(node, node->storageChildIndex()); 2272 2273 if (node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) { 2274 node->setArrayMode( 2275 node->arrayMode().refine( 2276 m_graph, node, 2277 m_graph.varArgChild(node, 0)->prediction(), 2278 m_graph.varArgChild(node, 1)->prediction())); 2279 2280 fixEdge<CellUse>(base); 2281 blessArrayOperation(base, index, storageEdge); 2282 2283 ArrayMode arrayMode = node->arrayMode(); 2284 if (arrayMode.benefitsFromOriginalArray()) 2285 setSaneChainIfPossible(node, arrayMode.speculation() == Array::InBounds ? Array::InBoundsSaneChain : Array::OutOfBoundsSaneChain); 2286 } 2287 2288 if (node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && !m_graph.hasExitSite(node->origin.semantic, BadCache)) 2289 fixEdge<CellUse>(base); 2290 2291 fixEdge<KnownInt32Use>(index); 2292 fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 2)); 2293 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 3)); 2294 break; 2295 } 2296 2297 case EnumeratorNextExtractIndex: 2298 case EnumeratorNextExtractMode: { 2299 break; 2300 } 2301 2302 case EnumeratorNextUpdatePropertyName: { 2303 fixEdge<KnownInt32Use>(node->child1()); 2304 fixEdge<KnownInt32Use>(node->child2()); 2305 fixEdge<KnownCellUse>(node->child3()); 2306 break; 2307 } 2308 2309 case EnumeratorHasOwnProperty: 2310 case EnumeratorInByVal: { 2311 if (m_graph.varArgChild(node, 0)->shouldSpeculateCell()) 2312 fixEdge<CellUse>(m_graph.varArgChild(node, 0)); 2313 fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 2)); 2314 fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 3)); 2315 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 4)); 2316 break; 2317 } 2318 2348 2319 case ProfileType: { 2349 2320 // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet. … … 3691 3662 } 3692 3663 3664 void setJSArraySaneChainIfPossible(Node* node) 3665 { 3666 ArrayMode arrayMode = node->arrayMode(); 3667 std::optional<Array::Speculation> saneChainSpeculation; 3668 if (arrayMode.isJSArrayWithOriginalStructure()) { 3669 // Check if InBoundsSaneChain will work on a per-type basis. Note that: 3670 // 3671 // 1) We don't want double arrays to sometimes return undefined, since 3672 // that would require a change to the return type and it would pessimise 3673 // things a lot. So, we'd only want to do that if we actually had 3674 // evidence that we could read from a hole. That's pretty annoying. 3675 // Likely the best way to handle that case is with an equivalent of 3676 // InBoundsSaneChain for OutOfBounds. For now we just detect when Undefined and 3677 // NaN are indistinguishable according to backwards propagation, and just 3678 // use InBoundsSaneChain in that case. This happens to catch a lot of cases. 3679 // 3680 // 2) We don't want int32 array loads to have to do a hole check just to 3681 // coerce to Undefined, since that would mean twice the checks. We want to 3682 // be able to say we always return Int32. FIXME: Maybe this should be profiling 3683 // based? 3684 // 3685 // This has two implications. First, we have to do more checks than we'd 3686 // like. It's unfortunate that we have to do the hole check. Second, 3687 // some accesses that hit a hole will now need to take the full-blown 3688 // out-of-bounds slow path. We can fix that with: 3689 // https://bugs.webkit.org/show_bug.cgi?id=144668 3690 3691 switch (arrayMode.type()) { 3692 case Array::Int32: 3693 if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex)) 3694 saneChainSpeculation = Array::OutOfBoundsSaneChain; 3695 break; 3696 case Array::Contiguous: 3697 // This is happens to be entirely natural. We already would have 3698 // returned any JSValue, and now we'll return Undefined. We still do 3699 // the check but it doesn't require taking any kind of slow path. 3700 if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex)) 3701 saneChainSpeculation = Array::OutOfBoundsSaneChain; 3702 else if (arrayMode.speculation() == Array::InBounds) 3703 saneChainSpeculation = Array::InBoundsSaneChain; 3704 break; 3705 3706 case Array::Double: 3707 if (!(node->flags() & NodeBytecodeUsesAsOther) && arrayMode.speculation() == Array::InBounds) { 3708 // Holes look like NaN already, so if the user doesn't care 3709 // about the difference between Undefined and NaN then we can 3710 // do this. 3711 saneChainSpeculation = Array::InBoundsSaneChain; 3712 } else if (is64Bit() && arrayMode.speculation() == Array::OutOfBounds && !m_graph.hasExitSite(node->origin.semantic, NegativeIndex)) 3713 saneChainSpeculation = Array::OutOfBoundsSaneChain; 3714 break; 3715 3716 default: 3717 break; 3718 } 3719 } 3720 3721 if (saneChainSpeculation) 3722 setSaneChainIfPossible(node, *saneChainSpeculation); 3723 } 3724 3693 3725 void setSaneChainIfPossible(Node* node, Array::Speculation speculation) 3694 3726 { -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r278945 r280760 388 388 if (node->hasPutByIdStatus()) 389 389 out.print(comma, *node->putByIdStatus()); 390 if (node->hasEnumeratorMetadata()) 391 out.print(comma, "enumeratorModes = ", node->enumeratorMetadata().toRaw()); 390 392 if (node->isJump()) 391 393 out.print(comma, "T:", *node->targetBlock()); -
trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp
r269107 r280760 1345 1345 } 1346 1346 1347 case EnumeratorGetByVal: 1347 1348 case GetByVal: { 1348 1349 if (node->arrayMode().type() != Array::Undecided) … … 1381 1382 { 1382 1383 switch (node->op()) { 1384 // FIXME: Teach this about EnumeratorNextExtractIndex. 1383 1385 case CheckInBounds: { 1384 1386 setRelationship(Relationship::safeCreate(node->child1().node(), node->child2().node(), Relationship::LessThan)); -
trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp
r279604 r280760 112 112 case FilterCheckPrivateBrandStatus: 113 113 case FilterSetPrivateBrandStatus: 114 case EnumeratorNextExtractMode: 115 case EnumeratorNextExtractIndex: 114 116 break; 115 117 118 case EnumeratorNextUpdatePropertyName: 116 119 case StrCat: 117 120 case Call: -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r278696 r280760 53 53 #include "GetByVariant.h" 54 54 #include "JSCJSValue.h" 55 #include "JSPropertyNameEnumerator.h" 55 56 #include "Operands.h" 56 57 #include "PrivateFieldPutKind.h" … … 1765 1766 case ArithCeil: 1766 1767 case ArithTrunc: 1767 case GetDirectPname:1768 1768 case GetById: 1769 1769 case GetByIdFlush: … … 1773 1773 case GetPrototypeOf: 1774 1774 case TryGetById: 1775 case EnumeratorGetByVal: 1775 1776 case GetByVal: 1776 1777 case GetByValWithThis: … … 1942 1943 } 1943 1944 1945 bool hasStorageChild() const 1946 { 1947 switch (op()) { 1948 case StringCharAt: 1949 case StringCharCodeAt: 1950 case StringCodePointAt: 1951 case EnumeratorGetByVal: 1952 case GetByVal: 1953 case PutByValDirect: 1954 case PutByVal: 1955 case PutByValAlias: 1956 case AtomicsAdd: 1957 case AtomicsAnd: 1958 case AtomicsCompareExchange: 1959 case AtomicsExchange: 1960 case AtomicsLoad: 1961 case AtomicsOr: 1962 case AtomicsStore: 1963 case AtomicsSub: 1964 case AtomicsXor: 1965 case ArrayPush: 1966 case ArrayPop: 1967 case GetArrayLength: 1968 case HasIndexedProperty: 1969 case EnumeratorNextUpdateIndexAndMode: 1970 case ArrayIndexOf: 1971 return true; 1972 default: 1973 break; 1974 } 1975 return false; 1976 } 1977 1978 unsigned storageChildIndex() 1979 { 1980 ASSERT(hasStorageChild()); 1981 switch (op()) { 1982 case StringCharAt: 1983 case StringCharCodeAt: 1984 case StringCodePointAt: 1985 case EnumeratorGetByVal: 1986 case GetByVal: 1987 return 2; 1988 case PutByValDirect: 1989 case PutByVal: 1990 case PutByValAlias: 1991 return 3; 1992 case AtomicsAdd: 1993 case AtomicsAnd: 1994 case AtomicsCompareExchange: 1995 case AtomicsExchange: 1996 case AtomicsLoad: 1997 case AtomicsOr: 1998 case AtomicsStore: 1999 case AtomicsSub: 2000 case AtomicsXor: 2001 return 2 + numExtraAtomicsArgs(op()); 2002 case ArrayPush: 2003 return 0; 2004 2005 case ArrayPop: 2006 case GetArrayLength: 2007 return 2; 2008 2009 case HasIndexedProperty: 2010 return 2; 2011 2012 case EnumeratorNextUpdateIndexAndMode: 2013 return 4; 2014 2015 default: 2016 // FIXME: Add ArrayIndexOf but it does non-trivial things to determine storage edge. 2017 RELEASE_ASSERT_NOT_REACHED(); 2018 } 2019 } 2020 1944 2021 bool hasUidOperand() 1945 2022 { … … 2206 2283 case PutByValAlias: 2207 2284 case GetByVal: 2285 case EnumeratorNextUpdateIndexAndMode: 2286 case EnumeratorGetByVal: 2287 case EnumeratorInByVal: 2288 case EnumeratorHasOwnProperty: 2208 2289 case StringCharAt: 2209 2290 case StringCharCodeAt: … … 2217 2298 case ArrayIndexOf: 2218 2299 case HasIndexedProperty: 2219 case HasEnumerableIndexedProperty:2220 2300 case AtomicsAdd: 2221 2301 case AtomicsAnd: … … 3175 3255 } 3176 3256 3257 bool hasEnumeratorMetadata() const 3258 { 3259 switch (op()) { 3260 case EnumeratorNextUpdateIndexAndMode: 3261 case EnumeratorNextUpdatePropertyName: 3262 case EnumeratorHasOwnProperty: 3263 case EnumeratorInByVal: 3264 return true; 3265 default: 3266 return false; 3267 } 3268 } 3269 3270 OptionSet<JSPropertyNameEnumerator::Mode> enumeratorMetadata() 3271 { 3272 ASSERT(hasEnumeratorMetadata()); 3273 return OptionSet<JSPropertyNameEnumerator::Mode>::fromRaw(m_opInfo2.as<unsigned>()); 3274 } 3275 3177 3276 void dumpChildren(PrintStream& out) 3178 3277 { -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r279604 r280760 502 502 macro(FencedStoreBarrier, NodeMustGenerate) \ 503 503 \ 504 /* For-in enumeration opcodes */\505 macro(GetEnumerableLength, NodeMustGenerate | NodeResultJS) \506 504 /* Must generate because of Proxies on the prototype chain */ \ 507 505 macro(HasIndexedProperty, NodeMustGenerate | NodeResultBoolean | NodeHasVarArgs) \ 508 macro(HasEnumerableIndexedProperty, NodeMustGenerate | NodeResultBoolean | NodeHasVarArgs) \ 509 macro(HasEnumerableStructureProperty, NodeResultBoolean) \ 510 macro(HasEnumerableProperty, NodeResultBoolean) \ 511 macro(HasOwnStructureProperty, NodeResultBoolean | NodeMustGenerate) \ 512 macro(InStructureProperty, NodeMustGenerate | NodeResultBoolean) \ 513 macro(GetDirectPname, NodeMustGenerate | NodeHasVarArgs | NodeResultJS) \ 506 /* For-in enumeration opcodes */\ 514 507 macro(GetPropertyEnumerator, NodeMustGenerate | NodeResultJS) \ 515 macro(GetEnumeratorStructurePname, NodeMustGenerate | NodeResultJS) \ 516 macro(GetEnumeratorGenericPname, NodeMustGenerate | NodeResultJS) \ 517 macro(ToIndexString, NodeResultJS) \ 508 macro(EnumeratorNextUpdateIndexAndMode, NodeResultJS | NodeHasVarArgs) \ 509 macro(EnumeratorNextExtractMode, NodeResultInt32) \ 510 macro(EnumeratorNextExtractIndex, NodeResultInt32) \ 511 macro(EnumeratorNextUpdatePropertyName, NodeResultJS) \ 512 macro(EnumeratorGetByVal, NodeResultJS | NodeHasVarArgs | NodeMustGenerate) \ 513 macro(EnumeratorInByVal, NodeResultBoolean | NodeHasVarArgs | NodeMustGenerate) \ 514 macro(EnumeratorHasOwnProperty, NodeResultBoolean | NodeHasVarArgs | NodeMustGenerate) \ 518 515 /* Nodes for JSMap and JSSet */ \ 519 516 macro(MapHash, NodeResultInt32) \ -
trunk/Source/JavaScriptCore/dfg/DFGOpInfo.h
r267489 r280760 30 30 #include "HeapCell.h" 31 31 #include "PrivateFieldPutKind.h" 32 #include <wtf/OptionSet.h> 32 33 #include <wtf/StdLibExtras.h> 33 34 … … 51 52 explicit OpInfo(ECMAMode ecmaMode) : m_value(ecmaMode.value()) { } 52 53 explicit OpInfo(PrivateFieldPutKind putKind) : m_value(putKind.value()) { } 54 template<typename EnumType> 55 explicit OpInfo(OptionSet<EnumType> optionSet) : m_value(optionSet.toRaw()) { } 53 56 54 57 template <typename T> -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r280060 r280760 2400 2400 } 2401 2401 2402 JSC_DEFINE_JIT_OPERATION(operationHasEnumerableProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, JSCell* property))2403 {2404 VM& vm = globalObject->vm();2405 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);2406 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);2407 auto scope = DECLARE_THROW_SCOPE(vm);2408 2409 JSValue baseValue = JSValue::decode(encodedBaseValue);2410 if (baseValue.isUndefinedOrNull())2411 return JSValue::encode(jsBoolean(false));2412 2413 JSObject* base = baseValue.toObject(globalObject);2414 EXCEPTION_ASSERT(!scope.exception() || !base);2415 if (!base)2416 return JSValue::encode(JSValue());2417 auto propertyName = asString(property)->toIdentifier(globalObject);2418 RETURN_IF_EXCEPTION(scope, { });2419 RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName))));2420 }2421 2422 JSC_DEFINE_JIT_OPERATION(operationInStructureProperty, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, JSString* property))2423 {2424 VM& vm = globalObject->vm();2425 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);2426 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);2427 2428 return JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, property)));2429 }2430 2431 JSC_DEFINE_JIT_OPERATION(operationHasOwnStructureProperty, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, JSString* property))2432 {2433 VM& vm = globalObject->vm();2434 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);2435 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);2436 2437 auto scope = DECLARE_THROW_SCOPE(vm);2438 auto propertyName = property->toIdentifier(globalObject);2439 RETURN_IF_EXCEPTION(scope, { });2440 scope.release();2441 return JSValue::encode(jsBoolean(objectPrototypeHasOwnProperty(globalObject, base, propertyName)));2442 }2443 2444 2402 JSC_DEFINE_JIT_OPERATION(operationHasIndexedProperty, size_t, (JSGlobalObject* globalObject, JSCell* baseCell, int32_t subscript)) 2445 2403 { … … 2498 2456 } 2499 2457 2500 JSC_DEFINE_JIT_OPERATION(operationToIndexString, JSCell*, (JSGlobalObject* globalObject, int32_t index)) 2501 { 2502 VM& vm = globalObject->vm(); 2503 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 2504 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 2505 return jsString(vm, Identifier::from(vm, index).string()); 2458 JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdateIndexAndMode, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator)) 2459 { 2460 VM& vm = globalObject->vm(); 2461 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 2462 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 2463 auto scope = DECLARE_THROW_SCOPE(vm); 2464 2465 JSPropertyNameEnumerator::Mode mode = static_cast<JSPropertyNameEnumerator::Mode>(modeNumber); 2466 if (JSValue::decode(baseValue).isUndefinedOrNull()) { 2467 ASSERT(mode == JSPropertyNameEnumerator::InitMode); 2468 ASSERT(!index); 2469 ASSERT(!enumerator->sizeOfPropertyNames()); 2470 mode = JSPropertyNameEnumerator::GenericMode; 2471 } else { 2472 JSObject* base = JSValue::decode(baseValue).toObject(globalObject); 2473 RETURN_IF_EXCEPTION(scope, { }); 2474 2475 constexpr bool shouldAllocateIndexedNameString = false; 2476 enumerator->computeNext(globalObject, base, index, mode, shouldAllocateIndexedNameString); 2477 RETURN_IF_EXCEPTION(scope, { }); 2478 } 2479 2480 #if USE(JSVALUE64) 2481 JSValue result = bitwise_cast<JSValue>(static_cast<uint64_t>(mode) << 32 | index | JSValue::DoubleEncodeOffset); 2482 #else 2483 JSValue result = JSValue(mode, index); 2484 #endif 2485 ASSERT(result.isDouble()); 2486 return JSValue::encode(result); 2487 } 2488 2489 JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator)) 2490 { 2491 VM& vm = globalObject->vm(); 2492 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 2493 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 2494 2495 if (modeNumber == JSPropertyNameEnumerator::IndexedMode) { 2496 if (index < enumerator->indexedLength()) 2497 return JSValue::encode(jsString(vm, Identifier::from(vm, index).string())); 2498 return JSValue::encode(jsNull()); 2499 } 2500 2501 JSString* result = enumerator->propertyNameAtIndex(index); 2502 if (!result) 2503 return JSValue::encode(jsNull()); 2504 2505 return JSValue::encode(result); 2506 } 2507 2508 JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator)) 2509 { 2510 VM& vm = globalObject->vm(); 2511 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 2512 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 2513 auto scope = DECLARE_THROW_SCOPE(vm); 2514 2515 JSString* string = enumerator->propertyNameAtIndex(index); 2516 PropertyName propertyName = string->toIdentifier(globalObject); 2517 // This should only really return for TerminationException since we know string is backed by a UUID. 2518 RETURN_IF_EXCEPTION(scope, { }); 2519 JSObject* object = base->toObject(globalObject); 2520 RETURN_IF_EXCEPTION(scope, { }); 2521 2522 RELEASE_AND_RETURN(scope, JSValue::encode(object->get(globalObject, propertyName))); 2523 } 2524 2525 JSC_DEFINE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber)) 2526 { 2527 VM& vm = globalObject->vm(); 2528 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 2529 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 2530 auto scope = DECLARE_THROW_SCOPE(vm); 2531 2532 JSValue base = JSValue::decode(baseValue); 2533 RETURN_IF_EXCEPTION(scope, { }); 2534 if (modeNumber == JSPropertyNameEnumerator::IndexedMode && base.isObject()) 2535 return JSValue::encode(jsBoolean(jsCast<JSObject*>(base)->hasProperty(globalObject, index))); 2536 2537 JSString* propertyName = jsSecureCast<JSString*>(vm, JSValue::decode(propertyNameValue)); 2538 RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, propertyName)))); 2539 } 2540 2541 JSC_DEFINE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber)) 2542 { 2543 VM& vm = globalObject->vm(); 2544 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 2545 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 2546 auto scope = DECLARE_THROW_SCOPE(vm); 2547 2548 JSValue base = JSValue::decode(baseValue); 2549 RETURN_IF_EXCEPTION(scope, { }); 2550 if (modeNumber == JSPropertyNameEnumerator::IndexedMode && base.isObject()) 2551 return JSValue::encode(jsBoolean(jsCast<JSObject*>(base)->hasOwnProperty(globalObject, index))); 2552 2553 JSString* propertyName = jsSecureCast<JSString*>(vm, JSValue::decode(propertyNameValue)); 2554 auto identifier = propertyName->toIdentifier(globalObject); 2555 RETURN_IF_EXCEPTION(scope, { }); 2556 RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(objectPrototypeHasOwnProperty(globalObject, base, identifier)))); 2506 2557 } 2507 2558 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r279690 r280760 37 37 class JSBigInt; 38 38 struct UnlinkedStringJumpTable; 39 class JSPropertyNameEnumerator; 39 40 40 41 namespace DFG { … … 105 106 JSC_DECLARE_JIT_OPERATION(operationHasIndexedProperty, size_t, (JSGlobalObject*, JSCell*, int32_t)); 106 107 JSC_DECLARE_JIT_OPERATION(operationHasEnumerableIndexedProperty, size_t, (JSGlobalObject*, JSCell*, int32_t)); 107 JSC_DECLARE_JIT_OPERATION(operationHasEnumerableProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, JSCell*));108 JSC_DECLARE_JIT_OPERATION(operationHasOwnStructureProperty, EncodedJSValue, (JSGlobalObject*, JSCell*, JSString*));109 JSC_DECLARE_JIT_OPERATION(operationInStructureProperty, EncodedJSValue, (JSGlobalObject*, JSCell*, JSString*));110 108 JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumerator, JSCell*, (JSGlobalObject*, EncodedJSValue)); 111 109 JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumeratorCell, JSCell*, (JSGlobalObject*, JSCell*)); 112 JSC_DECLARE_JIT_OPERATION(operationToIndexString, JSCell*, (JSGlobalObject*, int32_t)); 110 JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdateIndexAndMode, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*)); 111 JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*)); 112 JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t)); 113 JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t)); 114 JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, uint32_t, JSPropertyNameEnumerator*)); 115 113 116 JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue)); 114 117 JSC_DECLARE_JIT_OPERATION(operationNewArray, char*, (JSGlobalObject*, Structure*, void*, size_t)); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r279604 r280760 474 474 if (!child1->prediction()) 475 475 break; 476 476 477 477 Edge child2 = m_graph.child(node, 1); 478 478 ArrayMode arrayMode = node->arrayMode().refine( … … 481 481 child2->prediction(), 482 482 SpecNone); 483 483 484 484 switch (arrayMode.type()) { 485 485 case Array::Int32: … … 863 863 } 864 864 865 case EnumeratorGetByVal: 865 866 case ArrayPop: 866 867 case ArrayPush: … … 883 884 case GetPrivateNameById: 884 885 case MultiGetByOffset: 885 case GetDirectPname:886 886 case Call: 887 887 case DirectCall: … … 1206 1206 break; 1207 1207 1208 case GetEnumerableLength: { 1208 case EnumeratorNextExtractMode: 1209 case EnumeratorNextExtractIndex: { 1209 1210 setPrediction(SpecInt32Only); 1210 1211 break; 1211 1212 } 1213 1214 case EnumeratorInByVal: 1215 case EnumeratorHasOwnProperty: 1212 1216 case InByVal: 1213 1217 case InById: … … 1215 1219 case HasPrivateBrand: 1216 1220 case HasOwnProperty: 1217 case HasOwnStructureProperty: 1218 case InStructureProperty: 1219 case HasIndexedProperty: 1220 case HasEnumerableIndexedProperty: 1221 case HasEnumerableStructureProperty: 1222 case HasEnumerableProperty: { 1221 case HasIndexedProperty: { 1223 1222 setPrediction(SpecBoolean); 1224 1223 break; … … 1228 1227 break; 1229 1228 } 1230 case GetEnumeratorStructurePname: { 1231 setPrediction(SpecCell | SpecOther); 1232 break; 1233 } 1234 case GetEnumeratorGenericPname: { 1235 setPrediction(SpecCell | SpecOther); 1236 break; 1237 } 1238 case ToIndexString: { 1239 setPrediction(SpecString); 1240 break; 1241 } 1229 1230 case EnumeratorNextUpdateIndexAndMode: { 1231 setPrediction(SpecFullNumber); 1232 break; 1233 } 1234 1235 case EnumeratorNextUpdatePropertyName: { 1236 setPrediction(SpecString | SpecOther); 1237 break; 1238 } 1239 1242 1240 case ParseInt: { 1243 1241 // We expect this node to almost always produce an int32. However, -
trunk/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp
r270874 r280760 83 83 84 84 case HasIndexedProperty: 85 case HasEnumerableIndexedProperty:86 85 lowerBoundsCheck(m_graph.child(m_node, 0), m_graph.child(m_node, 1), m_graph.child(m_node, 2)); 87 86 break; 88 87 88 case EnumeratorGetByVal: 89 89 case GetByVal: { 90 90 lowerBoundsCheck(m_graph.varArgChild(m_node, 0), m_graph.varArgChild(m_node, 1), m_graph.varArgChild(m_node, 2)); -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r279604 r280760 297 297 case FiatInt52: 298 298 case HasIndexedProperty: 299 case HasEnumerableIndexedProperty:300 case GetEnumeratorStructurePname:301 case GetEnumeratorGenericPname:302 case ToIndexString:303 299 case CheckStructureImmediate: 304 300 case GetMyArgumentByVal: … … 373 369 return false; 374 370 371 case EnumeratorGetByVal: 375 372 case GetByVal: 376 373 case GetIndexedPropertyStorage: … … 497 494 } 498 495 496 case EnumeratorNextUpdateIndexAndMode: 497 // These technically don't have effects but they'll only ever follow a EnumeratorNextUpdateIndexAndMode so we might as well return false. 498 case EnumeratorNextExtractMode: 499 case EnumeratorNextExtractIndex: 500 case EnumeratorNextUpdatePropertyName: 499 501 case ToThis: 500 502 case CreateThis: … … 596 598 case InByVal: 597 599 case InById: 600 case EnumeratorInByVal: 601 case EnumeratorHasOwnProperty: 598 602 case HasPrivateName: 599 603 case HasPrivateBrand: … … 640 644 case MultiPutByOffset: 641 645 case MultiDeleteByOffset: 642 case GetEnumerableLength:643 case HasEnumerableStructureProperty:644 case HasEnumerableProperty:645 case HasOwnStructureProperty:646 case InStructureProperty:647 case GetDirectPname:648 646 case GetPropertyEnumerator: 649 647 case PhantomNewObject: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r280716 r280760 1638 1638 } 1639 1639 1640 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, GPRReg specificPayload) 1640 1641 #if USE(JSVALUE64) 1641 template<typename T> 1642 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord) 1643 : m_gpr(jit, Reuse, operand) 1644 { 1645 } 1642 : m_gpr(jit, specificPayload) 1646 1643 #else 1647 template<typename T> 1648 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord resultWord) 1649 { 1650 if (resultWord == PayloadWord) { 1651 m_payloadGPR = GPRTemporary(jit, Reuse, operand); 1652 m_tagGPR = GPRTemporary(jit); 1653 } else { 1654 m_payloadGPR = GPRTemporary(jit); 1655 m_tagGPR = GPRTemporary(jit, Reuse, operand); 1656 } 1657 } 1644 : m_payloadGPR(jit, specificPayload) 1645 , m_tagGPR(jit) 1658 1646 #endif 1647 { 1648 } 1659 1649 1660 1650 #if USE(JSVALUE64) … … 2598 2588 } 2599 2589 2600 void SpeculativeJIT::compileGetByValOnString(Node* node )2590 void SpeculativeJIT::compileGetByValOnString(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 2601 2591 { 2602 2592 SpeculateCellOperand base(this, m_graph.child(node, 0)); … … 2607 2597 GPRReg storageReg = storage.gpr(); 2608 2598 2609 GPRTemporary scratch(this); 2610 GPRReg scratchReg = scratch.gpr(); 2611 #if USE(JSVALUE32_64) 2612 GPRTemporary resultTag; 2613 GPRReg resultTagReg = InvalidGPRReg; 2614 if (node->arrayMode().isOutOfBounds()) { 2615 GPRTemporary realResultTag(this); 2616 resultTag.adopt(realResultTag); 2617 resultTagReg = resultTag.gpr(); 2618 } 2619 #endif 2599 JSValueRegs resultRegs; 2600 DataFormat format; 2601 std::tie(resultRegs, format) = prefix(node->arrayMode().isOutOfBounds() ? DataFormatJS : DataFormatCell); 2602 GPRReg scratchReg = resultRegs.payloadGPR(); 2620 2603 2621 2604 // unsigned comparison so we can filter out negative indices and indices that are too large … … 2653 2636 2654 2637 if (node->arrayMode().isOutOfBounds()) { 2638 ASSERT(format == DataFormatJS); 2655 2639 #if USE(JSVALUE32_64) 2656 m_jit.move(TrustedImm32(JSValue::CellTag), result TagReg);2640 m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR()); 2657 2641 #endif 2658 2642 … … 2672 2656 m_jit.graph().registerAndWatchStructureTransition(objectPrototypeStructure); 2673 2657 2674 #if USE(JSVALUE64)2675 2658 addSlowPathGenerator(makeUnique<SaneStringGetByValSlowPathGenerator>( 2676 outOfBounds, this, JSValueRegs(scratchReg), TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg)); 2677 #else 2678 addSlowPathGenerator(makeUnique<SaneStringGetByValSlowPathGenerator>( 2679 outOfBounds, this, JSValueRegs(resultTagReg, scratchReg), TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg)); 2680 #endif 2659 outOfBounds, this, resultRegs, TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg)); 2681 2660 } else { 2682 #if USE(JSVALUE64)2683 2661 addSlowPathGenerator( 2684 2662 slowPathCall( 2685 2663 outOfBounds, this, operationGetByValStringInt, 2686 scratchReg, TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg)); 2687 #else 2688 addSlowPathGenerator( 2689 slowPathCall( 2690 outOfBounds, this, operationGetByValStringInt, 2691 JSValueRegs(resultTagReg, scratchReg), TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg)); 2692 #endif 2693 } 2694 2695 #if USE(JSVALUE64) 2696 jsValueResult(scratchReg, m_currentNode); 2697 #else 2698 jsValueResult(resultTagReg, scratchReg, m_currentNode); 2699 #endif 2700 } else 2701 cellResult(scratchReg, m_currentNode); 2664 resultRegs, TrustedImmPtr::weakPointer(m_graph, globalObject), baseReg, propertyReg)); 2665 } 2666 2667 jsValueResult(resultRegs, m_currentNode); 2668 } else { 2669 if (format == DataFormatJS) 2670 jsValueResult(resultRegs, m_currentNode); 2671 else { 2672 ASSERT(format == DataFormatCell); 2673 cellResult(resultRegs.payloadGPR(), m_currentNode); 2674 } 2675 } 2702 2676 } 2703 2677 … … 3352 3326 } 3353 3327 3354 void SpeculativeJIT::setIntTypedArrayLoadResult(Node* node, GPRReg resultReg, TypedArrayType type, bool canSpeculate) 3355 { 3356 if (elementSize(type) < 4 || isSigned(type)) { 3328 void SpeculativeJIT::setIntTypedArrayLoadResult(Node* node, JSValueRegs resultRegs, TypedArrayType type, bool canSpeculate, bool shouldBox) 3329 { 3330 bool isUInt32 = elementSize(type) == 4 && !isSigned(type); 3331 GPRReg resultReg = resultRegs.payloadGPR(); 3332 3333 if (shouldBox) { 3334 if (isUInt32) { 3335 FPRTemporary fresult(this); 3336 m_jit.convertInt32ToDouble(resultReg, fresult.fpr()); 3337 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0)); 3338 m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr()); 3339 positive.link(&m_jit); 3340 m_jit.boxDouble(fresult.fpr(), resultRegs); 3341 } else 3342 m_jit.boxInt32(resultRegs.payloadGPR(), resultRegs); 3343 jsValueResult(resultRegs, node); 3344 return; 3345 } 3346 3347 if (!isUInt32) { 3348 ASSERT(elementSize(type) < 4 || isSigned(type)); 3357 3349 strictInt32Result(resultReg, node); 3358 3350 return; 3359 3351 } 3360 3361 ASSERT(elementSize(type) == 4 && !isSigned(type)); 3352 3362 3353 if (node->shouldSpeculateInt32() && canSpeculate) { 3363 3354 speculationCheck(Overflow, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0))); … … 3383 3374 } 3384 3375 3385 void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type )3376 void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 3386 3377 { 3387 3378 ASSERT(isInt(type)); … … 3395 3386 GPRReg storageReg = storage.gpr(); 3396 3387 3397 GPRTemporary result(this); 3398 GPRReg resultReg = result.gpr(); 3388 JSValueRegs resultRegs; 3389 DataFormat format; 3390 std::tie(resultRegs, format) = prefix(DataFormatInt32); 3391 bool shouldBox = format == DataFormatJS; 3399 3392 3400 3393 emitTypedArrayBoundsCheck(node, baseReg, propertyReg); 3401 loadFromIntTypedArray(storageReg, propertyReg, resultReg , type);3394 loadFromIntTypedArray(storageReg, propertyReg, resultRegs.payloadGPR(), type); 3402 3395 constexpr bool canSpeculate = true; 3403 setIntTypedArrayLoadResult(node, resultReg , type, canSpeculate);3396 setIntTypedArrayLoadResult(node, resultRegs, type, canSpeculate, shouldBox); 3404 3397 } 3405 3398 … … 3639 3632 } 3640 3633 3641 void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType type )3634 void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType type, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 3642 3635 { 3643 3636 ASSERT(isFloat(type)); … … 3650 3643 GPRReg propertyReg = property.gpr(); 3651 3644 GPRReg storageReg = storage.gpr(); 3645 3646 JSValueRegs resultRegs; 3647 DataFormat format; 3648 std::tie(resultRegs, format) = prefix(DataFormatDouble); 3652 3649 3653 3650 FPRTemporary result(this); … … 3667 3664 } 3668 3665 3669 doubleResult(resultReg, node); 3666 if (format == DataFormatJS) { 3667 m_jit.boxDouble(resultReg, resultRegs); 3668 jsValueResult(resultRegs, node); 3669 } else { 3670 ASSERT(format == DataFormatDouble); 3671 doubleResult(resultReg, node); 3672 } 3670 3673 } 3671 3674 … … 3706 3709 } 3707 3710 3708 void SpeculativeJIT::compileGetByValForObjectWithString(Node* node )3711 void SpeculativeJIT::compileGetByValForObjectWithString(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 3709 3712 { 3710 3713 SpeculateCellOperand arg1(this, m_graph.varArgChild(node, 0)); … … 3714 3717 GPRReg arg2GPR = arg2.gpr(); 3715 3718 3719 JSValueRegs resultRegs; 3720 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 3721 3716 3722 speculateObject(m_graph.varArgChild(node, 0), arg1GPR); 3717 3723 speculateString(m_graph.varArgChild(node, 1), arg2GPR); 3718 3724 3719 3725 flushRegisters(); 3720 JSValueRegsFlushedCallResult result(this);3721 JSValueRegs resultRegs = result.regs();3722 3726 callOperation(operationGetByValObjectString, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR); 3723 3727 m_jit.exceptionCheck(); … … 3726 3730 } 3727 3731 3728 void SpeculativeJIT::compileGetByValForObjectWithSymbol(Node* node )3732 void SpeculativeJIT::compileGetByValForObjectWithSymbol(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 3729 3733 { 3730 3734 SpeculateCellOperand arg1(this, m_graph.varArgChild(node, 0)); … … 3734 3738 GPRReg arg2GPR = arg2.gpr(); 3735 3739 3740 JSValueRegs resultRegs; 3741 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 3742 3736 3743 speculateObject(m_graph.varArgChild(node, 0), arg1GPR); 3737 3744 speculateSymbol(m_graph.varArgChild(node, 1), arg2GPR); 3738 3745 3739 3746 flushRegisters(); 3740 JSValueRegsFlushedCallResult result(this);3741 JSValueRegs resultRegs = result.regs();3742 3747 callOperation(operationGetByValObjectSymbol, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR); 3743 3748 m_jit.exceptionCheck(); … … 8041 8046 } 8042 8047 8043 void SpeculativeJIT::compileGetByValOnDirectArguments(Node* node )8048 void SpeculativeJIT::compileGetByValOnDirectArguments(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 8044 8049 { 8045 8050 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 8046 8051 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 8047 JSValueRegsTemporary result(this);8048 GPRTemporary scratch(this);8049 8052 8050 8053 GPRReg baseReg = base.gpr(); 8051 8054 GPRReg propertyReg = property.gpr(); 8052 JSValueRegs resultRegs = result.regs(); 8053 GPRReg scratchReg = scratch.gpr(); 8055 8056 JSValueRegs resultRegs; 8057 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 8058 GPRReg scratchReg = resultRegs.payloadGPR(); 8054 8059 8055 8060 if (!m_compileOkay) … … 8082 8087 } 8083 8088 8084 void SpeculativeJIT::compileGetByValOnScopedArguments(Node* node )8089 void SpeculativeJIT::compileGetByValOnScopedArguments(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 8085 8090 { 8086 8091 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 8087 8092 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 8088 JSValueRegsTemporary result(this);8089 8093 GPRTemporary scratch(this); 8090 8094 GPRTemporary scratch2(this); … … 8092 8096 GPRReg baseReg = base.gpr(); 8093 8097 GPRReg propertyReg = property.gpr(); 8094 JSValueRegs resultRegs = result.regs();8095 8098 GPRReg scratchReg = scratch.gpr(); 8096 8099 GPRReg scratch2Reg = scratch2.gpr(); … … 8098 8101 if (!m_compileOkay) 8099 8102 return; 8103 8104 JSValueRegs resultRegs; 8105 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 8100 8106 8101 8107 m_jit.loadPtr( … … 13445 13451 } 13446 13452 13447 void SpeculativeJIT::compileGetEnumerableLength(Node* node) 13448 { 13449 SpeculateCellOperand enumerator(this, node->child1()); 13450 GPRTemporary result(this, Reuse, enumerator); 13453 void SpeculativeJIT::compileEnumeratorNextUpdateIndexAndMode(Node* node) 13454 { 13455 Edge baseEdge = m_graph.varArgChild(node, 0); 13456 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1)); 13457 SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 2)); 13458 SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 3)); 13459 13460 GPRReg indexGPR = index.gpr(); 13461 GPRReg modeGPR = mode.gpr(); 13451 13462 GPRReg enumeratorGPR = enumerator.gpr(); 13452 GPRReg resultGPR = result.gpr(); 13453 13454 m_jit.load32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::indexedLengthOffset()), resultGPR); 13455 strictInt32Result(resultGPR, node); 13456 } 13457 13458 void SpeculativeJIT::compileHasEnumerableProperty(Node* node) 13459 { 13460 JSValueOperand base(this, node->child1()); 13461 SpeculateCellOperand property(this, node->child2()); 13462 13463 JSValueRegs baseRegs = base.jsValueRegs(); 13464 GPRReg propertyGPR = property.gpr(); 13463 13464 if (node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) { 13465 JSValueRegsTemporary result(this); 13466 GPRTemporary scratch(this, Reuse, index); 13467 JSValueRegs resultRegs = result.regs(); 13468 13469 speculationCheck(BadCache, JSValueSource(), node, m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()), TrustedImm32(0))); 13470 13471 MacroAssembler::Label incrementLoop; 13472 MacroAssembler::Jump done; 13473 compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty, scopedLambda<std::tuple<GPRReg, GPRReg>()>([&] { 13474 13475 m_jit.move(indexGPR, scratch.gpr()); 13476 MacroAssembler::Jump initMode = m_jit.branchTest32(MacroAssembler::Zero, modeGPR); 13477 13478 incrementLoop = m_jit.label(); 13479 m_jit.add32(TrustedImm32(1), scratch.gpr()); 13480 13481 initMode.link(&m_jit); 13482 done = m_jit.branch32(MacroAssembler::AboveOrEqual, scratch.gpr(), MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::indexedLengthOffset())); 13483 return std::make_pair(scratch.gpr(), resultRegs.payloadGPR()); 13484 })); 13485 m_jit.branchTest32(MacroAssembler::Zero, resultRegs.payloadGPR()).linkTo(incrementLoop, &m_jit); 13486 13487 done.link(&m_jit); 13488 13489 #if USE(JSVALUE64) 13490 m_jit.move(TrustedImm64(JSValue::DoubleEncodeOffset | static_cast<uint64_t>(JSPropertyNameEnumerator::IndexedMode) << 32), resultRegs.payloadGPR()); 13491 m_jit.or64(scratch.gpr(), resultRegs.payloadGPR()); 13492 #else 13493 m_jit.move(TrustedImm32(JSPropertyNameEnumerator::IndexedMode), resultRegs.tagGPR()); 13494 #endif 13495 13496 jsValueResult(resultRegs, node); 13497 return; 13498 } 13499 13500 if (node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && baseEdge.useKind() == CellUse) { 13501 SpeculateCellOperand base(this, baseEdge); 13502 JSValueRegsTemporary result(this); 13503 GPRReg baseGPR = base.gpr(); 13504 JSValueRegs resultRegs = result.regs(); 13505 13506 // Has the same structure as the enumerator. 13507 m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), resultRegs.payloadGPR()); 13508 speculationCheck(BadCache, JSValueSource(), node, m_jit.branch32(MacroAssembler::NotEqual, resultRegs.payloadGPR(), MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()))); 13509 13510 m_jit.load32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::modeSetOffset()), resultRegs.payloadGPR()); 13511 speculationCheck(BadCache, JSValueSource(), node, m_jit.branch32(MacroAssembler::NotEqual, TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode), resultRegs.payloadGPR())); 13512 13513 m_jit.move(indexGPR, resultRegs.payloadGPR()); 13514 MacroAssembler::Jump initMode = m_jit.branchTest32(MacroAssembler::Zero, modeGPR); 13515 13516 m_jit.add32(MacroAssembler::TrustedImm32(1), resultRegs.payloadGPR()); 13517 13518 initMode.link(&m_jit); 13519 #if USE(JSVALUE64) 13520 m_jit.or64(TrustedImm64(JSValue::DoubleEncodeOffset | static_cast<uint64_t>(JSPropertyNameEnumerator::OwnStructureMode) << 32), resultRegs.payloadGPR()); 13521 #else 13522 m_jit.move(TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode), resultRegs.tagGPR()); 13523 #endif 13524 13525 jsValueResult(resultRegs, node); 13526 return; 13527 } 13528 13529 JSValueOperand base(this, baseEdge); 13530 JSValueRegs baseRegs = base.regs(); 13465 13531 13466 13532 flushRegisters(); 13467 13533 JSValueRegsFlushedCallResult result(this); 13468 13534 JSValueRegs resultRegs = result.regs(); 13469 callOperation(operation HasEnumerableProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR);13535 callOperation(operationEnumeratorNextUpdateIndexAndMode, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, indexGPR, modeGPR, enumeratorGPR); 13470 13536 m_jit.exceptionCheck(); 13471 blessedBooleanResult(resultRegs.payloadGPR(), node);13472 } 13473 13474 void SpeculativeJIT::compile ToIndexString(Node* node)13475 { 13476 SpeculateInt32Operand index(this, node->child1());13477 GPRReg indexGPR = index.gpr();13478 13479 flushRegisters(); 13480 GPR FlushedCallResultresult(this);13537 jsValueResult(resultRegs, node); 13538 } 13539 13540 void SpeculativeJIT::compileEnumeratorNextExtractIndex(Node* node) 13541 { 13542 JSValueOperand updatedPair(this, node->child1()); 13543 JSValueRegs pairRegs = updatedPair.jsValueRegs(); 13544 GPRReg payloadGPR = pairRegs.payloadGPR(); 13545 13546 GPRTemporary result(this); 13481 13547 GPRReg resultGPR = result.gpr(); 13482 callOperation(operationToIndexString, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), indexGPR); 13483 m_jit.exceptionCheck(); 13484 cellResult(resultGPR, node); 13548 13549 m_jit.and32(TrustedImm32(std::numeric_limits<uint32_t>::max()), payloadGPR, resultGPR); 13550 13551 strictInt32Result(resultGPR, node); 13552 } 13553 13554 void SpeculativeJIT::compileEnumeratorNextExtractMode(Node* node) 13555 { 13556 JSValueOperand updatedPair(this, node->child1()); 13557 JSValueRegs pairRegs = updatedPair.jsValueRegs(); 13558 GPRReg pairGPR = is64Bit() ? pairRegs.payloadGPR() : pairRegs.tagGPR(); 13559 13560 GPRTemporary result(this); 13561 GPRReg resultGPR = result.gpr(); 13562 13563 #if CPU(ARM64) && USE(JSVALUE64) 13564 m_jit.extractUnsignedBitfield64(pairGPR, TrustedImm32(32), TrustedImm32(WTF::fastLog2(static_cast<unsigned>(JSPropertyNameEnumerator::enumerationModeMask + 1))), resultGPR); 13565 #else 13566 #if USE(JSVALUE64) 13567 m_jit.rshift64(pairGPR, TrustedImm32(32), resultGPR); 13568 #else 13569 m_jit.move(pairGPR, resultGPR); 13570 #endif 13571 m_jit.and32(TrustedImm32(JSPropertyNameEnumerator::enumerationModeMask), resultGPR); 13572 #endif 13573 13574 strictInt32Result(resultGPR, node); 13575 } 13576 13577 void SpeculativeJIT::compileEnumeratorNextUpdatePropertyName(Node* node) 13578 { 13579 SpeculateStrictInt32Operand indexOperand(this, node->child1()); 13580 SpeculateStrictInt32Operand modeOperand(this, node->child2()); 13581 SpeculateCellOperand enumeratorOperand(this, node->child3()); 13582 JSValueRegsTemporary resultTemp(this); 13583 13584 GPRReg index = indexOperand.gpr(); 13585 GPRReg mode = modeOperand.gpr(); 13586 GPRReg enumerator = enumeratorOperand.gpr(); 13587 JSValueRegs resultRegs = resultTemp.regs(); 13588 13589 OptionSet seenModes = node->enumeratorMetadata(); 13590 13591 MacroAssembler::JumpList doneCases; 13592 MacroAssembler::Jump operationCall; 13593 13594 bool needsOperation = seenModes.contains(JSPropertyNameEnumerator::IndexedMode); 13595 13596 // Make sure we flush on all code paths if we could call the operation. 13597 if (needsOperation) 13598 flushRegisters(); 13599 13600 if (seenModes.containsAny({ JSPropertyNameEnumerator::OwnStructureMode, JSPropertyNameEnumerator::GenericMode })) { 13601 13602 if (needsOperation) 13603 operationCall = m_jit.branchTest32(MacroAssembler::NonZero, mode, TrustedImm32(JSPropertyNameEnumerator::IndexedMode)); 13604 13605 auto outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, index, MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::endGenericPropertyIndexOffset())); 13606 13607 m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultRegs.payloadGPR()); 13608 m_jit.loadPtr(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), index, MacroAssembler::ScalePtr), resultRegs.payloadGPR()); 13609 #if USE(JSVALUE32_64) 13610 m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR()); 13611 #endif 13612 doneCases.append(m_jit.jump()); 13613 13614 outOfBounds.link(&m_jit); 13615 m_jit.moveTrustedValue(jsNull(), resultRegs); 13616 } 13617 13618 if (needsOperation) { 13619 if (operationCall.isSet()) { 13620 doneCases.append(m_jit.jump()); 13621 operationCall.link(&m_jit); 13622 } 13623 callOperation(operationEnumeratorNextUpdatePropertyName, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator); 13624 m_jit.exceptionCheck(); 13625 } 13626 13627 doneCases.link(&m_jit); 13628 jsValueResult(resultRegs, node); 13629 } 13630 13631 void SpeculativeJIT::compileEnumeratorGetByVal(Node* node) 13632 { 13633 Edge baseEdge = m_graph.varArgChild(node, 0); 13634 auto generate = [&] (GPRReg baseCellGPR) { 13635 MacroAssembler::JumpList doneCases; 13636 JSValueRegsTemporary result; 13637 JSValueRegs resultRegs; 13638 GPRReg indexGPR; 13639 GPRReg enumeratorGPR; 13640 MacroAssembler::Jump badStructureSlowPath; 13641 13642 compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) { 13643 Edge storageEdge = m_graph.varArgChild(node, 2); 13644 StorageOperand storage; 13645 if (storageEdge) 13646 storage.emplace(this, storageEdge); 13647 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3)); 13648 SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4)); 13649 SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5)); 13650 13651 GPRReg modeGPR = mode.gpr(); 13652 indexGPR = index.gpr(); 13653 enumeratorGPR = enumerator.gpr(); 13654 13655 result = JSValueRegsTemporary(this); 13656 resultRegs = result.regs(); 13657 GPRReg scratchGPR = resultRegs.payloadGPR(); 13658 13659 bool haveStorage = !!storageEdge; 13660 GPRTemporary storageTemporary; 13661 GPRReg storageGPR; 13662 if (!haveStorage) { 13663 storageTemporary = GPRTemporary(this, Reuse, enumerator); 13664 storageGPR = storageTemporary.gpr(); 13665 } else 13666 storageGPR = storage.gpr(); 13667 13668 MacroAssembler::JumpList notFastNamedCases; 13669 13670 // FIXME: We shouldn't generate this code if we know base is not an object. 13671 notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode))); 13672 { 13673 if (!m_state.forNode(baseEdge).isType(SpecCell)) 13674 notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR)); 13675 13676 // Check the structure 13677 // FIXME: If we know there's only one structure for base we can just embed it here. 13678 m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR); 13679 13680 auto badStructure = m_jit.branch32( 13681 MacroAssembler::NotEqual, 13682 scratchGPR, 13683 MacroAssembler::Address( 13684 enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())); 13685 13686 // FIXME: Maybe we should have a better way to represent Indexed+Named? 13687 if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node()) 13688 badStructureSlowPath = badStructure; 13689 else 13690 notFastNamedCases.append(badStructure); 13691 13692 // Compute the offset 13693 // If index is less than the enumerator's cached inline storage, then it's an inline access 13694 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual, 13695 indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset())); 13696 13697 m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs); 13698 13699 doneCases.append(m_jit.jump()); 13700 13701 // Otherwise it's out of line 13702 outOfLineAccess.link(&m_jit); 13703 m_jit.move(indexGPR, scratchGPR); 13704 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR); 13705 m_jit.neg32(scratchGPR); 13706 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR); 13707 if (!haveStorage) 13708 m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR); 13709 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); 13710 m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs); 13711 doneCases.append(m_jit.jump()); 13712 } 13713 13714 notFastNamedCases.link(&m_jit); 13715 return std::make_pair(resultRegs, DataFormatJS); 13716 })); 13717 13718 // We rely on compileGetByVal to call jsValueResult for us. 13719 // FIXME: This is kinda hacky... 13720 ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS); 13721 13722 if (badStructureSlowPath.isSet()) 13723 addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR)); 13724 13725 doneCases.link(&m_jit); 13726 }; 13727 13728 if (isCell(baseEdge.useKind())) { 13729 // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse. 13730 speculate(node, baseEdge); 13731 SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation); 13732 generate(baseOperand.gpr()); 13733 } else { 13734 JSValueOperand baseOperand(this, baseEdge); 13735 generate(baseOperand.gpr()); 13736 } 13737 } 13738 13739 template<typename SlowPathFunctionType> 13740 void SpeculativeJIT::compileEnumeratorHasProperty(Node* node, SlowPathFunctionType slowPathFunction) 13741 { 13742 Edge baseEdge = m_graph.varArgChild(node, 0); 13743 auto generate = [&] (auto base, GPRReg baseCellGPR) { 13744 JSValueOperand propertyName(this, m_graph.varArgChild(node, 1)); 13745 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 2)); 13746 SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 3)); 13747 SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 4)); 13748 13749 JSValueRegs propertyNameRegs = propertyName.regs(); 13750 GPRReg indexGPR = index.gpr(); 13751 GPRReg modeGPR = mode.gpr(); 13752 GPRReg enumeratorGPR = enumerator.gpr(); 13753 13754 JSValueRegsTemporary result(this); 13755 JSValueRegs resultRegs = result.regs(); 13756 13757 MacroAssembler::JumpList operationCases; 13758 13759 if (m_state.forNode(baseEdge).m_type & ~SpecCell) 13760 operationCases.append(m_jit.branchIfNotCell(base)); 13761 13762 // FIXME: We shouldn't generate this code if we know base is not a cell. 13763 operationCases.append(m_jit.branchTest32(MacroAssembler::Zero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode))); 13764 13765 m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), resultRegs.payloadGPR()); 13766 operationCases.append(m_jit.branch32(MacroAssembler::NotEqual, resultRegs.payloadGPR(), MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()))); 13767 13768 moveTrueTo(resultRegs.payloadGPR()); 13769 MacroAssembler::Jump done = m_jit.jump(); 13770 13771 operationCases.link(&m_jit); 13772 13773 flushRegisters(); 13774 #if USE(JSVALUE32_64) 13775 m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR()); 13776 auto baseRegs = JSValueRegs(baseCellGPR, resultRegs.tagGPR()); 13777 #else 13778 auto baseRegs = base; 13779 #endif 13780 callOperation(slowPathFunction, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyNameRegs, indexGPR, modeGPR); 13781 m_jit.exceptionCheck(); 13782 13783 done.link(&m_jit); 13784 13785 blessedBooleanResult(resultRegs.payloadGPR(), node); 13786 }; 13787 13788 if (isCell(baseEdge.useKind())) { 13789 SpeculateCellOperand base(this, baseEdge); 13790 generate(base.gpr(), base.gpr()); 13791 } else { 13792 JSValueOperand base(this, baseEdge); 13793 generate(base.regs(), base.regs().payloadGPR()); 13794 } 13795 } 13796 13797 void SpeculativeJIT::compileEnumeratorInByVal(Node* node) 13798 { 13799 compileEnumeratorHasProperty(node, operationEnumeratorInByVal); 13800 } 13801 13802 void SpeculativeJIT::compileEnumeratorHasOwnProperty(Node* node) 13803 { 13804 compileEnumeratorHasProperty(node, operationEnumeratorHasOwnProperty); 13485 13805 } 13486 13806 … … 13625 13945 } 13626 13946 13627 void SpeculativeJIT::compileHasEnumerableStructureProperty(Node* node)13628 {13629 JSValueOperand base(this, node->child1());13630 SpeculateCellOperand property(this, node->child2());13631 SpeculateCellOperand enumerator(this, node->child3());13632 JSValueRegsTemporary result(this);13633 13634 JSValueRegs baseRegs = base.jsValueRegs();13635 GPRReg propertyGPR = property.gpr();13636 JSValueRegs resultRegs = result.regs();13637 13638 CCallHelpers::JumpList wrongStructure;13639 13640 wrongStructure.append(m_jit.branchIfNotCell(baseRegs));13641 13642 m_jit.load32(MacroAssembler::Address(baseRegs.payloadGPR(), JSCell::structureIDOffset()), resultRegs.payloadGPR());13643 wrongStructure.append(m_jit.branch32(MacroAssembler::NotEqual,13644 resultRegs.payloadGPR(),13645 MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset())));13646 13647 moveTrueTo(resultRegs.payloadGPR());13648 13649 addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasEnumerableProperty, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyGPR));13650 blessedBooleanResult(resultRegs.payloadGPR(), node);13651 }13652 13653 template <typename Function>13654 void SpeculativeJIT::compileHasOwnStructurePropertyImpl(Node* node, Function slowPath)13655 {13656 SpeculateCellOperand base(this, node->child1());13657 SpeculateCellOperand property(this, node->child2());13658 SpeculateCellOperand enumerator(this, node->child3());13659 JSValueRegsTemporary result(this);13660 13661 GPRReg baseGPR = base.gpr();13662 GPRReg propertyGPR = property.gpr();13663 JSValueRegs resultRegs = result.regs();13664 13665 CCallHelpers::JumpList wrongStructure;13666 13667 m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), resultRegs.payloadGPR());13668 wrongStructure.append(m_jit.branch32(MacroAssembler::NotEqual,13669 resultRegs.payloadGPR(),13670 MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset())));13671 13672 moveTrueTo(resultRegs.payloadGPR());13673 13674 addSlowPathGenerator(slowPathCall(wrongStructure, this, slowPath, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyGPR));13675 blessedBooleanResult(resultRegs.payloadGPR(), node);13676 }13677 13678 void SpeculativeJIT::compileHasOwnStructureProperty(Node* node)13679 {13680 compileHasOwnStructurePropertyImpl(node, operationHasOwnStructureProperty);13681 }13682 13683 void SpeculativeJIT::compileInStructureProperty(Node* node)13684 {13685 compileHasOwnStructurePropertyImpl(node, operationInStructureProperty);13686 }13687 13688 13947 void SpeculativeJIT::compileGetPropertyEnumerator(Node* node) 13689 13948 { … … 13710 13969 m_jit.exceptionCheck(); 13711 13970 cellResult(resultGPR, node); 13712 }13713 13714 void SpeculativeJIT::compileGetEnumeratorPname(Node* node)13715 {13716 ASSERT(node->op() == GetEnumeratorStructurePname || node->op() == GetEnumeratorGenericPname);13717 SpeculateCellOperand enumerator(this, node->child1());13718 SpeculateStrictInt32Operand index(this, node->child2());13719 GPRTemporary scratch(this);13720 JSValueRegsTemporary result(this);13721 13722 GPRReg enumeratorGPR = enumerator.gpr();13723 GPRReg indexGPR = index.gpr();13724 GPRReg scratchGPR = scratch.gpr();13725 JSValueRegs resultRegs = result.regs();13726 13727 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, indexGPR,13728 MacroAssembler::Address(enumeratorGPR, (node->op() == GetEnumeratorStructurePname)13729 ? JSPropertyNameEnumerator::endStructurePropertyIndexOffset()13730 : JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));13731 13732 m_jit.moveValue(jsNull(), resultRegs);13733 13734 MacroAssembler::Jump done = m_jit.jump();13735 inBounds.link(&m_jit);13736 13737 m_jit.loadPtr(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), scratchGPR);13738 m_jit.loadPtr(MacroAssembler::BaseIndex(scratchGPR, indexGPR, MacroAssembler::ScalePtr), resultRegs.payloadGPR());13739 #if USE(JSVALUE32_64)13740 m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());13741 #endif13742 13743 done.link(&m_jit);13744 jsValueResult(resultRegs, node);13745 13971 } 13746 13972 … … 14937 15163 } 14938 15164 14939 void SpeculativeJIT::compileHasIndexedProperty(Node* node, S_JITOperation_GCZ slowPathOperation )15165 void SpeculativeJIT::compileHasIndexedProperty(Node* node, S_JITOperation_GCZ slowPathOperation, const ScopedLambda<std::tuple<GPRReg, GPRReg>()>& prefix) 14940 15166 { 14941 15167 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 14942 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));14943 GPRTemporary result(this);14944 15168 14945 15169 GPRReg baseGPR = base.gpr(); 14946 GPRReg indexGPR = index.gpr();14947 GPRReg resultGPR = result.gpr();15170 GPRReg indexGPR = InvalidGPRReg; 15171 GPRReg resultGPR = InvalidGPRReg; 14948 15172 14949 15173 MacroAssembler::JumpList slowCases; … … 14952 15176 case Array::Int32: 14953 15177 case Array::Contiguous: { 14954 ASSERT(!!m_graph.varArgChild(node, 2));14955 StorageOperand storage(this, m_graph.varArgChild(node, 2));15178 ASSERT(!!m_graph.varArgChild(node, node->storageChildIndex())); 15179 StorageOperand storage(this, m_graph.varArgChild(node, node->storageChildIndex())); 14956 15180 GPRTemporary scratch(this); 14957 15181 14958 15182 GPRReg storageGPR = storage.gpr(); 14959 15183 GPRReg scratchGPR = scratch.gpr(); 15184 15185 std::tie(indexGPR, resultGPR) = prefix(); 14960 15186 14961 15187 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); … … 14986 15212 } 14987 15213 case Array::Double: { 14988 ASSERT(!!m_graph.varArgChild(node, 2));14989 StorageOperand storage(this, m_graph.varArgChild(node, 2));15214 ASSERT(!!m_graph.varArgChild(node, node->storageChildIndex())); 15215 StorageOperand storage(this, m_graph.varArgChild(node, node->storageChildIndex())); 14990 15216 FPRTemporary scratch(this); 14991 15217 FPRReg scratchFPR = scratch.fpr(); 14992 15218 GPRReg storageGPR = storage.gpr(); 15219 15220 std::tie(indexGPR, resultGPR) = prefix(); 14993 15221 14994 15222 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); … … 15015 15243 } 15016 15244 case Array::ArrayStorage: { 15017 ASSERT(!!m_graph.varArgChild(node, 2));15018 StorageOperand storage(this, m_graph.varArgChild(node, 2));15245 ASSERT(!!m_graph.varArgChild(node, node->storageChildIndex())); 15246 StorageOperand storage(this, m_graph.varArgChild(node, node->storageChildIndex())); 15019 15247 GPRTemporary scratch(this); 15020 15248 15021 15249 GPRReg storageGPR = storage.gpr(); 15022 15250 GPRReg scratchGPR = scratch.gpr(); 15251 15252 std::tie(indexGPR, resultGPR) = prefix(); 15023 15253 15024 15254 MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); … … 15050 15280 // FIXME: Optimize TypedArrays in HasIndexedProperty IC 15051 15281 // https://bugs.webkit.org/show_bug.cgi?id=221183 15282 std::tie(indexGPR, resultGPR) = prefix(); 15052 15283 slowCases.append(m_jit.jump()); 15053 15284 break; … … 15056 15287 15057 15288 addSlowPathGenerator(slowPathCall(slowCases, this, slowPathOperation, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, indexGPR)); 15058 15059 unblessedBooleanResult(resultGPR, node);15060 }15061 15062 void SpeculativeJIT::compileGetDirectPname(Node* node)15063 {15064 Edge& baseEdge = m_jit.graph().varArgChild(node, 0);15065 Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);15066 Edge& indexEdge = m_jit.graph().varArgChild(node, 2);15067 15068 SpeculateCellOperand base(this, baseEdge);15069 SpeculateCellOperand property(this, propertyEdge);15070 GPRReg baseGPR = base.gpr();15071 GPRReg propertyGPR = property.gpr();15072 15073 Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3);15074 SpeculateStrictInt32Operand index(this, indexEdge);15075 SpeculateCellOperand enumerator(this, enumeratorEdge);15076 GPRTemporary scratch(this);15077 JSValueRegsTemporary result(this);15078 15079 GPRReg indexGPR = index.gpr();15080 GPRReg enumeratorGPR = enumerator.gpr();15081 GPRReg scratchGPR = scratch.gpr();15082 JSValueRegs resultRegs = result.regs();15083 15084 MacroAssembler::JumpList slowPath;15085 15086 // Check the structure15087 m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);15088 slowPath.append(15089 m_jit.branch32(15090 MacroAssembler::NotEqual,15091 scratchGPR,15092 MacroAssembler::Address(15093 enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())));15094 15095 // Compute the offset15096 // If index is less than the enumerator's cached inline storage, then it's an inline access15097 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,15098 indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));15099 15100 m_jit.loadValue(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);15101 15102 MacroAssembler::Jump done = m_jit.jump();15103 15104 // Otherwise it's out of line15105 outOfLineAccess.link(&m_jit);15106 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultRegs.payloadGPR());15107 m_jit.move(indexGPR, scratchGPR);15108 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);15109 m_jit.neg32(scratchGPR);15110 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);15111 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);15112 m_jit.loadValue(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);15113 15114 done.link(&m_jit);15115 15116 addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, CCallHelpers::CellValue(propertyGPR)));15117 15118 jsValueResult(resultRegs, node);15119 15289 } 15120 15290 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r279604 r280760 48 48 49 49 class GPRTemporary; 50 class JSValueRegsTemporary; 50 51 class JSValueOperand; 51 52 class SlowPathGenerator; … … 247 248 GPRReg allocate(GPRReg specific) 248 249 { 250 if (specific == InvalidGPRReg) 251 allocate(); 249 252 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) 250 253 m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset()); … … 1346 1349 } 1347 1350 1351 // We use a scopedLambda to placate register allocation validation. 1352 void compileGetByVal(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1353 1348 1354 void compileGetCharCodeAt(Node*); 1349 void compileGetByValOnString(Node* );1355 void compileGetByValOnString(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1350 1356 void compileFromCharCode(Node*); 1351 1357 1352 void compileGetByValOnDirectArguments(Node* );1353 void compileGetByValOnScopedArguments(Node* );1358 void compileGetByValOnDirectArguments(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1359 void compileGetByValOnScopedArguments(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1354 1360 1355 1361 void compileGetPrivateName(Node*); … … 1425 1431 void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR); 1426 1432 void compileGetTypedArrayByteOffset(Node*); 1427 void compileGetByValOnIntTypedArray(Node*, TypedArrayType );1433 void compileGetByValOnIntTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1428 1434 void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType); 1429 void compileGetByValOnFloatTypedArray(Node*, TypedArrayType );1435 void compileGetByValOnFloatTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1430 1436 void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType); 1431 void compileGetByValForObjectWithString(Node* );1432 void compileGetByValForObjectWithSymbol(Node* );1437 void compileGetByValForObjectWithString(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1438 void compileGetByValForObjectWithSymbol(Node*, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1433 1439 void compilePutByValForCellWithString(Node*, Edge& child1, Edge& child2, Edge& child3); 1434 1440 void compilePutByValForCellWithSymbol(Node*, Edge& child1, Edge& child2, Edge& child3); … … 1459 1465 Edge valueUse); 1460 1466 void loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType); 1461 void setIntTypedArrayLoadResult(Node*, GPRReg resultReg, TypedArrayType, bool canSpeculate);1467 void setIntTypedArrayLoadResult(Node*, JSValueRegs resultRegs, TypedArrayType, bool canSpeculate, bool shouldBox); 1462 1468 template <typename ClassType> void compileNewFunctionCommon(GPRReg, RegisteredStructure, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*); 1463 1469 void compileNewFunction(Node*); … … 1525 1531 void compileThrow(Node*); 1526 1532 void compileThrowStaticError(Node*); 1527 void compileGetEnumerableLength(Node*); 1528 void compileHasEnumerableStructureProperty(Node*); 1529 void compileHasEnumerableProperty(Node*); 1530 void compileToIndexString(Node*); 1533 1534 void compileEnumeratorNextUpdateIndexAndMode(Node*); 1535 void compileEnumeratorNextExtractMode(Node*); 1536 void compileEnumeratorNextExtractIndex(Node*); 1537 void compileEnumeratorNextUpdatePropertyName(Node*); 1538 void compileEnumeratorGetByVal(Node*); 1539 template<typename SlowPathFunctionType> 1540 void compileEnumeratorHasProperty(Node*, SlowPathFunctionType); 1541 void compileEnumeratorInByVal(Node*); 1542 void compileEnumeratorHasOwnProperty(Node*); 1543 1531 1544 void compilePutByIdFlush(Node*); 1532 1545 void compilePutById(Node*); 1533 1546 void compilePutByIdDirect(Node*); 1534 1547 void compilePutByIdWithThis(Node*); 1535 template <typename Function>1536 void compileHasOwnStructurePropertyImpl(Node*, Function);1537 void compileHasOwnStructureProperty(Node*);1538 void compileInStructureProperty(Node*);1539 void compileGetDirectPname(Node*);1540 1548 void compileGetPropertyEnumerator(Node*); 1541 void compileGetEnumeratorPname(Node*);1542 1549 void compileGetExecutable(Node*); 1543 1550 void compileGetGetter(Node*); … … 1569 1576 void compileLogShadowChickenPrologue(Node*); 1570 1577 void compileLogShadowChickenTail(Node*); 1571 void compileHasIndexedProperty(Node*, S_JITOperation_GCZ );1578 void compileHasIndexedProperty(Node*, S_JITOperation_GCZ, const ScopedLambda<std::tuple<GPRReg, GPRReg>()>& prefix); 1572 1579 void compileExtractCatchLocal(Node*); 1573 1580 void compileClearCatchLocals(Node*); … … 1927 1934 } 1928 1935 1936 JSValueRegs regs() { return jsValueRegs(); } 1937 1929 1938 #if USE(JSVALUE64) 1930 1939 GPRReg gpr() … … 1966 1975 } 1967 1976 1968 GPRReg gpr(WhichValueWord which )1977 GPRReg gpr(WhichValueWord which = PayloadWord) 1969 1978 { 1970 1979 return jsValueRegs().gpr(which); … … 2004 2013 WTF_MAKE_FAST_ALLOCATED; 2005 2014 public: 2015 StorageOperand() = default; 2016 2006 2017 explicit StorageOperand(SpeculativeJIT* jit, Edge edge) 2007 2018 : m_jit(jit) … … 2009 2020 , m_gprOrInvalid(InvalidGPRReg) 2010 2021 { 2022 emplace(jit, edge); 2023 } 2024 2025 ~StorageOperand() 2026 { 2027 if (m_gprOrInvalid != InvalidGPRReg) 2028 m_jit->unlock(m_gprOrInvalid); 2029 } 2030 2031 Edge edge() const 2032 { 2033 return m_edge; 2034 } 2035 2036 Node* node() const 2037 { 2038 return edge().node(); 2039 } 2040 2041 GPRReg gpr() 2042 { 2043 if (m_gprOrInvalid == InvalidGPRReg) 2044 m_gprOrInvalid = m_jit->fillStorage(edge()); 2045 return m_gprOrInvalid; 2046 } 2047 2048 void emplace(SpeculativeJIT* jit, Edge edge) 2049 { 2050 m_jit = jit; 2051 m_edge = edge; 2052 ASSERT(m_gprOrInvalid == InvalidGPRReg); 2011 2053 ASSERT(m_jit); 2012 2054 ASSERT(edge.useKind() == UntypedUse || edge.useKind() == KnownCellUse); … … 2015 2057 } 2016 2058 2017 ~StorageOperand()2018 {2019 ASSERT(m_gprOrInvalid != InvalidGPRReg);2020 m_jit->unlock(m_gprOrInvalid);2021 }2022 2023 Edge edge() const2024 {2025 return m_edge;2026 }2027 2028 Node* node() const2029 {2030 return edge().node();2031 }2032 2033 GPRReg gpr()2034 {2035 if (m_gprOrInvalid == InvalidGPRReg)2036 m_gprOrInvalid = m_jit->fillStorage(edge());2037 return m_gprOrInvalid;2038 }2039 2040 2059 void use() 2041 2060 { … … 2044 2063 2045 2064 private: 2046 SpeculativeJIT* m_jit ;2065 SpeculativeJIT* m_jit { nullptr }; 2047 2066 Edge m_edge; 2048 GPRReg m_gprOrInvalid ;2067 GPRReg m_gprOrInvalid { InvalidGPRReg }; 2049 2068 }; 2050 2069 … … 2135 2154 JSValueRegsTemporary(); 2136 2155 JSValueRegsTemporary(SpeculativeJIT*); 2156 JSValueRegsTemporary(SpeculativeJIT*, GPRReg specificPayload); 2157 #if USE(JSVALUE32_64) 2158 JSValueRegsTemporary(SpeculativeJIT*, GPRReg specificPayload, GPRReg specificTag); 2159 #endif 2137 2160 template<typename T> 2138 2161 JSValueRegsTemporary(SpeculativeJIT*, ReuseTag, T& operand, WhichValueWord resultRegWord = PayloadWord); … … 2140 2163 ~JSValueRegsTemporary(); 2141 2164 2165 explicit operator bool() { return !!regs(); } 2166 2167 JSValueRegsTemporary& operator=(JSValueRegsTemporary&&) = default; 2168 2142 2169 JSValueRegs regs(); 2143 2170 … … 2150 2177 #endif 2151 2178 }; 2179 2180 #if USE(JSVALUE64) 2181 template<typename T> 2182 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord) 2183 : m_gpr(jit, Reuse, operand) 2184 { 2185 } 2186 #else 2187 template<typename T> 2188 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord resultWord) 2189 { 2190 if (resultWord == PayloadWord) { 2191 m_payloadGPR = GPRTemporary(jit, Reuse, operand); 2192 m_tagGPR = GPRTemporary(jit); 2193 } else { 2194 m_payloadGPR = GPRTemporary(jit); 2195 m_tagGPR = GPRTemporary(jit, Reuse, operand); 2196 } 2197 } 2198 #endif 2152 2199 2153 2200 class FPRTemporary { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r279604 r280760 1813 1813 } 1814 1814 1815 void SpeculativeJIT::compileGetByVal(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 1816 { 1817 switch (node->arrayMode().type()) { 1818 case Array::SelectUsingPredictions: 1819 case Array::ForceExit: 1820 RELEASE_ASSERT_NOT_REACHED(); 1821 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE) 1822 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 1823 #endif 1824 break; 1825 case Array::Undecided: { 1826 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1)); 1827 1828 GPRReg indexGPR = index.gpr(); 1829 1830 JSValueRegs resultRegs; 1831 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 1832 1833 speculationCheck(OutOfBounds, JSValueRegs(), node, 1834 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0))); 1835 1836 m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultRegs.tagGPR()); 1837 m_jit.move(MacroAssembler::TrustedImm32(0), resultRegs.payloadGPR()); 1838 jsValueResult(resultRegs, node); 1839 break; 1840 } 1841 case Array::Generic: { 1842 if (m_graph.m_slowGetByVal.contains(node)) { 1843 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) { 1844 if (m_graph.varArgChild(node, 1).useKind() == StringUse) { 1845 compileGetByValForObjectWithString(node, prefix); 1846 break; 1847 } 1848 1849 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) { 1850 compileGetByValForObjectWithSymbol(node, prefix); 1851 break; 1852 } 1853 } 1854 1855 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right. 1856 JSValueOperand property(this, m_graph.varArgChild(node, 1)); 1857 GPRReg baseGPR = base.gpr(); 1858 JSValueRegs propertyRegs = property.jsValueRegs(); 1859 1860 JSValueRegs resultRegs; 1861 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 1862 1863 flushRegisters(); 1864 callOperation(operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs); 1865 m_jit.exceptionCheck(); 1866 1867 jsValueResult(resultRegs, node); 1868 break; 1869 } 1870 1871 speculate(node, m_graph.varArgChild(node, 0)); 1872 speculate(node, m_graph.varArgChild(node, 1)); 1873 1874 JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation); 1875 JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation); 1876 1877 JSValueRegs baseRegs = base.jsValueRegs(); 1878 JSValueRegs propertyRegs = property.jsValueRegs(); 1879 1880 JSValueRegs resultRegs; 1881 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 1882 1883 CodeOrigin codeOrigin = node->origin.semantic; 1884 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size()); 1885 RegisterSet usedRegisters = this->usedRegisters(); 1886 1887 JITCompiler::JumpList slowCases; 1888 if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell)) 1889 slowCases.append(m_jit.branchIfNotCell(baseRegs.tagGPR())); 1890 1891 JITGetByValGenerator gen( 1892 m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters, 1893 baseRegs, propertyRegs, resultRegs, InvalidGPRReg); 1894 1895 if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString)) 1896 gen.stubInfo()->propertyIsString = true; 1897 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only)) 1898 gen.stubInfo()->propertyIsInt32 = true; 1899 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol)) 1900 gen.stubInfo()->propertyIsSymbol = true; 1901 1902 gen.generateFastPath(m_jit); 1903 1904 slowCases.append(gen.slowPathJump()); 1905 1906 std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall( 1907 slowCases, this, operationGetByValOptimize, 1908 resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs); 1909 1910 m_jit.addGetByVal(gen, slowPath.get()); 1911 addSlowPathGenerator(WTFMove(slowPath)); 1912 1913 jsValueResult(resultRegs, node); 1914 break; 1915 } 1916 case Array::Int32: 1917 case Array::Contiguous: { 1918 if (node->arrayMode().isInBounds()) { 1919 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 1920 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 1921 1922 GPRReg propertyReg = property.gpr(); 1923 GPRReg storageReg = storage.gpr(); 1924 1925 if (!m_compileOkay) 1926 return; 1927 1928 JSValueRegs resultRegs; 1929 DataFormat format; 1930 std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatInt32 : DataFormatJS); 1931 1932 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 1933 1934 if (format == DataFormatInt32) { 1935 ASSERT(!node->arrayMode().isInBoundsSaneChain()); 1936 1937 speculationCheck( 1938 OutOfBounds, JSValueRegs(), 0, 1939 m_jit.branch32( 1940 MacroAssembler::Equal, 1941 MacroAssembler::BaseIndex( 1942 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset), 1943 TrustedImm32(JSValue::EmptyValueTag))); 1944 m_jit.load32( 1945 MacroAssembler::BaseIndex( 1946 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset), 1947 resultRegs.payloadGPR()); 1948 strictInt32Result(resultRegs.payloadGPR(), node); 1949 break; 1950 } 1951 1952 ASSERT(format == DataFormatJS); 1953 m_jit.load32( 1954 MacroAssembler::BaseIndex( 1955 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset), 1956 resultRegs.tagGPR()); 1957 m_jit.load32( 1958 MacroAssembler::BaseIndex( 1959 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset), 1960 resultRegs.payloadGPR()); 1961 if (node->arrayMode().isInBoundsSaneChain()) { 1962 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultRegs.tagGPR()); 1963 m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultRegs.tagGPR()); 1964 m_jit.move(TrustedImm32(0), resultRegs.payloadGPR()); 1965 notHole.link(&m_jit); 1966 } else { 1967 speculationCheck( 1968 LoadFromHole, JSValueRegs(), nullptr, 1969 m_jit.branchIfEmpty(resultRegs.tagGPR())); 1970 } 1971 jsValueResult(resultRegs, node); 1972 break; 1973 } 1974 1975 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 1976 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 1977 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 1978 1979 GPRReg baseReg = base.gpr(); 1980 GPRReg propertyReg = property.gpr(); 1981 GPRReg storageReg = storage.gpr(); 1982 1983 if (!m_compileOkay) 1984 return; 1985 1986 JSValueRegs resultRegs; 1987 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 1988 1989 MacroAssembler::JumpList slowCases; 1990 1991 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 1992 1993 m_jit.loadValue(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultRegs); 1994 slowCases.append(m_jit.branchIfEmpty(resultRegs.tagGPR())); 1995 1996 addSlowPathGenerator( 1997 slowPathCall( 1998 slowCases, this, operationGetByValObjectInt, 1999 resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2000 2001 jsValueResult(resultRegs, node); 2002 break; 2003 } 2004 case Array::Double: { 2005 if (node->arrayMode().isInBounds()) { 2006 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2007 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2008 2009 GPRReg propertyReg = property.gpr(); 2010 GPRReg storageReg = storage.gpr(); 2011 2012 if (!m_compileOkay) 2013 return; 2014 2015 FPRTemporary result(this); 2016 2017 JSValueRegs resultRegs; 2018 DataFormat format; 2019 std::tie(resultRegs, format) = prefix(DataFormatDouble); 2020 2021 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2022 2023 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr()); 2024 if (!node->arrayMode().isInBoundsSaneChain()) 2025 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr())); 2026 if (format == DataFormatJS) { 2027 boxDouble(result.fpr(), resultRegs); 2028 jsValueResult(resultRegs, node); 2029 } else { 2030 ASSERT(format == DataFormatDouble && !resultRegs); 2031 doubleResult(result.fpr(), node); 2032 } 2033 break; 2034 } 2035 2036 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2037 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2038 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2039 2040 GPRReg baseReg = base.gpr(); 2041 GPRReg propertyReg = property.gpr(); 2042 GPRReg storageReg = storage.gpr(); 2043 2044 if (!m_compileOkay) 2045 return; 2046 2047 FPRTemporary temp(this); 2048 FPRReg tempReg = temp.fpr(); 2049 2050 JSValueRegs resultRegs; 2051 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2052 2053 MacroAssembler::JumpList slowCases; 2054 2055 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2056 2057 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg); 2058 slowCases.append(m_jit.branchIfNaN(tempReg)); 2059 boxDouble(tempReg, resultRegs); 2060 2061 addSlowPathGenerator( 2062 slowPathCall( 2063 slowCases, this, operationGetByValObjectInt, 2064 resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2065 2066 jsValueResult(resultRegs, node); 2067 break; 2068 } 2069 case Array::ArrayStorage: 2070 case Array::SlowPutArrayStorage: { 2071 if (node->arrayMode().isInBounds()) { 2072 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2073 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2074 GPRReg propertyReg = property.gpr(); 2075 GPRReg storageReg = storage.gpr(); 2076 2077 if (!m_compileOkay) 2078 return; 2079 2080 JSValueRegs resultRegs; 2081 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2082 2083 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()))); 2084 2085 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR()); 2086 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultRegs.tagGPR())); 2087 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR()); 2088 2089 jsValueResult(resultRegs, node); 2090 break; 2091 } 2092 2093 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2094 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2095 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2096 GPRReg propertyReg = property.gpr(); 2097 GPRReg storageReg = storage.gpr(); 2098 GPRReg baseReg = base.gpr(); 2099 2100 if (!m_compileOkay) 2101 return; 2102 2103 JSValueRegs resultRegs; 2104 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2105 2106 JITCompiler::Jump outOfBounds = m_jit.branch32( 2107 MacroAssembler::AboveOrEqual, propertyReg, 2108 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())); 2109 2110 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR()); 2111 JITCompiler::Jump hole = m_jit.branchIfEmpty(resultRegs.tagGPR()); 2112 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR()); 2113 2114 JITCompiler::JumpList slowCases; 2115 slowCases.append(outOfBounds); 2116 slowCases.append(hole); 2117 addSlowPathGenerator( 2118 slowPathCall( 2119 slowCases, this, operationGetByValObjectInt, 2120 resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), 2121 baseReg, propertyReg)); 2122 2123 jsValueResult(resultRegs, node); 2124 break; 2125 } 2126 case Array::String: 2127 compileGetByValOnString(node, prefix); 2128 break; 2129 case Array::DirectArguments: 2130 compileGetByValOnDirectArguments(node, prefix); 2131 break; 2132 case Array::ScopedArguments: 2133 compileGetByValOnScopedArguments(node, prefix); 2134 break; 2135 default: { 2136 TypedArrayType type = node->arrayMode().typedArrayType(); 2137 if (isInt(type)) 2138 compileGetByValOnIntTypedArray(node, type, prefix); 2139 else 2140 compileGetByValOnFloatTypedArray(node, type, prefix); 2141 } } 2142 } 2143 1815 2144 void SpeculativeJIT::compile(Node* node) 1816 2145 { … … 2234 2563 case StringCharAt: { 2235 2564 // Relies on StringCharAt node having same basic layout as GetByVal 2236 compileGetByValOnString(node); 2565 JSValueRegsTemporary result; 2566 compileGetByValOnString(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) { 2567 result = JSValueRegsTemporary(this); 2568 ASSERT(preferredFormat & DataFormatJS); 2569 return std::make_pair(result.regs(), preferredFormat); 2570 })); 2237 2571 break; 2238 2572 } … … 2266 2600 2267 2601 case GetByVal: { 2268 switch (node->arrayMode().type()) { 2269 case Array::SelectUsingPredictions: 2270 case Array::ForceExit: 2271 RELEASE_ASSERT_NOT_REACHED(); 2272 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE) 2273 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 2274 #endif 2275 break; 2276 case Array::Undecided: { 2277 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1)); 2278 GPRTemporary resultTag(this, Reuse, index); 2279 GPRTemporary resultPayload(this); 2280 2281 GPRReg indexGPR = index.gpr(); 2282 GPRReg resultTagGPR = resultTag.gpr(); 2283 GPRReg resultPayloadGPR = resultPayload.gpr(); 2284 2285 speculationCheck(OutOfBounds, JSValueRegs(), node, 2286 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0))); 2287 2288 use(m_graph.varArgChild(node, 0)); 2289 index.use(); 2290 2291 m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultTagGPR); 2292 m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR); 2293 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 2294 break; 2295 } 2296 case Array::Generic: { 2297 if (m_graph.m_slowGetByVal.contains(node)) { 2298 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) { 2299 if (m_graph.varArgChild(node, 1).useKind() == StringUse) { 2300 compileGetByValForObjectWithString(node); 2301 break; 2302 } 2303 2304 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) { 2305 compileGetByValForObjectWithSymbol(node); 2306 break; 2307 } 2308 } 2309 2310 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right. 2311 JSValueOperand property(this, m_graph.varArgChild(node, 1)); 2312 GPRReg baseGPR = base.gpr(); 2313 JSValueRegs propertyRegs = property.jsValueRegs(); 2314 2315 flushRegisters(); 2316 JSValueRegsFlushedCallResult result(this); 2317 JSValueRegs resultRegs = result.regs(); 2318 callOperation(operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs); 2319 m_jit.exceptionCheck(); 2320 2321 jsValueResult(resultRegs, node); 2602 JSValueRegsTemporary jsValueResult; 2603 GPRTemporary oneRegResult; 2604 compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) { 2605 JSValueRegs resultRegs; 2606 switch (preferredFormat) { 2607 case DataFormatDouble: 2608 break; 2609 case DataFormatInt32: 2610 case DataFormatCell: 2611 oneRegResult = GPRTemporary(this); 2612 resultRegs = JSValueRegs::payloadOnly(oneRegResult.gpr()); 2613 break; 2614 default: { 2615 ASSERT(preferredFormat == DataFormatJS); 2616 jsValueResult = JSValueRegsTemporary(this); 2617 resultRegs = jsValueResult.regs(); 2322 2618 break; 2323 2619 } 2324 2325 speculate(node, m_graph.varArgChild(node, 0)); 2326 speculate(node, m_graph.varArgChild(node, 1)); 2327 2328 JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation); 2329 JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation); 2330 GPRTemporary resultTag(this, Reuse, property, TagWord); 2331 GPRTemporary resultPayload(this, Reuse, property, PayloadWord); 2332 2333 JSValueRegs baseRegs = base.jsValueRegs(); 2334 JSValueRegs propertyRegs = property.jsValueRegs(); 2335 JSValueRegs resultRegs(resultTag.gpr(), resultPayload.gpr()); 2336 2337 CodeOrigin codeOrigin = node->origin.semantic; 2338 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size()); 2339 RegisterSet usedRegisters = this->usedRegisters(); 2340 2341 JITCompiler::JumpList slowCases; 2342 if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell)) 2343 slowCases.append(m_jit.branchIfNotCell(baseRegs.tagGPR())); 2344 2345 JITGetByValGenerator gen( 2346 m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters, 2347 baseRegs, propertyRegs, resultRegs, InvalidGPRReg); 2348 2349 if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString)) 2350 gen.stubInfo()->propertyIsString = true; 2351 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only)) 2352 gen.stubInfo()->propertyIsInt32 = true; 2353 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol)) 2354 gen.stubInfo()->propertyIsSymbol = true; 2355 2356 gen.generateFastPath(m_jit); 2357 2358 slowCases.append(gen.slowPathJump()); 2359 2360 std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall( 2361 slowCases, this, operationGetByValOptimize, 2362 resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs); 2363 2364 m_jit.addGetByVal(gen, slowPath.get()); 2365 addSlowPathGenerator(WTFMove(slowPath)); 2366 2367 jsValueResult(resultRegs, node); 2368 break; 2369 } 2370 case Array::Int32: 2371 case Array::Contiguous: { 2372 if (node->arrayMode().isInBounds()) { 2373 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2374 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2375 2376 GPRReg propertyReg = property.gpr(); 2377 GPRReg storageReg = storage.gpr(); 2378 2379 if (!m_compileOkay) 2380 return; 2381 2382 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2383 2384 GPRTemporary resultPayload(this); 2385 if (node->arrayMode().type() == Array::Int32) { 2386 ASSERT(!node->arrayMode().isInBoundsSaneChain()); 2387 2388 speculationCheck( 2389 OutOfBounds, JSValueRegs(), 0, 2390 m_jit.branch32( 2391 MacroAssembler::Equal, 2392 MacroAssembler::BaseIndex( 2393 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset), 2394 TrustedImm32(JSValue::EmptyValueTag))); 2395 m_jit.load32( 2396 MacroAssembler::BaseIndex( 2397 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset), 2398 resultPayload.gpr()); 2399 strictInt32Result(resultPayload.gpr(), node); 2400 break; 2401 } 2402 2403 GPRTemporary resultTag(this); 2404 m_jit.load32( 2405 MacroAssembler::BaseIndex( 2406 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset), 2407 resultTag.gpr()); 2408 m_jit.load32( 2409 MacroAssembler::BaseIndex( 2410 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset), 2411 resultPayload.gpr()); 2412 if (node->arrayMode().isInBoundsSaneChain()) { 2413 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultTag.gpr()); 2414 m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTag.gpr()); 2415 m_jit.move(TrustedImm32(0), resultPayload.gpr()); 2416 notHole.link(&m_jit); 2417 } else { 2418 speculationCheck( 2419 LoadFromHole, JSValueRegs(), 0, 2420 m_jit.branchIfEmpty(resultTag.gpr())); 2421 } 2422 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 2423 break; 2424 } 2425 2426 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2427 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2428 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2429 2430 GPRReg baseReg = base.gpr(); 2431 GPRReg propertyReg = property.gpr(); 2432 GPRReg storageReg = storage.gpr(); 2433 2434 if (!m_compileOkay) 2435 return; 2436 2437 GPRTemporary resultTag(this); 2438 GPRTemporary resultPayload(this); 2439 GPRReg resultTagReg = resultTag.gpr(); 2440 GPRReg resultPayloadReg = resultPayload.gpr(); 2441 2442 MacroAssembler::JumpList slowCases; 2443 2444 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2445 2446 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg); 2447 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg); 2448 slowCases.append(m_jit.branchIfEmpty(resultTagReg)); 2449 2450 addSlowPathGenerator( 2451 slowPathCall( 2452 slowCases, this, operationGetByValObjectInt, 2453 JSValueRegs(resultTagReg, resultPayloadReg), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2454 2455 jsValueResult(resultTagReg, resultPayloadReg, node); 2456 break; 2457 } 2458 case Array::Double: { 2459 if (node->arrayMode().isInBounds()) { 2460 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2461 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2462 2463 GPRReg propertyReg = property.gpr(); 2464 GPRReg storageReg = storage.gpr(); 2465 2466 if (!m_compileOkay) 2467 return; 2468 2469 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2470 2471 FPRTemporary result(this); 2472 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr()); 2473 if (!node->arrayMode().isInBoundsSaneChain()) 2474 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr())); 2475 doubleResult(result.fpr(), node); 2476 break; 2477 } 2478 2479 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2480 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2481 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2482 2483 GPRReg baseReg = base.gpr(); 2484 GPRReg propertyReg = property.gpr(); 2485 GPRReg storageReg = storage.gpr(); 2486 2487 if (!m_compileOkay) 2488 return; 2489 2490 GPRTemporary resultTag(this); 2491 GPRTemporary resultPayload(this); 2492 FPRTemporary temp(this); 2493 GPRReg resultTagReg = resultTag.gpr(); 2494 GPRReg resultPayloadReg = resultPayload.gpr(); 2495 FPRReg tempReg = temp.fpr(); 2496 2497 MacroAssembler::JumpList slowCases; 2498 2499 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2500 2501 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg); 2502 slowCases.append(m_jit.branchIfNaN(tempReg)); 2503 boxDouble(tempReg, resultTagReg, resultPayloadReg); 2504 2505 addSlowPathGenerator( 2506 slowPathCall( 2507 slowCases, this, operationGetByValObjectInt, 2508 JSValueRegs(resultTagReg, resultPayloadReg), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2509 2510 jsValueResult(resultTagReg, resultPayloadReg, node); 2511 break; 2512 } 2513 case Array::ArrayStorage: 2514 case Array::SlowPutArrayStorage: { 2515 if (node->arrayMode().isInBounds()) { 2516 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2517 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2518 GPRReg propertyReg = property.gpr(); 2519 GPRReg storageReg = storage.gpr(); 2520 2521 if (!m_compileOkay) 2522 return; 2523 2524 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()))); 2525 2526 GPRTemporary resultTag(this); 2527 GPRTemporary resultPayload(this); 2528 2529 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr()); 2530 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultTag.gpr())); 2531 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr()); 2532 2533 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 2534 break; 2535 } 2536 2537 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2538 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2539 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2540 GPRReg propertyReg = property.gpr(); 2541 GPRReg storageReg = storage.gpr(); 2542 GPRReg baseReg = base.gpr(); 2543 2544 if (!m_compileOkay) 2545 return; 2546 2547 GPRTemporary resultTag(this); 2548 GPRTemporary resultPayload(this); 2549 GPRReg resultTagReg = resultTag.gpr(); 2550 GPRReg resultPayloadReg = resultPayload.gpr(); 2551 2552 JITCompiler::Jump outOfBounds = m_jit.branch32( 2553 MacroAssembler::AboveOrEqual, propertyReg, 2554 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())); 2555 2556 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg); 2557 JITCompiler::Jump hole = m_jit.branchIfEmpty(resultTag.gpr()); 2558 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg); 2559 2560 JITCompiler::JumpList slowCases; 2561 slowCases.append(outOfBounds); 2562 slowCases.append(hole); 2563 addSlowPathGenerator( 2564 slowPathCall( 2565 slowCases, this, operationGetByValObjectInt, 2566 JSValueRegs(resultTagReg, resultPayloadReg), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), 2567 baseReg, propertyReg)); 2568 2569 jsValueResult(resultTagReg, resultPayloadReg, node); 2570 break; 2571 } 2572 case Array::String: 2573 compileGetByValOnString(node); 2574 break; 2575 case Array::DirectArguments: 2576 compileGetByValOnDirectArguments(node); 2577 break; 2578 case Array::ScopedArguments: 2579 compileGetByValOnScopedArguments(node); 2580 break; 2581 default: { 2582 TypedArrayType type = node->arrayMode().typedArrayType(); 2583 if (isInt(type)) 2584 compileGetByValOnIntTypedArray(node, type); 2585 else 2586 compileGetByValOnFloatTypedArray(node, type); 2587 } } 2620 }; 2621 return std::make_pair(resultRegs, preferredFormat); 2622 })); 2588 2623 break; 2589 2624 } … … 4113 4148 } 4114 4149 4115 case GetEnumerableLength: {4116 compileGetEnumerableLength(node);4117 break;4118 }4119 case HasEnumerableStructureProperty: {4120 compileHasEnumerableStructureProperty(node);4121 break;4122 }4123 case HasEnumerableProperty: {4124 compileHasEnumerableProperty(node);4125 break;4126 }4127 case HasOwnStructureProperty: {4128 compileHasOwnStructureProperty(node);4129 break;4130 }4131 case InStructureProperty: {4132 compileInStructureProperty(node);4133 break;4134 }4135 4150 case HasIndexedProperty: { 4136 compileHasIndexedProperty(node, operationHasIndexedProperty); 4137 break; 4138 } 4139 case HasEnumerableIndexedProperty: { 4140 compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty); 4141 break; 4142 } 4143 case GetDirectPname: { 4144 compileGetDirectPname(node); 4145 break; 4146 } 4151 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1)); 4152 GPRTemporary result(this, Reuse, index); 4153 4154 compileHasIndexedProperty(node, operationHasIndexedProperty, scopedLambda<std::tuple<GPRReg, GPRReg>()>([&] { return std::make_pair(index.gpr(), result.gpr()); })); 4155 unblessedBooleanResult(result.gpr(), node); 4156 break; 4157 } 4158 4147 4159 case GetPropertyEnumerator: { 4148 4160 compileGetPropertyEnumerator(node); 4149 4161 break; 4150 4162 } 4151 case GetEnumeratorStructurePname: 4152 case GetEnumeratorGenericPname: { 4153 compileGetEnumeratorPname(node); 4154 break; 4155 } 4156 case ToIndexString: { 4157 compileToIndexString(node); 4158 break; 4159 } 4163 4164 case EnumeratorNextUpdateIndexAndMode: { 4165 compileEnumeratorNextUpdateIndexAndMode(node); 4166 break; 4167 } 4168 4169 case EnumeratorNextExtractMode: { 4170 compileEnumeratorNextExtractMode(node); 4171 break; 4172 } 4173 4174 case EnumeratorNextExtractIndex: { 4175 compileEnumeratorNextExtractIndex(node); 4176 break; 4177 } 4178 4179 case EnumeratorNextUpdatePropertyName: { 4180 compileEnumeratorNextUpdatePropertyName(node); 4181 break; 4182 } 4183 4184 case EnumeratorGetByVal: { 4185 compileEnumeratorGetByVal(node); 4186 break; 4187 } 4188 4189 case EnumeratorInByVal: { 4190 compileEnumeratorInByVal(node); 4191 break; 4192 } 4193 4194 case EnumeratorHasOwnProperty: { 4195 compileEnumeratorHasOwnProperty(node); 4196 break; 4197 } 4198 4160 4199 case ProfileType: { 4161 4200 compileProfileType(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r279903 r280760 2247 2247 } 2248 2248 2249 void SpeculativeJIT::compileGetByVal(Node* node, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix) 2250 { 2251 switch (node->arrayMode().type()) { 2252 case Array::AnyTypedArray: 2253 case Array::ForceExit: 2254 case Array::SelectUsingArguments: 2255 case Array::SelectUsingPredictions: 2256 case Array::Unprofiled: 2257 DFG_CRASH(m_jit.graph(), node, "Bad array mode type"); 2258 break; 2259 case Array::Undecided: { 2260 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1)); 2261 GPRReg indexGPR = index.gpr(); 2262 2263 JSValueRegs resultRegs; 2264 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2265 2266 speculationCheck(OutOfBounds, JSValueRegs(), node, 2267 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0))); 2268 2269 m_jit.move(MacroAssembler::TrustedImm64(JSValue::ValueUndefined), resultRegs.gpr()); 2270 2271 jsValueResult(resultRegs, node); 2272 break; 2273 } 2274 case Array::BigInt64Array: 2275 case Array::BigUint64Array: 2276 case Array::Generic: { 2277 if (m_graph.m_slowGetByVal.contains(node)) { 2278 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) { 2279 if (m_graph.varArgChild(node, 1).useKind() == StringUse) { 2280 compileGetByValForObjectWithString(node, prefix); 2281 return; 2282 } 2283 2284 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) { 2285 compileGetByValForObjectWithSymbol(node, prefix); 2286 return; 2287 } 2288 } 2289 2290 JSValueOperand base(this, m_graph.varArgChild(node, 0)); 2291 JSValueOperand property(this, m_graph.varArgChild(node, 1)); 2292 GPRReg baseGPR = base.gpr(); 2293 GPRReg propertyGPR = property.gpr(); 2294 2295 JSValueRegs resultRegs; 2296 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2297 2298 flushRegisters(); 2299 callOperation(operationGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyGPR); 2300 m_jit.exceptionCheck(); 2301 2302 jsValueResult(resultRegs, node); 2303 return; 2304 } 2305 2306 JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation); 2307 JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation); 2308 GPRReg baseGPR = base.gpr(); 2309 GPRReg propertyGPR = property.gpr(); 2310 2311 GPRTemporary stubInfo; 2312 GPRReg stubInfoGPR = InvalidGPRReg; 2313 if (JITCode::useDataIC(JITType::DFGJIT)) { 2314 stubInfo = GPRTemporary(this); 2315 stubInfoGPR = stubInfo.gpr(); 2316 } 2317 2318 speculate(node, m_graph.varArgChild(node, 0)); 2319 speculate(node, m_graph.varArgChild(node, 1)); 2320 2321 JSValueRegs resultRegs; 2322 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2323 GPRReg resultGPR = resultRegs.gpr(); 2324 2325 CodeOrigin codeOrigin = node->origin.semantic; 2326 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size()); 2327 RegisterSet usedRegisters = this->usedRegisters(); 2328 2329 JITCompiler::JumpList slowCases; 2330 if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell)) 2331 slowCases.append(m_jit.branchIfNotCell(baseGPR)); 2332 2333 JITGetByValGenerator gen( 2334 m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters, 2335 JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(resultGPR), stubInfoGPR); 2336 2337 if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString)) 2338 gen.stubInfo()->propertyIsString = true; 2339 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only)) 2340 gen.stubInfo()->propertyIsInt32 = true; 2341 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol)) 2342 gen.stubInfo()->propertyIsSymbol = true; 2343 2344 gen.generateFastPath(m_jit); 2345 2346 if (!JITCode::useDataIC(JITType::DFGJIT)) 2347 slowCases.append(gen.slowPathJump()); 2348 2349 std::unique_ptr<SlowPathGenerator> slowPath; 2350 if (JITCode::useDataIC(JITType::DFGJIT)) { 2351 slowPath = slowPathICCall( 2352 slowCases, this, gen.stubInfo(), stubInfoGPR, CCallHelpers::Address(stubInfoGPR, StructureStubInfo::offsetOfSlowOperation()), operationGetByValOptimize, 2353 resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), stubInfoGPR, nullptr, baseGPR, propertyGPR); 2354 } else { 2355 slowPath = slowPathCall( 2356 slowCases, this, operationGetByValOptimize, 2357 resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseGPR, propertyGPR); 2358 } 2359 2360 m_jit.addGetByVal(gen, slowPath.get()); 2361 addSlowPathGenerator(WTFMove(slowPath)); 2362 2363 jsValueResult(resultGPR, node); 2364 break; 2365 } 2366 case Array::Int32: 2367 case Array::Contiguous: { 2368 if (node->arrayMode().isInBounds()) { 2369 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2370 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2371 2372 GPRReg propertyReg = property.gpr(); 2373 GPRReg storageReg = storage.gpr(); 2374 2375 if (!m_compileOkay) 2376 return; 2377 2378 JSValueRegs resultRegs; 2379 DataFormat format; 2380 std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS); 2381 GPRReg result = resultRegs.gpr(); 2382 2383 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2384 2385 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result); 2386 if (node->arrayMode().isInBoundsSaneChain()) { 2387 ASSERT(node->arrayMode().type() == Array::Contiguous); 2388 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(result); 2389 m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result); 2390 notHole.link(&m_jit); 2391 } else { 2392 speculationCheck( 2393 LoadFromHole, JSValueRegs(), nullptr, 2394 m_jit.branchIfEmpty(result)); 2395 } 2396 jsValueResult(result, node, format); 2397 break; 2398 } 2399 2400 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2401 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2402 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2403 2404 GPRReg baseReg = base.gpr(); 2405 GPRReg propertyReg = property.gpr(); 2406 GPRReg storageReg = storage.gpr(); 2407 2408 if (!m_compileOkay) 2409 return; 2410 2411 JSValueRegs resultRegs; 2412 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2413 GPRReg resultReg = resultRegs.gpr(); 2414 2415 MacroAssembler::JumpList slowCases; 2416 2417 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2418 2419 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg); 2420 2421 if (node->arrayMode().isOutOfBoundsSaneChain()) { 2422 auto done = m_jit.branchIfNotEmpty(resultReg); 2423 slowCases.link(&m_jit); 2424 speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0))); 2425 m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), resultReg); 2426 done.link(&m_jit); 2427 } else { 2428 slowCases.append(m_jit.branchIfEmpty(resultReg)); 2429 addSlowPathGenerator( 2430 slowPathCall( 2431 slowCases, this, operationGetByValObjectInt, 2432 resultReg, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2433 } 2434 2435 2436 jsValueResult(resultReg, node); 2437 break; 2438 } 2439 2440 case Array::Double: { 2441 if (node->arrayMode().isInBounds()) { 2442 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2443 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2444 2445 GPRReg propertyReg = property.gpr(); 2446 GPRReg storageReg = storage.gpr(); 2447 2448 if (!m_compileOkay) 2449 return; 2450 2451 FPRTemporary result(this); 2452 FPRReg resultReg = result.fpr(); 2453 2454 JSValueRegs resultRegs; 2455 DataFormat format; 2456 std::tie(resultRegs, format) = prefix(DataFormatDouble); 2457 2458 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2459 2460 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg); 2461 if (!node->arrayMode().isInBoundsSaneChain()) 2462 speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg)); 2463 if (format == DataFormatJS) { 2464 boxDouble(resultReg, resultRegs); 2465 jsValueResult(resultRegs, node); 2466 } else { 2467 ASSERT(format == DataFormatDouble && !resultRegs); 2468 doubleResult(resultReg, node); 2469 } 2470 break; 2471 } 2472 2473 bool resultIsUnboxed = node->arrayMode().isOutOfBoundsSaneChain() && !(node->flags() & NodeBytecodeUsesAsOther); 2474 2475 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2476 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2477 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2478 2479 GPRReg baseReg = base.gpr(); 2480 GPRReg propertyReg = property.gpr(); 2481 GPRReg storageReg = storage.gpr(); 2482 2483 if (!m_compileOkay) 2484 return; 2485 2486 FPRTemporary temp(this); 2487 FPRReg tempReg = temp.fpr(); 2488 2489 JSValueRegs resultRegs; 2490 DataFormat format; 2491 std::tie(resultRegs, format) = prefix(resultIsUnboxed ? DataFormatDouble : DataFormatJS); 2492 2493 MacroAssembler::JumpList slowCases; 2494 2495 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2496 2497 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg); 2498 if (node->arrayMode().isOutOfBoundsSaneChain()) { 2499 if (format == DataFormatDouble) { 2500 auto done = m_jit.jump(); 2501 slowCases.link(&m_jit); 2502 speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0))); 2503 static const double NaN = PNaN; 2504 m_jit.loadDouble(TrustedImmPtr(&NaN), tempReg); 2505 done.link(&m_jit); 2506 ASSERT(!resultRegs); 2507 doubleResult(tempReg, node); 2508 } else { 2509 slowCases.append(m_jit.branchIfNaN(tempReg)); 2510 boxDouble(tempReg, resultRegs.gpr()); 2511 auto done = m_jit.jump(); 2512 slowCases.link(&m_jit); 2513 speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0))); 2514 m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), resultRegs.gpr()); 2515 done.link(&m_jit); 2516 jsValueResult(resultRegs.gpr(), node); 2517 } 2518 } else { 2519 slowCases.append(m_jit.branchIfNaN(tempReg)); 2520 boxDouble(tempReg, resultRegs.gpr()); 2521 addSlowPathGenerator( 2522 slowPathCall( 2523 slowCases, this, operationGetByValObjectInt, 2524 resultRegs.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2525 jsValueResult(resultRegs.gpr(), node); 2526 } 2527 2528 break; 2529 } 2530 2531 case Array::ArrayStorage: 2532 case Array::SlowPutArrayStorage: { 2533 if (node->arrayMode().isInBounds()) { 2534 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2535 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2536 2537 GPRReg propertyReg = property.gpr(); 2538 GPRReg storageReg = storage.gpr(); 2539 2540 if (!m_compileOkay) 2541 return; 2542 2543 JSValueRegs resultRegs; 2544 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2545 GPRReg resultGPR = resultRegs.gpr(); 2546 2547 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()))); 2548 2549 2550 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultGPR); 2551 speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfEmpty(resultGPR)); 2552 2553 jsValueResult(resultGPR, node); 2554 break; 2555 } 2556 2557 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2558 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2559 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2560 2561 GPRReg baseReg = base.gpr(); 2562 GPRReg propertyReg = property.gpr(); 2563 GPRReg storageReg = storage.gpr(); 2564 2565 if (!m_compileOkay) 2566 return; 2567 2568 JSValueRegs resultRegs; 2569 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2570 GPRReg resultReg = resultRegs.gpr(); 2571 2572 MacroAssembler::JumpList slowCases; 2573 2574 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()))); 2575 2576 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg); 2577 slowCases.append(m_jit.branchIfEmpty(resultReg)); 2578 2579 addSlowPathGenerator( 2580 slowPathCall( 2581 slowCases, this, operationGetByValObjectInt, 2582 resultReg, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2583 2584 jsValueResult(resultReg, node); 2585 break; 2586 } 2587 case Array::String: 2588 compileGetByValOnString(node, prefix); 2589 break; 2590 case Array::DirectArguments: 2591 compileGetByValOnDirectArguments(node, prefix); 2592 break; 2593 case Array::ScopedArguments: 2594 compileGetByValOnScopedArguments(node, prefix); 2595 break; 2596 case Array::Int8Array: 2597 case Array::Int16Array: 2598 case Array::Int32Array: 2599 case Array::Uint8Array: 2600 case Array::Uint8ClampedArray: 2601 case Array::Uint16Array: 2602 case Array::Uint32Array: 2603 case Array::Float32Array: 2604 case Array::Float64Array: { 2605 TypedArrayType type = node->arrayMode().typedArrayType(); 2606 if (isInt(type)) 2607 compileGetByValOnIntTypedArray(node, type, prefix); 2608 else 2609 compileGetByValOnFloatTypedArray(node, type, prefix); 2610 } } 2611 } 2612 2249 2613 void SpeculativeJIT::compile(Node* node) 2250 2614 { … … 2714 3078 case StringCharAt: { 2715 3079 // Relies on StringCharAt node having same basic layout as GetByVal 2716 compileGetByValOnString(node); 3080 JSValueRegsTemporary result; 3081 compileGetByValOnString(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) { 3082 result = JSValueRegsTemporary(this); 3083 ASSERT(preferredFormat == DataFormatJS || preferredFormat == DataFormatCell); 3084 return std::make_pair(result.regs(), preferredFormat); 3085 })); 2717 3086 break; 2718 3087 } … … 2747 3116 2748 3117 case GetByVal: { 2749 switch (node->arrayMode().type()) { 2750 case Array::AnyTypedArray: 2751 case Array::ForceExit: 2752 case Array::SelectUsingArguments: 2753 case Array::SelectUsingPredictions: 2754 case Array::Unprofiled: 2755 DFG_CRASH(m_jit.graph(), node, "Bad array mode type"); 2756 break; 2757 case Array::Undecided: { 2758 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1)); 2759 GPRTemporary result(this, Reuse, index); 2760 GPRReg indexGPR = index.gpr(); 2761 GPRReg resultGPR = result.gpr(); 2762 2763 speculationCheck(OutOfBounds, JSValueRegs(), node, 2764 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0))); 2765 2766 use(m_graph.varArgChild(node, 0)); 2767 index.use(); 2768 2769 m_jit.move(MacroAssembler::TrustedImm64(JSValue::ValueUndefined), resultGPR); 2770 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 2771 break; 2772 } 2773 case Array::BigInt64Array: 2774 case Array::BigUint64Array: 2775 case Array::Generic: { 2776 if (m_graph.m_slowGetByVal.contains(node)) { 2777 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) { 2778 if (m_graph.varArgChild(node, 1).useKind() == StringUse) { 2779 compileGetByValForObjectWithString(node); 2780 break; 2781 } 2782 2783 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) { 2784 compileGetByValForObjectWithSymbol(node); 2785 break; 2786 } 2787 } 2788 2789 JSValueOperand base(this, m_graph.varArgChild(node, 0)); 2790 JSValueOperand property(this, m_graph.varArgChild(node, 1)); 2791 GPRReg baseGPR = base.gpr(); 2792 GPRReg propertyGPR = property.gpr(); 2793 2794 flushRegisters(); 2795 GPRFlushedCallResult result(this); 2796 callOperation(operationGetByVal, result.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyGPR); 2797 m_jit.exceptionCheck(); 2798 2799 jsValueResult(result.gpr(), node); 3118 JSValueRegsTemporary result; 3119 compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>([&] (DataFormat preferredFormat) { 3120 JSValueRegs resultRegs; 3121 switch (preferredFormat) { 3122 case DataFormatDouble: 3123 break; 3124 default: { 3125 result = JSValueRegsTemporary(this); 3126 resultRegs = result.regs(); 2800 3127 break; 2801 3128 } 2802 2803 std::optional<GPRTemporary> stubInfo; 2804 JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation); 2805 JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation); 2806 GPRTemporary result(this, Reuse, property); 2807 2808 GPRReg stubInfoGPR = InvalidGPRReg; 2809 if (JITCode::useDataIC(JITType::DFGJIT)) { 2810 stubInfo.emplace(this); 2811 stubInfoGPR = stubInfo->gpr(); 2812 } 2813 GPRReg baseGPR = base.gpr(); 2814 GPRReg propertyGPR = property.gpr(); 2815 GPRReg resultGPR = result.gpr(); 2816 2817 speculate(node, m_graph.varArgChild(node, 0)); 2818 speculate(node, m_graph.varArgChild(node, 1)); 2819 2820 CodeOrigin codeOrigin = node->origin.semantic; 2821 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size()); 2822 RegisterSet usedRegisters = this->usedRegisters(); 2823 2824 JITCompiler::JumpList slowCases; 2825 if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell)) 2826 slowCases.append(m_jit.branchIfNotCell(baseGPR)); 2827 2828 JITGetByValGenerator gen( 2829 m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters, 2830 JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(resultGPR), stubInfoGPR); 2831 2832 if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString)) 2833 gen.stubInfo()->propertyIsString = true; 2834 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only)) 2835 gen.stubInfo()->propertyIsInt32 = true; 2836 else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol)) 2837 gen.stubInfo()->propertyIsSymbol = true; 2838 2839 gen.generateFastPath(m_jit); 2840 2841 if (!JITCode::useDataIC(JITType::DFGJIT)) 2842 slowCases.append(gen.slowPathJump()); 2843 2844 std::unique_ptr<SlowPathGenerator> slowPath; 2845 if (JITCode::useDataIC(JITType::DFGJIT)) { 2846 slowPath = slowPathICCall( 2847 slowCases, this, gen.stubInfo(), stubInfoGPR, CCallHelpers::Address(stubInfoGPR, StructureStubInfo::offsetOfSlowOperation()), operationGetByValOptimize, 2848 resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), stubInfoGPR, nullptr, baseGPR, propertyGPR); 2849 } else { 2850 slowPath = slowPathCall( 2851 slowCases, this, operationGetByValOptimize, 2852 resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseGPR, propertyGPR); 2853 } 2854 2855 m_jit.addGetByVal(gen, slowPath.get()); 2856 addSlowPathGenerator(WTFMove(slowPath)); 2857 2858 jsValueResult(resultGPR, node); 2859 break; 2860 } 2861 case Array::Int32: 2862 case Array::Contiguous: { 2863 if (node->arrayMode().isInBounds()) { 2864 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2865 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2866 2867 GPRReg propertyReg = property.gpr(); 2868 GPRReg storageReg = storage.gpr(); 2869 2870 if (!m_compileOkay) 2871 return; 2872 2873 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2874 2875 GPRTemporary result(this); 2876 2877 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr()); 2878 if (node->arrayMode().isInBoundsSaneChain()) { 2879 ASSERT(node->arrayMode().type() == Array::Contiguous); 2880 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(result.gpr()); 2881 m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr()); 2882 notHole.link(&m_jit); 2883 } else { 2884 speculationCheck( 2885 LoadFromHole, JSValueRegs(), nullptr, 2886 m_jit.branchIfEmpty(result.gpr())); 2887 } 2888 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS); 2889 break; 2890 } 2891 2892 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2893 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2894 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2895 2896 GPRReg baseReg = base.gpr(); 2897 GPRReg propertyReg = property.gpr(); 2898 GPRReg storageReg = storage.gpr(); 2899 2900 if (!m_compileOkay) 2901 return; 2902 2903 GPRTemporary result(this); 2904 GPRReg resultReg = result.gpr(); 2905 2906 MacroAssembler::JumpList slowCases; 2907 2908 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2909 2910 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg); 2911 2912 if (node->arrayMode().isOutOfBoundsSaneChain()) { 2913 auto done = m_jit.branchIfNotEmpty(resultReg); 2914 slowCases.link(&m_jit); 2915 speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0))); 2916 m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), resultReg); 2917 done.link(&m_jit); 2918 } else { 2919 slowCases.append(m_jit.branchIfEmpty(resultReg)); 2920 addSlowPathGenerator( 2921 slowPathCall( 2922 slowCases, this, operationGetByValObjectInt, 2923 result.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 2924 } 2925 2926 2927 jsValueResult(resultReg, node); 2928 break; 2929 } 2930 2931 case Array::Double: { 2932 if (node->arrayMode().isInBounds()) { 2933 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2934 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2935 2936 GPRReg propertyReg = property.gpr(); 2937 GPRReg storageReg = storage.gpr(); 2938 2939 if (!m_compileOkay) 2940 return; 2941 2942 FPRTemporary result(this); 2943 FPRReg resultReg = result.fpr(); 2944 2945 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2946 2947 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg); 2948 if (!node->arrayMode().isInBoundsSaneChain()) 2949 speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg)); 2950 doubleResult(resultReg, node); 2951 break; 2952 } 2953 2954 bool resultIsUnboxed = node->arrayMode().isOutOfBoundsSaneChain() && !(node->flags() & NodeBytecodeUsesAsOther); 2955 2956 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 2957 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2958 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2959 2960 GPRReg baseReg = base.gpr(); 2961 GPRReg propertyReg = property.gpr(); 2962 GPRReg storageReg = storage.gpr(); 2963 2964 if (!m_compileOkay) 2965 return; 2966 2967 std::optional<GPRTemporary> result; 2968 std::optional<GPRReg> resultReg; 2969 if (!resultIsUnboxed) { 2970 result.emplace(this); 2971 resultReg = result->gpr(); 2972 } 2973 FPRTemporary temp(this); 2974 FPRReg tempReg = temp.fpr(); 2975 2976 MacroAssembler::JumpList slowCases; 2977 2978 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2979 2980 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg); 2981 if (node->arrayMode().isOutOfBoundsSaneChain()) { 2982 if (resultIsUnboxed) { 2983 auto done = m_jit.jump(); 2984 slowCases.link(&m_jit); 2985 speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0))); 2986 static const double NaN = PNaN; 2987 m_jit.loadDouble(TrustedImmPtr(&NaN), tempReg); 2988 done.link(&m_jit); 2989 doubleResult(tempReg, node); 2990 } else { 2991 slowCases.append(m_jit.branchIfNaN(tempReg)); 2992 boxDouble(tempReg, *resultReg); 2993 auto done = m_jit.jump(); 2994 slowCases.link(&m_jit); 2995 speculationCheck(NegativeIndex, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::LessThan, propertyReg, CCallHelpers::TrustedImm32(0))); 2996 m_jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), *resultReg); 2997 done.link(&m_jit); 2998 jsValueResult(*resultReg, node); 2999 } 3000 } else { 3001 slowCases.append(m_jit.branchIfNaN(tempReg)); 3002 boxDouble(tempReg, *resultReg); 3003 addSlowPathGenerator( 3004 slowPathCall( 3005 slowCases, this, operationGetByValObjectInt, 3006 *resultReg, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 3007 jsValueResult(*resultReg, node); 3008 } 3009 3010 break; 3011 } 3012 3013 case Array::ArrayStorage: 3014 case Array::SlowPutArrayStorage: { 3015 if (node->arrayMode().isInBounds()) { 3016 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 3017 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 3018 3019 GPRReg propertyReg = property.gpr(); 3020 GPRReg storageReg = storage.gpr(); 3021 3022 if (!m_compileOkay) 3023 return; 3024 3025 speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()))); 3026 3027 GPRTemporary result(this); 3028 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr()); 3029 speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfEmpty(result.gpr())); 3030 3031 jsValueResult(result.gpr(), node); 3032 break; 3033 } 3034 3035 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); 3036 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 3037 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 3038 3039 GPRReg baseReg = base.gpr(); 3040 GPRReg propertyReg = property.gpr(); 3041 GPRReg storageReg = storage.gpr(); 3042 3043 if (!m_compileOkay) 3044 return; 3045 3046 GPRTemporary result(this); 3047 GPRReg resultReg = result.gpr(); 3048 3049 MacroAssembler::JumpList slowCases; 3050 3051 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()))); 3052 3053 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg); 3054 slowCases.append(m_jit.branchIfEmpty(resultReg)); 3055 3056 addSlowPathGenerator( 3057 slowPathCall( 3058 slowCases, this, operationGetByValObjectInt, 3059 result.gpr(), TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg)); 3060 3061 jsValueResult(resultReg, node); 3062 break; 3063 } 3064 case Array::String: 3065 compileGetByValOnString(node); 3066 break; 3067 case Array::DirectArguments: 3068 compileGetByValOnDirectArguments(node); 3069 break; 3070 case Array::ScopedArguments: 3071 compileGetByValOnScopedArguments(node); 3072 break; 3073 case Array::Int8Array: 3074 case Array::Int16Array: 3075 case Array::Int32Array: 3076 case Array::Uint8Array: 3077 case Array::Uint8ClampedArray: 3078 case Array::Uint16Array: 3079 case Array::Uint32Array: 3080 case Array::Float32Array: 3081 case Array::Float64Array: { 3082 TypedArrayType type = node->arrayMode().typedArrayType(); 3083 if (isInt(type)) 3084 compileGetByValOnIntTypedArray(node, type); 3085 else 3086 compileGetByValOnFloatTypedArray(node, type); 3087 } } 3129 }; 3130 return std::make_pair(resultRegs, preferredFormat); 3131 })); 3088 3132 break; 3089 3133 } … … 3582 3626 } 3583 3627 constexpr bool canSpeculate = false; 3584 setIntTypedArrayLoadResult(node, resultGPR, type, canSpeculate); 3628 constexpr bool shouldBox = false; 3629 setIntTypedArrayLoadResult(node, JSValueRegs(resultGPR), type, canSpeculate, shouldBox); 3585 3630 break; 3586 3631 } … … 5270 5315 break; 5271 5316 } 5272 5273 case GetEnumerableLength: { 5274 compileGetEnumerableLength(node); 5275 break; 5276 } 5277 case HasEnumerableStructureProperty: { 5278 compileHasEnumerableStructureProperty(node); 5279 break; 5280 } 5281 case HasEnumerableProperty: { 5282 compileHasEnumerableProperty(node); 5283 break; 5284 } 5285 case HasOwnStructureProperty: { 5286 compileHasOwnStructureProperty(node); 5287 break; 5288 } 5289 case InStructureProperty: { 5290 compileInStructureProperty(node); 5291 break; 5292 } 5317 5293 5318 case HasIndexedProperty: { 5294 compileHasIndexedProperty(node, operationHasIndexedProperty); 5295 break; 5296 } 5297 case HasEnumerableIndexedProperty: { 5298 compileHasIndexedProperty(node, operationHasEnumerableIndexedProperty); 5299 break; 5300 } 5301 case GetDirectPname: { 5302 compileGetDirectPname(node); 5303 break; 5304 } 5319 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1)); 5320 GPRTemporary result(this, Reuse, index); 5321 5322 compileHasIndexedProperty(node, operationHasIndexedProperty, scopedLambda<std::tuple<GPRReg, GPRReg>()>([&] { return std::make_pair(index.gpr(), result.gpr()); })); 5323 unblessedBooleanResult(result.gpr(), node); 5324 break; 5325 } 5326 5305 5327 case GetPropertyEnumerator: { 5306 5328 compileGetPropertyEnumerator(node); 5307 5329 break; 5308 5330 } 5309 case GetEnumeratorStructurePname: 5310 case GetEnumeratorGenericPname: { 5311 compileGetEnumeratorPname(node); 5312 break; 5313 } 5314 case ToIndexString: { 5315 compileToIndexString(node); 5316 break; 5317 } 5331 5332 case EnumeratorNextUpdateIndexAndMode: { 5333 compileEnumeratorNextUpdateIndexAndMode(node); 5334 break; 5335 } 5336 5337 case EnumeratorNextExtractMode: { 5338 compileEnumeratorNextExtractMode(node); 5339 break; 5340 } 5341 5342 case EnumeratorNextExtractIndex: { 5343 compileEnumeratorNextExtractIndex(node); 5344 break; 5345 } 5346 5347 case EnumeratorNextUpdatePropertyName: { 5348 compileEnumeratorNextUpdatePropertyName(node); 5349 break; 5350 } 5351 5352 case EnumeratorGetByVal: { 5353 compileEnumeratorGetByVal(node); 5354 break; 5355 } 5356 5357 case EnumeratorInByVal: { 5358 compileEnumeratorInByVal(node); 5359 break; 5360 } 5361 5362 case EnumeratorHasOwnProperty: { 5363 compileEnumeratorHasOwnProperty(node); 5364 break; 5365 } 5366 5318 5367 case ProfileType: { 5319 5368 compileProfileType(node); -
trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
r278253 r280760 274 274 case NukeStructureAndSetButterfly: 275 275 case GetButterfly: 276 case EnumeratorGetByVal: 276 277 case GetByVal: 277 278 case PutByValDirect: … … 353 354 case ReallocatePropertyStorage: 354 355 case GetButterfly: 356 case EnumeratorGetByVal: 355 357 case GetByVal: 356 358 case PutByValDirect: -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r278462 r280760 115 115 macro(JSPropertyNameEnumerator_endStructurePropertyIndex, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()) \ 116 116 macro(JSPropertyNameEnumerator_indexLength, JSPropertyNameEnumerator::indexedLengthOffset()) \ 117 macro(JSPropertyNameEnumerator_modeSet, JSPropertyNameEnumerator::modeSetOffset()) \ 117 118 macro(JSRopeString_flags, JSRopeString::offsetOfFlags()) \ 118 119 macro(JSRopeString_length, JSRopeString::offsetOfLength()) \ -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r279604 r280760 287 287 case BooleanToNumber: 288 288 case HasIndexedProperty: 289 case HasEnumerableIndexedProperty:290 case HasEnumerableStructureProperty:291 case HasEnumerableProperty:292 case HasOwnStructureProperty:293 case InStructureProperty:294 case GetDirectPname:295 case GetEnumerableLength:296 289 case GetIndexedPropertyStorage: 297 290 case GetPropertyEnumerator: 298 case GetEnumeratorStructurePname: 299 case GetEnumeratorGenericPname: 300 case ToIndexString: 291 case EnumeratorNextUpdateIndexAndMode: 292 case EnumeratorNextExtractMode: 293 case EnumeratorNextExtractIndex: 294 case EnumeratorNextUpdatePropertyName: 295 case EnumeratorGetByVal: 296 case EnumeratorInByVal: 297 case EnumeratorHasOwnProperty: 301 298 case BottomValue: 302 299 case PhantomNewObject: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r280198 r280760 1524 1524 break; 1525 1525 case HasIndexedProperty: 1526 compileHasIndexedProperty(operationHasIndexedProperty); 1527 break; 1528 case HasEnumerableIndexedProperty: 1529 compileHasIndexedProperty(operationHasEnumerableIndexedProperty); 1530 break; 1531 case HasEnumerableStructureProperty: 1532 compileHasEnumerableStructureProperty(); 1533 break; 1534 case HasEnumerableProperty: 1535 compileHasEnumerableProperty(); 1536 break; 1537 case HasOwnStructureProperty: 1538 compileHasOwnStructureProperty(); 1539 break; 1540 case InStructureProperty: 1541 compileInStructureProperty(); 1542 break; 1543 case GetDirectPname: 1544 compileGetDirectPname(); 1545 break; 1546 case GetEnumerableLength: 1547 compileGetEnumerableLength(); 1526 compileHasIndexedProperty(); 1548 1527 break; 1549 1528 case GetPropertyEnumerator: 1550 1529 compileGetPropertyEnumerator(); 1551 1530 break; 1552 case GetEnumeratorStructurePname: 1553 compileGetEnumeratorStructurePname(); 1554 break; 1555 case GetEnumeratorGenericPname: 1556 compileGetEnumeratorGenericPname(); 1557 break; 1558 case ToIndexString: 1559 compileToIndexString(); 1531 case EnumeratorNextUpdateIndexAndMode: 1532 compileEnumeratorNextUpdateIndexAndMode(); 1533 break; 1534 case EnumeratorNextExtractIndex: 1535 compileEnumeratorNextExtractIndex(); 1536 break; 1537 case EnumeratorNextExtractMode: 1538 compileEnumeratorNextExtractMode(); 1539 break; 1540 case EnumeratorNextUpdatePropertyName: 1541 compileEnumeratorNextUpdatePropertyName(); 1542 break; 1543 case EnumeratorGetByVal: 1544 compileEnumeratorGetByVal(); 1545 break; 1546 case EnumeratorInByVal: 1547 compileEnumeratorInByVal(); 1548 break; 1549 case EnumeratorHasOwnProperty: 1550 compileEnumeratorHasOwnProperty(); 1560 1551 break; 1561 1552 case CheckStructureImmediate: … … 5021 5012 } 5022 5013 5023 void compileGetByVal()5014 LValue compileGetByValImpl() 5024 5015 { 5025 5016 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); … … 5048 5039 if (m_node->arrayMode().type() == Array::Contiguous) 5049 5040 ensureStillAliveHere(base); 5050 setJSValue(result); 5051 return; 5041 return result; 5052 5042 } 5053 5043 … … 5081 5071 if (m_node->arrayMode().type() == Array::Contiguous) 5082 5072 ensureStillAliveHere(base); 5083 setJSValue(m_out.phi(Int64, fastResult, slowResult)); 5084 return; 5073 return m_out.phi(Int64, fastResult, slowResult); 5085 5074 } 5086 5075 … … 5101 5090 m_out.doubleNotEqualOrUnordered(result, result)); 5102 5091 } 5103 setDouble(result); 5104 break;5092 5093 return result; 5105 5094 } 5106 5095 … … 5142 5131 m_out.appendTo(continuation, lastNext); 5143 5132 if (resultIsUnboxed) 5144 setDouble(m_out.phi(Double, fastResult, slowResult)); 5145 else 5146 setJSValue(m_out.phi(Int64, fastResult, slowResult)); 5147 return; 5133 return m_out.phi(Double, fastResult, slowResult); 5134 5135 return m_out.phi(Int64, fastResult, slowResult); 5148 5136 } 5149 5137 … … 5152 5140 5153 5141 speculate(OutOfBounds, noValue(), m_node, m_out.lessThan(index, m_out.int32Zero)); 5154 setJSValue(m_out.constInt64(JSValue::ValueUndefined)); 5155 return; 5142 return m_out.constInt64(JSValue::ValueUndefined); 5156 5143 } 5157 5144 … … 5170 5157 TypedPointer address = m_out.baseIndex( 5171 5158 m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index)); 5172 setJSValue(m_out.load64(address)); 5173 return; 5159 return m_out.load64(address); 5174 5160 } 5175 5161 … … 5193 5179 5194 5180 m_out.appendTo(continuation, lastNext); 5195 setJSValue(m_out.phi(Int64, fastResult, slowResult)); 5196 return; 5181 return m_out.phi(Int64, fastResult, slowResult); 5197 5182 } 5198 5183 … … 5247 5232 5248 5233 m_out.appendTo(continuation, lastNext); 5249 setJSValue(m_out.phi(Int64, namedResult, overflowResult)); 5250 return; 5234 return m_out.phi(Int64, namedResult, overflowResult); 5251 5235 } 5252 5236 … … 5257 5241 if (m_graph.varArgChild(m_node, 0).useKind() == ObjectUse) { 5258 5242 if (m_graph.varArgChild(m_node, 1).useKind() == StringUse) { 5259 setJSValue(vmCall(5243 return vmCall( 5260 5244 Int64, operationGetByValObjectString, weakPointer(globalObject), 5261 lowObject(m_graph.varArgChild(m_node, 0)), lowString(m_graph.varArgChild(m_node, 1)))); 5262 return; 5245 lowObject(m_graph.varArgChild(m_node, 0)), lowString(m_graph.varArgChild(m_node, 1))); 5263 5246 } 5264 5247 5265 5248 if (m_graph.varArgChild(m_node, 1).useKind() == SymbolUse) { 5266 setJSValue(vmCall(5249 return vmCall( 5267 5250 Int64, operationGetByValObjectSymbol, weakPointer(globalObject), 5268 lowObject(m_graph.varArgChild(m_node, 0)), lowSymbol(m_graph.varArgChild(m_node, 1)))); 5269 return; 5251 lowObject(m_graph.varArgChild(m_node, 0)), lowSymbol(m_graph.varArgChild(m_node, 1))); 5270 5252 } 5271 5253 } 5272 5254 5273 setJSValue(vmCall(5255 return vmCall( 5274 5256 Int64, operationGetByVal, weakPointer(globalObject), 5275 lowJSValue(m_graph.varArgChild(m_node, 0)), lowJSValue(m_graph.varArgChild(m_node, 1)))); 5276 return; 5257 lowJSValue(m_graph.varArgChild(m_node, 0)), lowJSValue(m_graph.varArgChild(m_node, 1))); 5277 5258 } 5278 5259 … … 5374 5355 }); 5375 5356 5376 setJSValue(patchpoint); 5377 return; 5357 return patchpoint; 5378 5358 } 5379 5359 … … 5391 5371 // We have to keep base alive to keep content in storage alive. 5392 5372 ensureStillAliveHere(base); 5393 setJSValue(result); 5394 return; 5373 return result; 5395 5374 } 5396 5375 … … 5418 5397 // We have to keep base alive to keep content in storage alive. 5419 5398 ensureStillAliveHere(base); 5420 setJSValue(m_out.phi(Int64, fastResult, slowResult)); 5421 return; 5399 return m_out.phi(Int64, fastResult, slowResult); 5422 5400 } 5423 5401 5424 5402 case Array::String: { 5425 compileStringCharAt(); 5426 return; 5403 return compileStringCharAtImpl(); 5427 5404 } 5428 5405 … … 5449 5426 // We have to keep base alive since that keeps storage alive. 5450 5427 ensureStillAliveHere(base); 5451 constexpr bool canSpeculate = true; 5452 setIntTypedArrayLoadResult(result, type, canSpeculate); 5453 return; 5428 return result; 5454 5429 } 5455 5430 … … 5470 5445 // We have to keep base alive since that keeps storage alive. 5471 5446 ensureStillAliveHere(base); 5472 setDouble(result); 5473 return; 5447 return result; 5474 5448 } 5475 5449 } … … 5481 5455 case Array::Unprofiled: 5482 5456 DFG_CRASH(m_graph, m_node, "Bad array type"); 5457 return nullptr; 5458 } 5459 } 5460 5461 void compileGetByVal() 5462 { 5463 LValue result = compileGetByValImpl(); 5464 TypedArrayType type = m_node->arrayMode().typedArrayType(); 5465 if (isInt(type)) { 5466 constexpr bool canSpeculate = true; 5467 setIntTypedArrayLoadResult(result, type, canSpeculate); 5483 5468 return; 5484 5469 } 5470 5471 if (result->type() == Double) 5472 setDouble(result); 5473 else 5474 setJSValue(result); 5485 5475 } 5486 5476 … … 8572 8562 } 8573 8563 8574 void compileStringCharAt()8564 LValue compileStringCharAtImpl() 8575 8565 { 8576 8566 LValue base = lowString(m_graph.child(m_node, 0)); … … 8680 8670 // We have to keep base alive since that keeps storage alive. 8681 8671 ensureStillAliveHere(base); 8682 setJSValue(m_out.phi(Int64, results)); 8672 return m_out.phi(Int64, results); 8673 } 8674 8675 void compileStringCharAt() 8676 { 8677 setJSValue(compileStringCharAtImpl()); 8683 8678 } 8684 8679 … … 12907 12902 } 12908 12903 12909 void compileHasIndexedProperty(S_JITOperation_GCZ slowPathOperation)12904 LValue compileHasIndexedPropertyImpl(LValue index, S_JITOperation_GCZ slowPathOperation) 12910 12905 { 12911 12906 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 12912 12907 LValue base = lowCell(m_graph.varArgChild(m_node, 0)); 12913 LValue index = lowInt32(m_graph.varArgChild(m_node, 1));12914 12908 ArrayMode mode = m_node->arrayMode(); 12915 12909 … … 12917 12911 case Array::Int32: 12918 12912 case Array::Contiguous: { 12919 LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));12913 LValue storage = lowStorage(m_graph.varArgChild(m_node, m_node->storageChildIndex())); 12920 12914 12921 12915 IndexedAbstractHeap& heap = mode.type() == Array::Int32 ? … … 12952 12946 12953 12947 m_out.appendTo(continuation, lastNext); 12954 setBoolean(m_out.phi(Int32, checkHoleResult, slowResult)); 12955 return; 12948 return m_out.phi(Int32, checkHoleResult, slowResult); 12956 12949 } 12957 12950 case Array::Double: { 12958 LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));12951 LValue storage = lowStorage(m_graph.varArgChild(m_node, m_node->storageChildIndex())); 12959 12952 12960 12953 IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties; … … 12990 12983 12991 12984 m_out.appendTo(continuation, lastNext); 12992 setBoolean(m_out.phi(Int32, checkHoleResult, slowResult)); 12993 return; 12985 return m_out.phi(Int32, checkHoleResult, slowResult); 12994 12986 } 12995 12987 12996 12988 case Array::ArrayStorage: { 12997 LValue storage = lowStorage(m_graph.varArgChild(m_node, 2));12989 LValue storage = lowStorage(m_graph.varArgChild(m_node, m_node->storageChildIndex())); 12998 12990 12999 12991 LBasicBlock slowCase = m_out.newBlock(); … … 13027 13019 13028 13020 m_out.appendTo(continuation, lastNext); 13029 setBoolean(m_out.phi(Int32, checkHoleResult, slowResult)); 13030 break; 13021 return m_out.phi(Int32, checkHoleResult, slowResult); 13031 13022 } 13032 13023 13033 13024 default: { 13034 setBoolean(m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index))); 13035 break; 13036 } 13037 } 13038 } 13039 13040 void compileHasEnumerableProperty() 13041 { 13042 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 13043 LValue base = lowJSValue(m_node->child1()); 13044 LValue property = lowCell(m_node->child2()); 13045 setJSValue(vmCall(Int64, operationHasEnumerableProperty, weakPointer(globalObject), base, property)); 13046 } 13047 13048 template <typename SlowPathCall> 13049 void compileHasStructurePropertyImpl(LValue base, SlowPathCall slowPathCall) 13050 { 13051 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 13052 LValue property = lowString(m_node->child2()); 13053 LValue enumerator = lowCell(m_node->child3()); 13054 13055 LBasicBlock isCellCase = m_out.newBlock(); 13056 LBasicBlock correctStructure = m_out.newBlock(); 13057 LBasicBlock slowPath = m_out.newBlock(); 13058 LBasicBlock continuation = m_out.newBlock(); 13059 13060 m_out.branch(isCell(base, provenType(m_node->child1())), 13061 usually(isCellCase), rarely(slowPath)); 13062 13063 LBasicBlock lastNext = m_out.appendTo(isCellCase, correctStructure); 13064 13065 m_out.branch(m_out.notEqual( 13066 m_out.load32(base, m_heaps.JSCell_structureID), 13067 m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)), 13068 rarely(slowPath), usually(correctStructure)); 13069 13070 m_out.appendTo(correctStructure, slowPath); 13071 ValueFromBlock correctStructureResult = m_out.anchor(m_out.booleanTrue); 13072 m_out.jump(continuation); 13073 13074 m_out.appendTo(slowPath, continuation); 13075 ValueFromBlock slowPathResult = m_out.anchor( 13076 m_out.equal( 13077 m_out.constInt64(JSValue::encode(jsBoolean(true))), 13078 vmCall(Int64, slowPathCall, weakPointer(globalObject), base, property))); 13079 m_out.jump(continuation); 13080 13081 m_out.appendTo(continuation, lastNext); 13082 setBoolean(m_out.phi(Int32, correctStructureResult, slowPathResult)); 13083 } 13084 13085 void compileHasEnumerableStructureProperty() 13086 { 13087 compileHasStructurePropertyImpl(lowJSValue(m_node->child1()), operationHasEnumerableProperty); 13088 } 13089 13090 void compileHasOwnStructureProperty() 13091 { 13092 compileHasStructurePropertyImpl(lowCell(m_node->child1()), operationHasOwnStructureProperty); 13093 } 13094 13095 void compileInStructureProperty() 13096 { 13097 compileHasStructurePropertyImpl(lowCell(m_node->child1()), operationInStructureProperty); 13098 } 13099 13100 void compileGetDirectPname() 13101 { 13102 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 13103 LValue base = lowCell(m_graph.varArgChild(m_node, 0)); 13104 LValue property = lowCell(m_graph.varArgChild(m_node, 1)); 13105 LValue index = lowInt32(m_graph.varArgChild(m_node, 2)); 13106 LValue enumerator = lowCell(m_graph.varArgChild(m_node, 3)); 13107 13108 LBasicBlock checkOffset = m_out.newBlock(); 13109 LBasicBlock inlineLoad = m_out.newBlock(); 13110 LBasicBlock outOfLineLoad = m_out.newBlock(); 13111 LBasicBlock slowCase = m_out.newBlock(); 13112 LBasicBlock continuation = m_out.newBlock(); 13113 13114 m_out.branch(m_out.notEqual( 13115 m_out.load32(base, m_heaps.JSCell_structureID), 13116 m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)), 13117 rarely(slowCase), usually(checkOffset)); 13118 13119 LBasicBlock lastNext = m_out.appendTo(checkOffset, inlineLoad); 13120 m_out.branch(m_out.aboveOrEqual(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity)), 13121 unsure(outOfLineLoad), unsure(inlineLoad)); 13122 13123 m_out.appendTo(inlineLoad, outOfLineLoad); 13124 ValueFromBlock inlineResult = m_out.anchor( 13125 m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), 13126 base, m_out.zeroExt(index, Int64), ScaleEight, JSObject::offsetOfInlineStorage()))); 13127 m_out.jump(continuation); 13128 13129 m_out.appendTo(outOfLineLoad, slowCase); 13130 LValue storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly); 13131 LValue realIndex = m_out.signExt32To64( 13132 m_out.neg(m_out.sub(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity)))); 13133 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); 13134 ValueFromBlock outOfLineResult = m_out.anchor( 13135 m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), storage, realIndex, ScaleEight, offsetOfFirstProperty))); 13136 m_out.jump(continuation); 13137 13138 m_out.appendTo(slowCase, continuation); 13139 ValueFromBlock slowCaseResult = m_out.anchor( 13140 vmCall(Int64, operationGetByVal, weakPointer(globalObject), base, property)); 13141 m_out.jump(continuation); 13142 13143 m_out.appendTo(continuation, lastNext); 13144 setJSValue(m_out.phi(Int64, inlineResult, outOfLineResult, slowCaseResult)); 13145 } 13146 13147 void compileGetEnumerableLength() 13148 { 13149 LValue enumerator = lowCell(m_node->child1()); 13150 setInt32(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_indexLength)); 13025 return m_out.notZero64(vmCall(Int64, slowPathOperation, weakPointer(globalObject), base, index)); 13026 } 13027 } 13028 } 13029 13030 void compileHasIndexedProperty() 13031 { 13032 LValue index = lowInt32(m_graph.varArgChild(m_node, 1)); 13033 setBoolean(compileHasIndexedPropertyImpl(index, operationHasIndexedProperty)); 13151 13034 } 13152 13035 … … 13160 13043 } 13161 13044 13162 void compileGetEnumeratorStructurePname() 13163 { 13164 LValue enumerator = lowCell(m_node->child1()); 13165 LValue index = lowInt32(m_node->child2()); 13166 13167 LBasicBlock inBounds = m_out.newBlock(); 13168 LBasicBlock outOfBounds = m_out.newBlock(); 13169 LBasicBlock continuation = m_out.newBlock(); 13170 13171 m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endStructurePropertyIndex)), 13172 usually(inBounds), rarely(outOfBounds)); 13173 13174 LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds); 13175 LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector); 13176 ValueFromBlock inBoundsResult = m_out.anchor( 13177 m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index)))); 13178 m_out.jump(continuation); 13179 13180 m_out.appendTo(outOfBounds, continuation); 13181 ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(JSValue::ValueNull)); 13182 m_out.jump(continuation); 13183 13184 m_out.appendTo(continuation, lastNext); 13185 setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult)); 13186 } 13187 13188 void compileGetEnumeratorGenericPname() 13189 { 13190 LValue enumerator = lowCell(m_node->child1()); 13191 LValue index = lowInt32(m_node->child2()); 13192 13193 LBasicBlock inBounds = m_out.newBlock(); 13194 LBasicBlock outOfBounds = m_out.newBlock(); 13195 LBasicBlock continuation = m_out.newBlock(); 13196 13197 m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex)), 13198 usually(inBounds), rarely(outOfBounds)); 13199 13200 LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds); 13201 LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector); 13202 ValueFromBlock inBoundsResult = m_out.anchor( 13203 m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index)))); 13204 m_out.jump(continuation); 13205 13206 m_out.appendTo(outOfBounds, continuation); 13207 ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(JSValue::ValueNull)); 13208 m_out.jump(continuation); 13209 13210 m_out.appendTo(continuation, lastNext); 13211 setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult)); 13212 } 13213 13214 void compileToIndexString() 13045 void compileEnumeratorNextUpdateIndexAndMode() 13046 { 13047 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 13048 LValue index = lowInt32(m_graph.varArgChild(m_node, 1)); 13049 LValue mode = lowInt32(m_graph.varArgChild(m_node, 2)); 13050 LValue enumerator = lowCell(m_graph.varArgChild(m_node, 3)); 13051 13052 if (m_node->enumeratorMetadata() == JSPropertyNameEnumerator::IndexedMode) { 13053 speculate(BadCache, noValue(), m_node, m_out.notZero32(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex))); 13054 13055 LBasicBlock increment = m_out.newBlock(); 13056 LBasicBlock checkHasProperty = m_out.newBlock(); 13057 LBasicBlock continuation = m_out.newBlock(); 13058 13059 ValueFromBlock initialIndex = m_out.anchor(index); 13060 ValueFromBlock initialIndexForHasProperty = m_out.anchor(index); 13061 m_out.branch(m_out.isZero32(mode), unsure(checkHasProperty), unsure(increment)); 13062 13063 m_out.appendTo(increment); 13064 LValue indexPhi = m_out.phi(Int32, initialIndex); 13065 LValue incrementedIndex = m_out.add(indexPhi, m_out.int32One); 13066 ValueFromBlock incrementedIndexResult = m_out.anchor(incrementedIndex); 13067 ValueFromBlock finalIncrementedIndex = m_out.anchor(incrementedIndex); 13068 m_out.branch(m_out.lessThan(incrementedIndex, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_indexLength)), unsure(checkHasProperty), unsure(continuation)); 13069 13070 m_out.appendTo(checkHasProperty); 13071 LValue propertyIndex = m_out.phi(Int32, initialIndexForHasProperty, incrementedIndexResult); 13072 m_out.addIncomingToPhi(indexPhi, m_out.anchor(propertyIndex)); 13073 ValueFromBlock finalPropertyIndex = m_out.anchor(propertyIndex); 13074 LValue hasProperty = compileHasIndexedPropertyImpl(propertyIndex, operationHasEnumerableIndexedProperty); 13075 m_out.branch(hasProperty, unsure(continuation), unsure(increment)); 13076 13077 m_out.appendTo(continuation); 13078 LValue finalIndex = m_out.phi(Int32, finalIncrementedIndex, finalPropertyIndex); 13079 setJSValue(m_out.bitOr(m_out.zeroExt(finalIndex, Int64), m_out.constInt64(JSValue::NumberTag | static_cast<uint64_t>(JSPropertyNameEnumerator::IndexedMode) << 32))); 13080 return; 13081 } 13082 13083 Edge& baseEdge = m_graph.varArgChild(m_node, 0); 13084 if (m_node->enumeratorMetadata() == JSPropertyNameEnumerator::OwnStructureMode && baseEdge.useKind() == CellUse) { 13085 LValue base = lowCell(baseEdge); 13086 speculate(BadCache, noValue(), m_node, m_out.notEqual(m_out.load32(base, m_heaps.JSCell_structureID), m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID))); 13087 13088 speculate(BadCache, noValue(), m_node, m_out.notEqual(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_modeSet), m_out.constInt32(JSPropertyNameEnumerator::OwnStructureMode))); 13089 13090 LBasicBlock increment = m_out.newBlock(); 13091 LBasicBlock continuation = m_out.newBlock(); 13092 13093 ValueFromBlock initialIndex = m_out.anchor(index); 13094 m_out.branch(m_out.isZero32(mode), unsure(continuation), unsure(increment)); 13095 13096 m_out.appendTo(increment); 13097 ValueFromBlock incrementedIndex = m_out.anchor(m_out.add(index, m_out.int32One)); 13098 m_out.jump(continuation); 13099 13100 m_out.appendTo(continuation); 13101 index = m_out.phi(Int32, initialIndex, incrementedIndex); 13102 setJSValue(m_out.bitOr(m_out.zeroExt(index, Int64), m_out.constInt64(JSValue::DoubleEncodeOffset | static_cast<uint64_t>(JSPropertyNameEnumerator::OwnStructureMode) << 32))); 13103 return; 13104 } 13105 13106 LValue base = lowJSValue(baseEdge); 13107 setJSValue(vmCall(Int64, operationEnumeratorNextUpdateIndexAndMode, weakPointer(globalObject), base, index, mode, enumerator)); 13108 } 13109 13110 void compileEnumeratorNextExtractIndex() 13111 { 13112 LValue boxedPair = lowJSValue(m_node->child1()); 13113 13114 setInt32(m_out.castToInt32(boxedPair)); 13115 } 13116 13117 void compileEnumeratorNextExtractMode() 13118 { 13119 LValue boxedPair = lowJSValue(m_node->child1()); 13120 13121 LValue highBits = m_out.castToInt32(m_out.lShr(boxedPair, m_out.constInt32(32))); 13122 setInt32(m_out.bitAnd(highBits, m_out.constInt32(JSPropertyNameEnumerator::enumerationModeMask))); 13123 } 13124 13125 // FIXME: We should probably have a method of value recovery for this node since it's "effect" free but always live in bytecode. 13126 void compileEnumeratorNextUpdatePropertyName() 13215 13127 { 13216 13128 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 13217 13129 LValue index = lowInt32(m_node->child1()); 13218 setJSValue(vmCall(Int64, operationToIndexString, weakPointer(globalObject), index)); 13130 LValue mode = lowInt32(m_node->child2()); 13131 LValue enumerator = lowCell(m_node->child3()); 13132 13133 LBasicBlock operationBlock = nullptr; 13134 LBasicBlock continuation = nullptr; 13135 13136 Vector<ValueFromBlock, 3> results; 13137 OptionSet seenModes = m_node->enumeratorMetadata(); 13138 13139 if (seenModes.containsAny({ JSPropertyNameEnumerator::OwnStructureMode, JSPropertyNameEnumerator::GenericMode })) { 13140 LBasicBlock checkIndex = nullptr; 13141 LBasicBlock outOfBoundsBlock = m_out.newBlock(); 13142 LBasicBlock loadPropertyNameBlock = m_out.newBlock(); 13143 continuation = m_out.newBlock(); 13144 13145 if (seenModes.contains(JSPropertyNameEnumerator::IndexedMode)) { 13146 checkIndex = m_out.newBlock(); 13147 operationBlock = m_out.newBlock(); 13148 m_out.branch(m_out.testIsZero32(mode, m_out.constInt32(JSPropertyNameEnumerator::IndexedMode)), unsure(checkIndex), unsure(operationBlock)); 13149 } 13150 13151 { 13152 if (checkIndex) 13153 m_out.appendTo(checkIndex); 13154 LValue outOfBounds = m_out.aboveOrEqual(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex)); 13155 m_out.branch(outOfBounds, unsure(outOfBoundsBlock), unsure(loadPropertyNameBlock)); 13156 } 13157 13158 { 13159 m_out.appendTo(outOfBoundsBlock); 13160 results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsNull())))); 13161 m_out.jump(continuation); 13162 } 13163 13164 { 13165 m_out.appendTo(loadPropertyNameBlock); 13166 LValue namesVector = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector); 13167 results.append(m_out.anchor(m_out.zeroExtPtr(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64), ScalePtr))))); 13168 m_out.jump(continuation); 13169 } 13170 } 13171 13172 if (seenModes.contains(JSPropertyNameEnumerator::IndexedMode)) { 13173 if (operationBlock) 13174 m_out.appendTo(operationBlock); 13175 results.append(m_out.anchor(vmCall(Int64, operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator))); 13176 if (continuation) 13177 m_out.jump(continuation); 13178 } 13179 13180 if (continuation) 13181 m_out.appendTo(continuation); 13182 13183 ASSERT(results.size()); 13184 LValue result = m_out.phi(Int64, results); 13185 setJSValue(result); 13186 } 13187 13188 void compileEnumeratorGetByVal() 13189 { 13190 Edge baseEdge = m_graph.varArgChild(m_node, 0); 13191 Edge propertyNameEdge = m_graph.varArgChild(m_node, 1); 13192 Edge storageEdge = m_graph.varArgChild(m_node, 2); 13193 Edge indexEdge = m_graph.varArgChild(m_node, 3); 13194 13195 LValue base = DFG::isCell(baseEdge.useKind()) ? lowCell(baseEdge, ManualOperandSpeculation) : lowJSValue(baseEdge); 13196 13197 LValue storage = storageEdge ? lowStorage(storageEdge) : nullptr; 13198 // We have to materialize the propertyName here in case it requires boxing since the IC path won't dominate subsequent uses in subsequent nodes. 13199 // If it's an Int32 and we use it as such this boxing will be DCE'd by b3 later anyway. 13200 lowJSValue(propertyNameEdge, ManualOperandSpeculation); 13201 13202 13203 LValue index = lowInt32(indexEdge); 13204 LValue mode = lowInt32(m_graph.varArgChild(m_node, 4)); 13205 LValue enumerator = lowCell(m_graph.varArgChild(m_node, 5)); 13206 13207 LBasicBlock checkIsCellBlock = m_out.newBlock(); 13208 LBasicBlock checkStructureBlock = m_out.newBlock(); 13209 LBasicBlock checkInlineOrOutOfLineBlock = m_out.newBlock(); 13210 LBasicBlock inlineLoadBlock = m_out.newBlock(); 13211 LBasicBlock outOfLineLoadBlock = m_out.newBlock(); 13212 LBasicBlock genericICBlock = m_out.newBlock(); 13213 LBasicBlock continuation = m_out.newBlock(); 13214 13215 Vector<ValueFromBlock, 4> results; 13216 13217 LValue isNotNamed = m_out.testNonZero32(mode, m_out.constInt32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)); 13218 m_out.branch(isNotNamed, unsure(genericICBlock), unsure(checkIsCellBlock)); 13219 13220 m_out.appendTo(checkIsCellBlock); 13221 m_out.branch(isCell(base, provenType(baseEdge)), usually(checkStructureBlock), rarely(genericICBlock)); 13222 13223 m_out.appendTo(checkStructureBlock); 13224 LValue structureID; 13225 auto structure = m_state.forNode(baseEdge.node()).m_structure.onlyStructure(); 13226 if (structure) 13227 structureID = m_out.constInt32(structure->id()); 13228 else 13229 structureID = m_out.load32(base, m_heaps.JSCell_structureID); 13230 13231 LValue hasEnumeratorStructure = m_out.equal(structureID, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)); 13232 13233 if (indexEdge.node() == propertyNameEdge.node()) { 13234 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 13235 LBasicBlock badStructureSlowPath = m_out.newBlock(); 13236 m_out.branch(hasEnumeratorStructure, usually(checkInlineOrOutOfLineBlock), rarely(genericICBlock)); 13237 13238 m_out.appendTo(badStructureSlowPath); 13239 results.append(m_out.anchor(vmCall(Int64, operationEnumeratorRecoverNameAndGetByVal, weakPointer(globalObject), base, index, enumerator))); 13240 } else 13241 m_out.branch(hasEnumeratorStructure, usually(checkInlineOrOutOfLineBlock), rarely(genericICBlock)); 13242 13243 m_out.appendTo(checkInlineOrOutOfLineBlock); 13244 LValue inlineCapacity = nullptr; 13245 bool hasNoOutOfLineProperties = false; 13246 if (structure) { 13247 hasNoOutOfLineProperties = !structure->outOfLineCapacity(); 13248 inlineCapacity = m_out.constInt32(structure->inlineCapacity()); 13249 } 13250 if (!inlineCapacity) 13251 inlineCapacity = m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity); 13252 LValue isInline = hasNoOutOfLineProperties ? m_out.int32One : m_out.below(index, inlineCapacity); 13253 m_out.branch(isInline, unsure(inlineLoadBlock), unsure(outOfLineLoadBlock)); 13254 13255 m_out.appendTo(inlineLoadBlock); 13256 results.append(m_out.anchor( 13257 m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), 13258 base, m_out.zeroExt(index, Int64), ScaleEight, JSObject::offsetOfInlineStorage())))); 13259 m_out.jump(continuation); 13260 13261 m_out.appendTo(outOfLineLoadBlock); 13262 if (!storage) 13263 storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly); 13264 13265 LValue realIndex = m_out.signExt32To64( 13266 m_out.neg(m_out.sub(index, inlineCapacity))); 13267 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); 13268 results.append(m_out.anchor( 13269 m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), storage, realIndex, ScaleEight, offsetOfFirstProperty)))); 13270 m_out.jump(continuation); 13271 13272 m_out.appendTo(genericICBlock); 13273 LValue genericResult = compileGetByValImpl(); 13274 TypedArrayType type = m_node->arrayMode().typedArrayType(); 13275 if (isInt(type)) { 13276 if (elementSize(type) < 4 || isSigned(type)) 13277 genericResult = boxInt32(genericResult); 13278 else 13279 genericResult = strictInt52ToJSValue(genericResult); 13280 } else if (genericResult->type() == Double) 13281 genericResult = boxDouble(genericResult); 13282 13283 results.append(m_out.anchor(genericResult)); 13284 m_out.jump(continuation); 13285 13286 m_out.appendTo(continuation); 13287 ASSERT(results.size()); 13288 LValue result = m_out.phi(Int64, results); 13289 setJSValue(result); 13290 } 13291 13292 template<typename SlowPathFunctionType> 13293 void compileEnumeratorHasProperty(SlowPathFunctionType slowPathFunction) 13294 { 13295 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 13296 Edge baseEdge = m_graph.varArgChild(m_node, 0); 13297 LValue base = baseEdge.useKind() == CellUse ? lowCell(baseEdge) : lowJSValue(baseEdge); 13298 LValue propertyName = lowJSValue(m_graph.varArgChild(m_node, 1)); 13299 LValue index = lowInt32(m_graph.varArgChild(m_node, 2)); 13300 LValue mode = lowInt32(m_graph.varArgChild(m_node, 3)); 13301 LValue enumerator = lowCell(m_graph.varArgChild(m_node, 4)); 13302 13303 LBasicBlock isNamedBlock = m_out.newBlock(); 13304 LBasicBlock isCellBlock = m_out.newBlock(); 13305 LBasicBlock matchesStructureBlock = m_out.newBlock(); 13306 LBasicBlock operationBlock = m_out.newBlock(); 13307 LBasicBlock continuation = m_out.newBlock(); 13308 13309 m_out.branch(m_out.testNonZero32(mode, m_out.constInt32(JSPropertyNameEnumerator::OwnStructureMode)), unsure(isNamedBlock), unsure(operationBlock)); 13310 m_out.appendTo(isNamedBlock); 13311 13312 m_out.branch(isCell(base, provenType(baseEdge)), unsure(isCellBlock), unsure(operationBlock)); 13313 13314 m_out.appendTo(isCellBlock); 13315 LValue structureID = m_out.load32(base, m_heaps.JSCell_structureID); 13316 m_out.branch(m_out.equal(structureID, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)), 13317 usually(matchesStructureBlock), rarely(operationBlock)); 13318 13319 m_out.appendTo(matchesStructureBlock); 13320 ValueFromBlock namedResult = m_out.anchor(m_out.booleanTrue); 13321 m_out.jump(continuation); 13322 13323 m_out.appendTo(operationBlock); 13324 ValueFromBlock operationResult = m_out.anchor(unboxBoolean(vmCall(Int64, slowPathFunction, weakPointer(globalObject), base, propertyName, index, mode))); 13325 m_out.jump(continuation); 13326 13327 m_out.appendTo(continuation); 13328 setBoolean(m_out.phi(Int32, namedResult, operationResult)); 13329 } 13330 13331 void compileEnumeratorInByVal() 13332 { 13333 compileEnumeratorHasProperty(operationEnumeratorInByVal); 13334 } 13335 13336 void compileEnumeratorHasOwnProperty() 13337 { 13338 compileEnumeratorHasProperty(operationEnumeratorHasOwnProperty); 13219 13339 } 13220 13340 … … 17345 17465 return; 17346 17466 } 17347 17467 17348 17468 if (m_node->shouldSpeculateInt32() && canSpeculate) { 17349 17469 speculate( … … 20297 20417 } 20298 20418 20419 // This only works for ints right now. 20420 PatchpointValue* dataLogForDebugging(const char* prefix, LValue value) 20421 { 20422 PatchpointValue* result = m_out.patchpoint(Void); 20423 result->effects.writesLocalState = true; 20424 result->append(value, ValueRep::reg(GPRInfo::regT0)); 20425 Type valueType = value->type(); 20426 result->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams&) { 20427 AllowMacroScratchRegisterUsage allowScratch(jit); 20428 20429 jit.probeDebug([=] (Probe::Context& context) { 20430 if (valueType == Int32) 20431 dataLogLn(prefix, context.gpr<int32_t>(GPRInfo::regT0)); 20432 else 20433 dataLogLn(prefix, context.gpr<JSValue>(GPRInfo::regT0)); 20434 }); 20435 }); 20436 20437 return result; 20438 } 20439 20299 20440 AvailabilityMap& availabilityMap() { return m_availabilityCalculator.m_availability; } 20300 20441 -
trunk/Source/JavaScriptCore/ftl/FTLOutput.h
r280198 r280760 1 1 /* 2 * Copyright (C) 2013-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 146 146 template<typename... Params> 147 147 void addIncomingToPhi(LValue phi, ValueFromBlock, Params... theRest); 148 template<typename... Params> 149 void addIncomingToPhiIfSet(LValue phi, Params... theRest); 148 150 149 151 LValue opaque(LValue); … … 481 483 inline LValue Output::phi(LType type, const VectorType& vector) 482 484 { 485 ASSERT(vector.size()); 483 486 LValue phiNode = phi(type); 484 487 for (const ValueFromBlock& valueFromBlock : vector) -
trunk/Source/JavaScriptCore/generator/DSL.rb
r267489 r280760 139 139 #include "Instruction.h" 140 140 #include "IterationModeMetadata.h" 141 #include "JSPropertyNameEnumerator.h" 141 142 #include "Opcode.h" 142 143 #include "PrivateFieldPutKind.h" -
trunk/Source/JavaScriptCore/interpreter/Register.h
r270855 r280760 54 54 ALWAYS_INLINE Register& operator=(CodeBlock*); 55 55 ALWAYS_INLINE Register& operator=(JSScope*); 56 ALWAYS_INLINE Register& operator=(JS Object*);56 ALWAYS_INLINE Register& operator=(JSCell*); 57 57 ALWAYS_INLINE Register& operator=(EncodedJSValue); 58 58 -
trunk/Source/JavaScriptCore/interpreter/RegisterInlines.h
r251886 r280760 64 64 } 65 65 66 ALWAYS_INLINE Register& Register::operator=(JS Object* object)66 ALWAYS_INLINE Register& Register::operator=(JSCell* object) 67 67 { 68 68 u.value = JSValue::encode(JSValue(object)); -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r279256 r280760 189 189 #endif 190 190 } 191 191 192 192 void loadValue(Address address, JSValueRegs regs) 193 193 { … … 890 890 Below, Address(cellGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType)); 891 891 } 892 892 893 893 // Note that first and last are inclusive. 894 894 Jump branchIfType(GPRReg cellGPR, JSTypeRange range) -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r279105 r280760 309 309 DEFINE_SLOW_OP(new_array_buffer) 310 310 DEFINE_SLOW_OP(spread) 311 DEFINE_SLOW_OP(get_enumerable_length)312 DEFINE_SLOW_OP(has_enumerable_property)313 311 DEFINE_SLOW_OP(get_property_enumerator) 314 DEFINE_SLOW_OP(to_index_string)315 312 DEFINE_SLOW_OP(create_direct_arguments) 316 313 DEFINE_SLOW_OP(create_scoped_arguments) … … 366 363 DEFINE_OP(op_get_by_id_direct) 367 364 DEFINE_OP(op_get_by_val) 365 DEFINE_OP(op_enumerator_next) 366 DEFINE_OP(op_enumerator_get_by_val) 367 DEFINE_OP(op_enumerator_in_by_val) 368 DEFINE_OP(op_enumerator_has_own_property) 368 369 DEFINE_OP(op_get_private_name) 369 370 DEFINE_OP(op_set_private_brand) … … 474 475 DEFINE_OP(op_put_to_arguments) 475 476 476 DEFINE_OP(op_has_enumerable_indexed_property)477 DEFINE_OP(op_has_enumerable_structure_property)478 DEFINE_OP(op_has_own_structure_property)479 DEFINE_OP(op_in_structure_property)480 DEFINE_OP(op_get_direct_pname)481 DEFINE_OP(op_enumerator_structure_pname)482 DEFINE_OP(op_enumerator_generic_pname)483 484 477 DEFINE_OP(op_log_shadow_chicken_prologue) 485 478 DEFINE_OP(op_log_shadow_chicken_tail) … … 579 572 DEFINE_SLOWCASE_OP(op_get_by_id_direct) 580 573 DEFINE_SLOWCASE_OP(op_get_by_val) 574 DEFINE_SLOWCASE_OP(op_enumerator_get_by_val) 581 575 DEFINE_SLOWCASE_OP(op_get_private_name) 582 576 DEFINE_SLOWCASE_OP(op_set_private_brand) … … 610 604 DEFINE_SLOWCASE_OP(op_del_by_id) 611 605 DEFINE_SLOWCASE_OP(op_sub) 612 DEFINE_SLOWCASE_OP(op_has_enumerable_indexed_property)613 606 #if !ENABLE(EXTRA_CTI_THUNKS) 614 607 DEFINE_SLOWCASE_OP(op_get_from_scope) … … 643 636 DEFINE_SLOWCASE_SLOW_OP(stricteq) 644 637 DEFINE_SLOWCASE_SLOW_OP(nstricteq) 645 DEFINE_SLOWCASE_SLOW_OP(get_direct_pname)646 638 DEFINE_SLOWCASE_SLOW_OP(get_prototype_of) 647 DEFINE_SLOWCASE_SLOW_OP(has_enumerable_structure_property)648 DEFINE_SLOWCASE_SLOW_OP(has_own_structure_property)649 DEFINE_SLOWCASE_SLOW_OP(in_structure_property)650 639 #if !ENABLE(EXTRA_CTI_THUNKS) 651 640 DEFINE_SLOWCASE_SLOW_OP(resolve_scope) -
trunk/Source/JavaScriptCore/jit/JIT.h
r279105 r280760 454 454 void emitGetVirtualRegister(VirtualRegister src, JSValueRegs dst); 455 455 void emitPutVirtualRegister(VirtualRegister dst, JSValueRegs src); 456 void emitStore(VirtualRegister, const JSValue constant, RegisterID base = callFrameRegister); 456 457 457 458 int32_t getOperandConstantInt(VirtualRegister src); … … 470 471 471 472 void emitStore(VirtualRegister, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister); 472 void emitStore(VirtualRegister, const JSValue constant, RegisterID base = callFrameRegister);473 473 void emitStoreInt32(VirtualRegister, RegisterID payload, bool indexIsInt32 = false); 474 474 void emitStoreInt32(VirtualRegister, TrustedImm32 payload, bool indexIsInt32 = false); … … 671 671 void emit_op_unsigned(const Instruction*); 672 672 void emit_op_urshift(const Instruction*); 673 template <typename OpCodeType>674 void emit_op_has_structure_propertyImpl(const Instruction*);675 void emit_op_has_enumerable_indexed_property(const Instruction*);676 void emit_op_has_enumerable_structure_property(const Instruction*);677 void emit_op_has_own_structure_property(const Instruction*);678 void emit_op_in_structure_property(const Instruction*);679 void emit_op_get_direct_pname(const Instruction*);680 void emit_op_enumerator_structure_pname(const Instruction*);681 void emit_op_enumerator_generic_pname(const Instruction*);682 673 void emit_op_get_internal_field(const Instruction*); 683 674 void emit_op_put_internal_field(const Instruction*); … … 685 676 void emit_op_log_shadow_chicken_tail(const Instruction*); 686 677 void emit_op_to_property_key(const Instruction*); 678 679 template<typename OpcodeType> 680 void generateGetByValSlowCase(const OpcodeType&, Vector<SlowCaseEntry>::iterator&); 681 682 void emit_op_enumerator_next(const Instruction*); 683 void emit_op_enumerator_get_by_val(const Instruction*); 684 void emitSlow_op_enumerator_get_by_val(const Instruction*, Vector<SlowCaseEntry>::iterator&); 685 686 template<typename OpcodeType, typename SlowPathFunctionType> 687 void emit_enumerator_has_propertyImpl(const Instruction*, const OpcodeType&, SlowPathFunctionType); 688 void emit_op_enumerator_in_by_val(const Instruction*); 689 void emit_op_enumerator_has_own_property(const Instruction*); 687 690 688 691 void emitSlow_op_add(const Instruction*, Vector<SlowCaseEntry>::iterator&); … … 736 739 void emitSlow_op_put_private_name(const Instruction*, Vector<SlowCaseEntry>::iterator&); 737 740 void emitSlow_op_sub(const Instruction*, Vector<SlowCaseEntry>::iterator&); 738 void emitSlow_op_has_enumerable_indexed_property(const Instruction*, Vector<SlowCaseEntry>::iterator&);739 741 740 742 void emit_op_resolve_scope(const Instruction*); -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r279216 r280760 1693 1693 #if USE(JSVALUE64) 1694 1694 1695 template <typename OpCodeType>1696 void JIT::emit_op_has_structure_propertyImpl(const Instruction* currentInstruction)1697 {1698 auto bytecode = currentInstruction->as<OpCodeType>();1699 VirtualRegister dst = bytecode.m_dst;1700 VirtualRegister base = bytecode.m_base;1701 VirtualRegister enumerator = bytecode.m_enumerator;1702 1703 emitGetVirtualRegister(base, regT0);1704 emitGetVirtualRegister(enumerator, regT1);1705 emitJumpSlowCaseIfNotJSCell(regT0, base);1706 1707 load32(Address(regT0, JSCell::structureIDOffset()), regT0);1708 addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));1709 1710 move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);1711 emitPutVirtualRegister(dst);1712 }1713 1714 void JIT::emit_op_has_enumerable_structure_property(const Instruction* currentInstruction)1715 {1716 emit_op_has_structure_propertyImpl<OpHasEnumerableStructureProperty>(currentInstruction);1717 }1718 1719 void JIT::emit_op_has_own_structure_property(const Instruction* currentInstruction)1720 {1721 emit_op_has_structure_propertyImpl<OpHasOwnStructureProperty>(currentInstruction);1722 }1723 1724 void JIT::emit_op_in_structure_property(const Instruction* currentInstruction)1725 {1726 emit_op_has_structure_propertyImpl<OpInStructureProperty>(currentInstruction);1727 }1728 1729 1695 void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) 1730 1696 { 1731 1697 const Instruction* currentInstruction = m_codeBlock->instructions().at(byValInfo->bytecodeIndex).ptr(); 1732 1698 1733 1699 PatchableJump badType; 1734 1700 1735 1701 // FIXME: Add support for other types like TypedArrays and Arguments. 1736 1702 // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034. … … 1740 1706 1741 1707 LinkBuffer patchBuffer(*this, m_codeBlock, LinkBuffer::Profile::InlineCache); 1742 1708 1743 1709 patchBuffer.link(badType, byValInfo->slowPathTarget); 1744 1710 patchBuffer.link(slowCases, byValInfo->slowPathTarget); … … 1749 1715 m_codeBlock, patchBuffer, JITStubRoutinePtrTag, 1750 1716 "Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.untaggedValue()); 1751 1717 1752 1718 if (JITCode::useDataIC(JITType::BaselineJIT)) { 1753 1719 byValInfo->m_badTypeJumpTarget = CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code()); … … 1757 1723 MacroAssembler::repatchCall(CodeLocationCall<ReturnAddressPtrTag>(MacroAssemblerCodePtr<ReturnAddressPtrTag>(returnAddress)), FunctionPtr<OperationPtrTag>(operationHasIndexedPropertyGeneric)); 1758 1724 } 1759 }1760 1761 void JIT::emit_op_has_enumerable_indexed_property(const Instruction* currentInstruction)1762 {1763 auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();1764 auto& metadata = bytecode.metadata(m_codeBlock);1765 VirtualRegister dst = bytecode.m_dst;1766 VirtualRegister base = bytecode.m_base;1767 VirtualRegister property = bytecode.m_property;1768 ArrayProfile* profile = &metadata.m_arrayProfile;1769 ByValInfo* byValInfo = m_codeBlock->addByValInfo(m_bytecodeIndex);1770 1771 emitGetVirtualRegisters(base, regT0, property, regT1);1772 1773 emitJumpSlowCaseIfNotInt(regT1);1774 1775 // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.1776 // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if1777 // number was signed since m_vectorLength is always less than intmax (since the total allocation1778 // size is always less than 4Gb). As such zero extending will have been correct (and extending the value1779 // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign1780 // extending since it makes it easier to re-tag the value in the slow case.1781 zeroExtend32ToWord(regT1, regT1);1782 1783 emitJumpSlowCaseIfNotJSCell(regT0, base);1784 emitArrayProfilingSiteWithCell(regT0, regT2, profile);1785 and32(TrustedImm32(IndexingShapeMask), regT2);1786 1787 JITArrayMode mode = chooseArrayMode(profile);1788 PatchableJump badType;1789 1790 // FIXME: Add support for other types like TypedArrays and Arguments.1791 // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.1792 JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType, byValInfo);1793 1794 move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);1795 1796 if (!JITCode::useDataIC(JITType::BaselineJIT))1797 addSlowCase(badType);1798 addSlowCase(slowCases);1799 1800 Label done = label();1801 1802 emitPutVirtualRegister(dst);1803 1804 Label nextHotPath = label();1805 1806 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, PatchableJump(), badType, mode, profile, done, nextHotPath));1807 }1808 1809 void JIT::emitSlow_op_has_enumerable_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)1810 {1811 linkAllSlowCases(iter);1812 1813 auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();1814 VirtualRegister dst = bytecode.m_dst;1815 VirtualRegister base = bytecode.m_base;1816 VirtualRegister property = bytecode.m_property;1817 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;1818 1819 Label slowPath = label();1820 1821 emitGetVirtualRegister(base, regT0);1822 emitGetVirtualRegister(property, regT1);1823 1824 Call call;1825 if (JITCode::useDataIC(JITType::BaselineJIT)) {1826 byValInfo->m_slowOperation = operationHasIndexedPropertyDefault;1827 move(TrustedImmPtr(byValInfo), GPRInfo::nonArgGPR0);1828 callOperation<decltype(operationHasIndexedPropertyDefault)>(Address(GPRInfo::nonArgGPR0, ByValInfo::offsetOfSlowOperation()), dst, TrustedImmPtr(m_codeBlock->globalObject()), regT0, regT1, GPRInfo::nonArgGPR0);1829 } else1830 call = callOperation(operationHasIndexedPropertyDefault, dst, TrustedImmPtr(m_codeBlock->globalObject()), regT0, regT1, byValInfo);1831 1832 m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;1833 m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;1834 m_byValInstructionIndex++;1835 }1836 1837 void JIT::emit_op_get_direct_pname(const Instruction* currentInstruction)1838 {1839 auto bytecode = currentInstruction->as<OpGetDirectPname>();1840 VirtualRegister dst = bytecode.m_dst;1841 VirtualRegister base = bytecode.m_base;1842 VirtualRegister index = bytecode.m_index;1843 VirtualRegister enumerator = bytecode.m_enumerator;1844 1845 // Check that base is a cell1846 emitGetVirtualRegister(base, regT0);1847 emitJumpSlowCaseIfNotJSCell(regT0, base);1848 1849 // Check the structure1850 emitGetVirtualRegister(enumerator, regT2);1851 load32(Address(regT0, JSCell::structureIDOffset()), regT1);1852 addSlowCase(branch32(NotEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedStructureIDOffset())));1853 1854 // Compute the offset1855 emitGetVirtualRegister(index, regT1);1856 // If index is less than the enumerator's cached inline storage, then it's an inline access1857 Jump outOfLineAccess = branch32(AboveOrEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));1858 addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);1859 signExtend32ToPtr(regT1, regT1);1860 load64(BaseIndex(regT0, regT1, TimesEight), regT0);1861 1862 Jump done = jump();1863 1864 // Otherwise it's out of line1865 outOfLineAccess.link(this);1866 loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);1867 sub32(Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT1);1868 neg32(regT1);1869 signExtend32ToPtr(regT1, regT1);1870 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);1871 load64(BaseIndex(regT0, regT1, TimesEight, offsetOfFirstProperty), regT0);1872 1873 done.link(this);1874 emitValueProfilingSite(bytecode.metadata(m_codeBlock), regT0);1875 emitPutVirtualRegister(dst, regT0);1876 }1877 1878 void JIT::emit_op_enumerator_structure_pname(const Instruction* currentInstruction)1879 {1880 auto bytecode = currentInstruction->as<OpEnumeratorStructurePname>();1881 VirtualRegister dst = bytecode.m_dst;1882 VirtualRegister enumerator = bytecode.m_enumerator;1883 VirtualRegister index = bytecode.m_index;1884 1885 emitGetVirtualRegister(index, regT0);1886 emitGetVirtualRegister(enumerator, regT1);1887 Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));1888 1889 move(TrustedImm64(JSValue::encode(jsNull())), regT0);1890 1891 Jump done = jump();1892 inBounds.link(this);1893 1894 loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);1895 signExtend32ToPtr(regT0, regT0);1896 load64(BaseIndex(regT1, regT0, TimesEight), regT0);1897 1898 done.link(this);1899 emitPutVirtualRegister(dst);1900 }1901 1902 void JIT::emit_op_enumerator_generic_pname(const Instruction* currentInstruction)1903 {1904 auto bytecode = currentInstruction->as<OpEnumeratorGenericPname>();1905 VirtualRegister dst = bytecode.m_dst;1906 VirtualRegister enumerator = bytecode.m_enumerator;1907 VirtualRegister index = bytecode.m_index;1908 1909 emitGetVirtualRegister(index, regT0);1910 emitGetVirtualRegister(enumerator, regT1);1911 Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));1912 1913 move(TrustedImm64(JSValue::encode(jsNull())), regT0);1914 1915 Jump done = jump();1916 inBounds.link(this);1917 1918 loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);1919 signExtend32ToPtr(regT0, regT0);1920 load64(BaseIndex(regT1, regT0, TimesEight), regT0);1921 1922 done.link(this);1923 emitPutVirtualRegister(dst);1924 1725 } 1925 1726 -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r279049 r280760 1143 1143 } 1144 1144 1145 template <typename OpCodeType>1146 void JIT::emit_op_has_structure_propertyImpl(const Instruction* currentInstruction)1147 {1148 auto bytecode = currentInstruction->as<OpCodeType>();1149 VirtualRegister dst = bytecode.m_dst;1150 VirtualRegister base = bytecode.m_base;1151 VirtualRegister enumerator = bytecode.m_enumerator;1152 1153 emitLoadPayload(base, regT0);1154 emitJumpSlowCaseIfNotJSCell(base);1155 1156 emitLoadPayload(enumerator, regT1);1157 1158 load32(Address(regT0, JSCell::structureIDOffset()), regT0);1159 addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));1160 1161 move(TrustedImm32(1), regT0);1162 emitStoreBool(dst, regT0);1163 }1164 1165 void JIT::emit_op_has_enumerable_structure_property(const Instruction* currentInstruction)1166 {1167 emit_op_has_structure_propertyImpl<OpHasEnumerableStructureProperty>(currentInstruction);1168 }1169 1170 void JIT::emit_op_has_own_structure_property(const Instruction* currentInstruction)1171 {1172 emit_op_has_structure_propertyImpl<OpHasOwnStructureProperty>(currentInstruction);1173 }1174 1175 void JIT::emit_op_in_structure_property(const Instruction* currentInstruction)1176 {1177 emit_op_has_structure_propertyImpl<OpInStructureProperty>(currentInstruction);1178 }1179 1180 1145 void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) 1181 1146 { 1182 1147 const Instruction* currentInstruction = m_codeBlock->instructions().at(byValInfo->bytecodeIndex).ptr(); 1183 1148 1184 1149 PatchableJump badType; 1185 1150 1186 1151 // FIXME: Add support for other types like TypedArrays and Arguments. 1187 1152 // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034. … … 1191 1156 1192 1157 LinkBuffer patchBuffer(*this, m_codeBlock, LinkBuffer::Profile::InlineCache); 1193 1158 1194 1159 patchBuffer.link(badType, byValInfo->slowPathTarget); 1195 1160 patchBuffer.link(slowCases, byValInfo->slowPathTarget); … … 1200 1165 m_codeBlock, patchBuffer, JITStubRoutinePtrTag, 1201 1166 "Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.untaggedValue()); 1202 1167 1203 1168 MacroAssembler::repatchJump(byValInfo->m_badTypeJump, CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code())); 1204 1169 MacroAssembler::repatchCall(CodeLocationCall<ReturnAddressPtrTag>(MacroAssemblerCodePtr<ReturnAddressPtrTag>(returnAddress)), FunctionPtr<OperationPtrTag>(operationHasIndexedPropertyGeneric)); 1205 }1206 1207 void JIT::emit_op_has_enumerable_indexed_property(const Instruction* currentInstruction)1208 {1209 auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();1210 auto& metadata = bytecode.metadata(m_codeBlock);1211 VirtualRegister dst = bytecode.m_dst;1212 VirtualRegister base = bytecode.m_base;1213 VirtualRegister property = bytecode.m_property;1214 ArrayProfile* profile = &metadata.m_arrayProfile;1215 ByValInfo* byValInfo = m_codeBlock->addByValInfo(m_bytecodeIndex);1216 1217 emitLoadPayload(base, regT0);1218 emitJumpSlowCaseIfNotJSCell(base);1219 1220 emitLoad(property, regT3, regT1);1221 addSlowCase(branchIfNotInt32(regT3));1222 1223 // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.1224 // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if1225 // number was signed since m_vectorLength is always less than intmax (since the total allocation1226 // size is always less than 4Gb). As such zero extending will have been correct (and extending the value1227 // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign1228 // extending since it makes it easier to re-tag the value in the slow case.1229 zeroExtend32ToWord(regT1, regT1);1230 1231 emitArrayProfilingSiteWithCell(regT0, regT2, profile);1232 and32(TrustedImm32(IndexingShapeMask), regT2);1233 1234 JITArrayMode mode = chooseArrayMode(profile);1235 PatchableJump badType;1236 1237 // FIXME: Add support for other types like TypedArrays and Arguments.1238 // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.1239 JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType, byValInfo);1240 move(TrustedImm32(1), regT0);1241 1242 addSlowCase(badType);1243 addSlowCase(slowCases);1244 1245 Label done = label();1246 1247 emitStoreBool(dst, regT0);1248 1249 Label nextHotPath = label();1250 1251 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, PatchableJump(), badType, mode, profile, done, nextHotPath));1252 }1253 1254 void JIT::emitSlow_op_has_enumerable_indexed_property(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)1255 {1256 linkAllSlowCases(iter);1257 1258 auto bytecode = currentInstruction->as<OpHasEnumerableIndexedProperty>();1259 VirtualRegister dst = bytecode.m_dst;1260 VirtualRegister base = bytecode.m_base;1261 VirtualRegister property = bytecode.m_property;1262 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;1263 1264 Label slowPath = label();1265 1266 emitLoad(base, regT1, regT0);1267 emitLoad(property, regT3, regT2);1268 Call call = callOperation(operationHasIndexedPropertyDefault, dst, m_codeBlock->globalObject(), JSValueRegs(regT1, regT0), JSValueRegs(regT3, regT2), byValInfo);1269 1270 m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;1271 m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;1272 m_byValInstructionIndex++;1273 }1274 1275 void JIT::emit_op_get_direct_pname(const Instruction* currentInstruction)1276 {1277 auto bytecode = currentInstruction->as<OpGetDirectPname>();1278 VirtualRegister dst = bytecode.m_dst;1279 VirtualRegister base = bytecode.m_base;1280 VirtualRegister index = bytecode.m_index;1281 VirtualRegister enumerator = bytecode.m_enumerator;1282 1283 // Check that base is a cell1284 emitLoadPayload(base, regT0);1285 emitJumpSlowCaseIfNotJSCell(base);1286 1287 // Check the structure1288 emitLoadPayload(enumerator, regT1);1289 load32(Address(regT0, JSCell::structureIDOffset()), regT2);1290 addSlowCase(branch32(NotEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));1291 1292 // Compute the offset1293 emitLoadPayload(index, regT2);1294 // If index is less than the enumerator's cached inline storage, then it's an inline access1295 Jump outOfLineAccess = branch32(AboveOrEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));1296 addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);1297 load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);1298 load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);1299 1300 Jump done = jump();1301 1302 // Otherwise it's out of line1303 outOfLineAccess.link(this);1304 loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);1305 sub32(Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT2);1306 neg32(regT2);1307 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);1308 load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);1309 load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);1310 1311 done.link(this);1312 emitValueProfilingSite(bytecode.metadata(m_codeBlock), JSValueRegs(regT1, regT0));1313 emitStore(dst, regT1, regT0);1314 }1315 1316 void JIT::emit_op_enumerator_structure_pname(const Instruction* currentInstruction)1317 {1318 auto bytecode = currentInstruction->as<OpEnumeratorStructurePname>();1319 VirtualRegister dst = bytecode.m_dst;1320 VirtualRegister enumerator = bytecode.m_enumerator;1321 VirtualRegister index = bytecode.m_index;1322 1323 emitLoadPayload(index, regT0);1324 emitLoadPayload(enumerator, regT1);1325 Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));1326 1327 move(TrustedImm32(JSValue::NullTag), regT2);1328 move(TrustedImm32(0), regT0);1329 1330 Jump done = jump();1331 inBounds.link(this);1332 1333 loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);1334 loadPtr(BaseIndex(regT1, regT0, ScalePtr), regT0);1335 move(TrustedImm32(JSValue::CellTag), regT2);1336 1337 done.link(this);1338 emitStore(dst, regT2, regT0);1339 }1340 1341 void JIT::emit_op_enumerator_generic_pname(const Instruction* currentInstruction)1342 {1343 auto bytecode = currentInstruction->as<OpEnumeratorGenericPname>();1344 VirtualRegister dst = bytecode.m_dst;1345 VirtualRegister enumerator = bytecode.m_enumerator;1346 VirtualRegister index = bytecode.m_index;1347 1348 emitLoadPayload(index, regT0);1349 emitLoadPayload(enumerator, regT1);1350 Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));1351 1352 move(TrustedImm32(JSValue::NullTag), regT2);1353 move(TrustedImm32(0), regT0);1354 1355 Jump done = jump();1356 inBounds.link(this);1357 1358 loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);1359 loadPtr(BaseIndex(regT1, regT0, ScalePtr), regT0);1360 move(TrustedImm32(JSValue::CellTag), regT2);1361 1362 done.link(this);1363 emitStore(dst, regT2, regT0);1364 1170 } 1365 1171 -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r279105 r280760 37 37 #include "LinkBuffer.h" 38 38 #include "PrivateFieldPutKind.h" 39 #include "ProbeContext.h" 39 40 #include "SlowPathCall.h" 40 41 #include "StructureStubInfo.h" … … 87 88 } 88 89 89 void JIT::emitSlow_op_get_by_val(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 90 template<typename OpcodeType> 91 void JIT::generateGetByValSlowCase(const OpcodeType& bytecode, Vector<SlowCaseEntry>::iterator& iter) 90 92 { 91 93 if (hasAnySlowCases(iter)) { 92 auto bytecode = currentInstruction->as<OpGetByVal>();93 94 VirtualRegister dst = bytecode.m_dst; 94 95 auto& metadata = bytecode.metadata(m_codeBlock); … … 135 136 gen.reportSlowPathCall(coldPathBegin, call); 136 137 } 138 } 139 140 void JIT::emitSlow_op_get_by_val(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 141 { 142 generateGetByValSlowCase(currentInstruction->as<OpGetByVal>(), iter); 137 143 } 138 144 … … 2978 2984 template void JIT::emit_op_put_by_val<OpPutByVal>(const Instruction*); 2979 2985 2986 void JIT::emit_op_enumerator_next(const Instruction* currentInstruction) 2987 { 2988 auto bytecode = currentInstruction->as<OpEnumeratorNext>(); 2989 auto& metadata = bytecode.metadata(m_codeBlock); 2990 2991 VirtualRegister base = bytecode.m_base; 2992 VirtualRegister mode = bytecode.m_mode; 2993 VirtualRegister index = bytecode.m_index; 2994 VirtualRegister propertyName = bytecode.m_propertyName; 2995 VirtualRegister enumerator = bytecode.m_enumerator; 2996 2997 JumpList done; 2998 JumpList operationCases; 2999 3000 GPRReg modeGPR = regT0; 3001 GPRReg indexGPR = regT1; 3002 GPRReg baseGPR = regT2; 3003 3004 // This is the most common mode set we tend to see, so special case it if we profile it in the LLInt. 3005 if (metadata.m_enumeratorMetadata == JSPropertyNameEnumerator::OwnStructureMode) { 3006 GPRReg enumeratorGPR = regT3; 3007 emitGetVirtualRegister(enumerator, enumeratorGPR); 3008 operationCases.append(branchTest32(NonZero, Address(enumeratorGPR, JSPropertyNameEnumerator::modeSetOffset()), TrustedImm32(~JSPropertyNameEnumerator::OwnStructureMode))); 3009 emitGetVirtualRegister(base, baseGPR); 3010 load32(Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()), indexGPR); 3011 operationCases.append(branch32(NotEqual, indexGPR, Address(baseGPR, JSCell::structureIDOffset()))); 3012 3013 emitGetVirtualRegister(mode, modeGPR); 3014 emitGetVirtualRegister(index, indexGPR); 3015 Jump notInit = branchTest32(Zero, modeGPR); 3016 // Need to use add64 since this is a JSValue int32. 3017 add64(TrustedImm32(1), indexGPR); 3018 emitPutVirtualRegister(index, indexGPR); 3019 notInit.link(this); 3020 storeTrustedValue(jsNumber(static_cast<uint8_t>(JSPropertyNameEnumerator::OwnStructureMode)), addressFor(mode)); 3021 3022 Jump outOfBounds = branch32(AboveOrEqual, indexGPR, Address(enumeratorGPR, JSPropertyNameEnumerator::endStructurePropertyIndexOffset())); 3023 loadPtr(Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), enumeratorGPR); 3024 // We need to clear the high bits from the number encoding. 3025 and32(TrustedImm32(-1), indexGPR); 3026 loadPtr(BaseIndex(enumeratorGPR, indexGPR, ScalePtr), enumeratorGPR); 3027 3028 emitPutVirtualRegister(propertyName, enumeratorGPR); 3029 done.append(jump()); 3030 3031 outOfBounds.link(this); 3032 storeTrustedValue(jsNull(), addressFor(propertyName)); 3033 done.append(jump()); 3034 } 3035 3036 operationCases.link(this); 3037 3038 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_next); 3039 slowPathCall.call(); 3040 3041 done.link(this); 3042 } 3043 3044 void JIT::emit_op_enumerator_get_by_val(const Instruction* currentInstruction) 3045 { 3046 auto bytecode = currentInstruction->as<OpEnumeratorGetByVal>(); 3047 auto& metadata = bytecode.metadata(m_codeBlock); 3048 VirtualRegister dst = bytecode.m_dst; 3049 VirtualRegister mode = bytecode.m_mode; 3050 VirtualRegister base = bytecode.m_base; 3051 VirtualRegister index = bytecode.m_index; 3052 VirtualRegister propertyName = bytecode.m_propertyName; 3053 VirtualRegister enumerator = bytecode.m_enumerator; 3054 ArrayProfile* profile = &metadata.m_arrayProfile; 3055 3056 JumpList doneCases; 3057 3058 auto resultGPR = regT0; 3059 3060 emitGetVirtualRegister(base, regT0); 3061 emitGetVirtualRegister(mode, regT2); 3062 emitGetVirtualRegister(propertyName, regT1); 3063 3064 or8(regT2, AbsoluteAddress(&metadata.m_enumeratorMetadata)); 3065 3066 addSlowCase(branchIfNotCell(regT0)); 3067 // This is always an int32 encoded value. 3068 Jump isNotOwnStructureMode = branchTest32(NonZero, regT2, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)); 3069 3070 // Check the structure 3071 emitGetVirtualRegister(enumerator, regT2); 3072 load32(Address(regT0, JSCell::structureIDOffset()), regT3); 3073 Jump structureMismatch = branch32(NotEqual, regT3, Address(regT2, JSPropertyNameEnumerator::cachedStructureIDOffset())); 3074 3075 // Compute the offset. 3076 emitGetVirtualRegister(index, regT3); 3077 // If index is less than the enumerator's cached inline storage, then it's an inline access 3078 Jump outOfLineAccess = branch32(AboveOrEqual, regT3, Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset())); 3079 addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0); 3080 signExtend32ToPtr(regT3, regT3); 3081 load64(BaseIndex(regT0, regT3, TimesEight), resultGPR); 3082 3083 doneCases.append(jump()); 3084 3085 // Otherwise it's out of line 3086 outOfLineAccess.link(this); 3087 loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0); 3088 sub32(Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT3); 3089 neg32(regT3); 3090 signExtend32ToPtr(regT3, regT3); 3091 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); 3092 load64(BaseIndex(regT0, regT3, TimesEight, offsetOfFirstProperty), resultGPR); 3093 doneCases.append(jump()); 3094 3095 structureMismatch.link(this); 3096 store8(TrustedImm32(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch), &metadata.m_enumeratorMetadata); 3097 3098 isNotOwnStructureMode.link(this); 3099 Jump isNotIndexed = branchTest32(Zero, regT2, TrustedImm32(JSPropertyNameEnumerator::IndexedMode)); 3100 // Replace the string with the index. 3101 emitGetVirtualRegister(index, regT1); 3102 3103 isNotIndexed.link(this); 3104 emitArrayProfilingSiteWithCell(regT0, regT2, profile); 3105 3106 JITGetByValGenerator gen( 3107 m_codeBlock, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), AccessType::GetByVal, RegisterSet::stubUnavailableRegisters(), 3108 JSValueRegs(regT0), JSValueRegs(regT1), JSValueRegs(resultGPR), regT2); 3109 gen.generateFastPath(*this); 3110 if (!JITCode::useDataIC(JITType::BaselineJIT)) 3111 addSlowCase(gen.slowPathJump()); 3112 else 3113 addSlowCase(); 3114 m_getByVals.append(gen); 3115 3116 doneCases.link(this); 3117 3118 emitValueProfilingSite(metadata, JSValueRegs(resultGPR)); 3119 emitPutVirtualRegister(dst); 3120 } 3121 3122 void JIT::emitSlow_op_enumerator_get_by_val(const Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 3123 { 3124 generateGetByValSlowCase(currentInstruction->as<OpEnumeratorGetByVal>(), iter); 3125 } 3126 3127 template <typename OpcodeType, typename SlowPathFunctionType> 3128 void JIT::emit_enumerator_has_propertyImpl(const Instruction* currentInstruction, const OpcodeType& bytecode, SlowPathFunctionType generalCase) 3129 { 3130 auto& metadata = bytecode.metadata(m_codeBlock); 3131 VirtualRegister dst = bytecode.m_dst; 3132 VirtualRegister base = bytecode.m_base; 3133 VirtualRegister enumerator = bytecode.m_enumerator; 3134 VirtualRegister mode = bytecode.m_mode; 3135 3136 JumpList slowCases; 3137 3138 emitGetVirtualRegister(mode, regT0); 3139 or8(regT0, AbsoluteAddress(&metadata.m_enumeratorMetadata)); 3140 3141 slowCases.append(branchTest32(Zero, regT0, TrustedImm32(JSPropertyNameEnumerator::OwnStructureMode))); 3142 3143 emitGetVirtualRegister(base, regT0); 3144 3145 slowCases.append(branchIfNotCell(regT0)); 3146 3147 emitGetVirtualRegister(enumerator, regT1); 3148 load32(Address(regT0, JSCell::structureIDOffset()), regT0); 3149 slowCases.append(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset()))); 3150 3151 move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0); 3152 emitPutVirtualRegister(dst); 3153 Jump done = jump(); 3154 3155 slowCases.link(this); 3156 3157 JITSlowPathCall slowPathCall(this, currentInstruction, generalCase); 3158 slowPathCall.call(); 3159 3160 done.link(this); 3161 } 3162 3163 void JIT::emit_op_enumerator_in_by_val(const Instruction* currentInstruction) 3164 { 3165 emit_enumerator_has_propertyImpl(currentInstruction, currentInstruction->as<OpEnumeratorInByVal>(), slow_path_enumerator_in_by_val); 3166 } 3167 3168 void JIT::emit_op_enumerator_has_own_property(const Instruction* currentInstruction) 3169 { 3170 emit_enumerator_has_propertyImpl(currentInstruction, currentInstruction->as<OpEnumeratorHasOwnProperty>(), slow_path_enumerator_has_own_property); 3171 } 3172 2980 3173 #else // USE(JSVALUE64) 2981 3174 -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r279105 r280760 1506 1506 template void JIT::emit_op_put_by_val<OpPutByVal>(const Instruction*); 1507 1507 1508 void JIT::emit_op_enumerator_next(const Instruction* currentInstruction) 1509 { 1510 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_next); 1511 slowPathCall.call(); 1512 } 1513 1514 void JIT::emit_op_enumerator_get_by_val(const Instruction* currentInstruction) 1515 { 1516 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_get_by_val); 1517 slowPathCall.call(); 1518 } 1519 1520 void JIT::emitSlow_op_enumerator_get_by_val(const Instruction*, Vector<SlowCaseEntry>::iterator&) 1521 { 1522 UNREACHABLE_FOR_PLATFORM(); 1523 } 1524 1525 void JIT::emit_op_enumerator_in_by_val(const Instruction* currentInstruction) 1526 { 1527 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_in_by_val); 1528 slowPathCall.call(); 1529 } 1530 1531 void JIT::emit_op_enumerator_has_own_property(const Instruction* currentInstruction) 1532 { 1533 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enumerator_has_own_property); 1534 slowPathCall.call(); 1535 } 1536 1508 1537 } // namespace JSC 1509 1538 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r279343 r280760 1993 1993 slowPathOp(define_accessor_property) 1994 1994 slowPathOp(define_data_property) 1995 slowPathOp(enumerator_generic_pname)1996 slowPathOp(enumerator_structure_pname)1997 1995 slowPathOp(get_by_val_with_this) 1998 slowPathOp(get_direct_pname)1999 slowPathOp(get_enumerable_length)2000 1996 slowPathOp(get_property_enumerator) 2001 slowPathOp(has_enumerable_indexed_property) 2002 slowPathOp(has_enumerable_property) 1997 slowPathOp(enumerator_next) 1998 slowPathOp(enumerator_get_by_val) 1999 slowPathOp(enumerator_in_by_val) 2000 slowPathOp(enumerator_has_own_property) 2003 2001 2004 2002 if not JSVALUE64 2005 slowPathOp(has_enumerable_structure_property)2006 slowPathOp(has_own_structure_property)2007 slowPathOp(in_structure_property)2008 2003 slowPathOp(get_prototype_of) 2009 2004 end … … 2022 2017 slowPathOp(strcat) 2023 2018 slowPathOp(throw_static_error) 2024 slowPathOp(to_index_string)2025 2019 slowPathOp(typeof) 2026 2020 slowPathOp(typeof_is_object) -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r279343 r280760 3142 3142 end) 3143 3143 3144 macro hasStructurePropertyImpl(size, get, dispatch, return, slowPathCall)3145 get(m_base, t0)3146 loadConstantOrVariable(size, t0, t1)3147 btqnz t1, notCellMask, .slowPath3148 3149 loadVariable(get, m_enumerator, t0)3150 loadi JSCell::m_structureID[t1], t13151 bineq t1, JSPropertyNameEnumerator::m_cachedStructureID[t0], .slowPath3152 3153 return(ValueTrue)3154 3155 .slowPath:3156 callSlowPath(slowPathCall)3157 dispatch()3158 end3159 3160 llintOpWithReturn(op_has_enumerable_structure_property, OpHasEnumerableStructureProperty, macro (size, get, dispatch, return)3161 hasStructurePropertyImpl(size, get, dispatch, return, _slow_path_has_enumerable_structure_property)3162 end)3163 3164 llintOpWithReturn(op_has_own_structure_property, OpHasOwnStructureProperty, macro (size, get, dispatch, return)3165 hasStructurePropertyImpl(size, get, dispatch, return, _slow_path_has_own_structure_property)3166 end)3167 3168 llintOpWithReturn(op_in_structure_property, OpInStructureProperty, macro (size, get, dispatch, return)3169 hasStructurePropertyImpl(size, get, dispatch, return, _slow_path_in_structure_property)3170 end)3171 3172 3144 op(fuzzer_return_early_from_loop_hint, macro () 3173 3145 loadp CodeBlock[cfr], t0 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r279105 r280760 963 963 } 964 964 965 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_enumerable_length)966 {967 BEGIN();968 auto bytecode = pc->as<OpGetEnumerableLength>();969 JSValue enumeratorValue = GET_C(bytecode.m_base).jsValue();970 if (enumeratorValue.isUndefinedOrNull())971 RETURN(jsNumber(0));972 973 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());974 975 RETURN(jsNumber(enumerator->indexedLength()));976 }977 978 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_indexed_property)979 {980 BEGIN();981 auto bytecode = pc->as<OpHasEnumerableIndexedProperty>();982 auto& metadata = bytecode.metadata(codeBlock);983 JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);984 CHECK_EXCEPTION();985 JSValue property = GET(bytecode.m_property).jsValue();986 metadata.m_arrayProfile.observeStructure(base->structure(vm));987 ASSERT(property.isUInt32AsAnyInt());988 RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, property.asUInt32AsAnyInt())));989 }990 991 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_structure_property)992 {993 BEGIN();994 auto bytecode = pc->as<OpHasEnumerableStructureProperty>();995 JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);996 CHECK_EXCEPTION();997 JSValue property = GET(bytecode.m_property).jsValue();998 RELEASE_ASSERT(property.isString());999 #if USE(JSVALUE32_64)1000 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());1001 if (base->structure(vm)->id() == enumerator->cachedStructureID())1002 RETURN(jsBoolean(true));1003 #endif1004 JSString* string = asString(property);1005 auto propertyName = string->toIdentifier(globalObject);1006 CHECK_EXCEPTION();1007 RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName)));1008 }1009 1010 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_own_structure_property)1011 {1012 BEGIN();1013 auto bytecode = pc->as<OpHasOwnStructureProperty>();1014 JSValue base = GET_C(bytecode.m_base).jsValue();1015 1016 #if USE(JSVALUE32_64)1017 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());1018 if (base.isCell() && base.asCell()->structure(vm)->id() == enumerator->cachedStructureID())1019 RETURN(jsBoolean(true));1020 #endif1021 1022 JSValue property = GET(bytecode.m_property).jsValue();1023 RELEASE_ASSERT(property.isString());1024 JSString* string = asString(property);1025 auto propertyName = string->toIdentifier(globalObject);1026 CHECK_EXCEPTION();1027 1028 RETURN(jsBoolean(objectPrototypeHasOwnProperty(globalObject, base, propertyName)));1029 }1030 1031 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_in_structure_property)1032 {1033 BEGIN();1034 auto bytecode = pc->as<OpInStructureProperty>();1035 JSValue base = GET_C(bytecode.m_base).jsValue();1036 #if USE(JSVALUE32_64)1037 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell());1038 if (base.isCell() && base.asCell()->structure(vm)->id() == enumerator->cachedStructureID())1039 RETURN(jsBoolean(true));1040 #endif1041 JSValue property = GET(bytecode.m_property).jsValue();1042 RELEASE_ASSERT(property.isString());1043 RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, asString(property))));1044 }1045 1046 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_enumerable_property)1047 {1048 BEGIN();1049 auto bytecode = pc->as<OpHasEnumerableProperty>();1050 JSObject* base = GET_C(bytecode.m_base).jsValue().toObject(globalObject);1051 CHECK_EXCEPTION();1052 JSValue property = GET(bytecode.m_property).jsValue();1053 ASSERT(property.isString());1054 JSString* string = asString(property);1055 auto propertyName = string->toIdentifier(globalObject);1056 CHECK_EXCEPTION();1057 RETURN(jsBoolean(base->hasEnumerableProperty(globalObject, propertyName)));1058 }1059 1060 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_direct_pname)1061 {1062 BEGIN();1063 auto bytecode = pc->as<OpGetDirectPname>();1064 JSValue baseValue = GET_C(bytecode.m_base).jsValue();1065 JSValue property = GET(bytecode.m_property).jsValue();1066 ASSERT(property.isString());1067 JSString* string = asString(property);1068 auto propertyName = string->toIdentifier(globalObject);1069 CHECK_EXCEPTION();1070 RETURN(baseValue.get(globalObject, propertyName));1071 }1072 1073 965 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_get_property_enumerator) 1074 966 { … … 1085 977 } 1086 978 1087 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_structure_pname) 1088 { 1089 BEGIN(); 1090 auto bytecode = pc->as<OpEnumeratorStructurePname>(); 1091 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell()); 1092 uint32_t index = GET(bytecode.m_index).jsValue().asUInt32AsAnyInt(); 1093 1094 JSString* propertyName = nullptr; 1095 if (index < enumerator->endStructurePropertyIndex()) 1096 propertyName = enumerator->propertyNameAtIndex(index); 1097 RETURN(propertyName ? propertyName : jsNull()); 1098 } 1099 1100 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_generic_pname) 1101 { 1102 BEGIN(); 1103 auto bytecode = pc->as<OpEnumeratorGenericPname>(); 1104 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue().asCell()); 1105 uint32_t index = GET(bytecode.m_index).jsValue().asUInt32AsAnyInt(); 1106 1107 JSString* propertyName = nullptr; 1108 if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex()) 1109 propertyName = enumerator->propertyNameAtIndex(index); 1110 RETURN(propertyName ? propertyName : jsNull()); 1111 } 1112 1113 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_to_index_string) 1114 { 1115 BEGIN(); 1116 auto bytecode = pc->as<OpToIndexString>(); 1117 JSValue indexValue = GET(bytecode.m_index).jsValue(); 1118 ASSERT(indexValue.isUInt32AsAnyInt()); 1119 RETURN(jsString(vm, Identifier::from(vm, indexValue.asUInt32AsAnyInt()).string())); 979 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_next) 980 { 981 BEGIN(); 982 auto bytecode = pc->as<OpEnumeratorNext>(); 983 auto& metadata = bytecode.metadata(codeBlock); 984 Register& modeRegister = GET(bytecode.m_mode); 985 Register& indexRegister = GET(bytecode.m_index); 986 Register& nameRegister = GET(bytecode.m_propertyName); 987 988 auto mode = static_cast<JSPropertyNameEnumerator::Mode>(modeRegister.jsValue().asUInt32()); 989 uint32_t index = indexRegister.jsValue().asUInt32(); 990 991 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue()); 992 JSValue baseValue = GET(bytecode.m_base).jsValue(); 993 ASSERT(!baseValue.isUndefinedOrNull()); 994 JSObject* base = baseValue.toObject(globalObject); 995 CHECK_EXCEPTION(); 996 metadata.m_arrayProfile.observeStructureID(base->structureID()); 997 998 JSString* name = enumerator->computeNext(globalObject, base, index, mode); 999 CHECK_EXCEPTION(); 1000 1001 metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode); 1002 modeRegister = jsNumber(static_cast<uint8_t>(mode)); 1003 indexRegister = jsNumber(index); 1004 nameRegister = name ? name : jsNull(); 1005 END(); 1006 } 1007 1008 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_get_by_val) 1009 { 1010 BEGIN(); 1011 auto bytecode = pc->as<OpEnumeratorGetByVal>(); 1012 JSValue baseValue = GET_C(bytecode.m_base).jsValue(); 1013 auto& metadata = bytecode.metadata(codeBlock); 1014 auto mode = static_cast<JSPropertyNameEnumerator::Mode>(GET(bytecode.m_mode).jsValue().asUInt32()); 1015 metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode); 1016 1017 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue()); 1018 unsigned index = GET(bytecode.m_index).jsValue().asInt32(); 1019 switch (mode) { 1020 case JSPropertyNameEnumerator::IndexedMode: { 1021 if (LIKELY(baseValue.isCell())) 1022 metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID()); 1023 RETURN_PROFILED(baseValue.get(globalObject, static_cast<unsigned>(index))); 1024 } 1025 case JSPropertyNameEnumerator::OwnStructureMode: { 1026 if (LIKELY(baseValue.isCell()) && baseValue.asCell()->structureID() == enumerator->cachedStructureID()) { 1027 // We'll only match the structure ID if the base is an object. 1028 ASSERT(index < enumerator->endStructurePropertyIndex()); 1029 RETURN_PROFILED(baseValue.getObject()->getDirect(index < enumerator->cachedInlineCapacity() ? index : index - enumerator->cachedInlineCapacity() + firstOutOfLineOffset)); 1030 } else 1031 metadata.m_enumeratorMetadata |= static_cast<uint8_t>(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch); 1032 FALLTHROUGH; 1033 } 1034 1035 case JSPropertyNameEnumerator::GenericMode: { 1036 if (baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode) 1037 metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID()); 1038 JSString* string = asString(GET(bytecode.m_propertyName).jsValue()); 1039 auto propertyName = string->toIdentifier(globalObject); 1040 CHECK_EXCEPTION(); 1041 RETURN_PROFILED(baseValue.get(globalObject, propertyName)); 1042 } 1043 1044 default: 1045 RELEASE_ASSERT_NOT_REACHED(); 1046 break; 1047 }; 1048 RELEASE_ASSERT_NOT_REACHED(); 1049 } 1050 1051 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_in_by_val) 1052 { 1053 BEGIN(); 1054 auto bytecode = pc->as<OpEnumeratorInByVal>(); 1055 JSValue baseValue = GET_C(bytecode.m_base).jsValue(); 1056 auto& metadata = bytecode.metadata(codeBlock); 1057 auto mode = static_cast<JSPropertyNameEnumerator::Mode>(GET(bytecode.m_mode).jsValue().asUInt32()); 1058 metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode); 1059 1060 CHECK_EXCEPTION(); 1061 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue()); 1062 if (auto* base = baseValue.getObject()) { 1063 if (mode == JSPropertyNameEnumerator::OwnStructureMode && base->structureID() == enumerator->cachedStructureID()) 1064 RETURN(jsBoolean(true)); 1065 1066 if (mode == JSPropertyNameEnumerator::IndexedMode) 1067 RETURN(jsBoolean(base->hasProperty(globalObject, GET(bytecode.m_index).jsValue().asUInt32()))); 1068 } 1069 1070 JSString* string = asString(GET(bytecode.m_propertyName).jsValue()); 1071 RETURN(jsBoolean(CommonSlowPaths::opInByVal(globalObject, baseValue, string, &metadata.m_arrayProfile))); 1072 } 1073 1074 JSC_DEFINE_COMMON_SLOW_PATH(slow_path_enumerator_has_own_property) 1075 { 1076 BEGIN(); 1077 auto bytecode = pc->as<OpEnumeratorHasOwnProperty>(); 1078 JSValue baseValue = GET_C(bytecode.m_base).jsValue(); 1079 auto& metadata = bytecode.metadata(codeBlock); 1080 auto mode = static_cast<JSPropertyNameEnumerator::Mode>(GET(bytecode.m_mode).jsValue().asUInt32()); 1081 metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode); 1082 1083 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue()); 1084 if (auto* base = baseValue.getObject()) { 1085 if (mode == JSPropertyNameEnumerator::OwnStructureMode && base->structureID() == enumerator->cachedStructureID()) 1086 RETURN(jsBoolean(true)); 1087 1088 if (mode == JSPropertyNameEnumerator::IndexedMode) 1089 RETURN(jsBoolean(base->hasOwnProperty(globalObject, GET(bytecode.m_index).jsValue().asUInt32()))); 1090 } 1091 1092 JSString* string = asString(GET(bytecode.m_propertyName).jsValue()); 1093 auto propertyName = string->toIdentifier(globalObject); 1094 CHECK_EXCEPTION(); 1095 RETURN(jsBoolean(objectPrototypeHasOwnProperty(globalObject, baseValue, propertyName))); 1120 1096 } 1121 1097 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h
r279105 r280760 255 255 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_primitive); 256 256 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_property_key); 257 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_enumerable_length);258 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_indexed_property);259 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_structure_property);260 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_enumerable_property);261 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_own_structure_property);262 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_in_structure_property);263 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_direct_pname);264 257 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_get_property_enumerator); 265 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_structure_pname); 266 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_generic_pname); 267 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_index_string); 258 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_next); 259 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_get_by_val); 260 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_in_by_val); 261 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_enumerator_has_own_property); 268 262 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_profile_type_clear_log); 269 263 JSC_DECLARE_COMMON_SLOW_PATH(slow_path_unreachable); -
trunk/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp
r278253 r280760 91 91 92 92 case op_get_by_val_with_this: 93 case op_get_direct_pname:94 93 case op_construct: 95 94 case op_construct_varargs: -
trunk/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp
r277909 r280760 1 1 /* 2 * Copyright (C) 2019 Apple Inc. All rights reserved.2 * Copyright (C) 2019-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 53 53 if (opcodeId == op_call_varargs || opcodeId == op_call_eval || opcodeId == op_tail_call || opcodeId == op_tail_call_varargs) 54 54 return op_call; 55 if (opcodeId == op_ get_direct_pname|| opcodeId == op_get_by_val_with_this)55 if (opcodeId == op_enumerator_get_by_val || opcodeId == op_get_by_val_with_this) 56 56 return op_get_by_val; 57 57 if (opcodeId == op_construct_varargs) -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r280289 r280760 1462 1462 #endif 1463 1463 1464 m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::emptyPropertyNameEnumerator)].initLater([] (const Initializer<JSCell>& init) { 1465 init.set(init.vm.emptyPropertyNameEnumerator()); 1466 }); 1467 1464 1468 if (Options::exposeProfilersOnGlobalObject()) { 1465 1469 #if ENABLE(SAMPLING_PROFILER) -
trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp
r278338 r280760 57 57 , m_cachedInlineCapacity(structure ? structure->inlineCapacity() : 0) 58 58 { 59 if (m_indexedLength) 60 m_modeSet |= JSPropertyNameEnumerator::IndexedMode; 61 if (m_endStructurePropertyIndex) 62 m_modeSet |= JSPropertyNameEnumerator::OwnStructureMode; 63 if (m_endGenericPropertyIndex - m_endStructurePropertyIndex) 64 m_modeSet |= JSPropertyNameEnumerator::GenericMode; 59 65 } 60 66 … … 149 155 } 150 156 157 JSString* JSPropertyNameEnumerator::computeNext(JSGlobalObject* globalObject, JSObject* base, uint32_t& index, Mode& mode, bool shouldAllocateIndexedNameString) 158 { 159 VM& vm = globalObject->vm(); 160 auto scope = DECLARE_THROW_SCOPE(vm); 161 162 ASSERT(indexedLength() || sizeOfPropertyNames()); 163 164 index++; 165 switch (mode) { 166 case InitMode: { 167 mode = IndexedMode; 168 index = 0; 169 FALLTHROUGH; 170 } 171 172 case JSPropertyNameEnumerator::IndexedMode: { 173 while (index < indexedLength() && !base->hasEnumerableProperty(globalObject, index)) { 174 RETURN_IF_EXCEPTION(scope, nullptr); 175 index++; 176 } 177 scope.assertNoException(); 178 179 if (index < indexedLength()) 180 return shouldAllocateIndexedNameString ? jsString(vm, Identifier::from(vm, index).string()) : nullptr; 181 182 if (!sizeOfPropertyNames()) 183 return nullptr; 184 185 mode = OwnStructureMode; 186 index = 0; 187 FALLTHROUGH; 188 } 189 190 case JSPropertyNameEnumerator::OwnStructureMode: 191 case JSPropertyNameEnumerator::GenericMode: { 192 JSString* name = nullptr; 193 while (true) { 194 if (index >= sizeOfPropertyNames()) 195 break; 196 name = propertyNameAtIndex(index); 197 if (!name) 198 break; 199 if (index < endStructurePropertyIndex() && base->structureID() == cachedStructureID()) 200 break; 201 auto id = Identifier::fromString(vm, name->value(globalObject)); 202 RETURN_IF_EXCEPTION(scope, nullptr); 203 if (base->hasEnumerableProperty(globalObject, id)) 204 break; 205 RETURN_IF_EXCEPTION(scope, nullptr); 206 name = nullptr; 207 index++; 208 } 209 scope.assertNoException(); 210 211 if (index >= endStructurePropertyIndex() && index < sizeOfPropertyNames()) 212 mode = GenericMode; 213 return name; 214 } 215 216 default: 217 break; 218 } 219 RELEASE_ASSERT_NOT_REACHED(); 220 return nullptr; 221 } 222 151 223 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h
r273766 r280760 29 29 #include "Operations.h" 30 30 #include "PropertyNameArray.h" 31 #include "Structure .h"31 #include "StructureChain.h" 32 32 33 33 namespace JSC { … … 37 37 using Base = JSCell; 38 38 static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; 39 40 enum Mode : uint8_t { 41 InitMode = 0, 42 IndexedMode = 1 << 0, 43 OwnStructureMode = 1 << 1, 44 GenericMode = 1 << 2, 45 // Profiling Only 46 HasSeenOwnStructureModeStructureMismatch = 1 << 3, 47 }; 48 49 static constexpr uint8_t enumerationModeMask = (GenericMode << 1) - 1; 39 50 40 51 template<typename CellType, SubspaceAccess mode> … … 75 86 uint32_t cachedInlineCapacity() const { return m_cachedInlineCapacity; } 76 87 uint32_t sizeOfPropertyNames() const { return endGenericPropertyIndex(); } 88 uint32_t modeSet() const { return m_modeSet; } 77 89 static ptrdiff_t cachedStructureIDOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedStructureID); } 78 90 static ptrdiff_t indexedLengthOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_indexedLength); } … … 80 92 static ptrdiff_t endGenericPropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_endGenericPropertyIndex); } 81 93 static ptrdiff_t cachedInlineCapacityOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedInlineCapacity); } 94 static ptrdiff_t modeSetOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_modeSet); } 82 95 static ptrdiff_t cachedPropertyNamesVectorOffset() 83 96 { 84 97 return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames); 85 98 } 99 100 JSString* computeNext(JSGlobalObject*, JSObject* base, uint32_t& currentIndex, Mode&, bool shouldAllocateIndexedNameString = true); 86 101 87 102 DECLARE_VISIT_CHILDREN; … … 100 115 uint32_t m_endGenericPropertyIndex; 101 116 uint32_t m_cachedInlineCapacity; 117 uint32_t m_modeSet { 0 }; 102 118 }; 103 119 … … 135 151 } 136 152 137 enumerator = JSPropertyNameEnumerator::create(vm, structureAfterGettingPropertyNames, indexedLength, numberStructureProperties, WTFMove(propertyNames)); 153 if (!indexedLength && !propertyNames.size()) 154 enumerator = vm.emptyPropertyNameEnumerator(); 155 else 156 enumerator = JSPropertyNameEnumerator::create(vm, structureAfterGettingPropertyNames, indexedLength, numberStructureProperties, WTFMove(propertyNames)); 138 157 if (!indexedLength && successfullyNormalizedChain && structureAfterGettingPropertyNames == structure) { 139 158 enumerator->setCachedPrototypeChain(vm, structure->prototypeChain(globalObject, base)); … … 144 163 } 145 164 165 using EnumeratorMetadata = std::underlying_type_t<JSPropertyNameEnumerator::Mode>; 166 146 167 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp
r253576 r280760 1 1 /* 2 * Copyright (C) 2019 Apple Inc. All rights reserved.2 * Copyright (C) 2019-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 53 53 case op_get_by_id_with_this: 54 54 case op_get_by_val_with_this: 55 case op_ get_direct_pname:55 case op_enumerator_get_by_val: 56 56 case op_construct: 57 57 case op_construct_varargs:
Note:
See TracChangeset
for help on using the changeset viewer.