Changeset 181993 in webkit
- Timestamp:
- Mar 25, 2015, 9:28:43 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 88 added
- 4 deleted
- 181 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r181988 r181993 1 2015-03-25 Filip Pizlo <fpizlo@apple.com> 2 3 Heap variables shouldn't end up in the stack frame 4 https://bugs.webkit.org/show_bug.cgi?id=141174 5 6 Reviewed by Geoffrey Garen. 7 8 * js/function-apply-aliased-expected.txt: 9 * js/function-dot-arguments-expected.txt: 10 * js/regress/arguments-expected.txt: Added. 11 * js/regress/arguments-named-and-reflective-expected.txt: Added. 12 * js/regress/arguments-named-and-reflective.html: Added. 13 * js/regress/arguments-strict-mode-expected.txt: Added. 14 * js/regress/arguments-strict-mode.html: Added. 15 * js/regress/arguments.html: Added. 16 * js/regress/script-tests/arguments-named-and-reflective.js: Added. 17 * js/regress/script-tests/arguments-strict-mode.js: Added. 18 * js/regress/script-tests/arguments.js: Added. 19 * js/regress/script-tests/try-catch-get-by-val-cloned-arguments.js: Added. 20 * js/regress/script-tests/try-catch-get-by-val-direct-arguments.js: Added. 21 * js/regress/script-tests/try-catch-get-by-val-scoped-arguments.js: Added. 22 * js/regress/script-tests/varargs-call.js: Added. 23 * js/regress/script-tests/varargs-construct-inline.js: Added. 24 * js/regress/script-tests/varargs-construct.js: Added. 25 * js/regress/script-tests/varargs-inline.js: Added. 26 * js/regress/script-tests/varargs-strict-mode.js: Added. 27 * js/regress/script-tests/varargs.js: Added. 28 * js/regress/try-catch-get-by-val-cloned-arguments-expected.txt: Added. 29 * js/regress/try-catch-get-by-val-cloned-arguments.html: Added. 30 * js/regress/try-catch-get-by-val-direct-arguments-expected.txt: Added. 31 * js/regress/try-catch-get-by-val-direct-arguments.html: Added. 32 * js/regress/try-catch-get-by-val-scoped-arguments-expected.txt: Added. 33 * js/regress/try-catch-get-by-val-scoped-arguments.html: Added. 34 * js/regress/varargs-call-expected.txt: Added. 35 * js/regress/varargs-call.html: Added. 36 * js/regress/varargs-construct-expected.txt: Added. 37 * js/regress/varargs-construct-inline-expected.txt: Added. 38 * js/regress/varargs-construct-inline.html: Added. 39 * js/regress/varargs-construct.html: Added. 40 * js/regress/varargs-expected.txt: Added. 41 * js/regress/varargs-inline-expected.txt: Added. 42 * js/regress/varargs-inline.html: Added. 43 * js/regress/varargs-strict-mode-expected.txt: Added. 44 * js/regress/varargs-strict-mode.html: Added. 45 * js/regress/varargs.html: Added. 46 * js/script-tests/function-apply-aliased.js: 47 * js/script-tests/function-dot-arguments.js: 48 1 49 2015-03-25 Chris Fleizach <cfleizach@apple.com> 2 50 -
trunk/LayoutTests/js/function-apply-aliased-expected.txt
r42337 r181993 23 23 PASS forwarder(myFunctionWithApply, myObject, arg1Array) is [myFunctionWithApply, "myFunctionWithApply.apply", myObject] 24 24 PASS myFunctionWithApply.aliasedApply(myObject, arg1Array) is [myObject, "myFunctionWithApply", "arg1"] 25 PASS throw 42 threw exception 42. 25 26 PASS myFunction.apply(null, new Array(5000000)) threw exception RangeError: Maximum call stack size exceeded.. 26 27 PASS myFunction.apply(null, new Array(1 << 30)) threw exception RangeError: Maximum call stack size exceeded.. -
trunk/LayoutTests/js/function-dot-arguments-expected.txt
r178517 r181993 33 33 PASS tearOffTest4b(1, 2, 3, false) is [1, 2, 3, false] 34 34 PASS tearOffTest4c(1, 2, 3, false) is [1, 2, 3, false] 35 PASS tearOffTest5(1, 2, 3, false) is [1 0, 2, 3, false]36 PASS tearOffTest5a(1, 2, 3, false) is [1 0, 2, 3, false]35 PASS tearOffTest5(1, 2, 3, false) is [1, 2, 3, false] 36 PASS tearOffTest5a(1, 2, 3, false) is [1, 2, 3, false] 37 37 PASS tearOffTest5b(1, 2, 3, false) is [1, 2, 3, false] 38 38 PASS tearOffTest5c(1, 2, 3, false) is [1, 2, 3, false] 39 PASS tearOffTest6(1, 2, 3, false) is [1 0, 2, 3, false]40 PASS tearOffTest6a(1, 2, 3, false) is [1 0, 2, 3, false]39 PASS tearOffTest6(1, 2, 3, false) is [1, 2, 3, false] 40 PASS tearOffTest6a(1, 2, 3, false) is [1, 2, 3, false] 41 41 PASS tearOffTest6b(1, 2, 3, false) is [1, 2, 3, false] 42 42 PASS tearOffTest6c(1, 2, 3, false) is [1, 2, 3, false] … … 57 57 PASS tearOffTest10b(1, 2, 3, false) is [undefined, 2, 3, false] 58 58 PASS tearOffTest10c(1, 2, 3, false) is [undefined, 2, 3, false] 59 PASS lexicalArgumentsLiveRead1(0, 2, 3) is 160 PASS lexicalArgumentsLiveRead2(1, 0, 3) is 261 PASS lexicalArgumentsLiveRead3(1, 2, 0) is 359 PASS lexicalArgumentsLiveRead1(0, 2, 3) is 0 60 PASS lexicalArgumentsLiveRead2(1, 0, 3) is 0 61 PASS lexicalArgumentsLiveRead3(1, 2, 0) is 0 62 62 PASS lexicalArgumentsLiveWrite1(0, 2, 3) is 0 63 63 PASS lexicalArgumentsLiveWrite2(1, 0, 3) is 0 -
trunk/LayoutTests/js/script-tests/function-apply-aliased.js
r98407 r181993 45 45 shouldBe("myFunctionWithApply.aliasedApply(myObject, arg1Array)", '[myObject, "myFunctionWithApply", "arg1"]'); 46 46 47 // Let's make sure that shouldThrow() is compiled before we do crazy. 48 shouldThrow("throw 42"); 49 47 50 function stackOverflowTest() { 48 51 try { -
trunk/LayoutTests/js/script-tests/function-dot-arguments.js
r178517 r181993 363 363 return arrayify(inner()); 364 364 } 365 shouldBe("tearOffTest5(1, 2, 3, false)", "[1 0, 2, 3, false]");365 shouldBe("tearOffTest5(1, 2, 3, false)", "[1, 2, 3, false]"); 366 366 367 367 … … 383 383 } 384 384 } 385 shouldBe("tearOffTest5a(1, 2, 3, false)", "[1 0, 2, 3, false]");385 shouldBe("tearOffTest5a(1, 2, 3, false)", "[1, 2, 3, false]"); 386 386 387 387 … … 427 427 return arrayify(tearOffTest6External()); 428 428 } 429 shouldBe("tearOffTest6(1, 2, 3, false)", "[1 0, 2, 3, false]");429 shouldBe("tearOffTest6(1, 2, 3, false)", "[1, 2, 3, false]"); 430 430 431 431 … … 447 447 } 448 448 } 449 shouldBe("tearOffTest6a(1, 2, 3, false)", "[1 0, 2, 3, false]");449 shouldBe("tearOffTest6a(1, 2, 3, false)", "[1, 2, 3, false]"); 450 450 451 451 … … 740 740 return lexicalArgumentsLiveRead1.arguments[0]; 741 741 } 742 shouldBe("lexicalArgumentsLiveRead1(0, 2, 3)", " 1");742 shouldBe("lexicalArgumentsLiveRead1(0, 2, 3)", "0"); 743 743 744 744 function lexicalArgumentsLiveRead2(a, b, c) … … 748 748 return lexicalArgumentsLiveRead2.arguments[1]; 749 749 } 750 shouldBe("lexicalArgumentsLiveRead2(1, 0, 3)", " 2");750 shouldBe("lexicalArgumentsLiveRead2(1, 0, 3)", "0"); 751 751 752 752 function lexicalArgumentsLiveRead3(a, b, c) … … 756 756 return lexicalArgumentsLiveRead3.arguments[2]; 757 757 } 758 shouldBe("lexicalArgumentsLiveRead3(1, 2, 0)", " 3");758 shouldBe("lexicalArgumentsLiveRead3(1, 2, 0)", "0"); 759 759 760 760 function lexicalArgumentsLiveWrite1(a, b, c) -
trunk/Source/JavaScriptCore/CMakeLists.txt
r181990 r181993 119 119 dfg/DFGAbstractHeap.cpp 120 120 dfg/DFGAbstractValue.cpp 121 dfg/DFGArgumentsSimplificationPhase.cpp122 121 dfg/DFGArithMode.cpp 122 dfg/DFGArgumentsEliminationPhase.cpp 123 dfg/DFGArgumentsUtilities.cpp 123 124 dfg/DFGArrayMode.cpp 124 125 dfg/DFGAtTailAbstractState.cpp … … 233 234 dfg/DFGValueSource.cpp 234 235 dfg/DFGValueStrength.cpp 236 dfg/DFGVarargsForwardingPhase.cpp 235 237 dfg/DFGVariableAccessData.cpp 236 238 dfg/DFGVariableAccessDataDump.cpp … … 399 401 set(JavaScriptCore_RUNTIME_SOURCES 400 402 runtime/ArgList.cpp 401 runtime/Arguments.cpp402 403 runtime/ArgumentsIteratorConstructor.cpp 403 404 runtime/ArgumentsIteratorPrototype.cpp … … 415 416 runtime/BundlePath.cpp 416 417 runtime/CallData.cpp 418 runtime/ClonedArguments.cpp 417 419 runtime/CodeCache.cpp 418 420 runtime/CodeSpecializationKind.cpp … … 424 426 runtime/ConsoleClient.cpp 425 427 runtime/ConsolePrototype.cpp 428 runtime/ConstantMode.cpp 426 429 runtime/ConstructData.cpp 427 430 runtime/ControlFlowProfiler.cpp … … 432 435 runtime/DateInstance.cpp 433 436 runtime/DatePrototype.cpp 437 runtime/DirectArguments.cpp 438 runtime/DirectArgumentsOffset.cpp 434 439 runtime/DumpContext.cpp 435 440 runtime/Error.cpp … … 539 544 runtime/RuntimeType.cpp 540 545 runtime/SamplingCounter.cpp 546 runtime/ScopeOffset.cpp 547 runtime/ScopedArguments.cpp 548 runtime/ScopedArgumentsTable.cpp 541 549 runtime/SetConstructor.cpp 542 550 runtime/SetIteratorConstructor.cpp … … 571 579 runtime/VM.cpp 572 580 runtime/VMEntryScope.cpp 581 runtime/VarOffset.cpp 573 582 runtime/Watchdog.cpp 574 583 runtime/WatchdogNone.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r181992 r181993 1 2015-03-25 Filip Pizlo <fpizlo@apple.com> 2 3 Heap variables shouldn't end up in the stack frame 4 https://bugs.webkit.org/show_bug.cgi?id=141174 5 6 Reviewed by Geoffrey Garen. 7 8 This is a major change to how JavaScriptCore handles declared variables (i.e. "var"). It removes 9 any ambiguity about whether a variable should be in the heap or on the stack. A variable will no 10 longer move between heap and stack during its lifetime. This enables a bunch of optimizations and 11 simplifications: 12 13 - Accesses to variables no longer need checks or indirections to determine where the variable is 14 at that moment in time. For example, loading a closure variable now takes just one load instead 15 of two. Loading an argument by index now takes a bounds check and a load in the fastest case 16 (when no arguments object allocation is required) while previously that same operation required 17 a "did I allocate arguments yet" check, a bounds check, and then the load. 18 19 - Reasoning about the allocation of an activation or arguments object now follows the same simple 20 logic as the allocation of any other kind of object. Previously, those objects were lazily 21 allocated - so an allocation instruction wasn't the actual allocation site, since it might not 22 allocate anything at all. This made the implementation of traditional escape analyses really 23 awkward, and ultimately it meant that we missed important cases. Now, we can reason about the 24 arguments object using the usual SSA tricks which allows for more comprehensive removal. 25 26 - The allocations of arguments objects, functions, and activations are now much faster. While 27 this patch generally expands our ability to eliminate arguments object allocations, an earlier 28 version of the patch - which lacked that functionality - was a progression on some arguments- 29 and closure-happy benchmarks because although no allocations were eliminated, all allocations 30 were faster. 31 32 - There is no tear-off. The runtime no loner needs to know about where on the stack a frame keeps 33 its arguments objects or activations. The runtime doesn't have to do things to the arguments 34 objects and activations that a frame allocated, when the frame is unwound. We always had horrid 35 bugs in that code, so it's good to see it go. This removes *a ton* of machinery from the DFG, 36 FTL, CodeBlock, and other places. All of the things having to do with "captured variables" is 37 now gone. This also enables implementing block-scoping. Without this change, block-scope 38 support would require telling CodeBlock and all of the rest of the runtime about all of the 39 variables that store currently-live scopes. That would have been so disastrously hard that it 40 might as well be impossible. With this change, it's fair game for the bytecode generator to 41 simply allocate whatever activations it wants, wherever it wants, and to keep them live for 42 however long it wants. This all works, because after bytecode generation, an activation is just 43 an object and variables that refer to it are just normal variables. 44 45 - SymbolTable can now tell you explicitly where a variable lives. The answer is in the form of a 46 VarOffset object, which has methods like isStack(), isScope(), etc. VirtualRegister is never 47 used for offsets of non-stack variables anymore. We now have shiny new objects for other kinds 48 of offsets - ScopeOffset for offsets into scopes, and DirectArgumentsOffset for offsets into 49 an arguments object. 50 51 - Functions that create activations can now tier-up into the FTL. Previously they couldn't. Also, 52 using activations used to prevent inlining; now functions that use activations can be inlined 53 just fine. 54 55 This is a >1% speed-up on Octane. This is a >2% speed-up on CompressionBench. This is a tiny 56 speed-up on AsmBench (~0.4% or something). This looks like it might be a speed-up on SunSpider. 57 It's only a slow-down on very short-running microbenchmarks we had previously written for our old 58 style of tear-off-based arguments optimization. Those benchmarks are not part of any major suite. 59 60 The easiest way of understanding this change is to start by looking at the changes in runtime/, 61 and then the changes in bytecompiler/, and then sort of work your way up the compiler tiers. 62 63 * CMakeLists.txt: 64 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 65 * JavaScriptCore.xcodeproj/project.pbxproj: 66 * assembler/AbortReason.h: 67 * assembler/AbstractMacroAssembler.h: 68 (JSC::AbstractMacroAssembler::BaseIndex::withOffset): 69 * bytecode/ByValInfo.h: 70 (JSC::hasOptimizableIndexingForJSType): 71 (JSC::hasOptimizableIndexing): 72 (JSC::jitArrayModeForJSType): 73 (JSC::jitArrayModePermitsPut): 74 (JSC::jitArrayModeForStructure): 75 * bytecode/BytecodeKills.h: Added. 76 (JSC::BytecodeKills::BytecodeKills): 77 (JSC::BytecodeKills::operandIsKilled): 78 (JSC::BytecodeKills::forEachOperandKilledAt): 79 (JSC::BytecodeKills::KillSet::KillSet): 80 (JSC::BytecodeKills::KillSet::add): 81 (JSC::BytecodeKills::KillSet::forEachLocal): 82 (JSC::BytecodeKills::KillSet::contains): 83 * bytecode/BytecodeList.json: 84 * bytecode/BytecodeLivenessAnalysis.cpp: 85 (JSC::isValidRegisterForLiveness): 86 (JSC::stepOverInstruction): 87 (JSC::BytecodeLivenessAnalysis::runLivenessFixpoint): 88 (JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset): 89 (JSC::BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset): 90 (JSC::BytecodeLivenessAnalysis::computeFullLiveness): 91 (JSC::BytecodeLivenessAnalysis::computeKills): 92 (JSC::indexForOperand): Deleted. 93 (JSC::BytecodeLivenessAnalysis::getLivenessInfoForNonCapturedVarsAtBytecodeOffset): Deleted. 94 (JSC::getLivenessInfo): Deleted. 95 * bytecode/BytecodeLivenessAnalysis.h: 96 * bytecode/BytecodeLivenessAnalysisInlines.h: 97 (JSC::operandIsAlwaysLive): 98 (JSC::operandThatIsNotAlwaysLiveIsLive): 99 (JSC::operandIsLive): 100 * bytecode/BytecodeUseDef.h: 101 (JSC::computeUsesForBytecodeOffset): 102 (JSC::computeDefsForBytecodeOffset): 103 * bytecode/CodeBlock.cpp: 104 (JSC::CodeBlock::dumpBytecode): 105 (JSC::CodeBlock::CodeBlock): 106 (JSC::CodeBlock::nameForRegister): 107 (JSC::CodeBlock::validate): 108 (JSC::CodeBlock::isCaptured): Deleted. 109 (JSC::CodeBlock::framePointerOffsetToGetActivationRegisters): Deleted. 110 (JSC::CodeBlock::machineSlowArguments): Deleted. 111 * bytecode/CodeBlock.h: 112 (JSC::unmodifiedArgumentsRegister): Deleted. 113 (JSC::CodeBlock::setArgumentsRegister): Deleted. 114 (JSC::CodeBlock::argumentsRegister): Deleted. 115 (JSC::CodeBlock::uncheckedArgumentsRegister): Deleted. 116 (JSC::CodeBlock::usesArguments): Deleted. 117 (JSC::CodeBlock::captureCount): Deleted. 118 (JSC::CodeBlock::captureStart): Deleted. 119 (JSC::CodeBlock::captureEnd): Deleted. 120 (JSC::CodeBlock::argumentIndexAfterCapture): Deleted. 121 (JSC::CodeBlock::hasSlowArguments): Deleted. 122 (JSC::ExecState::argumentAfterCapture): Deleted. 123 * bytecode/CodeOrigin.h: 124 * bytecode/DataFormat.h: 125 (JSC::dataFormatToString): 126 * bytecode/FullBytecodeLiveness.h: 127 (JSC::FullBytecodeLiveness::getLiveness): 128 (JSC::FullBytecodeLiveness::operandIsLive): 129 (JSC::FullBytecodeLiveness::FullBytecodeLiveness): Deleted. 130 (JSC::FullBytecodeLiveness::getOut): Deleted. 131 * bytecode/Instruction.h: 132 (JSC::Instruction::Instruction): 133 * bytecode/Operands.h: 134 (JSC::Operands::virtualRegisterForIndex): 135 * bytecode/SpeculatedType.cpp: 136 (JSC::dumpSpeculation): 137 (JSC::speculationToAbbreviatedString): 138 (JSC::speculationFromClassInfo): 139 * bytecode/SpeculatedType.h: 140 (JSC::isDirectArgumentsSpeculation): 141 (JSC::isScopedArgumentsSpeculation): 142 (JSC::isActionableMutableArraySpeculation): 143 (JSC::isActionableArraySpeculation): 144 (JSC::isArgumentsSpeculation): Deleted. 145 * bytecode/UnlinkedCodeBlock.cpp: 146 (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock): 147 * bytecode/UnlinkedCodeBlock.h: 148 (JSC::UnlinkedCodeBlock::setArgumentsRegister): Deleted. 149 (JSC::UnlinkedCodeBlock::usesArguments): Deleted. 150 (JSC::UnlinkedCodeBlock::argumentsRegister): Deleted. 151 * bytecode/ValueRecovery.cpp: 152 (JSC::ValueRecovery::dumpInContext): 153 * bytecode/ValueRecovery.h: 154 (JSC::ValueRecovery::directArgumentsThatWereNotCreated): 155 (JSC::ValueRecovery::outOfBandArgumentsThatWereNotCreated): 156 (JSC::ValueRecovery::nodeID): 157 (JSC::ValueRecovery::argumentsThatWereNotCreated): Deleted. 158 * bytecode/VirtualRegister.h: 159 (JSC::VirtualRegister::operator==): 160 (JSC::VirtualRegister::operator!=): 161 (JSC::VirtualRegister::operator<): 162 (JSC::VirtualRegister::operator>): 163 (JSC::VirtualRegister::operator<=): 164 (JSC::VirtualRegister::operator>=): 165 * bytecompiler/BytecodeGenerator.cpp: 166 (JSC::BytecodeGenerator::generate): 167 (JSC::BytecodeGenerator::BytecodeGenerator): 168 (JSC::BytecodeGenerator::initializeNextParameter): 169 (JSC::BytecodeGenerator::visibleNameForParameter): 170 (JSC::BytecodeGenerator::emitMove): 171 (JSC::BytecodeGenerator::variable): 172 (JSC::BytecodeGenerator::createVariable): 173 (JSC::BytecodeGenerator::emitResolveScope): 174 (JSC::BytecodeGenerator::emitGetFromScope): 175 (JSC::BytecodeGenerator::emitPutToScope): 176 (JSC::BytecodeGenerator::initializeVariable): 177 (JSC::BytecodeGenerator::emitInstanceOf): 178 (JSC::BytecodeGenerator::emitNewFunction): 179 (JSC::BytecodeGenerator::emitNewFunctionInternal): 180 (JSC::BytecodeGenerator::emitCall): 181 (JSC::BytecodeGenerator::emitReturn): 182 (JSC::BytecodeGenerator::emitConstruct): 183 (JSC::BytecodeGenerator::isArgumentNumber): 184 (JSC::BytecodeGenerator::emitEnumeration): 185 (JSC::BytecodeGenerator::addVar): Deleted. 186 (JSC::BytecodeGenerator::emitInitLazyRegister): Deleted. 187 (JSC::BytecodeGenerator::initializeCapturedVariable): Deleted. 188 (JSC::BytecodeGenerator::resolveCallee): Deleted. 189 (JSC::BytecodeGenerator::addCallee): Deleted. 190 (JSC::BytecodeGenerator::addParameter): Deleted. 191 (JSC::BytecodeGenerator::willResolveToArgumentsRegister): Deleted. 192 (JSC::BytecodeGenerator::uncheckedLocalArgumentsRegister): Deleted. 193 (JSC::BytecodeGenerator::createLazyRegisterIfNecessary): Deleted. 194 (JSC::BytecodeGenerator::isCaptured): Deleted. 195 (JSC::BytecodeGenerator::local): Deleted. 196 (JSC::BytecodeGenerator::constLocal): Deleted. 197 (JSC::BytecodeGenerator::emitResolveConstantLocal): Deleted. 198 (JSC::BytecodeGenerator::emitGetArgumentsLength): Deleted. 199 (JSC::BytecodeGenerator::emitGetArgumentByVal): Deleted. 200 (JSC::BytecodeGenerator::emitLazyNewFunction): Deleted. 201 (JSC::BytecodeGenerator::createArgumentsIfNecessary): Deleted. 202 * bytecompiler/BytecodeGenerator.h: 203 (JSC::Variable::Variable): 204 (JSC::Variable::isResolved): 205 (JSC::Variable::ident): 206 (JSC::Variable::offset): 207 (JSC::Variable::isLocal): 208 (JSC::Variable::local): 209 (JSC::Variable::isSpecial): 210 (JSC::BytecodeGenerator::argumentsRegister): 211 (JSC::BytecodeGenerator::emitNode): 212 (JSC::BytecodeGenerator::registerFor): 213 (JSC::Local::Local): Deleted. 214 (JSC::Local::operator bool): Deleted. 215 (JSC::Local::get): Deleted. 216 (JSC::Local::isSpecial): Deleted. 217 (JSC::ResolveScopeInfo::ResolveScopeInfo): Deleted. 218 (JSC::ResolveScopeInfo::isLocal): Deleted. 219 (JSC::ResolveScopeInfo::localIndex): Deleted. 220 (JSC::BytecodeGenerator::hasSafeLocalArgumentsRegister): Deleted. 221 (JSC::BytecodeGenerator::captureMode): Deleted. 222 (JSC::BytecodeGenerator::shouldTearOffArgumentsEagerly): Deleted. 223 (JSC::BytecodeGenerator::shouldCreateArgumentsEagerly): Deleted. 224 (JSC::BytecodeGenerator::hasWatchableVariable): Deleted. 225 (JSC::BytecodeGenerator::watchableVariableIdentifier): Deleted. 226 * bytecompiler/NodesCodegen.cpp: 227 (JSC::ResolveNode::isPure): 228 (JSC::ResolveNode::emitBytecode): 229 (JSC::BracketAccessorNode::emitBytecode): 230 (JSC::DotAccessorNode::emitBytecode): 231 (JSC::EvalFunctionCallNode::emitBytecode): 232 (JSC::FunctionCallResolveNode::emitBytecode): 233 (JSC::CallFunctionCallDotNode::emitBytecode): 234 (JSC::ApplyFunctionCallDotNode::emitBytecode): 235 (JSC::PostfixNode::emitResolve): 236 (JSC::DeleteResolveNode::emitBytecode): 237 (JSC::TypeOfResolveNode::emitBytecode): 238 (JSC::PrefixNode::emitResolve): 239 (JSC::ReadModifyResolveNode::emitBytecode): 240 (JSC::AssignResolveNode::emitBytecode): 241 (JSC::ConstDeclNode::emitCodeSingle): 242 (JSC::EmptyVarExpression::emitBytecode): 243 (JSC::ForInNode::tryGetBoundLocal): 244 (JSC::ForInNode::emitLoopHeader): 245 (JSC::ForOfNode::emitBytecode): 246 (JSC::ArrayPatternNode::emitDirectBinding): 247 (JSC::BindingNode::bindValue): 248 (JSC::getArgumentByVal): Deleted. 249 * dfg/DFGAbstractHeap.h: 250 * dfg/DFGAbstractInterpreter.h: 251 * dfg/DFGAbstractInterpreterInlines.h: 252 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 253 (JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberWorld): 254 (JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberCapturedVars): Deleted. 255 * dfg/DFGAbstractValue.h: 256 * dfg/DFGArgumentPosition.h: 257 (JSC::DFG::ArgumentPosition::addVariable): 258 * dfg/DFGArgumentsEliminationPhase.cpp: Added. 259 (JSC::DFG::performArgumentsElimination): 260 * dfg/DFGArgumentsEliminationPhase.h: Added. 261 * dfg/DFGArgumentsSimplificationPhase.cpp: Removed. 262 * dfg/DFGArgumentsSimplificationPhase.h: Removed. 263 * dfg/DFGArgumentsUtilities.cpp: Added. 264 (JSC::DFG::argumentsInvolveStackSlot): 265 (JSC::DFG::emitCodeToGetArgumentsArrayLength): 266 * dfg/DFGArgumentsUtilities.h: Added. 267 * dfg/DFGArrayMode.cpp: 268 (JSC::DFG::ArrayMode::refine): 269 (JSC::DFG::ArrayMode::alreadyChecked): 270 (JSC::DFG::arrayTypeToString): 271 * dfg/DFGArrayMode.h: 272 (JSC::DFG::ArrayMode::canCSEStorage): 273 (JSC::DFG::ArrayMode::modeForPut): 274 * dfg/DFGAvailabilityMap.cpp: 275 (JSC::DFG::AvailabilityMap::prune): 276 * dfg/DFGAvailabilityMap.h: 277 (JSC::DFG::AvailabilityMap::closeOverNodes): 278 (JSC::DFG::AvailabilityMap::closeStartingWithLocal): 279 * dfg/DFGBackwardsPropagationPhase.cpp: 280 (JSC::DFG::BackwardsPropagationPhase::propagate): 281 * dfg/DFGByteCodeParser.cpp: 282 (JSC::DFG::ByteCodeParser::newVariableAccessData): 283 (JSC::DFG::ByteCodeParser::getLocal): 284 (JSC::DFG::ByteCodeParser::setLocal): 285 (JSC::DFG::ByteCodeParser::getArgument): 286 (JSC::DFG::ByteCodeParser::setArgument): 287 (JSC::DFG::ByteCodeParser::flushDirect): 288 (JSC::DFG::ByteCodeParser::flush): 289 (JSC::DFG::ByteCodeParser::noticeArgumentsUse): 290 (JSC::DFG::ByteCodeParser::handleVarargsCall): 291 (JSC::DFG::ByteCodeParser::attemptToInlineCall): 292 (JSC::DFG::ByteCodeParser::handleInlining): 293 (JSC::DFG::ByteCodeParser::parseBlock): 294 (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry): 295 (JSC::DFG::ByteCodeParser::parseCodeBlock): 296 * dfg/DFGCPSRethreadingPhase.cpp: 297 (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor): 298 (JSC::DFG::CPSRethreadingPhase::canonicalizeLocalsInBlock): 299 * dfg/DFGCSEPhase.cpp: 300 * dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h: Added. 301 (JSC::DFG::CallCreateDirectArgumentsSlowPathGenerator::CallCreateDirectArgumentsSlowPathGenerator): 302 * dfg/DFGCapabilities.cpp: 303 (JSC::DFG::isSupportedForInlining): 304 (JSC::DFG::capabilityLevel): 305 * dfg/DFGClobberize.h: 306 (JSC::DFG::clobberize): 307 * dfg/DFGCommon.h: 308 * dfg/DFGCommonData.h: 309 (JSC::DFG::CommonData::CommonData): 310 * dfg/DFGConstantFoldingPhase.cpp: 311 (JSC::DFG::ConstantFoldingPhase::foldConstants): 312 * dfg/DFGDCEPhase.cpp: 313 (JSC::DFG::DCEPhase::cleanVariables): 314 * dfg/DFGDisassembler.h: 315 * dfg/DFGDoesGC.cpp: 316 (JSC::DFG::doesGC): 317 * dfg/DFGFixupPhase.cpp: 318 (JSC::DFG::FixupPhase::fixupNode): 319 * dfg/DFGFlushFormat.cpp: 320 (WTF::printInternal): 321 * dfg/DFGFlushFormat.h: 322 (JSC::DFG::resultFor): 323 (JSC::DFG::useKindFor): 324 (JSC::DFG::dataFormatFor): 325 * dfg/DFGForAllKills.h: Added. 326 (JSC::DFG::forAllLiveNodesAtTail): 327 (JSC::DFG::forAllDirectlyKilledOperands): 328 (JSC::DFG::forAllKilledOperands): 329 (JSC::DFG::forAllKilledNodesAtNodeIndex): 330 (JSC::DFG::forAllKillsInBlock): 331 * dfg/DFGGraph.cpp: 332 (JSC::DFG::Graph::Graph): 333 (JSC::DFG::Graph::dump): 334 (JSC::DFG::Graph::substituteGetLocal): 335 (JSC::DFG::Graph::livenessFor): 336 (JSC::DFG::Graph::killsFor): 337 (JSC::DFG::Graph::tryGetConstantClosureVar): 338 (JSC::DFG::Graph::tryGetRegisters): Deleted. 339 * dfg/DFGGraph.h: 340 (JSC::DFG::Graph::symbolTableFor): 341 (JSC::DFG::Graph::uses): 342 (JSC::DFG::Graph::bytecodeRegisterForArgument): Deleted. 343 (JSC::DFG::Graph::capturedVarsFor): Deleted. 344 (JSC::DFG::Graph::usesArguments): Deleted. 345 (JSC::DFG::Graph::argumentsRegisterFor): Deleted. 346 (JSC::DFG::Graph::machineArgumentsRegisterFor): Deleted. 347 (JSC::DFG::Graph::uncheckedArgumentsRegisterFor): Deleted. 348 * dfg/DFGHeapLocation.cpp: 349 (WTF::printInternal): 350 * dfg/DFGHeapLocation.h: 351 * dfg/DFGInPlaceAbstractState.cpp: 352 (JSC::DFG::InPlaceAbstractState::initialize): 353 (JSC::DFG::InPlaceAbstractState::mergeStateAtTail): 354 * dfg/DFGJITCompiler.cpp: 355 (JSC::DFG::JITCompiler::link): 356 * dfg/DFGMayExit.cpp: 357 (JSC::DFG::mayExit): 358 * dfg/DFGMinifiedID.h: 359 * dfg/DFGMinifiedNode.cpp: 360 (JSC::DFG::MinifiedNode::fromNode): 361 * dfg/DFGMinifiedNode.h: 362 (JSC::DFG::belongsInMinifiedGraph): 363 (JSC::DFG::MinifiedNode::hasInlineCallFrame): 364 (JSC::DFG::MinifiedNode::inlineCallFrame): 365 * dfg/DFGNode.cpp: 366 (JSC::DFG::Node::convertToIdentityOn): 367 * dfg/DFGNode.h: 368 (JSC::DFG::Node::hasConstant): 369 (JSC::DFG::Node::constant): 370 (JSC::DFG::Node::hasScopeOffset): 371 (JSC::DFG::Node::scopeOffset): 372 (JSC::DFG::Node::hasDirectArgumentsOffset): 373 (JSC::DFG::Node::capturedArgumentsOffset): 374 (JSC::DFG::Node::variablePointer): 375 (JSC::DFG::Node::hasCallVarargsData): 376 (JSC::DFG::Node::hasLoadVarargsData): 377 (JSC::DFG::Node::hasHeapPrediction): 378 (JSC::DFG::Node::hasCellOperand): 379 (JSC::DFG::Node::objectMaterializationData): 380 (JSC::DFG::Node::isPhantomAllocation): 381 (JSC::DFG::Node::willHaveCodeGenOrOSR): 382 (JSC::DFG::Node::shouldSpeculateDirectArguments): 383 (JSC::DFG::Node::shouldSpeculateScopedArguments): 384 (JSC::DFG::Node::isPhantomArguments): Deleted. 385 (JSC::DFG::Node::hasVarNumber): Deleted. 386 (JSC::DFG::Node::varNumber): Deleted. 387 (JSC::DFG::Node::registerPointer): Deleted. 388 (JSC::DFG::Node::shouldSpeculateArguments): Deleted. 389 * dfg/DFGNodeType.h: 390 * dfg/DFGOSRAvailabilityAnalysisPhase.cpp: 391 (JSC::DFG::OSRAvailabilityAnalysisPhase::run): 392 (JSC::DFG::LocalOSRAvailabilityCalculator::executeNode): 393 * dfg/DFGOSRExitCompiler.cpp: 394 (JSC::DFG::OSRExitCompiler::emitRestoreArguments): 395 * dfg/DFGOSRExitCompiler.h: 396 (JSC::DFG::OSRExitCompiler::badIndex): Deleted. 397 (JSC::DFG::OSRExitCompiler::initializePoisoned): Deleted. 398 (JSC::DFG::OSRExitCompiler::poisonIndex): Deleted. 399 * dfg/DFGOSRExitCompiler32_64.cpp: 400 (JSC::DFG::OSRExitCompiler::compileExit): 401 * dfg/DFGOSRExitCompiler64.cpp: 402 (JSC::DFG::OSRExitCompiler::compileExit): 403 * dfg/DFGOSRExitCompilerCommon.cpp: 404 (JSC::DFG::reifyInlinedCallFrames): 405 (JSC::DFG::ArgumentsRecoveryGenerator::ArgumentsRecoveryGenerator): Deleted. 406 (JSC::DFG::ArgumentsRecoveryGenerator::~ArgumentsRecoveryGenerator): Deleted. 407 (JSC::DFG::ArgumentsRecoveryGenerator::generateFor): Deleted. 408 * dfg/DFGOSRExitCompilerCommon.h: 409 * dfg/DFGOperations.cpp: 410 * dfg/DFGOperations.h: 411 * dfg/DFGPlan.cpp: 412 (JSC::DFG::Plan::compileInThreadImpl): 413 * dfg/DFGPreciseLocalClobberize.h: 414 (JSC::DFG::PreciseLocalClobberizeAdaptor::read): 415 (JSC::DFG::PreciseLocalClobberizeAdaptor::write): 416 (JSC::DFG::PreciseLocalClobberizeAdaptor::def): 417 (JSC::DFG::PreciseLocalClobberizeAdaptor::readTop): 418 (JSC::DFG::preciseLocalClobberize): 419 (JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop): Deleted. 420 (JSC::DFG::forEachLocalReadByUnwind): Deleted. 421 * dfg/DFGPredictionPropagationPhase.cpp: 422 (JSC::DFG::PredictionPropagationPhase::run): 423 (JSC::DFG::PredictionPropagationPhase::propagate): 424 (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): 425 (JSC::DFG::PredictionPropagationPhase::propagateThroughArgumentPositions): 426 * dfg/DFGPromoteHeapAccess.h: 427 (JSC::DFG::promoteHeapAccess): 428 * dfg/DFGPromotedHeapLocation.cpp: 429 (WTF::printInternal): 430 * dfg/DFGPromotedHeapLocation.h: 431 * dfg/DFGSSAConversionPhase.cpp: 432 (JSC::DFG::SSAConversionPhase::run): 433 * dfg/DFGSafeToExecute.h: 434 (JSC::DFG::safeToExecute): 435 * dfg/DFGSpeculativeJIT.cpp: 436 (JSC::DFG::SpeculativeJIT::emitAllocateJSArray): 437 (JSC::DFG::SpeculativeJIT::emitGetLength): 438 (JSC::DFG::SpeculativeJIT::emitGetCallee): 439 (JSC::DFG::SpeculativeJIT::emitGetArgumentStart): 440 (JSC::DFG::SpeculativeJIT::checkArray): 441 (JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments): 442 (JSC::DFG::SpeculativeJIT::compileGetByValOnScopedArguments): 443 (JSC::DFG::SpeculativeJIT::compileGetArrayLength): 444 (JSC::DFG::SpeculativeJIT::compileNewFunction): 445 (JSC::DFG::SpeculativeJIT::compileForwardVarargs): 446 (JSC::DFG::SpeculativeJIT::compileCreateActivation): 447 (JSC::DFG::SpeculativeJIT::compileCreateDirectArguments): 448 (JSC::DFG::SpeculativeJIT::compileGetFromArguments): 449 (JSC::DFG::SpeculativeJIT::compilePutToArguments): 450 (JSC::DFG::SpeculativeJIT::compileCreateScopedArguments): 451 (JSC::DFG::SpeculativeJIT::compileCreateClonedArguments): 452 (JSC::DFG::SpeculativeJIT::emitAllocateArguments): Deleted. 453 (JSC::DFG::SpeculativeJIT::compileGetByValOnArguments): Deleted. 454 (JSC::DFG::SpeculativeJIT::compileGetArgumentsLength): Deleted. 455 (JSC::DFG::SpeculativeJIT::compileNewFunctionNoCheck): Deleted. 456 (JSC::DFG::SpeculativeJIT::compileNewFunctionExpression): Deleted. 457 * dfg/DFGSpeculativeJIT.h: 458 (JSC::DFG::SpeculativeJIT::callOperation): 459 (JSC::DFG::SpeculativeJIT::emitAllocateJSObjectWithKnownSize): 460 (JSC::DFG::SpeculativeJIT::emitAllocateJSObject): 461 (JSC::DFG::SpeculativeJIT::framePointerOffsetToGetActivationRegisters): Deleted. 462 * dfg/DFGSpeculativeJIT32_64.cpp: 463 (JSC::DFG::SpeculativeJIT::emitCall): 464 (JSC::DFG::SpeculativeJIT::compile): 465 * dfg/DFGSpeculativeJIT64.cpp: 466 (JSC::DFG::SpeculativeJIT::emitCall): 467 (JSC::DFG::SpeculativeJIT::compile): 468 * dfg/DFGStackLayoutPhase.cpp: 469 (JSC::DFG::StackLayoutPhase::run): 470 * dfg/DFGStrengthReductionPhase.cpp: 471 (JSC::DFG::StrengthReductionPhase::handleNode): 472 * dfg/DFGStructureRegistrationPhase.cpp: 473 (JSC::DFG::StructureRegistrationPhase::run): 474 * dfg/DFGUnificationPhase.cpp: 475 (JSC::DFG::UnificationPhase::run): 476 * dfg/DFGValidate.cpp: 477 (JSC::DFG::Validate::validateCPS): 478 * dfg/DFGValueSource.cpp: 479 (JSC::DFG::ValueSource::dump): 480 * dfg/DFGValueSource.h: 481 (JSC::DFG::dataFormatToValueSourceKind): 482 (JSC::DFG::valueSourceKindToDataFormat): 483 (JSC::DFG::ValueSource::ValueSource): 484 (JSC::DFG::ValueSource::forFlushFormat): 485 (JSC::DFG::ValueSource::valueRecovery): 486 * dfg/DFGVarargsForwardingPhase.cpp: Added. 487 (JSC::DFG::performVarargsForwarding): 488 * dfg/DFGVarargsForwardingPhase.h: Added. 489 * dfg/DFGVariableAccessData.cpp: 490 (JSC::DFG::VariableAccessData::VariableAccessData): 491 (JSC::DFG::VariableAccessData::flushFormat): 492 (JSC::DFG::VariableAccessData::mergeIsCaptured): Deleted. 493 * dfg/DFGVariableAccessData.h: 494 (JSC::DFG::VariableAccessData::shouldNeverUnbox): 495 (JSC::DFG::VariableAccessData::shouldUseDoubleFormat): 496 (JSC::DFG::VariableAccessData::isCaptured): Deleted. 497 (JSC::DFG::VariableAccessData::mergeIsArgumentsAlias): Deleted. 498 (JSC::DFG::VariableAccessData::isArgumentsAlias): Deleted. 499 * dfg/DFGVariableAccessDataDump.cpp: 500 (JSC::DFG::VariableAccessDataDump::dump): 501 * dfg/DFGVariableAccessDataDump.h: 502 * dfg/DFGVariableEventStream.cpp: 503 (JSC::DFG::VariableEventStream::tryToSetConstantRecovery): 504 * dfg/DFGVariableEventStream.h: 505 * ftl/FTLAbstractHeap.cpp: 506 (JSC::FTL::AbstractHeap::dump): 507 (JSC::FTL::AbstractField::dump): 508 (JSC::FTL::IndexedAbstractHeap::dump): 509 (JSC::FTL::NumberedAbstractHeap::dump): 510 (JSC::FTL::AbsoluteAbstractHeap::dump): 511 * ftl/FTLAbstractHeap.h: 512 * ftl/FTLAbstractHeapRepository.cpp: 513 * ftl/FTLAbstractHeapRepository.h: 514 * ftl/FTLCapabilities.cpp: 515 (JSC::FTL::canCompile): 516 * ftl/FTLCompile.cpp: 517 (JSC::FTL::mmAllocateDataSection): 518 * ftl/FTLExitArgument.cpp: 519 (JSC::FTL::ExitArgument::dump): 520 * ftl/FTLExitPropertyValue.cpp: 521 (JSC::FTL::ExitPropertyValue::withLocalsOffset): 522 * ftl/FTLExitPropertyValue.h: 523 * ftl/FTLExitTimeObjectMaterialization.cpp: 524 (JSC::FTL::ExitTimeObjectMaterialization::ExitTimeObjectMaterialization): 525 (JSC::FTL::ExitTimeObjectMaterialization::accountForLocalsOffset): 526 * ftl/FTLExitTimeObjectMaterialization.h: 527 (JSC::FTL::ExitTimeObjectMaterialization::origin): 528 * ftl/FTLExitValue.cpp: 529 (JSC::FTL::ExitValue::withLocalsOffset): 530 (JSC::FTL::ExitValue::valueFormat): 531 (JSC::FTL::ExitValue::dumpInContext): 532 * ftl/FTLExitValue.h: 533 (JSC::FTL::ExitValue::isArgument): 534 (JSC::FTL::ExitValue::argumentsObjectThatWasNotCreated): Deleted. 535 (JSC::FTL::ExitValue::isArgumentsObjectThatWasNotCreated): Deleted. 536 (JSC::FTL::ExitValue::valueFormat): Deleted. 537 * ftl/FTLInlineCacheSize.cpp: 538 (JSC::FTL::sizeOfCallForwardVarargs): 539 (JSC::FTL::sizeOfConstructForwardVarargs): 540 (JSC::FTL::sizeOfICFor): 541 * ftl/FTLInlineCacheSize.h: 542 * ftl/FTLIntrinsicRepository.h: 543 * ftl/FTLJSCallVarargs.cpp: 544 (JSC::FTL::JSCallVarargs::JSCallVarargs): 545 (JSC::FTL::JSCallVarargs::emit): 546 * ftl/FTLJSCallVarargs.h: 547 * ftl/FTLLowerDFGToLLVM.cpp: 548 (JSC::FTL::LowerDFGToLLVM::lower): 549 (JSC::FTL::LowerDFGToLLVM::compileNode): 550 (JSC::FTL::LowerDFGToLLVM::compilePutStack): 551 (JSC::FTL::LowerDFGToLLVM::compileGetArrayLength): 552 (JSC::FTL::LowerDFGToLLVM::compileGetByVal): 553 (JSC::FTL::LowerDFGToLLVM::compileGetMyArgumentByVal): 554 (JSC::FTL::LowerDFGToLLVM::compilePutByVal): 555 (JSC::FTL::LowerDFGToLLVM::compileArrayPush): 556 (JSC::FTL::LowerDFGToLLVM::compileArrayPop): 557 (JSC::FTL::LowerDFGToLLVM::compileCreateActivation): 558 (JSC::FTL::LowerDFGToLLVM::compileNewFunction): 559 (JSC::FTL::LowerDFGToLLVM::compileCreateDirectArguments): 560 (JSC::FTL::LowerDFGToLLVM::compileCreateScopedArguments): 561 (JSC::FTL::LowerDFGToLLVM::compileCreateClonedArguments): 562 (JSC::FTL::LowerDFGToLLVM::compileStringCharAt): 563 (JSC::FTL::LowerDFGToLLVM::compileStringCharCodeAt): 564 (JSC::FTL::LowerDFGToLLVM::compileGetGlobalVar): 565 (JSC::FTL::LowerDFGToLLVM::compilePutGlobalVar): 566 (JSC::FTL::LowerDFGToLLVM::compileGetArgumentCount): 567 (JSC::FTL::LowerDFGToLLVM::compileGetClosureVar): 568 (JSC::FTL::LowerDFGToLLVM::compilePutClosureVar): 569 (JSC::FTL::LowerDFGToLLVM::compileGetFromArguments): 570 (JSC::FTL::LowerDFGToLLVM::compilePutToArguments): 571 (JSC::FTL::LowerDFGToLLVM::compileCallOrConstructVarargs): 572 (JSC::FTL::LowerDFGToLLVM::compileForwardVarargs): 573 (JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorPname): 574 (JSC::FTL::LowerDFGToLLVM::ArgumentsLength::ArgumentsLength): 575 (JSC::FTL::LowerDFGToLLVM::getArgumentsLength): 576 (JSC::FTL::LowerDFGToLLVM::getCurrentCallee): 577 (JSC::FTL::LowerDFGToLLVM::getArgumentsStart): 578 (JSC::FTL::LowerDFGToLLVM::baseIndex): 579 (JSC::FTL::LowerDFGToLLVM::allocateObject): 580 (JSC::FTL::LowerDFGToLLVM::allocateVariableSizedObject): 581 (JSC::FTL::LowerDFGToLLVM::isArrayType): 582 (JSC::FTL::LowerDFGToLLVM::emitStoreBarrier): 583 (JSC::FTL::LowerDFGToLLVM::buildExitArguments): 584 (JSC::FTL::LowerDFGToLLVM::exitValueForAvailability): 585 (JSC::FTL::LowerDFGToLLVM::exitValueForNode): 586 (JSC::FTL::LowerDFGToLLVM::loadStructure): 587 (JSC::FTL::LowerDFGToLLVM::compilePhantomArguments): Deleted. 588 (JSC::FTL::LowerDFGToLLVM::compileGetMyArgumentsLength): Deleted. 589 (JSC::FTL::LowerDFGToLLVM::compileGetClosureRegisters): Deleted. 590 (JSC::FTL::LowerDFGToLLVM::compileCheckArgumentsNotCreated): Deleted. 591 (JSC::FTL::LowerDFGToLLVM::checkArgumentsNotCreated): Deleted. 592 * ftl/FTLOSRExitCompiler.cpp: 593 (JSC::FTL::compileRecovery): 594 (JSC::FTL::compileStub): 595 * ftl/FTLOperations.cpp: 596 (JSC::FTL::operationMaterializeObjectInOSR): 597 * ftl/FTLOutput.h: 598 (JSC::FTL::Output::aShr): 599 (JSC::FTL::Output::lShr): 600 (JSC::FTL::Output::zeroExtPtr): 601 * heap/CopyToken.h: 602 * interpreter/CallFrame.h: 603 (JSC::ExecState::getArgumentUnsafe): 604 * interpreter/Interpreter.cpp: 605 (JSC::sizeOfVarargs): 606 (JSC::sizeFrameForVarargs): 607 (JSC::loadVarargs): 608 (JSC::unwindCallFrame): 609 * interpreter/Interpreter.h: 610 * interpreter/StackVisitor.cpp: 611 (JSC::StackVisitor::Frame::createArguments): 612 (JSC::StackVisitor::Frame::existingArguments): Deleted. 613 * interpreter/StackVisitor.h: 614 * jit/AssemblyHelpers.h: 615 (JSC::AssemblyHelpers::storeValue): 616 (JSC::AssemblyHelpers::loadValue): 617 (JSC::AssemblyHelpers::storeTrustedValue): 618 (JSC::AssemblyHelpers::branchIfNotCell): 619 (JSC::AssemblyHelpers::branchIsEmpty): 620 (JSC::AssemblyHelpers::argumentsStart): 621 (JSC::AssemblyHelpers::baselineArgumentsRegisterFor): Deleted. 622 (JSC::AssemblyHelpers::offsetOfLocals): Deleted. 623 (JSC::AssemblyHelpers::offsetOfArguments): Deleted. 624 * jit/CCallHelpers.h: 625 (JSC::CCallHelpers::setupArgument): 626 * jit/GPRInfo.h: 627 (JSC::JSValueRegs::withTwoAvailableRegs): 628 * jit/JIT.cpp: 629 (JSC::JIT::privateCompileMainPass): 630 (JSC::JIT::privateCompileSlowCases): 631 * jit/JIT.h: 632 * jit/JITCall.cpp: 633 (JSC::JIT::compileSetupVarargsFrame): 634 * jit/JITCall32_64.cpp: 635 (JSC::JIT::compileSetupVarargsFrame): 636 * jit/JITInlines.h: 637 (JSC::JIT::callOperation): 638 * jit/JITOpcodes.cpp: 639 (JSC::JIT::emit_op_create_lexical_environment): 640 (JSC::JIT::emit_op_new_func): 641 (JSC::JIT::emit_op_create_direct_arguments): 642 (JSC::JIT::emit_op_create_scoped_arguments): 643 (JSC::JIT::emit_op_create_out_of_band_arguments): 644 (JSC::JIT::emit_op_tear_off_arguments): Deleted. 645 (JSC::JIT::emit_op_create_arguments): Deleted. 646 (JSC::JIT::emit_op_init_lazy_reg): Deleted. 647 (JSC::JIT::emit_op_get_arguments_length): Deleted. 648 (JSC::JIT::emitSlow_op_get_arguments_length): Deleted. 649 (JSC::JIT::emit_op_get_argument_by_val): Deleted. 650 (JSC::JIT::emitSlow_op_get_argument_by_val): Deleted. 651 * jit/JITOpcodes32_64.cpp: 652 (JSC::JIT::emit_op_create_lexical_environment): 653 (JSC::JIT::emit_op_tear_off_arguments): Deleted. 654 (JSC::JIT::emit_op_create_arguments): Deleted. 655 (JSC::JIT::emit_op_init_lazy_reg): Deleted. 656 (JSC::JIT::emit_op_get_arguments_length): Deleted. 657 (JSC::JIT::emitSlow_op_get_arguments_length): Deleted. 658 (JSC::JIT::emit_op_get_argument_by_val): Deleted. 659 (JSC::JIT::emitSlow_op_get_argument_by_val): Deleted. 660 * jit/JITOperations.cpp: 661 * jit/JITOperations.h: 662 * jit/JITPropertyAccess.cpp: 663 (JSC::JIT::emitGetClosureVar): 664 (JSC::JIT::emitPutClosureVar): 665 (JSC::JIT::emit_op_get_from_arguments): 666 (JSC::JIT::emit_op_put_to_arguments): 667 (JSC::JIT::emit_op_init_global_const): 668 (JSC::JIT::privateCompileGetByVal): 669 (JSC::JIT::emitDirectArgumentsGetByVal): 670 (JSC::JIT::emitScopedArgumentsGetByVal): 671 * jit/JITPropertyAccess32_64.cpp: 672 (JSC::JIT::emitGetClosureVar): 673 (JSC::JIT::emitPutClosureVar): 674 (JSC::JIT::emit_op_get_from_arguments): 675 (JSC::JIT::emit_op_put_to_arguments): 676 (JSC::JIT::emit_op_init_global_const): 677 * jit/SetupVarargsFrame.cpp: 678 (JSC::emitSetupVarargsFrameFastCase): 679 * llint/LLIntOffsetsExtractor.cpp: 680 * llint/LLIntSlowPaths.cpp: 681 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 682 * llint/LowLevelInterpreter.asm: 683 * llint/LowLevelInterpreter32_64.asm: 684 * llint/LowLevelInterpreter64.asm: 685 * parser/Nodes.h: 686 (JSC::ScopeNode::captures): 687 * runtime/Arguments.cpp: Removed. 688 * runtime/Arguments.h: Removed. 689 * runtime/ArgumentsMode.h: Added. 690 * runtime/DirectArgumentsOffset.cpp: Added. 691 (JSC::DirectArgumentsOffset::dump): 692 * runtime/DirectArgumentsOffset.h: Added. 693 (JSC::DirectArgumentsOffset::DirectArgumentsOffset): 694 * runtime/CommonSlowPaths.cpp: 695 (JSC::SLOW_PATH_DECL): 696 * runtime/CommonSlowPaths.h: 697 * runtime/ConstantMode.cpp: Added. 698 (WTF::printInternal): 699 * runtime/ConstantMode.h: 700 (JSC::modeForIsConstant): 701 * runtime/DirectArguments.cpp: Added. 702 (JSC::DirectArguments::DirectArguments): 703 (JSC::DirectArguments::createUninitialized): 704 (JSC::DirectArguments::create): 705 (JSC::DirectArguments::createByCopying): 706 (JSC::DirectArguments::visitChildren): 707 (JSC::DirectArguments::copyBackingStore): 708 (JSC::DirectArguments::createStructure): 709 (JSC::DirectArguments::overrideThings): 710 (JSC::DirectArguments::overrideThingsIfNecessary): 711 (JSC::DirectArguments::overrideArgument): 712 (JSC::DirectArguments::copyToArguments): 713 (JSC::DirectArguments::overridesSize): 714 * runtime/DirectArguments.h: Added. 715 (JSC::DirectArguments::internalLength): 716 (JSC::DirectArguments::length): 717 (JSC::DirectArguments::canAccessIndexQuickly): 718 (JSC::DirectArguments::getIndexQuickly): 719 (JSC::DirectArguments::setIndexQuickly): 720 (JSC::DirectArguments::callee): 721 (JSC::DirectArguments::argument): 722 (JSC::DirectArguments::overrodeThings): 723 (JSC::DirectArguments::offsetOfCallee): 724 (JSC::DirectArguments::offsetOfLength): 725 (JSC::DirectArguments::offsetOfMinCapacity): 726 (JSC::DirectArguments::offsetOfOverrides): 727 (JSC::DirectArguments::storageOffset): 728 (JSC::DirectArguments::offsetOfSlot): 729 (JSC::DirectArguments::allocationSize): 730 (JSC::DirectArguments::storage): 731 * runtime/FunctionPrototype.cpp: 732 * runtime/GenericArguments.h: Added. 733 (JSC::GenericArguments::GenericArguments): 734 * runtime/GenericArgumentsInlines.h: Added. 735 (JSC::GenericArguments<Type>::getOwnPropertySlot): 736 (JSC::GenericArguments<Type>::getOwnPropertySlotByIndex): 737 (JSC::GenericArguments<Type>::getOwnPropertyNames): 738 (JSC::GenericArguments<Type>::put): 739 (JSC::GenericArguments<Type>::putByIndex): 740 (JSC::GenericArguments<Type>::deleteProperty): 741 (JSC::GenericArguments<Type>::deletePropertyByIndex): 742 (JSC::GenericArguments<Type>::defineOwnProperty): 743 (JSC::GenericArguments<Type>::copyToArguments): 744 * runtime/GenericOffset.h: Added. 745 (JSC::GenericOffset::GenericOffset): 746 (JSC::GenericOffset::operator!): 747 (JSC::GenericOffset::offsetUnchecked): 748 (JSC::GenericOffset::offset): 749 (JSC::GenericOffset::operator==): 750 (JSC::GenericOffset::operator!=): 751 (JSC::GenericOffset::operator<): 752 (JSC::GenericOffset::operator>): 753 (JSC::GenericOffset::operator<=): 754 (JSC::GenericOffset::operator>=): 755 (JSC::GenericOffset::operator+): 756 (JSC::GenericOffset::operator-): 757 (JSC::GenericOffset::operator+=): 758 (JSC::GenericOffset::operator-=): 759 * runtime/JSArgumentsIterator.cpp: 760 (JSC::JSArgumentsIterator::finishCreation): 761 (JSC::argumentsFuncIterator): 762 * runtime/JSArgumentsIterator.h: 763 (JSC::JSArgumentsIterator::create): 764 (JSC::JSArgumentsIterator::next): 765 * runtime/JSEnvironmentRecord.cpp: 766 (JSC::JSEnvironmentRecord::visitChildren): 767 * runtime/JSEnvironmentRecord.h: 768 (JSC::JSEnvironmentRecord::variables): 769 (JSC::JSEnvironmentRecord::isValid): 770 (JSC::JSEnvironmentRecord::variableAt): 771 (JSC::JSEnvironmentRecord::offsetOfVariables): 772 (JSC::JSEnvironmentRecord::offsetOfVariable): 773 (JSC::JSEnvironmentRecord::allocationSizeForScopeSize): 774 (JSC::JSEnvironmentRecord::allocationSize): 775 (JSC::JSEnvironmentRecord::JSEnvironmentRecord): 776 (JSC::JSEnvironmentRecord::finishCreationUninitialized): 777 (JSC::JSEnvironmentRecord::finishCreation): 778 (JSC::JSEnvironmentRecord::registers): Deleted. 779 (JSC::JSEnvironmentRecord::registerAt): Deleted. 780 (JSC::JSEnvironmentRecord::addressOfRegisters): Deleted. 781 (JSC::JSEnvironmentRecord::offsetOfRegisters): Deleted. 782 * runtime/JSFunction.cpp: 783 * runtime/JSGlobalObject.cpp: 784 (JSC::JSGlobalObject::init): 785 (JSC::JSGlobalObject::addGlobalVar): 786 (JSC::JSGlobalObject::addFunction): 787 (JSC::JSGlobalObject::visitChildren): 788 (JSC::JSGlobalObject::addStaticGlobals): 789 * runtime/JSGlobalObject.h: 790 (JSC::JSGlobalObject::directArgumentsStructure): 791 (JSC::JSGlobalObject::scopedArgumentsStructure): 792 (JSC::JSGlobalObject::outOfBandArgumentsStructure): 793 (JSC::JSGlobalObject::argumentsStructure): Deleted. 794 * runtime/JSLexicalEnvironment.cpp: 795 (JSC::JSLexicalEnvironment::symbolTableGet): 796 (JSC::JSLexicalEnvironment::symbolTablePut): 797 (JSC::JSLexicalEnvironment::getOwnNonIndexPropertyNames): 798 (JSC::JSLexicalEnvironment::symbolTablePutWithAttributes): 799 (JSC::JSLexicalEnvironment::visitChildren): Deleted. 800 * runtime/JSLexicalEnvironment.h: 801 (JSC::JSLexicalEnvironment::create): 802 (JSC::JSLexicalEnvironment::JSLexicalEnvironment): 803 (JSC::JSLexicalEnvironment::registersOffset): Deleted. 804 (JSC::JSLexicalEnvironment::storageOffset): Deleted. 805 (JSC::JSLexicalEnvironment::storage): Deleted. 806 (JSC::JSLexicalEnvironment::allocationSize): Deleted. 807 (JSC::JSLexicalEnvironment::isValidIndex): Deleted. 808 (JSC::JSLexicalEnvironment::isValid): Deleted. 809 (JSC::JSLexicalEnvironment::registerAt): Deleted. 810 * runtime/JSNameScope.cpp: 811 (JSC::JSNameScope::visitChildren): Deleted. 812 * runtime/JSNameScope.h: 813 (JSC::JSNameScope::create): 814 (JSC::JSNameScope::value): 815 (JSC::JSNameScope::finishCreation): 816 (JSC::JSNameScope::JSNameScope): 817 * runtime/JSScope.cpp: 818 (JSC::abstractAccess): 819 * runtime/JSSegmentedVariableObject.cpp: 820 (JSC::JSSegmentedVariableObject::findVariableIndex): 821 (JSC::JSSegmentedVariableObject::addVariables): 822 (JSC::JSSegmentedVariableObject::visitChildren): 823 (JSC::JSSegmentedVariableObject::findRegisterIndex): Deleted. 824 (JSC::JSSegmentedVariableObject::addRegisters): Deleted. 825 * runtime/JSSegmentedVariableObject.h: 826 (JSC::JSSegmentedVariableObject::variableAt): 827 (JSC::JSSegmentedVariableObject::assertVariableIsInThisObject): 828 (JSC::JSSegmentedVariableObject::registerAt): Deleted. 829 (JSC::JSSegmentedVariableObject::assertRegisterIsInThisObject): Deleted. 830 * runtime/JSSymbolTableObject.h: 831 (JSC::JSSymbolTableObject::offsetOfSymbolTable): 832 (JSC::symbolTableGet): 833 (JSC::symbolTablePut): 834 (JSC::symbolTablePutWithAttributes): 835 * runtime/JSType.h: 836 * runtime/Options.h: 837 * runtime/ClonedArguments.cpp: Added. 838 (JSC::ClonedArguments::ClonedArguments): 839 (JSC::ClonedArguments::createEmpty): 840 (JSC::ClonedArguments::createWithInlineFrame): 841 (JSC::ClonedArguments::createWithMachineFrame): 842 (JSC::ClonedArguments::createByCopyingFrom): 843 (JSC::ClonedArguments::createStructure): 844 (JSC::ClonedArguments::getOwnPropertySlot): 845 (JSC::ClonedArguments::getOwnPropertyNames): 846 (JSC::ClonedArguments::put): 847 (JSC::ClonedArguments::deleteProperty): 848 (JSC::ClonedArguments::defineOwnProperty): 849 (JSC::ClonedArguments::materializeSpecials): 850 (JSC::ClonedArguments::materializeSpecialsIfNecessary): 851 * runtime/ClonedArguments.h: Added. 852 (JSC::ClonedArguments::specialsMaterialized): 853 * runtime/ScopeOffset.cpp: Added. 854 (JSC::ScopeOffset::dump): 855 * runtime/ScopeOffset.h: Added. 856 (JSC::ScopeOffset::ScopeOffset): 857 * runtime/ScopedArguments.cpp: Added. 858 (JSC::ScopedArguments::ScopedArguments): 859 (JSC::ScopedArguments::finishCreation): 860 (JSC::ScopedArguments::createUninitialized): 861 (JSC::ScopedArguments::create): 862 (JSC::ScopedArguments::createByCopying): 863 (JSC::ScopedArguments::createByCopyingFrom): 864 (JSC::ScopedArguments::visitChildren): 865 (JSC::ScopedArguments::createStructure): 866 (JSC::ScopedArguments::overrideThings): 867 (JSC::ScopedArguments::overrideThingsIfNecessary): 868 (JSC::ScopedArguments::overrideArgument): 869 (JSC::ScopedArguments::copyToArguments): 870 * runtime/ScopedArguments.h: Added. 871 (JSC::ScopedArguments::internalLength): 872 (JSC::ScopedArguments::length): 873 (JSC::ScopedArguments::canAccessIndexQuickly): 874 (JSC::ScopedArguments::getIndexQuickly): 875 (JSC::ScopedArguments::setIndexQuickly): 876 (JSC::ScopedArguments::callee): 877 (JSC::ScopedArguments::overrodeThings): 878 (JSC::ScopedArguments::offsetOfOverrodeThings): 879 (JSC::ScopedArguments::offsetOfTotalLength): 880 (JSC::ScopedArguments::offsetOfTable): 881 (JSC::ScopedArguments::offsetOfScope): 882 (JSC::ScopedArguments::overflowStorageOffset): 883 (JSC::ScopedArguments::allocationSize): 884 (JSC::ScopedArguments::overflowStorage): 885 * runtime/ScopedArgumentsTable.cpp: Added. 886 (JSC::ScopedArgumentsTable::ScopedArgumentsTable): 887 (JSC::ScopedArgumentsTable::~ScopedArgumentsTable): 888 (JSC::ScopedArgumentsTable::destroy): 889 (JSC::ScopedArgumentsTable::create): 890 (JSC::ScopedArgumentsTable::clone): 891 (JSC::ScopedArgumentsTable::setLength): 892 (JSC::ScopedArgumentsTable::set): 893 (JSC::ScopedArgumentsTable::createStructure): 894 * runtime/ScopedArgumentsTable.h: Added. 895 (JSC::ScopedArgumentsTable::length): 896 (JSC::ScopedArgumentsTable::get): 897 (JSC::ScopedArgumentsTable::lock): 898 (JSC::ScopedArgumentsTable::offsetOfLength): 899 (JSC::ScopedArgumentsTable::offsetOfArguments): 900 (JSC::ScopedArgumentsTable::at): 901 * runtime/SymbolTable.cpp: 902 (JSC::SymbolTableEntry::prepareToWatch): 903 (JSC::SymbolTable::SymbolTable): 904 (JSC::SymbolTable::visitChildren): 905 (JSC::SymbolTable::localToEntry): 906 (JSC::SymbolTable::entryFor): 907 (JSC::SymbolTable::cloneScopePart): 908 (JSC::SymbolTable::prepareForTypeProfiling): 909 (JSC::SymbolTable::uniqueIDForOffset): 910 (JSC::SymbolTable::globalTypeSetForOffset): 911 (JSC::SymbolTable::cloneCapturedNames): Deleted. 912 (JSC::SymbolTable::uniqueIDForRegister): Deleted. 913 (JSC::SymbolTable::globalTypeSetForRegister): Deleted. 914 * runtime/SymbolTable.h: 915 (JSC::SymbolTableEntry::varOffsetFromBits): 916 (JSC::SymbolTableEntry::scopeOffsetFromBits): 917 (JSC::SymbolTableEntry::Fast::varOffset): 918 (JSC::SymbolTableEntry::Fast::scopeOffset): 919 (JSC::SymbolTableEntry::Fast::isDontEnum): 920 (JSC::SymbolTableEntry::Fast::getAttributes): 921 (JSC::SymbolTableEntry::SymbolTableEntry): 922 (JSC::SymbolTableEntry::varOffset): 923 (JSC::SymbolTableEntry::isWatchable): 924 (JSC::SymbolTableEntry::scopeOffset): 925 (JSC::SymbolTableEntry::setAttributes): 926 (JSC::SymbolTableEntry::constantMode): 927 (JSC::SymbolTableEntry::isDontEnum): 928 (JSC::SymbolTableEntry::disableWatching): 929 (JSC::SymbolTableEntry::pack): 930 (JSC::SymbolTableEntry::isValidVarOffset): 931 (JSC::SymbolTable::createNameScopeTable): 932 (JSC::SymbolTable::maxScopeOffset): 933 (JSC::SymbolTable::didUseScopeOffset): 934 (JSC::SymbolTable::didUseVarOffset): 935 (JSC::SymbolTable::scopeSize): 936 (JSC::SymbolTable::nextScopeOffset): 937 (JSC::SymbolTable::takeNextScopeOffset): 938 (JSC::SymbolTable::add): 939 (JSC::SymbolTable::set): 940 (JSC::SymbolTable::argumentsLength): 941 (JSC::SymbolTable::setArgumentsLength): 942 (JSC::SymbolTable::argumentOffset): 943 (JSC::SymbolTable::setArgumentOffset): 944 (JSC::SymbolTable::arguments): 945 (JSC::SlowArgument::SlowArgument): Deleted. 946 (JSC::SymbolTableEntry::Fast::getIndex): Deleted. 947 (JSC::SymbolTableEntry::getIndex): Deleted. 948 (JSC::SymbolTableEntry::isValidIndex): Deleted. 949 (JSC::SymbolTable::captureStart): Deleted. 950 (JSC::SymbolTable::setCaptureStart): Deleted. 951 (JSC::SymbolTable::captureEnd): Deleted. 952 (JSC::SymbolTable::setCaptureEnd): Deleted. 953 (JSC::SymbolTable::captureCount): Deleted. 954 (JSC::SymbolTable::isCaptured): Deleted. 955 (JSC::SymbolTable::parameterCount): Deleted. 956 (JSC::SymbolTable::parameterCountIncludingThis): Deleted. 957 (JSC::SymbolTable::setParameterCountIncludingThis): Deleted. 958 (JSC::SymbolTable::slowArguments): Deleted. 959 (JSC::SymbolTable::setSlowArguments): Deleted. 960 * runtime/VM.cpp: 961 (JSC::VM::VM): 962 * runtime/VM.h: 963 * runtime/VarOffset.cpp: Added. 964 (JSC::VarOffset::dump): 965 (WTF::printInternal): 966 * runtime/VarOffset.h: Added. 967 (JSC::VarOffset::VarOffset): 968 (JSC::VarOffset::assemble): 969 (JSC::VarOffset::isValid): 970 (JSC::VarOffset::operator!): 971 (JSC::VarOffset::kind): 972 (JSC::VarOffset::isStack): 973 (JSC::VarOffset::isScope): 974 (JSC::VarOffset::isDirectArgument): 975 (JSC::VarOffset::stackOffsetUnchecked): 976 (JSC::VarOffset::scopeOffsetUnchecked): 977 (JSC::VarOffset::capturedArgumentsOffsetUnchecked): 978 (JSC::VarOffset::stackOffset): 979 (JSC::VarOffset::scopeOffset): 980 (JSC::VarOffset::capturedArgumentsOffset): 981 (JSC::VarOffset::rawOffset): 982 (JSC::VarOffset::checkSanity): 983 (JSC::VarOffset::operator==): 984 (JSC::VarOffset::operator!=): 985 (JSC::VarOffset::hash): 986 (JSC::VarOffset::isHashTableDeletedValue): 987 (JSC::VarOffsetHash::hash): 988 (JSC::VarOffsetHash::equal): 989 * tests/stress/arguments-exit-strict-mode.js: Added. 990 * tests/stress/arguments-exit.js: Added. 991 * tests/stress/arguments-inlined-exit-strict-mode-fixed.js: Added. 992 * tests/stress/arguments-inlined-exit-strict-mode.js: Added. 993 * tests/stress/arguments-inlined-exit.js: Added. 994 * tests/stress/arguments-interference.js: Added. 995 * tests/stress/arguments-interference-cfg.js: Added. 996 * tests/stress/dead-get-closure-var.js: Added. 997 * tests/stress/get-declared-unpassed-argument-in-direct-arguments.js: Added. 998 * tests/stress/get-declared-unpassed-argument-in-scoped-arguments.js: Added. 999 * tests/stress/varargs-closure-inlined-exit-strict-mode.js: Added. 1000 * tests/stress/varargs-closure-inlined-exit.js: Added. 1001 * tests/stress/varargs-exit.js: Added. 1002 * tests/stress/varargs-inlined-exit.js: Added. 1003 * tests/stress/varargs-inlined-simple-exit-aliasing-weird-reversed-args.js: Added. 1004 * tests/stress/varargs-inlined-simple-exit-aliasing-weird.js: Added. 1005 * tests/stress/varargs-inlined-simple-exit-aliasing.js: Added. 1006 * tests/stress/varargs-inlined-simple-exit.js: Added. 1007 * tests/stress/varargs-too-few-arguments.js: Added. 1008 * tests/stress/varargs-varargs-closure-inlined-exit.js: Added. 1009 * tests/stress/varargs-varargs-inlined-exit-strict-mode.js: Added. 1010 * tests/stress/varargs-varargs-inlined-exit.js: Added. 1011 1 1012 2015-03-25 Andy Estes <aestes@apple.com> 2 1013 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r181990 r181993 363 363 <ClCompile Include="..\dfg\DFGAbstractHeap.cpp" /> 364 364 <ClCompile Include="..\dfg\DFGAbstractValue.cpp" /> 365 <ClCompile Include="..\dfg\DFGArgumentsSimplificationPhase.cpp" /> 365 <ClCompile Include="..\dfg\DFGArgumentsEliminationPhase.cpp" /> 366 <ClCompile Include="..\dfg\DFGArgumentsUtilities.cpp" /> 366 367 <ClCompile Include="..\dfg\DFGArithMode.cpp" /> 367 368 <ClCompile Include="..\dfg\DFGArrayMode.cpp" /> … … 479 480 <ClCompile Include="..\dfg\DFGValueSource.cpp" /> 480 481 <ClCompile Include="..\dfg\DFGValueStrength.cpp" /> 482 <ClCompile Include="..\dfg\DFGVarargsForwardingPhase.cpp" /> 481 483 <ClCompile Include="..\dfg\DFGVariableAccessData.cpp" /> 482 484 <ClCompile Include="..\dfg\DFGVariableAccessDataDump.cpp" /> … … 668 670 <ClCompile Include="..\profiler\ProfilerProfiledBytecodes.cpp" /> 669 671 <ClCompile Include="..\runtime\ArgList.cpp" /> 670 <ClCompile Include="..\runtime\Arguments.cpp" />671 672 <ClCompile Include="..\runtime\ArgumentsIteratorConstructor.cpp" /> 672 673 <ClCompile Include="..\runtime\ArgumentsIteratorPrototype.cpp" /> … … 683 684 <ClCompile Include="..\runtime\BooleanPrototype.cpp" /> 684 685 <ClCompile Include="..\runtime\CallData.cpp" /> 686 <ClCompile Include="..\runtime\ClonedArguments.cpp" /> 685 687 <ClCompile Include="..\runtime\CodeCache.cpp" /> 686 688 <ClCompile Include="..\runtime\CodeSpecializationKind.cpp" /> … … 692 694 <ClCompile Include="..\runtime\ConsoleClient.cpp" /> 693 695 <ClCompile Include="..\runtime\ConsolePrototype.cpp" /> 696 <ClCompile Include="..\runtime\ConstantMode.cpp" /> 694 697 <ClCompile Include="..\runtime\ConstructData.cpp" /> 695 698 <ClCompile Include="..\runtime\ControlFlowProfiler.cpp" /> … … 700 703 <ClCompile Include="..\runtime\DateInstance.cpp" /> 701 704 <ClCompile Include="..\runtime\DatePrototype.cpp" /> 705 <ClCompile Include="..\runtime\DirectArguments.cpp" /> 706 <ClCompile Include="..\runtime\DirectArgumentsOffset.cpp" /> 702 707 <ClCompile Include="..\runtime\DumpContext.cpp" /> 703 708 <ClCompile Include="..\runtime\Error.cpp" /> … … 810 815 <ClCompile Include="..\runtime\SetIteratorPrototype.cpp" /> 811 816 <ClCompile Include="..\runtime\SetPrototype.cpp" /> 817 <ClCompile Include="..\runtime\ScopeOffset.cpp" /> 818 <ClCompile Include="..\runtime\ScopedArguments.cpp" /> 819 <ClCompile Include="..\runtime\ScopedArgumentsTable.cpp" /> 812 820 <ClCompile Include="..\runtime\SimpleTypedArrayController.cpp" /> 813 821 <ClCompile Include="..\runtime\SmallStrings.cpp" /> … … 838 846 <ClCompile Include="..\runtime\VM.cpp" /> 839 847 <ClCompile Include="..\runtime\VMEntryScope.cpp" /> 848 <ClCompile Include="..\runtime\VarOffset.cpp" /> 840 849 <ClCompile Include="..\runtime\Watchdog.cpp" /> 841 850 <ClCompile Include="..\runtime\WatchdogNone.cpp" /> … … 942 951 <ClInclude Include="..\bytecode\ByValInfo.h" /> 943 952 <ClInclude Include="..\bytecode\BytecodeBasicBlock.h" /> 953 <ClInclude Include="..\bytecode\BytecodeKills.h" /> 944 954 <ClInclude Include="..\bytecode\BytecodeLivenessAnalysis.h" /> 945 955 <ClInclude Include="..\bytecode\BytecodeUseDef.h" /> … … 1017 1027 <ClInclude Include="..\dfg\DFGAnalysis.h" /> 1018 1028 <ClInclude Include="..\dfg\DFGArgumentPosition.h" /> 1019 <ClInclude Include="..\dfg\DFGArgumentsSimplificationPhase.h" /> 1029 <ClInclude Include="..\dfg\DFGArgumentsEliminationPhase.h" /> 1030 <ClInclude Include="..\dfg\DFGArgumentsUtilities.h" /> 1020 1031 <ClInclude Include="..\dfg\DFGArrayifySlowPathGenerator.h" /> 1021 1032 <ClInclude Include="..\dfg\DFGArithMode.h" /> … … 1036 1047 <ClInclude Include="..\dfg\DFGByteCodeParser.h" /> 1037 1048 <ClInclude Include="..\dfg\DFGCallArrayAllocatorSlowPathGenerator.h" /> 1049 <ClInclude Include="..\dfg\DFGCallCreateDirectArgumentsSlowPathGenerator.h" /> 1038 1050 <ClInclude Include="..\dfg\DFGCapabilities.h" /> 1039 1051 <ClInclude Include="..\dfg\DFGCCallHelpers.h" /> … … 1070 1082 <ClInclude Include="..\dfg\DFGFlushedAt.h" /> 1071 1083 <ClInclude Include="..\dfg\DFGFlushFormat.h" /> 1084 <ClInclude Include="..\dfg\DFGForAllKills.h" /> 1072 1085 <ClInclude Include="..\dfg\DFGFPRInfo.h" /> 1073 1086 <ClInclude Include="..\dfg\DFGFrozenValue.h" /> … … 1164 1177 <ClInclude Include="..\dfg\DFGValueSource.h" /> 1165 1178 <ClInclude Include="..\dfg\DFGValueStrength.h" /> 1179 <ClInclude Include="..\dfg\DFGVarargsForwardingPhase.h" /> 1166 1180 <ClInclude Include="..\dfg\DFGVariableAccessData.h" /> 1167 1181 <ClInclude Include="..\dfg\DFGVariableAccessDataDump.h" /> … … 1425 1439 <ClInclude Include="..\profiler\ProfilerProfiledBytecodes.h" /> 1426 1440 <ClInclude Include="..\runtime\ArgList.h" /> 1427 <ClInclude Include="..\runtime\Arguments .h" />1441 <ClInclude Include="..\runtime\ArgumentsMode.h" /> 1428 1442 <ClInclude Include="..\runtime\ArrayBuffer.h" /> 1429 1443 <ClInclude Include="..\runtime\ArrayBufferNeuteringWatchpoint.h" /> … … 1445 1459 <ClInclude Include="..\runtime\CallData.h" /> 1446 1460 <ClInclude Include="..\runtime\ClassInfo.h" /> 1461 <ClInclude Include="..\runtime\ClonedArguments.h" /> 1447 1462 <ClInclude Include="..\runtime\CodeCache.h" /> 1448 1463 <ClInclude Include="..\runtime\CodeSpecializationKind.h" /> … … 1465 1480 <ClInclude Include="..\runtime\DateInstanceCache.h" /> 1466 1481 <ClInclude Include="..\runtime\DatePrototype.h" /> 1482 <ClInclude Include="..\runtime\DirectArguments.h" /> 1483 <ClInclude Include="..\runtime\DirectArgumentsOffset.h" /> 1467 1484 <ClInclude Include="..\runtime\DumpContext.h" /> 1468 1485 <ClInclude Include="..\runtime\EnumerationMode.h" /> … … 1481 1498 <ClInclude Include="..\runtime\FunctionHasExecutedCache.h" /> 1482 1499 <ClInclude Include="..\runtime\FunctionPrototype.h" /> 1500 <ClInclude Include="..\runtime\GenericArguments.h" /> 1501 <ClInclude Include="..\runtime\GenericArgumentsInlines.h" /> 1502 <ClInclude Include="..\runtime\GenericOffset.h" /> 1483 1503 <ClInclude Include="..\runtime\GenericTypedArrayView.h" /> 1484 1504 <ClInclude Include="..\runtime\GenericTypedArrayViewInlines.h" /> … … 1620 1640 <ClInclude Include="..\runtime\RuntimeType.h" /> 1621 1641 <ClInclude Include="..\runtime\SamplingCounter.h" /> 1642 <ClInclude Include="..\runtime\ScopeOffset.h" /> 1643 <ClInclude Include="..\runtime\ScopedArguments.h" /> 1644 <ClInclude Include="..\runtime\ScopedArgumentsTable.h" /> 1622 1645 <ClInclude Include="..\runtime\SetConstructor.h" /> 1623 1646 <ClInclude Include="..\runtime\SetIteratorConstructor.h" /> … … 1665 1688 <ClInclude Include="..\runtime\VM.h" /> 1666 1689 <ClInclude Include="..\runtime\VMEntryScope.h" /> 1690 <ClInclude Include="..\runtime\VarOffset.h" /> 1667 1691 <ClInclude Include="..\runtime\Watchdog.h" /> 1668 1692 <ClInclude Include="..\runtime\WeakGCMap.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r181990 r181993 105 105 0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; }; 106 106 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; }; 107 0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */; };108 0F16015E156198C900C2587C /* DFGArgumentsSimplificationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F16015B156198BF00C2587C /* DFGArgumentsSimplificationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };109 107 0F190CAC189D82F6000AE5F0 /* ProfilerJettisonReason.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F190CAA189D82F6000AE5F0 /* ProfilerJettisonReason.cpp */; }; 110 108 0F190CAD189D82F6000AE5F0 /* ProfilerJettisonReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F190CAB189D82F6000AE5F0 /* ProfilerJettisonReason.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 252 250 0F2D4DEF19832DD3007D4B19 /* TypeSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DE319832D91007D4B19 /* TypeSet.cpp */; }; 253 251 0F2D4DF019832DD6007D4B19 /* TypeSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DE419832D91007D4B19 /* TypeSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; 252 0F2DD80B1AB3D85800BBB8E8 /* BytecodeKills.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2DD80A1AB3D85800BBB8E8 /* BytecodeKills.h */; settings = {ATTRIBUTES = (Private, ); }; }; 253 0F2DD8111AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2DD80C1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.cpp */; }; 254 0F2DD8121AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2DD80D1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 255 0F2DD8131AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2DD80E1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.cpp */; }; 256 0F2DD8141AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2DD80F1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; 257 0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2DD8101AB3D8BE00BBB8E8 /* DFGForAllKills.h */; settings = {ATTRIBUTES = (Private, ); }; }; 254 258 0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2F16828A7E003C2F8D /* UnusedPointer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 255 259 0F2E892D16D02BAF009E4FD2 /* DFGMinifiedID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51016B3A964003F696B /* DFGMinifiedID.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 442 446 0F96EBB316676EF6008BADE3 /* CodeBlockWithJITType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 443 447 0F9749711687ADE400A4FF6A /* JSCellInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 448 0F978B3B1AAEA71D007C7369 /* ConstantMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */; }; 444 449 0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */; }; 445 450 0F98206116BFE38300240D02 /* PreciseJumpTargets.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 499 504 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 500 505 0FBD7E691447999600481315 /* CodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBD7E671447998F00481315 /* CodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; }; 506 0FBDB9AD1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBDB9AC1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 501 507 0FBE0F7216C1DB030082C5E8 /* DFGCPSRethreadingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE0F6B16C1DB010082C5E8 /* DFGCPSRethreadingPhase.cpp */; }; 502 508 0FBE0F7316C1DB050082C5E8 /* DFGCPSRethreadingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBE0F6C16C1DB010082C5E8 /* DFGCPSRethreadingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 605 611 0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */; }; 606 612 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; settings = {ATTRIBUTES = (Private, ); }; }; 613 0FE050141AA9091100D33B33 /* ArgumentsMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE0500C1AA9091100D33B33 /* ArgumentsMode.h */; settings = {ATTRIBUTES = (Private, ); }; }; 614 0FE050151AA9091100D33B33 /* DirectArgumentsOffset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE0500D1AA9091100D33B33 /* DirectArgumentsOffset.cpp */; }; 615 0FE050161AA9091100D33B33 /* DirectArgumentsOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE0500E1AA9091100D33B33 /* DirectArgumentsOffset.h */; settings = {ATTRIBUTES = (Private, ); }; }; 616 0FE050171AA9091100D33B33 /* DirectArguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE0500F1AA9091100D33B33 /* DirectArguments.cpp */; }; 617 0FE050181AA9091100D33B33 /* DirectArguments.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE050101AA9091100D33B33 /* DirectArguments.h */; settings = {ATTRIBUTES = (Private, ); }; }; 618 0FE050191AA9091100D33B33 /* GenericArguments.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE050111AA9091100D33B33 /* GenericArguments.h */; settings = {ATTRIBUTES = (Private, ); }; }; 619 0FE0501A1AA9091100D33B33 /* GenericArgumentsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE050121AA9091100D33B33 /* GenericArgumentsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 620 0FE0501B1AA9091100D33B33 /* GenericOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE050131AA9091100D33B33 /* GenericOffset.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621 0FE050251AA9095600D33B33 /* ClonedArguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE0501C1AA9095600D33B33 /* ClonedArguments.cpp */; }; 622 0FE050261AA9095600D33B33 /* ClonedArguments.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE0501D1AA9095600D33B33 /* ClonedArguments.h */; settings = {ATTRIBUTES = (Private, ); }; }; 623 0FE050271AA9095600D33B33 /* ScopedArguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE0501E1AA9095600D33B33 /* ScopedArguments.cpp */; }; 624 0FE050281AA9095600D33B33 /* ScopedArguments.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE0501F1AA9095600D33B33 /* ScopedArguments.h */; settings = {ATTRIBUTES = (Private, ); }; }; 625 0FE050291AA9095600D33B33 /* ScopedArgumentsTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE050201AA9095600D33B33 /* ScopedArgumentsTable.h */; settings = {ATTRIBUTES = (Private, ); }; }; 626 0FE0502A1AA9095600D33B33 /* ScopeOffset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE050211AA9095600D33B33 /* ScopeOffset.cpp */; }; 627 0FE0502B1AA9095600D33B33 /* ScopeOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE050221AA9095600D33B33 /* ScopeOffset.h */; settings = {ATTRIBUTES = (Private, ); }; }; 628 0FE0502C1AA9095600D33B33 /* VarOffset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE050231AA9095600D33B33 /* VarOffset.cpp */; }; 629 0FE0502D1AA9095600D33B33 /* VarOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE050241AA9095600D33B33 /* VarOffset.h */; settings = {ATTRIBUTES = (Private, ); }; }; 630 0FE0502F1AAA806900D33B33 /* ScopedArgumentsTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE0502E1AAA806900D33B33 /* ScopedArgumentsTable.cpp */; }; 607 631 0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; }; 608 632 0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; }; 633 0FE254F61ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE254F41ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp */; }; 634 0FE254F71ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE254F51ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 609 635 0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE7211B193B9C590031F6ED /* DFGTransition.cpp */; }; 610 636 0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE7211C193B9C590031F6ED /* DFGTransition.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 804 830 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 147B84620E6DE6B1004775A4 /* PutPropertySlot.h */; settings = {ATTRIBUTES = (Private, ); }; }; 805 831 147F39BD107EC37600427A48 /* ArgList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCF605110E203EF800B9A64D /* ArgList.cpp */; }; 806 147F39BE107EC37600427A48 /* Arguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC257DE50E1F51C50016B6C9 /* Arguments.cpp */; };807 832 147F39BF107EC37600427A48 /* ArrayConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7952060E15E8A800A898AB /* ArrayConstructor.cpp */; }; 808 833 147F39C0107EC37600427A48 /* ArrayPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */; }; … … 1524 1549 BC18C52C0E16FCD200B34460 /* RegExpObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C52B0E16FCD200B34460 /* RegExpObject.lut.h */; }; 1525 1550 BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C52D0E16FCE100B34460 /* Lexer.lut.h */; }; 1526 BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DE60E1F51C50016B6C9 /* Arguments.h */; };1527 1551 BC3046070E1F497F003232CF /* Error.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3046060E1F497F003232CF /* Error.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1528 1552 BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1798 1822 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = "<group>"; }; 1799 1823 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; }; 1800 0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArgumentsSimplificationPhase.cpp; path = dfg/DFGArgumentsSimplificationPhase.cpp; sourceTree = "<group>"; };1801 0F16015B156198BF00C2587C /* DFGArgumentsSimplificationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArgumentsSimplificationPhase.h; path = dfg/DFGArgumentsSimplificationPhase.h; sourceTree = "<group>"; };1802 1824 0F190CAA189D82F6000AE5F0 /* ProfilerJettisonReason.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerJettisonReason.cpp; path = profiler/ProfilerJettisonReason.cpp; sourceTree = "<group>"; }; 1803 1825 0F190CAB189D82F6000AE5F0 /* ProfilerJettisonReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerJettisonReason.h; path = profiler/ProfilerJettisonReason.h; sourceTree = "<group>"; }; … … 1946 1968 0F2D4DE619832DAC007D4B19 /* ToThisStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToThisStatus.h; sourceTree = "<group>"; }; 1947 1969 0F2D4DE719832DAC007D4B19 /* TypeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeLocation.h; sourceTree = "<group>"; }; 1970 0F2DD80A1AB3D85800BBB8E8 /* BytecodeKills.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeKills.h; sourceTree = "<group>"; }; 1971 0F2DD80C1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArgumentsEliminationPhase.cpp; path = dfg/DFGArgumentsEliminationPhase.cpp; sourceTree = "<group>"; }; 1972 0F2DD80D1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArgumentsEliminationPhase.h; path = dfg/DFGArgumentsEliminationPhase.h; sourceTree = "<group>"; }; 1973 0F2DD80E1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArgumentsUtilities.cpp; path = dfg/DFGArgumentsUtilities.cpp; sourceTree = "<group>"; }; 1974 0F2DD80F1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArgumentsUtilities.h; path = dfg/DFGArgumentsUtilities.h; sourceTree = "<group>"; }; 1975 0F2DD8101AB3D8BE00BBB8E8 /* DFGForAllKills.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGForAllKills.h; path = dfg/DFGForAllKills.h; sourceTree = "<group>"; }; 1948 1976 0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDCEPhase.cpp; path = dfg/DFGDCEPhase.cpp; sourceTree = "<group>"; }; 1949 1977 0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDCEPhase.h; path = dfg/DFGDCEPhase.h; sourceTree = "<group>"; }; … … 2133 2161 0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockWithJITType.h; sourceTree = "<group>"; }; 2134 2162 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCellInlines.h; sourceTree = "<group>"; }; 2163 0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantMode.cpp; sourceTree = "<group>"; }; 2135 2164 0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreciseJumpTargets.cpp; sourceTree = "<group>"; }; 2136 2165 0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreciseJumpTargets.h; sourceTree = "<group>"; }; … … 2200 2229 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = "<group>"; }; 2201 2230 0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; }; 2231 0FBDB9AC1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCallCreateDirectArgumentsSlowPathGenerator.h; path = dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h; sourceTree = "<group>"; }; 2202 2232 0FBE0F6B16C1DB010082C5E8 /* DFGCPSRethreadingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCPSRethreadingPhase.cpp; path = dfg/DFGCPSRethreadingPhase.cpp; sourceTree = "<group>"; }; 2203 2233 0FBE0F6C16C1DB010082C5E8 /* DFGCPSRethreadingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCPSRethreadingPhase.h; path = dfg/DFGCPSRethreadingPhase.h; sourceTree = "<group>"; }; … … 2310 2340 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessDataDump.cpp; path = dfg/DFGVariableAccessDataDump.cpp; sourceTree = "<group>"; }; 2311 2341 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = "<group>"; }; 2342 0FE0500C1AA9091100D33B33 /* ArgumentsMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgumentsMode.h; sourceTree = "<group>"; }; 2343 0FE0500D1AA9091100D33B33 /* DirectArgumentsOffset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectArgumentsOffset.cpp; sourceTree = "<group>"; }; 2344 0FE0500E1AA9091100D33B33 /* DirectArgumentsOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectArgumentsOffset.h; sourceTree = "<group>"; }; 2345 0FE0500F1AA9091100D33B33 /* DirectArguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectArguments.cpp; sourceTree = "<group>"; }; 2346 0FE050101AA9091100D33B33 /* DirectArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectArguments.h; sourceTree = "<group>"; }; 2347 0FE050111AA9091100D33B33 /* GenericArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericArguments.h; sourceTree = "<group>"; }; 2348 0FE050121AA9091100D33B33 /* GenericArgumentsInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericArgumentsInlines.h; sourceTree = "<group>"; }; 2349 0FE050131AA9091100D33B33 /* GenericOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericOffset.h; sourceTree = "<group>"; }; 2350 0FE0501C1AA9095600D33B33 /* ClonedArguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClonedArguments.cpp; sourceTree = "<group>"; }; 2351 0FE0501D1AA9095600D33B33 /* ClonedArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClonedArguments.h; sourceTree = "<group>"; }; 2352 0FE0501E1AA9095600D33B33 /* ScopedArguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScopedArguments.cpp; sourceTree = "<group>"; }; 2353 0FE0501F1AA9095600D33B33 /* ScopedArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopedArguments.h; sourceTree = "<group>"; }; 2354 0FE050201AA9095600D33B33 /* ScopedArgumentsTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopedArgumentsTable.h; sourceTree = "<group>"; }; 2355 0FE050211AA9095600D33B33 /* ScopeOffset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScopeOffset.cpp; sourceTree = "<group>"; }; 2356 0FE050221AA9095600D33B33 /* ScopeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopeOffset.h; sourceTree = "<group>"; }; 2357 0FE050231AA9095600D33B33 /* VarOffset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VarOffset.cpp; sourceTree = "<group>"; }; 2358 0FE050241AA9095600D33B33 /* VarOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VarOffset.h; sourceTree = "<group>"; }; 2359 0FE0502E1AAA806900D33B33 /* ScopedArgumentsTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScopedArgumentsTable.cpp; sourceTree = "<group>"; }; 2312 2360 0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; }; 2313 2361 0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; }; 2362 0FE254F41ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVarargsForwardingPhase.cpp; path = dfg/DFGVarargsForwardingPhase.cpp; sourceTree = "<group>"; }; 2363 0FE254F51ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVarargsForwardingPhase.h; path = dfg/DFGVarargsForwardingPhase.h; sourceTree = "<group>"; }; 2314 2364 0FE7211B193B9C590031F6ED /* DFGTransition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGTransition.cpp; path = dfg/DFGTransition.cpp; sourceTree = "<group>"; }; 2315 2365 0FE7211C193B9C590031F6ED /* DFGTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGTransition.h; path = dfg/DFGTransition.h; sourceTree = "<group>"; }; … … 3199 3249 BC22A3990E16E14800AF21C8 /* JSObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObject.h; sourceTree = "<group>"; }; 3200 3250 BC22A39A0E16E14800AF21C8 /* JSEnvironmentRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEnvironmentRecord.cpp; sourceTree = "<group>"; }; 3201 BC257DE50E1F51C50016B6C9 /* Arguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Arguments.cpp; sourceTree = "<group>"; };3202 BC257DE60E1F51C50016B6C9 /* Arguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Arguments.h; sourceTree = "<group>"; };3203 3251 BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionConstructor.cpp; sourceTree = "<group>"; }; 3204 3252 BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionConstructor.h; sourceTree = "<group>"; }; … … 4235 4283 BCF605110E203EF800B9A64D /* ArgList.cpp */, 4236 4284 BCF605120E203EF800B9A64D /* ArgList.h */, 4237 BC257DE50E1F51C50016B6C9 /* Arguments.cpp */,4238 BC257DE60E1F51C50016B6C9 /* Arguments.h */,4239 4285 A76140C7182982CB00750624 /* ArgumentsIteratorConstructor.cpp */, 4240 4286 A76140C8182982CB00750624 /* ArgumentsIteratorConstructor.h */, 4241 4287 A76140C9182982CB00750624 /* ArgumentsIteratorPrototype.cpp */, 4242 4288 A76140CA182982CB00750624 /* ArgumentsIteratorPrototype.h */, 4289 0FE0500C1AA9091100D33B33 /* ArgumentsMode.h */, 4243 4290 0F6B1CB71861244C00845D97 /* ArityCheckMode.h */, 4244 4291 A7A8AF2517ADB5F2005AB174 /* ArrayBuffer.cpp */, … … 4275 4322 145C507F0D9DF63B0088F6B9 /* CallData.h */, 4276 4323 BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */, 4324 0FE0501C1AA9095600D33B33 /* ClonedArguments.cpp */, 4325 0FE0501D1AA9095600D33B33 /* ClonedArguments.h */, 4277 4326 A77F181F164088B200640A47 /* CodeCache.cpp */, 4278 4327 A77F1820164088B200640A47 /* CodeCache.h */, … … 4295 4344 A53CE08218BC1A5600BEDF76 /* ConsolePrototype.h */, 4296 4345 A5FD0071189B038C00633231 /* ConsoleTypes.h */, 4346 0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */, 4297 4347 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */, 4298 4348 BCA62DFF0E2826310004F30D /* ConstructData.cpp */, … … 4313 4363 BCD203470E17135E002C7E82 /* DatePrototype.cpp */, 4314 4364 BCD203480E17135E002C7E82 /* DatePrototype.h */, 4365 0FE0500F1AA9091100D33B33 /* DirectArguments.cpp */, 4366 0FE050101AA9091100D33B33 /* DirectArguments.h */, 4367 0FE0500D1AA9091100D33B33 /* DirectArgumentsOffset.cpp */, 4368 0FE0500E1AA9091100D33B33 /* DirectArgumentsOffset.h */, 4315 4369 A70447EB17A0BD7000F5898E /* DumpContext.cpp */, 4316 4370 A70447EC17A0BD7000F5898E /* DumpContext.h */, … … 4342 4396 F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */, 4343 4397 F692A85D0255597D01FF60F7 /* FunctionPrototype.h */, 4398 0FE050111AA9091100D33B33 /* GenericArguments.h */, 4399 0FE050121AA9091100D33B33 /* GenericArgumentsInlines.h */, 4400 0FE050131AA9091100D33B33 /* GenericOffset.h */, 4344 4401 0F2B66B217B6B5AB00A7AE3F /* GenericTypedArrayView.h */, 4345 4402 0F2B66B317B6B5AB00A7AE3F /* GenericTypedArrayViewInlines.h */, … … 4579 4636 0F7700911402FF280078EB39 /* SamplingCounter.cpp */, 4580 4637 0F77008E1402FDD60078EB39 /* SamplingCounter.h */, 4638 0FE0501E1AA9095600D33B33 /* ScopedArguments.cpp */, 4639 0FE0501F1AA9095600D33B33 /* ScopedArguments.h */, 4640 0FE0502E1AAA806900D33B33 /* ScopedArgumentsTable.cpp */, 4641 0FE050201AA9095600D33B33 /* ScopedArgumentsTable.h */, 4642 0FE050211AA9095600D33B33 /* ScopeOffset.cpp */, 4643 0FE050221AA9095600D33B33 /* ScopeOffset.h */, 4581 4644 A7299DA317D12858005F5FF9 /* SetConstructor.cpp */, 4582 4645 A7299DA417D12858005F5FF9 /* SetConstructor.h */, … … 4655 4718 866739D113BFDE710023D87C /* Uint16WithFraction.h */, 4656 4719 A7A8AF3317ADB5F3005AB174 /* Uint32Array.h */, 4720 0FE050231AA9095600D33B33 /* VarOffset.cpp */, 4721 0FE050241AA9095600D33B33 /* VarOffset.h */, 4657 4722 E18E3A570DF9278C00D90B34 /* VM.cpp */, 4658 4723 E18E3A560DF9278C00D90B34 /* VM.h */, … … 4725 4790 A73781091799EA2E00817533 /* DFGAnalysis.h */, 4726 4791 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */, 4727 0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */, 4728 0F16015B156198BF00C2587C /* DFGArgumentsSimplificationPhase.h */, 4792 0F2DD80C1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.cpp */, 4793 0F2DD80D1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h */, 4794 0F2DD80E1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.cpp */, 4795 0F2DD80F1AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h */, 4729 4796 0F48531F187750560083B687 /* DFGArithMode.cpp */, 4730 4797 0F485320187750560083B687 /* DFGArithMode.h */, … … 4756 4823 86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */, 4757 4824 0F256C341627B0AA007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h */, 4825 0FBDB9AC1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h */, 4758 4826 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */, 4759 4827 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */, … … 4818 4886 A7D89CE817A0B8CC00773AD8 /* DFGFlushFormat.cpp */, 4819 4887 A7D89CE917A0B8CC00773AD8 /* DFGFlushFormat.h */, 4888 0F2DD8101AB3D8BE00BBB8E8 /* DFGForAllKills.h */, 4820 4889 0F69CC86193AC60A0045759E /* DFGFrozenValue.cpp */, 4821 4890 0F69CC87193AC60A0045759E /* DFGFrozenValue.h */, … … 4985 5054 0F0123301944EA1B00843A0C /* DFGValueStrength.cpp */, 4986 5055 0F0123311944EA1B00843A0C /* DFGValueStrength.h */, 5056 0FE254F41ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp */, 5057 0FE254F51ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h */, 4987 5058 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */, 4988 5059 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */, … … 5106 5177 C2FCAE0D17A9C24E0034C735 /* BytecodeBasicBlock.h */, 5107 5178 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */, 5179 0F2DD80A1AB3D85800BBB8E8 /* BytecodeKills.h */, 5108 5180 6529FB3118B2D99900C61102 /* BytecodeList.json */, 5109 5181 C2FCAE0E17A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp */, … … 5460 5532 0FFA549816B8835300B3A982 /* A64DOpcode.h in Headers */, 5461 5533 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */, 5534 0FE050291AA9095600D33B33 /* ScopedArgumentsTable.h in Headers */, 5462 5535 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */, 5463 5536 2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */, … … 5465 5538 BCF605140E203EF800B9A64D /* ArgList.h in Headers */, 5466 5539 2A88067919107D5500CB0BBB /* DFGFunctionWhitelist.h in Headers */, 5467 BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */,5468 5540 A76140CE182982CB00750624 /* ArgumentsIteratorConstructor.h in Headers */, 5469 5541 A76140D0182982CB00750624 /* ArgumentsIteratorPrototype.h in Headers */, … … 5472 5544 A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */, 5473 5545 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */, 5546 0FE050281AA9095600D33B33 /* ScopedArguments.h in Headers */, 5474 5547 52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */, 5475 5548 C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */, … … 5632 5705 0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */, 5633 5706 A5C3A1A618C0490200C9593A /* JSGlobalObjectConsoleClient.h in Headers */, 5634 0F16015E156198C900C2587C /* DFGArgumentsSimplificationPhase.h in Headers */,5635 5707 0F485322187750560083B687 /* DFGArithMode.h in Headers */, 5636 5708 0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */, … … 5647 5719 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */, 5648 5720 0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */, 5721 0F2DD80B1AB3D85800BBB8E8 /* BytecodeKills.h in Headers */, 5649 5722 0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */, 5650 5723 A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */, … … 5736 5809 A741017F179DAF80002EB8BA /* DFGSaneStringGetByValSlowPathGenerator.h in Headers */, 5737 5810 0F2FCCFD18A60070001A27F8 /* DFGScannable.h in Headers */, 5811 0F2DD8141AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h in Headers */, 5738 5812 86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */, 5739 5813 0F1E3A67153A21E2000F9456 /* DFGSilentRegisterSavePlan.h in Headers */, … … 5790 5864 0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */, 5791 5865 A53CE08A18BC21C300BEDF76 /* ConsoleClient.h in Headers */, 5866 0FE050191AA9091100D33B33 /* GenericArguments.h in Headers */, 5792 5867 0FEA0A1D1708B00700BB722C /* FTLAbstractHeap.h in Headers */, 5793 5868 DC00039319D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h in Headers */, … … 5874 5949 2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */, 5875 5950 2A6F462617E959CE00C45C98 /* HeapOperation.h in Headers */, 5951 0FE050141AA9091100D33B33 /* ArgumentsMode.h in Headers */, 5876 5952 14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */, 5877 5953 C24D31E3161CD695002AA4DB /* HeapStatistics.h in Headers */, … … 5900 5976 0F3E01AB19D353A500F61B7F /* DFGPrePostNumbering.h in Headers */, 5901 5977 A593CF87184038CA00BFCE27 /* InspectorAgentRegistry.h in Headers */, 5978 0FE050261AA9095600D33B33 /* ClonedArguments.h in Headers */, 5902 5979 A593CF7D1840360300BFCE27 /* InspectorBackendDispatcher.h in Headers */, 5903 5980 A5FD0082189B191A00633231 /* InspectorConsoleAgent.h in Headers */, … … 5975 6052 0F9749711687ADE400A4FF6A /* JSCellInlines.h in Headers */, 5976 6053 0F1DD84A18A945BE0026F3FA /* JSCInlines.h in Headers */, 6054 0FE0501A1AA9091100D33B33 /* GenericArgumentsInlines.h in Headers */, 5977 6055 BC18C42B0E16F5CD00B34460 /* JSCJSValue.h in Headers */, 5978 6056 0F64B2721A784BAF006E4E66 /* BinarySwitch.h in Headers */, … … 6055 6133 0F919D0D157EE0A2004A4E7D /* JSSymbolTableObject.h in Headers */, 6056 6134 BC18C42A0E16F5CD00B34460 /* JSType.h in Headers */, 6135 0FE050161AA9091100D33B33 /* DirectArgumentsOffset.h in Headers */, 6057 6136 0F2B66FB17B6B5AB00A7AE3F /* JSTypedArrayConstructors.h in Headers */, 6058 6137 0F2B66FD17B6B5AB00A7AE3F /* JSTypedArrayPrototypes.h in Headers */, … … 6063 6142 0F2D4DF019832DD6007D4B19 /* TypeSet.h in Headers */, 6064 6143 0F2B670017B6B5AB00A7AE3F /* JSUint8Array.h in Headers */, 6144 0FE0502D1AA9095600D33B33 /* VarOffset.h in Headers */, 6065 6145 0F2B670117B6B5AB00A7AE3F /* JSUint8ClampedArray.h in Headers */, 6066 6146 86E3C612167BABD7006D760A /* JSValue.h in Headers */, … … 6091 6171 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */, 6092 6172 0FC3CD0019ADA410006AC72A /* DFGBlockWorklist.h in Headers */, 6173 0FE050181AA9091100D33B33 /* DirectArguments.h in Headers */, 6093 6174 FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */, 6094 6175 0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */, 6176 0FBDB9AD1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h in Headers */, 6095 6177 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */, 6096 6178 0F38B01217CF078300B144D3 /* LLIntEntrypoint.h in Headers */, … … 6165 6247 0F2D4DDE19832D34007D4B19 /* DebuggerScope.h in Headers */, 6166 6248 BC18C4480E16F5CD00B34460 /* Operations.h in Headers */, 6249 0FE0501B1AA9091100D33B33 /* GenericOffset.h in Headers */, 6167 6250 0FE228ED1436AB2700196C48 /* Options.h in Headers */, 6168 6251 BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */, … … 6174 6257 0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */, 6175 6258 0F98206116BFE38300240D02 /* PreciseJumpTargets.h in Headers */, 6259 0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */, 6176 6260 868916B0155F286300CB2B9A /* PrivateName.h in Headers */, 6177 6261 A5EA70E719F5B1010098F5EC /* AugmentableInspectorController.h in Headers */, … … 6246 6330 C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */, 6247 6331 1429D8860ED21C3D00B89619 /* SamplingTool.h in Headers */, 6332 0FE254F71ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.h in Headers */, 6248 6333 0F24E55217EE274900ABB217 /* ScratchRegisterAllocator.h in Headers */, 6249 6334 A5FD0068189AFE9C00633231 /* ScriptArguments.h in Headers */, … … 6325 6410 70B0A9D11A9B66460001306A /* RuntimeFlags.h in Headers */, 6326 6411 A7E5AB391799E4B200D2833D /* UDis86Disassembler.h in Headers */, 6412 0FE0502B1AA9095600D33B33 /* ScopeOffset.h in Headers */, 6327 6413 A7A8AF4117ADB5F3005AB174 /* Uint16Array.h in Headers */, 6328 6414 0FE834181A6EF97B00D04847 /* PolymorphicCallStubRoutine.h in Headers */, … … 6349 6435 14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */, 6350 6436 14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */, 6437 0F2DD8121AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h in Headers */, 6351 6438 14BE7D3317135CF400D1807A /* WeakInlines.h in Headers */, 6352 6439 A7CA3AE417DA41AE006538AF /* WeakMapConstructor.h in Headers */, … … 6835 6922 9E729407190F01A5001A91B5 /* InitializeThreading.cpp in Sources */, 6836 6923 0FFA549716B8835000B3A982 /* A64DOpcode.cpp in Sources */, 6924 0FE050151AA9091100D33B33 /* DirectArgumentsOffset.cpp in Sources */, 6837 6925 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */, 6838 6926 147F39BD107EC37600427A48 /* ArgList.cpp in Sources */, 6839 147F39BE107EC37600427A48 /* Arguments.cpp in Sources */,6840 6927 A76140CD182982CB00750624 /* ArgumentsIteratorConstructor.cpp in Sources */, 6841 6928 A76140CF182982CB00750624 /* ArgumentsIteratorPrototype.cpp in Sources */, … … 6885 6972 6553A33117A1F1EE008CF6F3 /* CommonSlowPathsExceptions.cpp in Sources */, 6886 6973 0F64B2791A7957B2006E4E66 /* CallEdge.cpp in Sources */, 6974 0FE254F61ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp in Sources */, 6887 6975 A7E5A3A71797432D00E893C0 /* CompilationResult.cpp in Sources */, 6888 6976 147F39C2107EC37600427A48 /* Completion.cpp in Sources */, … … 6907 6995 A77A423D17A0BBFD00A8DB81 /* DFGAbstractHeap.cpp in Sources */, 6908 6996 0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */, 6909 0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */,6910 6997 0F485321187750560083B687 /* DFGArithMode.cpp in Sources */, 6911 6998 0F2D4DDD19832D34007D4B19 /* DebuggerScope.cpp in Sources */, … … 6917 7004 A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */, 6918 7005 2A88067819107D5500CB0BBB /* DFGFunctionWhitelist.cpp in Sources */, 7006 0F2DD8131AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.cpp in Sources */, 6919 7007 A7D89CF317A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp in Sources */, 6920 7008 86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */, … … 6963 7051 0FEA0A33170D40BF00BB722C /* DFGJITCode.cpp in Sources */, 6964 7052 86EC9DCB1328DF82002B2AD7 /* DFGJITCompiler.cpp in Sources */, 7053 0FE0502A1AA9095600D33B33 /* ScopeOffset.cpp in Sources */, 6965 7054 A78A9778179738B8009DF744 /* DFGJITFinalizer.cpp in Sources */, 6966 7055 0FC97F3F18202119002C9B26 /* DFGJumpReplacement.cpp in Sources */, … … 7041 7130 A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */, 7042 7131 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */, 7132 0F2DD8111AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.cpp in Sources */, 7043 7133 0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */, 7044 7134 52678F8E1A031009006A306D /* BasicBlockLocation.cpp in Sources */, … … 7047 7137 0FB105851675480F00F8AB6E /* ExitKind.cpp in Sources */, 7048 7138 0FEA0A1C1708B00700BB722C /* FTLAbstractHeap.cpp in Sources */, 7139 0F978B3B1AAEA71D007C7369 /* ConstantMode.cpp in Sources */, 7140 0FE050251AA9095600D33B33 /* ClonedArguments.cpp in Sources */, 7049 7141 0F79085519A290B200F6310C /* DFGStructureRegistrationPhase.cpp in Sources */, 7050 7142 0FEA0A1E1708B00700BB722C /* FTLAbstractHeapRepository.cpp in Sources */, … … 7185 7277 0F2D4DE819832DAC007D4B19 /* ToThisStatus.cpp in Sources */, 7186 7278 978801401471AD920041B016 /* JSDateMath.cpp in Sources */, 7279 0FE050171AA9091100D33B33 /* DirectArguments.cpp in Sources */, 7187 7280 140566D6107EC271005DBC8D /* JSFunction.cpp in Sources */, 7188 7281 147F39D2107EC37600427A48 /* JSGlobalObject.cpp in Sources */, … … 7333 7426 14280841107EC0930013E7B2 /* RegExp.cpp in Sources */, 7334 7427 A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */, 7428 0FE0502C1AA9095600D33B33 /* VarOffset.cpp in Sources */, 7335 7429 8642C510151C06A90046D4EF /* RegExpCachedResult.cpp in Sources */, 7336 7430 14280842107EC0930013E7B2 /* RegExpConstructor.cpp in Sources */, … … 7426 7520 2A4EC90B1860D6C20094F782 /* WriteBarrierBuffer.cpp in Sources */, 7427 7521 0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */, 7522 0FE050271AA9095600D33B33 /* ScopedArguments.cpp in Sources */, 7428 7523 0F3B7E2A19A11B8000D9BC56 /* CallVariant.cpp in Sources */, 7429 7524 A7E5AB3A1799E4B200D2833D /* X86Disassembler.cpp in Sources */, 7430 7525 863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */, 7526 0FE0502F1AAA806900D33B33 /* ScopedArgumentsTable.cpp in Sources */, 7431 7527 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */, 7432 7528 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */, -
trunk/Source/JavaScriptCore/assembler/AbortReason.h
r169942 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 58 58 DFGUnreachableBasicBlock = 220, 59 59 DFGUnreasonableOSREntryJumpDestination = 230, 60 DFGVarargsThrowingPathDidNotThrow = 235, 60 61 JITDivOperandsAreNotNumbers = 240, 61 62 JITGetByValResultIsNotEmpty = 250, -
trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
r181570 r181993 1 1 /* 2 * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2012, 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 206 206 Scale scale; 207 207 int32_t offset; 208 209 BaseIndex withOffset(int32_t additionalOffset) 210 { 211 return BaseIndex(base, index, scale, offset + additionalOffset); 212 } 208 213 }; 209 214 -
trunk/Source/JavaScriptCore/bytecode/ByValInfo.h
r164424 r181993 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 42 42 JITContiguous, 43 43 JITArrayStorage, 44 JITDirectArguments, 45 JITScopedArguments, 44 46 JITInt8Array, 45 47 JITInt16Array, … … 66 68 } 67 69 70 inline bool hasOptimizableIndexingForJSType(JSType type) 71 { 72 switch (type) { 73 case DirectArgumentsType: 74 case ScopedArgumentsType: 75 return true; 76 default: 77 return false; 78 } 79 } 80 68 81 inline bool hasOptimizableIndexingForClassInfo(const ClassInfo* classInfo) 69 82 { … … 74 87 { 75 88 return isOptimizableIndexingType(structure->indexingType()) 89 || hasOptimizableIndexingForJSType(structure->typeInfo().type()) 76 90 || hasOptimizableIndexingForClassInfo(structure->classInfo()); 77 91 } … … 90 104 default: 91 105 CRASH(); 106 return JITContiguous; 107 } 108 } 109 110 inline JITArrayMode jitArrayModeForJSType(JSType type) 111 { 112 switch (type) { 113 case DirectArgumentsType: 114 return JITDirectArguments; 115 case ScopedArgumentsType: 116 return JITScopedArguments; 117 default: 118 RELEASE_ASSERT_NOT_REACHED(); 92 119 return JITContiguous; 93 120 } … … 121 148 } 122 149 150 inline bool jitArrayModePermitsPut(JITArrayMode mode) 151 { 152 switch (mode) { 153 case JITDirectArguments: 154 case JITScopedArguments: 155 // We could support put_by_val on these at some point, but it's just not that profitable 156 // at the moment. 157 return false; 158 default: 159 return true; 160 } 161 } 162 123 163 inline TypedArrayType typedArrayTypeForJITArrayMode(JITArrayMode mode) 124 164 { … … 153 193 return jitArrayModeForIndexingType(structure->indexingType()); 154 194 195 if (hasOptimizableIndexingForJSType(structure->typeInfo().type())) 196 return jitArrayModeForJSType(structure->typeInfo().type()); 197 155 198 ASSERT(hasOptimizableIndexingForClassInfo(structure->classInfo())); 156 199 return jitArrayModeForClassInfo(structure->classInfo()); -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r181891 r181993 8 8 { "name" : "op_get_scope", "length" : 2 }, 9 9 { "name" : "op_touch_entry", "length" : 1 }, 10 { "name" : "op_init_lazy_reg", "length" : 2 }, 11 { "name" : "op_create_arguments", "length" : 3 }, 10 { "name" : "op_create_direct_arguments", "length" : 2 }, 11 { "name" : "op_create_scoped_arguments", "length" : 3 }, 12 { "name" : "op_create_out_of_band_arguments", "length" : 2 }, 12 13 { "name" : "op_create_this", "length" : 4 }, 13 14 { "name" : "op_to_this", "length" : 4 }, … … 62 63 { "name" : "op_get_by_id_out_of_line", "length" : 9 }, 63 64 { "name" : "op_get_array_length", "length" : 9 }, 64 { "name" : "op_get_arguments_length", "length" : 4 },65 65 { "name" : "op_put_by_id", "length" : 9 }, 66 66 { "name" : "op_put_by_id_out_of_line", "length" : 9 }, … … 71 71 { "name" : "op_del_by_id", "length" : 4 }, 72 72 { "name" : "op_get_by_val", "length" : 6 }, 73 { "name" : "op_get_argument_by_val", "length" : 7 },74 73 { "name" : "op_put_by_val", "length" : 5 }, 75 74 { "name" : "op_put_by_val_direct", "length" : 5 }, … … 95 94 { "name" : "op_switch_char", "length" : 4 }, 96 95 { "name" : "op_switch_string", "length" : 4 }, 97 { "name" : "op_new_func", "length" : 5},96 { "name" : "op_new_func", "length" : 4 }, 98 97 { "name" : "op_new_func_exp", "length" : 4 }, 99 98 { "name" : "op_call", "length" : 9 }, 100 99 { "name" : "op_call_eval", "length" : 9 }, 101 100 { "name" : "op_call_varargs", "length" : 9 }, 102 { "name" : "op_tear_off_arguments", "length" : 3 },103 101 { "name" : "op_ret", "length" : 2 }, 104 102 { "name" : "op_construct", "length" : 9 }, … … 109 107 { "name" : "op_get_from_scope", "length" : 8 }, 110 108 { "name" : "op_put_to_scope", "length" : 7 }, 109 { "name" : "op_get_from_arguments", "length" : 5 }, 110 { "name" : "op_put_to_arguments", "length" : 4 }, 111 111 { "name" : "op_push_with_scope", "length" : 3 }, 112 112 { "name" : "op_pop_scope", "length" : 2 }, -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
r181467 r181993 27 27 #include "BytecodeLivenessAnalysis.h" 28 28 29 #include "BytecodeKills.h" 29 30 #include "BytecodeLivenessAnalysisInlines.h" 30 31 #include "BytecodeUseDef.h" … … 48 49 49 50 VirtualRegister virtualReg(operand); 50 if (!virtualReg.isLocal()) 51 return false; 52 53 if (codeBlock->captureCount() 54 && operand <= codeBlock->captureStart() 55 && operand > codeBlock->captureEnd()) 56 return false; 57 58 return true; 59 } 60 61 static unsigned indexForOperand(CodeBlock* codeBlock, int operand) 62 { 63 ASSERT(isValidRegisterForLiveness(codeBlock, operand)); 64 VirtualRegister virtualReg(operand); 65 if (virtualReg.offset() > codeBlock->captureStart()) 66 return virtualReg.toLocal(); 67 return virtualReg.toLocal() - codeBlock->captureCount(); 51 return virtualReg.isLocal(); 68 52 } 69 53 … … 136 120 [&] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) { 137 121 if (isValidRegisterForLiveness(codeBlock, operand)) 138 def( indexForOperand(codeBlock, operand));122 def(VirtualRegister(operand).toLocal()); 139 123 }); 140 124 141 125 computeUsesForBytecodeOffset( 142 126 codeBlock, bytecodeOffset, 143 127 [&] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) { 144 128 if (isValidRegisterForLiveness(codeBlock, operand)) 145 use( indexForOperand(codeBlock, operand));129 use(VirtualRegister(operand).toLocal()); 146 130 }); 147 131 … … 197 181 { 198 182 UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock->unlinkedCodeBlock(); 199 unsigned numberOfVariables = 200 unlinkedCodeBlock->m_numCalleeRegisters - m_codeBlock->captureCount(); 183 unsigned numberOfVariables = unlinkedCodeBlock->m_numCalleeRegisters; 201 184 202 185 for (unsigned i = 0; i < m_basicBlocks.size(); i++) { … … 213 196 do { 214 197 changed = false; 215 for ( int i = m_basicBlocks.size() - 2; i >= 0; i--) {198 for (unsigned i = m_basicBlocks.size() - 1; i--;) { 216 199 BytecodeBasicBlock* block = m_basicBlocks[i].get(); 217 200 newOut.clearAll(); … … 225 208 } 226 209 227 void BytecodeLivenessAnalysis::getLivenessInfo ForNonCapturedVarsAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector& result)210 void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector& result) 228 211 { 229 212 BytecodeBasicBlock* block = findBasicBlockForBytecodeOffset(m_basicBlocks, bytecodeOffset); … … 237 220 bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset) 238 221 { 239 if (operandIsAlwaysLive( m_codeBlock,operand))222 if (operandIsAlwaysLive(operand)) 240 223 return true; 241 224 FastBitVector result; 242 getLivenessInfoForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, result); 243 return operandThatIsNotAlwaysLiveIsLive(m_codeBlock, result, operand); 244 } 245 246 FastBitVector getLivenessInfo(CodeBlock* codeBlock, const FastBitVector& out) 247 { 248 FastBitVector result; 249 250 unsigned numCapturedVars = codeBlock->captureCount(); 251 if (numCapturedVars) { 252 int firstCapturedLocal = VirtualRegister(codeBlock->captureStart()).toLocal(); 253 result.resize(out.numBits() + numCapturedVars); 254 for (unsigned i = 0; i < numCapturedVars; ++i) 255 result.set(firstCapturedLocal + i); 256 } else 257 result.resize(out.numBits()); 258 259 int outLength = out.numBits(); 260 ASSERT(outLength >= 0); 261 for (int i = 0; i < outLength; i++) { 262 if (!out.get(i)) 263 continue; 264 265 if (!numCapturedVars) { 266 result.set(i); 267 continue; 268 } 269 270 if (virtualRegisterForLocal(i).offset() > codeBlock->captureStart()) 271 result.set(i); 272 else 273 result.set(numCapturedVars + i); 274 } 275 return result; 225 getLivenessInfoAtBytecodeOffset(bytecodeOffset, result); 226 return operandThatIsNotAlwaysLiveIsLive(result, operand); 276 227 } 277 228 … … 279 230 { 280 231 FastBitVector out; 281 getLivenessInfo ForNonCapturedVarsAtBytecodeOffset(bytecodeOffset, out);282 return getLivenessInfo(m_codeBlock, out);232 getLivenessInfoAtBytecodeOffset(bytecodeOffset, out); 233 return out; 283 234 } 284 235 … … 287 238 FastBitVector out; 288 239 289 result.m_codeBlock = m_codeBlock;290 240 result.m_map.clear(); 291 241 … … 301 251 stepOverInstruction(m_codeBlock, m_basicBlocks, bytecodeOffset, out); 302 252 result.m_map.add(bytecodeOffset, out); 253 } 254 } 255 } 256 257 void BytecodeLivenessAnalysis::computeKills(BytecodeKills& result) 258 { 259 FastBitVector out; 260 261 result.m_codeBlock = m_codeBlock; 262 result.m_killSets = std::make_unique<BytecodeKills::KillSet[]>(m_codeBlock->instructions().size()); 263 264 for (unsigned i = m_basicBlocks.size(); i--;) { 265 BytecodeBasicBlock* block = m_basicBlocks[i].get(); 266 if (block->isEntryBlock() || block->isExitBlock()) 267 continue; 268 269 out = block->out(); 270 271 for (unsigned i = block->bytecodeOffsets().size(); i--;) { 272 unsigned bytecodeOffset = block->bytecodeOffsets()[i]; 273 stepOverInstruction( 274 m_codeBlock, m_basicBlocks, bytecodeOffset, 275 [&] (unsigned index) { 276 // This is for uses. 277 if (out.get(index)) 278 return; 279 result.m_killSets[bytecodeOffset].add(index); 280 out.set(index); 281 }, 282 [&] (unsigned index) { 283 // This is for defs. 284 out.clear(index); 285 }); 303 286 } 304 287 } -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h
r159394 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 34 34 namespace JSC { 35 35 36 class BytecodeKills; 36 37 class CodeBlock; 37 38 class FullBytecodeLiveness; … … 45 46 46 47 void computeFullLiveness(FullBytecodeLiveness& result); 48 void computeKills(BytecodeKills& result); 47 49 48 50 private: … … 51 53 void dumpResults(); 52 54 53 void getLivenessInfo ForNonCapturedVarsAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector&);55 void getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector&); 54 56 55 57 CodeBlock* m_codeBlock; … … 57 59 }; 58 60 59 inline bool operandIsAlwaysLive(CodeBlock*, int operand); 60 inline bool operandThatIsNotAlwaysLiveIsLive(CodeBlock*, const FastBitVector& out, int operand); 61 inline bool operandIsLive(CodeBlock*, const FastBitVector& out, int operand); 62 63 FastBitVector getLivenessInfo(CodeBlock*, const FastBitVector& out); 61 inline bool operandIsAlwaysLive(int operand); 62 inline bool operandThatIsNotAlwaysLiveIsLive(const FastBitVector& out, int operand); 63 inline bool operandIsLive(const FastBitVector& out, int operand); 64 64 65 65 } // namespace JSC -
trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h
r163760 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 namespace JSC { 34 34 35 inline bool operandIsAlwaysLive( CodeBlock* codeBlock,int operand)35 inline bool operandIsAlwaysLive(int operand) 36 36 { 37 if (VirtualRegister(operand).isArgument()) 38 return true; 39 return operand <= codeBlock->captureStart() && operand > codeBlock->captureEnd(); 37 return !VirtualRegister(operand).isLocal(); 40 38 } 41 39 42 inline bool operandThatIsNotAlwaysLiveIsLive( CodeBlock* codeBlock,const FastBitVector& out, int operand)40 inline bool operandThatIsNotAlwaysLiveIsLive(const FastBitVector& out, int operand) 43 41 { 44 VirtualRegister virtualReg(operand); 45 if (virtualReg.offset() > codeBlock->captureStart()) 46 return out.get(virtualReg.toLocal()); 47 size_t index = virtualReg.toLocal() - codeBlock->captureCount(); 48 if (index >= out.numBits()) 42 unsigned local = VirtualRegister(operand).toLocal(); 43 if (local >= out.numBits()) 49 44 return false; 50 return out.get( index);45 return out.get(local); 51 46 } 52 47 53 inline bool operandIsLive( CodeBlock* codeBlock,const FastBitVector& out, int operand)48 inline bool operandIsLive(const FastBitVector& out, int operand) 54 49 { 55 return operandIsAlwaysLive( codeBlock, operand) || operandThatIsNotAlwaysLiveIsLive(codeBlock,out, operand);50 return operandIsAlwaysLive(operand) || operandThatIsNotAlwaysLiveIsLive(out, operand); 56 51 } 57 52 -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
r181891 r181993 49 49 case op_jmp: 50 50 case op_new_object: 51 case op_init_lazy_reg:52 51 case op_enter: 53 52 case op_catch: 54 53 case op_touch_entry: 55 54 case op_profile_control_flow: 55 case op_create_direct_arguments: 56 case op_create_out_of_band_arguments: 56 57 return; 57 58 case op_get_scope: … … 74 75 return; 75 76 } 76 case op_create_arguments:77 case op_new_func:78 77 case op_jlesseq: 79 78 case op_jgreater: … … 102 101 case op_put_by_id_out_of_line: 103 102 case op_put_by_id: 104 case op_put_to_scope: { 103 case op_put_to_scope: 104 case op_put_to_arguments: { 105 105 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 106 106 functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); … … 128 128 case op_get_by_id_out_of_line: 129 129 case op_get_array_length: 130 case op_get_arguments_length:131 130 case op_typeof: 132 131 case op_is_undefined: … … 146 145 case op_create_this: 147 146 case op_del_by_id: 148 case op_unsigned: { 147 case op_unsigned: 148 case op_new_func: 149 case op_create_scoped_arguments: 150 case op_get_from_arguments: { 149 151 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); 150 152 return; … … 183 185 } 184 186 case op_has_structure_property: 185 case op_get_argument_by_val:186 187 case op_construct_varargs: 187 188 case op_call_varargs: { … … 221 222 for (int i = 0; i < argCount; i++) 222 223 functor(codeBlock, instruction, opcodeID, lastArg + i); 223 return;224 }225 case op_tear_off_arguments: {226 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);227 functor(codeBlock, instruction, opcodeID, unmodifiedArgumentsRegister(VirtualRegister(instruction[1].u.operand)).offset());228 functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);229 224 return; 230 225 } … … 282 277 case op_put_by_val_direct: 283 278 case op_put_by_index: 284 case op_tear_off_arguments:285 279 case op_profile_type: 286 280 case op_profile_control_flow: 287 281 case op_touch_entry: 282 case op_put_to_arguments: 288 283 #define LLINT_HELPER_OPCODES(opcode, length) case opcode: 289 284 FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES); … … 326 321 case op_instanceof: 327 322 case op_get_by_val: 328 case op_get_argument_by_val:329 case op_get_arguments_length:330 323 case op_typeof: 331 324 case op_is_undefined: … … 367 360 case op_to_this: 368 361 case op_check_tdz: 369 case op_init_lazy_reg:370 362 case op_get_scope: 371 case op_create_arguments: 363 case op_create_direct_arguments: 364 case op_create_scoped_arguments: 365 case op_create_out_of_band_arguments: 372 366 case op_del_by_id: 373 367 case op_del_by_val: 374 case op_unsigned: { 368 case op_unsigned: 369 case op_get_from_arguments: { 375 370 functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); 376 371 return; -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r181979 r181993 570 570 static_cast<unsigned long>(instructions().size() * sizeof(Instruction)), 571 571 m_numParameters, m_numCalleeRegisters, m_numVars); 572 if (symbolTable() && symbolTable()->captureCount()) {573 out.printf(574 "; %d captured var(s) (from r%d to r%d, inclusive)",575 symbolTable()->captureCount(), symbolTable()->captureStart(), symbolTable()->captureEnd() + 1);576 }577 if (usesArguments()) {578 out.printf(579 "; uses arguments, in r%d, r%d",580 argumentsRegister().offset(),581 unmodifiedArgumentsRegister(argumentsRegister()).offset());582 }583 572 if (needsActivation() && codeType() == FunctionCode) 584 573 out.printf("; lexical environment in r%d", activationRegister().offset()); … … 753 742 int r1 = (++it)->u.operand; 754 743 printLocationAndOp(out, exec, location, it, "create_lexical_environment"); 755 out.printf("%s %s", registerName(r0).data(), registerName(r1).data());744 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data()); 756 745 break; 757 746 } … … 761 750 break; 762 751 } 763 case op_create_arguments: { 752 case op_create_direct_arguments: { 753 int r0 = (++it)->u.operand; 754 printLocationAndOp(out, exec, location, it, "create_direct_arguments"); 755 out.printf("%s", registerName(r0).data()); 756 break; 757 } 758 case op_create_scoped_arguments: { 764 759 int r0 = (++it)->u.operand; 765 760 int r1 = (++it)->u.operand; 766 printLocationAndOp(out, exec, location, it, "create_arguments"); 767 out.printf("%s %s", registerName(r0).data(), registerName(r1).data()); 768 break; 769 } 770 case op_init_lazy_reg: { 771 int r0 = (++it)->u.operand; 772 printLocationOpAndRegisterOperand(out, exec, location, it, "init_lazy_reg", r0); 761 printLocationAndOp(out, exec, location, it, "create_scoped_arguments"); 762 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data()); 763 break; 764 } 765 case op_create_out_of_band_arguments: { 766 int r0 = (++it)->u.operand; 767 printLocationAndOp(out, exec, location, it, "create_out_of_band_arguments"); 768 out.printf("%s", registerName(r0).data()); 773 769 break; 774 770 } … … 786 782 Structure* structure = (++it)->u.structure.get(); 787 783 if (structure) 788 out.print(" cache(struct = ", RawPointer(structure), ")");789 out.print(" ", (++it)->u.toThisStatus);784 out.print(", cache(struct = ", RawPointer(structure), ")"); 785 out.print(", ", (++it)->u.toThisStatus); 790 786 break; 791 787 } … … 1042 1038 } 1043 1039 case op_init_global_const: { 1044 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;1040 WriteBarrier<Unknown>* variablePointer = (++it)->u.variablePointer; 1045 1041 int r0 = (++it)->u.operand; 1046 1042 printLocationAndOp(out, exec, location, it, "init_global_const"); 1047 out.printf("g%d(%p), %s", m_globalObject->find RegisterIndex(registerPointer), registerPointer, registerName(r0).data());1043 out.printf("g%d(%p), %s", m_globalObject->findVariableIndex(variablePointer).offset(), variablePointer, registerName(r0).data()); 1048 1044 it++; 1049 1045 it++; … … 1058 1054 break; 1059 1055 } 1060 case op_get_arguments_length: {1061 printUnaryOp(out, exec, location, it, "get_arguments_length");1062 it++;1063 break;1064 }1065 1056 case op_put_by_id: { 1066 1057 printPutByIdOp(out, exec, location, it, "put_by_id"); … … 1120 1111 break; 1121 1112 } 1122 case op_get_argument_by_val: {1123 int r0 = (++it)->u.operand;1124 int r1 = (++it)->u.operand;1125 int r2 = (++it)->u.operand;1126 int r3 = (++it)->u.operand;1127 printLocationAndOp(out, exec, location, it, "get_argument_by_val");1128 out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());1129 ++it;1130 dumpValueProfiling(out, it, hasPrintedProfiling);1131 break;1132 }1133 1113 case op_put_by_val: { 1134 1114 int r0 = (++it)->u.operand; … … 1291 1271 int r1 = (++it)->u.operand; 1292 1272 int f0 = (++it)->u.operand; 1293 int shouldCheck = (++it)->u.operand;1294 1273 printLocationAndOp(out, exec, location, it, "new_func"); 1295 out.printf("%s, %s, f%d , %s", registerName(r0).data(), registerName(r1).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>");1274 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0); 1296 1275 break; 1297 1276 } … … 1328 1307 } 1329 1308 1330 case op_tear_off_arguments: {1331 int r0 = (++it)->u.operand;1332 int r1 = (++it)->u.operand;1333 printLocationAndOp(out, exec, location, it, "tear_off_arguments");1334 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());1335 break;1336 }1337 1309 case op_ret: { 1338 1310 int r0 = (++it)->u.operand; … … 1523 1495 ++it; // Structure 1524 1496 int operand = (++it)->u.operand; // Operand 1525 ++it; // Skip value profile.1526 1497 printLocationAndOp(out, exec, location, it, "get_from_scope"); 1527 out.printf("%s, %s, %s, %u<%s|%s>, <structure>, %d", 1528 registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data(), 1529 modeAndType.operand(), resolveModeName(modeAndType.mode()), resolveTypeName(modeAndType.type()), 1530 operand); 1498 out.print(registerName(r0), ", ", registerName(r1)); 1499 if (static_cast<unsigned>(id0) == UINT_MAX) 1500 out.print(", anonymous"); 1501 else 1502 out.print(", ", idName(id0, identifier(id0))); 1503 out.print(", ", modeAndType.operand(), "<", resolveModeName(modeAndType.mode()), "|", resolveTypeName(modeAndType.type()), ">, ", operand); 1504 dumpValueProfiling(out, it, hasPrintedProfiling); 1531 1505 break; 1532 1506 } … … 1539 1513 int operand = (++it)->u.operand; // Operand 1540 1514 printLocationAndOp(out, exec, location, it, "put_to_scope"); 1541 out.printf("%s, %s, %s, %u<%s|%s>, <structure>, %d", 1542 registerName(r0).data(), idName(id0, identifier(id0)).data(), registerName(r1).data(), 1543 modeAndType.operand(), resolveModeName(modeAndType.mode()), resolveTypeName(modeAndType.type()), 1544 operand); 1515 out.print(registerName(r0)); 1516 if (static_cast<unsigned>(id0) == UINT_MAX) 1517 out.print(", anonymous"); 1518 else 1519 out.print(", ", idName(id0, identifier(id0))); 1520 out.print(", ", registerName(r1), ", ", modeAndType.operand(), "<", resolveModeName(modeAndType.mode()), "|", resolveTypeName(modeAndType.type()), ">, <structure>, ", operand); 1521 break; 1522 } 1523 case op_get_from_arguments: { 1524 int r0 = (++it)->u.operand; 1525 int r1 = (++it)->u.operand; 1526 int offset = (++it)->u.operand; 1527 printLocationAndOp(out, exec, location, it, "get_from_arguments"); 1528 out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), offset); 1529 dumpValueProfiling(out, it, hasPrintedProfiling); 1530 break; 1531 } 1532 case op_put_to_arguments: { 1533 int r0 = (++it)->u.operand; 1534 int offset = (++it)->u.operand; 1535 int r1 = (++it)->u.operand; 1536 printLocationAndOp(out, exec, location, it, "put_to_arguments"); 1537 out.printf("%s, %d, %s", registerName(r0).data(), offset, registerName(r1).data()); 1545 1538 break; 1546 1539 } … … 1640 1633 , m_thisRegister(other.m_thisRegister) 1641 1634 , m_scopeRegister(other.m_scopeRegister) 1642 , m_argumentsRegister(other.m_argumentsRegister)1643 1635 , m_lexicalEnvironmentRegister(other.m_lexicalEnvironmentRegister) 1644 1636 , m_isStrictMode(other.m_isStrictMode) … … 1703 1695 , m_thisRegister(unlinkedCodeBlock->thisRegister()) 1704 1696 , m_scopeRegister(unlinkedCodeBlock->scopeRegister()) 1705 , m_argumentsRegister(unlinkedCodeBlock->argumentsRegister())1706 1697 , m_lexicalEnvironmentRegister(unlinkedCodeBlock->activationRegister()) 1707 1698 , m_isStrictMode(unlinkedCodeBlock->isStrictMode()) … … 1732 1723 } 1733 1724 1734 if (codeType() == FunctionCode && symbolTable-> captureCount()) {1735 m_symbolTable.set(*m_vm, m_ownerExecutable.get(), symbolTable->clone CapturedNames(*m_vm));1725 if (codeType() == FunctionCode && symbolTable->scopeSize()) { 1726 m_symbolTable.set(*m_vm, m_ownerExecutable.get(), symbolTable->cloneScopePart(*m_vm)); 1736 1727 didCloneSymbolTable = true; 1737 1728 } else … … 1850 1841 case op_call_varargs: 1851 1842 case op_construct_varargs: 1852 case op_get_by_val: 1853 case op_get_argument_by_val: { 1843 case op_get_by_val: { 1854 1844 int arrayProfileIndex = pc[opLength - 2].u.operand; 1855 1845 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i); … … 1859 1849 } 1860 1850 case op_get_direct_pname: 1861 case op_get_by_id: { 1851 case op_get_by_id: 1852 case op_get_from_arguments: { 1862 1853 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand]; 1863 1854 ASSERT(profile->m_bytecodeOffset == -1); … … 1929 1920 1930 1921 instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const); 1931 instructions[i + 1] = &m_globalObject-> registerAt(entry.getIndex());1922 instructions[i + 1] = &m_globalObject->variableAt(entry.varOffset().scopeOffset()); 1932 1923 break; 1933 1924 } … … 1954 1945 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand 1955 1946 1956 const Identifier& ident = identifier(pc[3].u.operand);1957 1947 ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand); 1958 1948 if (modeAndType.type() == LocalClosureVar) { … … 1960 1950 break; 1961 1951 } 1952 1953 const Identifier& ident = identifier(pc[3].u.operand); 1962 1954 1963 1955 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), needsActivation(), scope, ident, Get, modeAndType.type()); … … 1975 1967 case op_put_to_scope: { 1976 1968 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand 1977 const Identifier& ident = identifier(pc[2].u.operand);1978 1979 1969 ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand); 1980 1970 if (modeAndType.type() == LocalClosureVar) { 1981 bool isWatchableVariable = pc[5].u.operand; 1982 if (!isWatchableVariable) { 1983 instructions[i + 5].u.watchpointSet = nullptr; 1984 break; 1985 } 1986 StringImpl* uid = ident.impl(); 1987 RELEASE_ASSERT(didCloneSymbolTable); 1988 if (ident != m_vm->propertyNames->arguments) { 1971 // Only do watching if the property we're putting to is not anonymous. 1972 if (static_cast<unsigned>(pc[2].u.operand) != UINT_MAX) { 1973 RELEASE_ASSERT(didCloneSymbolTable); 1974 const Identifier& ident = identifier(pc[2].u.operand); 1975 StringImpl* uid = ident.impl(); 1989 1976 ConcurrentJITLocker locker(m_symbolTable->m_lock); 1990 1977 SymbolTable::Map::iterator iter = m_symbolTable->find(locker, uid); … … 1996 1983 break; 1997 1984 } 1985 1986 const Identifier& ident = identifier(pc[2].u.operand); 1998 1987 1999 1988 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), needsActivation(), scope, ident, Put, modeAndType.type()); … … 2065 2054 symbolTable = m_symbolTable.get(); 2066 2055 ConcurrentJITLocker locker(symbolTable->m_lock); 2067 globalVariableID = symbolTable->uniqueIDFor Register(locker, profileRegister.offset(), *vm());2068 globalTypeSet = symbolTable->globalTypeSetFor Register(locker, profileRegister.offset(), *vm());2056 globalVariableID = symbolTable->uniqueIDForOffset(locker, VarOffset(profileRegister), *vm()); 2057 globalTypeSet = symbolTable->globalTypeSetForOffset(locker, VarOffset(profileRegister), *vm()); 2069 2058 break; 2070 2059 } … … 2822 2811 #endif 2823 2812 2824 bool CodeBlock::isCaptured(VirtualRegister operand, InlineCallFrame* inlineCallFrame) const2825 {2826 if (operand.isArgument())2827 return operand.toArgument() && usesArguments();2828 2829 if (inlineCallFrame)2830 return inlineCallFrame->capturedVars.get(operand.toLocal());2831 2832 // The lexical environment object isn't in the captured region, but it's "captured"2833 // in the sense that stores to its location can be observed indirectly.2834 if (needsActivation() && operand == activationRegister())2835 return true;2836 2837 // Ditto for the arguments object.2838 if (usesArguments() && operand == argumentsRegister())2839 return true;2840 if (usesArguments() && operand == unmodifiedArgumentsRegister(argumentsRegister()))2841 return true;2842 2843 // We're in global code so there are no locals to capture2844 if (!symbolTable())2845 return false;2846 2847 return symbolTable()->isCaptured(operand.offset());2848 }2849 2850 int CodeBlock::framePointerOffsetToGetActivationRegisters(int machineCaptureStart)2851 {2852 // We'll be adding this to the stack pointer to get a registers pointer that looks2853 // like it would have looked in the baseline engine. For example, if bytecode would2854 // have put the first captured variable at offset -5 but we put it at offset -1, then2855 // we'll have an offset of 4.2856 int32_t offset = 0;2857 2858 // Compute where we put the captured variables. This offset will point the registers2859 // pointer directly at the first captured var.2860 offset += machineCaptureStart;2861 2862 // Now compute the offset needed to make the runtime see the captured variables at the2863 // same offset that the bytecode would have used.2864 offset -= symbolTable()->captureStart();2865 2866 return offset;2867 }2868 2869 int CodeBlock::framePointerOffsetToGetActivationRegisters()2870 {2871 if (!JITCode::isOptimizingJIT(jitType()))2872 return 0;2873 #if ENABLE(DFG_JIT)2874 return framePointerOffsetToGetActivationRegisters(jitCode()->dfgCommon()->machineCaptureStart);2875 #else2876 RELEASE_ASSERT_NOT_REACHED();2877 return 0;2878 #endif2879 }2880 2881 2813 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) 2882 2814 { … … 3061 2993 { 3062 2994 return ownerExecutable()->newReplacementCodeBlockFor(specializationKind()); 3063 }3064 3065 const SlowArgument* CodeBlock::machineSlowArguments()3066 {3067 if (!JITCode::isOptimizingJIT(jitType()))3068 return symbolTable()->slowArguments();3069 3070 #if ENABLE(DFG_JIT)3071 return jitCode()->dfgCommon()->slowArguments.get();3072 #else // ENABLE(DFG_JIT)3073 return 0;3074 #endif // ENABLE(DFG_JIT)3075 2995 } 3076 2996 … … 3857 3777 SymbolTable::Map::iterator end = symbolTable()->end(locker); 3858 3778 for (SymbolTable::Map::iterator ptr = symbolTable()->begin(locker); ptr != end; ++ptr) { 3859 if (ptr->value. getIndex() == virtualRegister.offset()) {3779 if (ptr->value.varOffset() == VarOffset(virtualRegister)) { 3860 3780 // FIXME: This won't work from the compilation thread. 3861 3781 // https://bugs.webkit.org/show_bug.cgi?id=115300 … … 3863 3783 } 3864 3784 } 3865 if (needsActivation() && virtualRegister == activationRegister())3866 return ASCIILiteral("lexical environment");3867 3785 if (virtualRegister == thisRegister()) 3868 3786 return ASCIILiteral("this"); 3869 if (usesArguments()) {3870 if (virtualRegister == argumentsRegister())3871 return ASCIILiteral("arguments");3872 if (unmodifiedArgumentsRegister(argumentsRegister()) == virtualRegister)3873 return ASCIILiteral("real arguments");3874 }3875 3787 if (virtualRegister.isArgument()) 3876 3788 return String::format("arguments[%3d]", virtualRegister.toArgument()); … … 3878 3790 return ""; 3879 3791 } 3880 3881 namespace {3882 3883 struct VerifyCapturedDef {3884 void operator()(CodeBlock* codeBlock, Instruction* instruction, OpcodeID opcodeID, int operand) const3885 {3886 unsigned bytecodeOffset = instruction - codeBlock->instructions().begin();3887 3888 if (codeBlock->isConstantRegisterIndex(operand)) {3889 codeBlock->beginValidationDidFail();3890 dataLog(" At bc#", bytecodeOffset, " encountered a definition of a constant.\n");3891 codeBlock->endValidationDidFail();3892 return;3893 }3894 3895 switch (opcodeID) {3896 case op_enter:3897 case op_init_lazy_reg:3898 case op_create_arguments:3899 return;3900 default:3901 break;3902 }3903 3904 VirtualRegister virtualReg(operand);3905 if (!virtualReg.isLocal())3906 return;3907 3908 if (codeBlock->usesArguments() && virtualReg == codeBlock->argumentsRegister())3909 return;3910 if (codeBlock->usesArguments() && virtualReg == unmodifiedArgumentsRegister(codeBlock->argumentsRegister()))3911 return;3912 3913 if (codeBlock->captureCount() && codeBlock->symbolTable()->isCaptured(operand)) {3914 codeBlock->beginValidationDidFail();3915 dataLog(" At bc#", bytecodeOffset, " encountered invalid assignment to captured variable ", virtualReg, ".\n");3916 codeBlock->endValidationDidFail();3917 return;3918 }3919 3920 return;3921 }3922 };3923 3924 } // anonymous namespace3925 3792 3926 3793 void CodeBlock::validate() … … 3939 3806 3940 3807 for (unsigned i = m_numCalleeRegisters; i--;) { 3941 bool isCaptured = false;3942 3808 VirtualRegister reg = virtualRegisterForLocal(i); 3943 3809 3944 if (captureCount()) 3945 isCaptured = reg.offset() <= captureStart() && reg.offset() > captureEnd(); 3946 3947 if (isCaptured) { 3948 if (!liveAtHead.get(i)) { 3949 beginValidationDidFail(); 3950 dataLog(" Variable loc", i, " is expected to be live because it is captured, but it isn't live.\n"); 3951 dataLog(" Result: ", liveAtHead, "\n"); 3952 endValidationDidFail(); 3953 } 3954 } else { 3955 if (liveAtHead.get(i)) { 3956 beginValidationDidFail(); 3957 dataLog(" Variable loc", i, " is expected to be dead.\n"); 3958 dataLog(" Result: ", liveAtHead, "\n"); 3959 endValidationDidFail(); 3960 } 3961 } 3962 } 3963 3964 for (unsigned bytecodeOffset = 0; bytecodeOffset < instructions().size();) { 3965 Instruction* currentInstruction = instructions().begin() + bytecodeOffset; 3966 OpcodeID opcodeID = m_vm->interpreter->getOpcodeID(currentInstruction->u.opcode); 3967 3968 VerifyCapturedDef verifyCapturedDef; 3969 computeDefsForBytecodeOffset(this, bytecodeOffset, verifyCapturedDef); 3970 3971 bytecodeOffset += opcodeLength(opcodeID); 3810 if (liveAtHead.get(i)) { 3811 beginValidationDidFail(); 3812 dataLog(" Variable ", reg, " is expected to be dead.\n"); 3813 dataLog(" Result: ", liveAtHead, "\n"); 3814 endValidationDidFail(); 3815 } 3972 3816 } 3973 3817 } -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r181481 r181993 84 84 class TypeLocation; 85 85 86 inline VirtualRegister unmodifiedArgumentsRegister(VirtualRegister argumentsRegister) { return VirtualRegister(argumentsRegister.offset() + 1); }87 88 86 enum ReoptimizationMode { DontCountReoptimization, CountReoptimization }; 89 87 … … 260 258 unsigned instructionCount() const { return m_instructions.size(); } 261 259 262 int argumentIndexAfterCapture(size_t argument);263 264 bool hasSlowArguments();265 const SlowArgument* machineSlowArguments();266 267 260 // Exactly equivalent to codeBlock->ownerExecutable()->installCode(codeBlock); 268 261 void install(); … … 328 321 } 329 322 330 void setArgumentsRegister(VirtualRegister argumentsRegister)331 {332 ASSERT(argumentsRegister.isValid());333 m_argumentsRegister = argumentsRegister;334 ASSERT(usesArguments());335 }336 VirtualRegister argumentsRegister() const337 {338 ASSERT(usesArguments());339 return m_argumentsRegister;340 }341 VirtualRegister uncheckedArgumentsRegister()342 {343 if (!usesArguments())344 return VirtualRegister();345 return argumentsRegister();346 }347 348 323 void setActivationRegister(VirtualRegister activationRegister) 349 324 { … … 362 337 } 363 338 364 bool usesArguments() const { return m_argumentsRegister.isValid(); }365 366 339 bool needsActivation() const 367 340 { … … 370 343 } 371 344 372 unsigned captureCount() const373 {374 if (!symbolTable())375 return 0;376 return symbolTable()->captureCount();377 }378 379 int captureStart() const380 {381 if (!symbolTable())382 return 0;383 return symbolTable()->captureStart();384 }385 386 int captureEnd() const387 {388 if (!symbolTable())389 return 0;390 return symbolTable()->captureEnd();391 }392 393 bool isCaptured(VirtualRegister operand, InlineCallFrame* = 0) const;394 395 int framePointerOffsetToGetActivationRegisters(int machineCaptureStart);396 int framePointerOffsetToGetActivationRegisters();397 398 345 CodeType codeType() const { return m_unlinkedCode->codeType(); } 399 346 PutPropertySlot::Context putByIdContext() const … … 1060 1007 VirtualRegister m_thisRegister; 1061 1008 VirtualRegister m_scopeRegister; 1062 VirtualRegister m_argumentsRegister;1063 1009 VirtualRegister m_lexicalEnvironmentRegister; 1064 1010 … … 1221 1167 } 1222 1168 1223 inline int CodeBlock::argumentIndexAfterCapture(size_t argument)1224 {1225 if (argument >= static_cast<size_t>(symbolTable()->parameterCount()))1226 return CallFrame::argumentOffset(argument);1227 1228 const SlowArgument* slowArguments = symbolTable()->slowArguments();1229 if (!slowArguments || slowArguments[argument].status == SlowArgument::Normal)1230 return CallFrame::argumentOffset(argument);1231 1232 ASSERT(slowArguments[argument].status == SlowArgument::Captured);1233 return slowArguments[argument].index;1234 }1235 1236 inline bool CodeBlock::hasSlowArguments()1237 {1238 return !!symbolTable()->slowArguments();1239 }1240 1241 1169 inline Register& ExecState::r(int index) 1242 1170 { … … 1261 1189 { 1262 1190 return uncheckedR(reg.offset()); 1263 }1264 1265 inline JSValue ExecState::argumentAfterCapture(size_t argument)1266 {1267 if (argument >= argumentCount())1268 return jsUndefined();1269 1270 if (!codeBlock())1271 return this[argumentOffset(argument)].jsValue();1272 1273 return this[codeBlock()->argumentIndexAfterCapture(argument)].jsValue();1274 1191 } 1275 1192 -
trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h
r180279 r181993 190 190 ValueRecovery calleeRecovery; 191 191 CodeOrigin caller; 192 BitVector capturedVars; // Indexed by the machine call frame's variable numbering.193 192 194 193 signed stackOffset : 28; 195 194 unsigned kind : 3; // real type is Kind 196 195 bool isClosureCall : 1; // If false then we know that callee/scope are constants and the DFG won't treat them as variables, i.e. they have to be recovered manually. 197 VirtualRegister argumentsRegister; // This is only set if the code uses arguments. The unmodified arguments register follows the unmodifiedArgumentsRegister() convention (see CodeBlock.h).198 196 VirtualRegister argumentCountRegister; // Only set when we inline a varargs call. 199 197 -
trunk/Source/JavaScriptCore/bytecode/DataFormat.h
r156047 r181993 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 57 57 // Special data formats used only for OSR. 58 58 DataFormatDead = 33, // Implies jsUndefined(). 59 DataFormatArguments = 34 // Implies that the arguments object must be reified.60 59 }; 61 60 … … 91 90 case DataFormatDead: 92 91 return "Dead"; 93 case DataFormatArguments:94 return "Arguments";95 92 default: 96 93 RELEASE_ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/bytecode/FullBytecodeLiveness.h
r159394 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 37 37 class FullBytecodeLiveness { 38 38 public: 39 FullBytecodeLiveness() : m_codeBlock(0) { } 40 41 // We say "out" to refer to the bitvector that contains raw results for a bytecode 42 // instruction. 43 const FastBitVector& getOut(unsigned bytecodeIndex) const 39 const FastBitVector& getLiveness(unsigned bytecodeIndex) const 44 40 { 45 41 BytecodeToBitmapMap::const_iterator iter = m_map.find(bytecodeIndex); … … 50 46 bool operandIsLive(int operand, unsigned bytecodeIndex) const 51 47 { 52 return operandIsAlwaysLive(m_codeBlock, operand) || operandThatIsNotAlwaysLiveIsLive(m_codeBlock, getOut(bytecodeIndex), operand); 53 } 54 55 FastBitVector getLiveness(unsigned bytecodeIndex) const 56 { 57 return getLivenessInfo(m_codeBlock, getOut(bytecodeIndex)); 48 return operandIsAlwaysLive(operand) || operandThatIsNotAlwaysLiveIsLive(getLiveness(bytecodeIndex), operand); 58 49 } 59 50 … … 61 52 friend class BytecodeLivenessAnalysis; 62 53 63 CodeBlock* m_codeBlock;64 54 BytecodeToBitmapMap m_map; 65 55 }; -
trunk/Source/JavaScriptCore/bytecode/Instruction.h
r176836 r181993 1 1 /* 2 * Copyright (C) 2008, 2012 , 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 98 98 Instruction(ArrayAllocationProfile* profile) { u.arrayAllocationProfile = profile; } 99 99 Instruction(ObjectAllocationProfile* profile) { u.objectAllocationProfile = profile; } 100 Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; }100 Instruction(WriteBarrier<Unknown>* variablePointer) { u.variablePointer = variablePointer; } 101 101 Instruction(Special::Pointer pointer) { u.specialPointer = pointer; } 102 102 Instruction(StringImpl* uid) { u.uid = uid; } … … 109 109 WriteBarrierBase<StructureChain> structureChain; 110 110 WriteBarrierBase<JSCell> jsCell; 111 WriteBarrier<Unknown>* registerPointer;111 WriteBarrier<Unknown>* variablePointer; 112 112 Special::Pointer specialPointer; 113 113 PropertySlot::GetValueFunc getterFunc; -
trunk/Source/JavaScriptCore/bytecode/Operands.h
r174318 r181993 210 210 return virtualRegisterForLocal(index - numberOfArguments()).offset(); 211 211 } 212 VirtualRegister virtualRegisterForIndex(size_t index) const 213 { 214 return VirtualRegister(operandForIndex(index)); 215 } 212 216 size_t indexForOperand(int operand) const 213 217 { -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
r180098 r181993 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013Apple Inc. All rights reserved.2 * Copyright (C) 2011-2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 #include "SpeculatedType.h" 31 31 32 #include " Arguments.h"32 #include "DirectArguments.h" 33 33 #include "JSArray.h" 34 34 #include "JSFunction.h" 35 35 #include "JSCInlines.h" 36 #include "ScopedArguments.h" 36 37 #include "StringObject.h" 37 38 #include "ValueProfile.h" … … 128 129 isTop = false; 129 130 130 if (value & SpecArguments) 131 myOut.print("Arguments"); 131 if (value & SpecDirectArguments) 132 myOut.print("Directarguments"); 133 else 134 isTop = false; 135 136 if (value & SpecScopedArguments) 137 myOut.print("Scopedarguments"); 132 138 else 133 139 isTop = false; … … 233 239 if (isFloat64ArraySpeculation(prediction)) 234 240 return "<Float64array>"; 235 if (isArgumentsSpeculation(prediction)) 236 return "<Arguments>"; 241 if (isDirectArgumentsSpeculation(prediction)) 242 return "<DirectArguments>"; 243 if (isScopedArgumentsSpeculation(prediction)) 244 return "<ScopedArguments>"; 237 245 if (isStringObjectSpeculation(prediction)) 238 246 return "<StringObject>"; … … 306 314 return SpecArray; 307 315 308 if (classInfo == Arguments::info()) 309 return SpecArguments; 316 if (classInfo == DirectArguments::info()) 317 return SpecDirectArguments; 318 319 if (classInfo == ScopedArguments::info()) 320 return SpecScopedArguments; 310 321 311 322 if (classInfo == StringObject::info()) -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h
r180098 r181993 1 1 /* 2 * Copyright (C) 2011-201 4Apple Inc. All rights reserved.2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 53 53 static const SpeculatedType SpecFloat64Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses. 54 54 static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array; 55 static const SpeculatedType SpecArguments = 0x00001000; // It's definitely an Arguments object. 56 static const SpeculatedType SpecStringObject = 0x00002000; // It's definitely a StringObject. 55 static const SpeculatedType SpecDirectArguments = 0x00001000; // It's definitely a DirectArguments object. 56 static const SpeculatedType SpecScopedArguments = 0x00002000; // It's definitely a ScopedArguments object. 57 static const SpeculatedType SpecStringObject = 0x00004000; // It's definitely a StringObject. 57 58 static const SpeculatedType SpecObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. 58 59 static const SpeculatedType SpecObject = 0x0000ffff; // Bitmask used for testing for any kind of object prediction. … … 194 195 } 195 196 196 inline bool isArgumentsSpeculation(SpeculatedType value) 197 { 198 return !!value && (value & SpecArguments) == value; 197 inline bool isDirectArgumentsSpeculation(SpeculatedType value) 198 { 199 return value == SpecDirectArguments; 200 } 201 202 inline bool isScopedArgumentsSpeculation(SpeculatedType value) 203 { 204 return value == SpecScopedArguments; 199 205 } 200 206 … … 225 231 { 226 232 return isArraySpeculation(value) 227 || isArgumentsSpeculation(value)228 233 || isActionableTypedMutableArraySpeculation(value); 229 234 } … … 232 237 { 233 238 return isStringSpeculation(value) 239 || isDirectArgumentsSpeculation(value) 240 || isScopedArgumentsSpeculation(value) 234 241 || isActionableMutableArraySpeculation(value); 235 242 } -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
r181901 r181993 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.2 * Copyright (C) 2012, 2013, 2015 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 210 210 , m_numParameters(0) 211 211 , m_vm(vm) 212 , m_argumentsRegister(VirtualRegister())213 212 , m_globalObjectRegister(VirtualRegister()) 214 213 , m_needsFullScopeChain(info.needsActivation()) -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
r181901 r181993 1 1 /* 2 * Copyright (C) 2012 , 2013, 2014Apple Inc. All Rights Reserved.2 * Copyright (C) 2012-2015 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 288 288 void setActivationRegister(VirtualRegister activationRegister) { m_lexicalEnvironmentRegister = activationRegister; } 289 289 290 void setArgumentsRegister(VirtualRegister argumentsRegister) { m_argumentsRegister = argumentsRegister; }291 bool usesArguments() const { return m_argumentsRegister.isValid(); }292 VirtualRegister argumentsRegister() const { return m_argumentsRegister; }293 294 295 290 bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); } 296 291 void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; } … … 532 527 533 528 VirtualRegister m_thisRegister; 534 VirtualRegister m_argumentsRegister;535 529 VirtualRegister m_scopeRegister; 536 530 VirtualRegister m_lexicalEnvironmentRegister; -
trunk/Source/JavaScriptCore/bytecode/ValueRecovery.cpp
r180279 r181993 113 113 out.print("*bool(", virtualRegister(), ")"); 114 114 return; 115 case ArgumentsThatWereNotCreated: 116 out.printf("arguments"); 115 case DirectArgumentsThatWereNotCreated: 116 out.print("DirectArguments(", nodeID(), ")"); 117 return; 118 case ClonedArgumentsThatWereNotCreated: 119 out.print("ClonedArguments(", nodeID(), ")"); 117 120 return; 118 121 case Constant: -
trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h
r164424 r181993 1 1 /* 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #define ValueRecovery_h 28 28 29 #include "DFGMinifiedID.h" 29 30 #include "DataFormat.h" 30 31 #if ENABLE(JIT) … … 39 40 40 41 struct DumpContext; 42 struct InlineCallFrame; 41 43 42 44 // Describes how to recover a given bytecode virtual register at a given … … 63 65 CellDisplacedInJSStack, 64 66 BooleanDisplacedInJSStack, 65 // It's an Arguments object. 66 ArgumentsThatWereNotCreated, 67 // It's an Arguments object. This arises because of the simplified arguments simplification done by the DFG. 68 DirectArgumentsThatWereNotCreated, 69 ClonedArgumentsThatWereNotCreated, 67 70 // It's a constant. 68 71 Constant, … … 168 171 } 169 172 170 static ValueRecovery argumentsThatWereNotCreated() 171 { 172 ValueRecovery result; 173 result.m_technique = ArgumentsThatWereNotCreated; 173 static ValueRecovery directArgumentsThatWereNotCreated(DFG::MinifiedID id) 174 { 175 ValueRecovery result; 176 result.m_technique = DirectArgumentsThatWereNotCreated; 177 result.m_source.nodeID = id.bits(); 178 return result; 179 } 180 181 static ValueRecovery outOfBandArgumentsThatWereNotCreated(DFG::MinifiedID id) 182 { 183 ValueRecovery result; 184 result.m_technique = ClonedArgumentsThatWereNotCreated; 185 result.m_source.nodeID = id.bits(); 174 186 return result; 175 187 } … … 257 269 } 258 270 271 DFG::MinifiedID nodeID() const 272 { 273 ASSERT(m_technique == DirectArgumentsThatWereNotCreated || m_technique == ClonedArgumentsThatWereNotCreated); 274 return DFG::MinifiedID::fromBits(m_source.nodeID); 275 } 276 259 277 JSValue recover(ExecState*) const; 260 278 … … 277 295 int virtualReg; 278 296 EncodedJSValue constant; 297 uintptr_t nodeID; 279 298 } m_source; 280 299 }; -
trunk/Source/JavaScriptCore/bytecode/VirtualRegister.h
r179862 r181993 68 68 int offsetInBytes() const { return m_virtualRegister * sizeof(Register); } 69 69 70 bool operator==(const VirtualRegister other) const { return m_virtualRegister == other.m_virtualRegister; } 71 bool operator!=(const VirtualRegister other) const { return m_virtualRegister != other.m_virtualRegister; } 70 bool operator==(VirtualRegister other) const { return m_virtualRegister == other.m_virtualRegister; } 71 bool operator!=(VirtualRegister other) const { return m_virtualRegister != other.m_virtualRegister; } 72 bool operator<(VirtualRegister other) const { return m_virtualRegister < other.m_virtualRegister; } 73 bool operator>(VirtualRegister other) const { return m_virtualRegister > other.m_virtualRegister; } 74 bool operator<=(VirtualRegister other) const { return m_virtualRegister <= other.m_virtualRegister; } 75 bool operator>=(VirtualRegister other) const { return m_virtualRegister >= other.m_virtualRegister; } 72 76 73 77 VirtualRegister operator+(int value) const -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r181924 r181993 65 65 66 66 m_codeBlock->setThisRegister(m_thisRegister.virtualRegister()); 67 68 // If we have declared a variable named "arguments" and we are using arguments then we should 69 // perform that assignment now. 70 if (m_needToInitializeArguments) 71 initializeVariable(variable(propertyNames().arguments), m_argumentsRegister); 72 73 { 74 RefPtr<RegisterID> temp = newTemporary(); 75 for (FunctionBodyNode* functionBody : m_functionsToInitialize) { 76 emitNewFunction(temp.get(), functionBody); 77 initializeVariable(variable(functionBody->ident()), temp.get()); 78 } 79 } 80 67 81 for (size_t i = 0; i < m_deconstructedParameters.size(); i++) { 68 82 auto& entry = m_deconstructedParameters[i]; … … 120 134 121 135 if (m_codeBlock->symbolTable() && !m_codeBlock->vm()->typeProfiler()) 122 m_codeBlock->setSymbolTable(m_codeBlock->symbolTable()->clone CapturedNames(*m_codeBlock->vm()));136 m_codeBlock->setSymbolTable(m_codeBlock->symbolTable()->cloneScopePart(*m_codeBlock->vm())); 123 137 124 138 if (m_expressionTooDeep) 125 139 return ParserError(ParserError::OutOfMemory); 126 140 return ParserError(ParserError::ErrorNone); 127 }128 129 RegisterID* BytecodeGenerator::addVar(130 const Identifier& ident, ConstantMode constantMode, WatchMode watchMode)131 {132 ASSERT(static_cast<size_t>(m_codeBlock->m_numVars) == m_calleeRegisters.size());133 134 ConcurrentJITLocker locker(symbolTable().m_lock);135 int index = virtualRegisterForLocal(m_calleeRegisters.size()).offset();136 SymbolTableEntry newEntry(index, constantMode == IsConstant ? ReadOnly : 0);137 SymbolTable::Map::AddResult result = symbolTable().add(locker, ident.impl(), newEntry);138 139 if (!result.isNewEntry)140 return ®isterFor(result.iterator->value.getIndex());141 142 if (watchMode == IsWatchable) {143 while (m_watchableVariables.size() < static_cast<size_t>(m_codeBlock->m_numVars))144 m_watchableVariables.append(Identifier());145 m_watchableVariables.append(ident);146 }147 148 RegisterID* regID = addVar();149 ASSERT(watchMode == NotWatchable || static_cast<size_t>(m_codeBlock->m_numVars) == m_watchableVariables.size());150 151 return regID;152 141 } 153 142 … … 193 182 if (m_isBuiltinFunction) 194 183 m_shouldEmitDebugHooks = false; 195 184 196 185 m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode()); 197 186 Vector<Identifier> boundParameterProperties; … … 204 193 continue; 205 194 } 206 m_symbolTable->setParameterCountIncludingThis(functionNode->parameters()->size() + 1); 195 196 bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || m_codeBlock->needsFullScopeChain(); 197 bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval(); 198 bool needsArguments = functionNode->usesArguments() || codeBlock->usesEval(); 199 200 auto captures = [&] (StringImpl* uid) -> bool { 201 if (shouldCaptureAllOfTheThings) 202 return true; 203 if (!shouldCaptureSomeOfTheThings) 204 return false; 205 if (needsArguments && uid == propertyNames().arguments.impl()) { 206 // Actually, we only need to capture the arguments object when we "need full activation" 207 // because of name scopes. But historically we did it this way, so for now we just preserve 208 // the old behavior. 209 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=143072 210 return true; 211 } 212 return functionNode->captures(uid); 213 }; 214 auto varKind = [&] (StringImpl* uid) -> VarKind { 215 return captures(uid) ? VarKind::Scope : VarKind::Stack; 216 }; 207 217 208 218 emitOpcode(op_enter); 209 219 210 220 allocateAndEmitScope(); 221 222 m_calleeRegister.setIndex(JSStack::Callee); 211 223 212 224 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode()) … … 218 230 // be any more correct, but it would be more performant. 219 231 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141887 220 RegisterID calleeRegister; 221 calleeRegister.setIndex(JSStack::Callee); 222 emitPushFunctionNameScope(m_scopeRegister, functionNode->ident(), &calleeRegister, ReadOnly | DontDelete); 223 } 224 225 if (m_codeBlock->needsFullScopeChain() || m_shouldEmitDebugHooks) { 232 emitPushFunctionNameScope(m_scopeRegister, functionNode->ident(), &m_calleeRegister, ReadOnly | DontDelete); 233 } 234 235 if (shouldCaptureSomeOfTheThings) { 226 236 m_lexicalEnvironmentRegister = addVar(); 227 237 m_codeBlock->setActivationRegister(m_lexicalEnvironmentRegister->virtualRegister()); … … 229 239 instructions().append(m_lexicalEnvironmentRegister->index()); 230 240 instructions().append(scopeRegister()->index()); 231 } 232 RegisterID* localArgumentsRegister = nullptr; 233 RegisterID* scratch = addVar(); 234 m_symbolTable->setCaptureStart(virtualRegisterForLocal(m_codeBlock->m_numVars).offset()); 235 236 if (functionNode->usesArguments() || codeBlock->usesEval()) { // May reify arguments object. 237 RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. 238 RegisterID* argumentsRegister = addVar(propertyNames().arguments, IsVariable, NotWatchable); // Can be changed by assigning to 'arguments'. 239 240 localArgumentsRegister = argumentsRegister; 241 242 // We can save a little space by hard-coding the knowledge that the two 243 // 'arguments' values are stored in consecutive registers, and storing 244 // only the index of the assignable one. 245 codeBlock->setArgumentsRegister(argumentsRegister->virtualRegister()); 246 ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->virtualRegister() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister())); 247 248 emitInitLazyRegister(argumentsRegister); 249 emitInitLazyRegister(unmodifiedArgumentsRegister); 250 251 if (shouldCreateArgumentsEagerly() || shouldTearOffArgumentsEagerly()) { 252 emitOpcode(op_create_arguments); 253 instructions().append(argumentsRegister->index()); 254 instructions().append(m_codeBlock->activationRegister().offset()); 255 256 if (m_codeBlock->hasActivationRegister()) { 257 RegisterID* argumentsRegister = ®isterFor(m_codeBlock->argumentsRegister().offset()); 258 initializeCapturedVariable(argumentsRegister, propertyNames().arguments, argumentsRegister); 259 RegisterID* uncheckedArgumentsRegister = ®isterFor(JSC::unmodifiedArgumentsRegister(m_codeBlock->argumentsRegister()).offset()); 260 initializeCapturedVariable(uncheckedArgumentsRegister, propertyNames().arguments, uncheckedArgumentsRegister); 261 if (functionNode->modifiesArguments()) { 262 emitOpcode(op_mov); 263 instructions().append(argumentsRegister->index()); 264 instructions().append(addConstantValue(jsUndefined())->index()); 265 emitOpcode(op_mov); 266 instructions().append(uncheckedArgumentsRegister->index()); 267 instructions().append(addConstantValue(jsUndefined())->index()); 268 localArgumentsRegister = nullptr; 269 } 270 } 271 } 272 } 273 274 bool shouldCaptureAllTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval(); 275 241 emitOpcode(op_mov); 242 instructions().append(scopeRegister()->index()); 243 instructions().append(m_lexicalEnvironmentRegister->index()); 244 } 245 246 // Make sure the code block knows about all of our parameters, and make sure that parameters 247 // needing deconstruction are noted. 248 m_parameters.grow(parameters.size() + 1); // reserve space for "this" 249 m_thisRegister.setIndex(initializeNextParameter()->index()); // this 250 for (unsigned i = 0; i < parameters.size(); ++i) { 251 auto pattern = parameters.at(i); 252 RegisterID* reg = initializeNextParameter(); 253 if (!pattern->isBindingNode()) 254 m_deconstructedParameters.append(std::make_pair(reg, pattern)); 255 } 256 257 // Figure out some interesting facts about our arguments. 276 258 bool capturesAnyArgumentByName = false; 277 Vector<RegisterID*, 0, UnsafeVectorOverflow> capturedArguments; 278 if (functionNode->hasCapturedVariables() || shouldCaptureAllTheThings) { 259 if (functionNode->hasCapturedVariables()) { 279 260 FunctionParameters& parameters = *functionNode->parameters(); 280 capturedArguments.resize(parameters.size());281 261 for (size_t i = 0; i < parameters.size(); ++i) { 282 capturedArguments[i] = 0;283 262 auto pattern = parameters.at(i); 284 263 if (!pattern->isBindingNode()) 285 264 continue; 286 265 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty(); 287 if (!functionNode->captures(ident) && !shouldCaptureAllTheThings) 266 capturesAnyArgumentByName |= captures(ident.impl()); 267 } 268 } 269 270 if (capturesAnyArgumentByName) 271 ASSERT(m_lexicalEnvironmentRegister); 272 273 // Need to know what our functions are called. Parameters have some goofy behaviors when it 274 // comes to functions of the same name. 275 for (FunctionBodyNode* function : functionNode->functionStack()) 276 m_functions.add(function->ident().impl()); 277 278 if (needsArguments) { 279 // Create the arguments object now. We may put the arguments object into the activation if 280 // it is captured. Either way, we create two arguments object variables: one is our 281 // private variable that is immutable, and another that is the user-visible variable. The 282 // immutable one is only used here, or during formal parameter resolutions if we opt for 283 // DirectArguments. 284 285 m_argumentsRegister = addVar(); 286 m_argumentsRegister->ref(); 287 } 288 289 if (needsArguments && !codeBlock->isStrictMode()) { 290 // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we 291 // use DirectArguments. With ScopedArguments, we lift all of our arguments into the 292 // activation. 293 294 if (capturesAnyArgumentByName) { 295 m_symbolTable->setArgumentsLength(vm, parameters.size()); 296 297 // For each parameter, we have two possibilities: 298 // Either it's a binding node with no function overlap, in which case it gets a name 299 // in the symbol table - or it just gets space reserved in the symbol table. Either 300 // way we lift the value into the scope. 301 for (unsigned i = 0; i < parameters.size(); ++i) { 302 ScopeOffset offset = m_symbolTable->takeNextScopeOffset(); 303 m_symbolTable->setArgumentOffset(vm, i, offset); 304 if (StringImpl* name = visibleNameForParameter(parameters.at(i))) { 305 VarOffset varOffset(offset); 306 SymbolTableEntry entry(varOffset); 307 // Stores to these variables via the ScopedArguments object will not do 308 // notifyWrite(), since that would be cumbersome. Also, watching formal 309 // parameters when "arguments" is in play is unlikely to be super profitable. 310 // So, we just disable it. 311 entry.disableWatching(); 312 m_symbolTable->set(name, entry); 313 } 314 emitOpcode(op_put_to_scope); 315 instructions().append(m_lexicalEnvironmentRegister->index()); 316 instructions().append(UINT_MAX); 317 instructions().append(virtualRegisterForArgument(1 + i).offset()); 318 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand()); 319 instructions().append(0); 320 instructions().append(offset.offset()); 321 } 322 323 // This creates a scoped arguments object and copies the overflow arguments into the 324 // scope. It's the equivalent of calling ScopedArguments::createByCopying(). 325 emitOpcode(op_create_scoped_arguments); 326 instructions().append(m_argumentsRegister->index()); 327 instructions().append(m_lexicalEnvironmentRegister->index()); 328 } else { 329 // We're going to put all parameters into the DirectArguments object. First ensure 330 // that the symbol table knows that this is happening. 331 for (unsigned i = 0; i < parameters.size(); ++i) { 332 if (StringImpl* name = visibleNameForParameter(parameters.at(i))) 333 m_symbolTable->set(name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i)))); 334 } 335 336 emitOpcode(op_create_direct_arguments); 337 instructions().append(m_argumentsRegister->index()); 338 } 339 } else { 340 // Create the formal parameters the normal way. Any of them could be captured, or not. If 341 // captured, lift them into the scope. 342 for (unsigned i = 0; i < parameters.size(); ++i) { 343 StringImpl* name = visibleNameForParameter(parameters.at(i)); 344 if (!name) 288 345 continue; 289 capturesAnyArgumentByName = true; 290 capturedArguments[i] = addVar(ident, IsVariable, IsWatchable); 291 } 292 } 293 294 if (capturesAnyArgumentByName && !shouldTearOffArgumentsEagerly()) { 295 size_t parameterCount = m_symbolTable->parameterCount(); 296 auto slowArguments = std::make_unique<SlowArgument[]>(parameterCount); 297 for (size_t i = 0; i < parameterCount; ++i) { 298 if (!capturedArguments[i]) { 299 ASSERT(slowArguments[i].status == SlowArgument::Normal); 300 slowArguments[i].index = CallFrame::argumentOffset(i); 346 347 if (!captures(name)) { 348 // This is the easy case - just tell the symbol table about the argument. It will 349 // be accessed directly. 350 m_symbolTable->set(name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i)))); 301 351 continue; 302 352 } 303 slowArguments[i].status = SlowArgument::Captured; 304 slowArguments[i].index = capturedArguments[i]->index(); 305 } 306 m_symbolTable->setSlowArguments(WTF::move(slowArguments)); 307 } 308 309 RegisterID* calleeRegister = resolveCallee(functionNode); // May push to the scope chain and/or add a captured var. 310 311 const DeclarationStacks::FunctionStack& functionStack = functionNode->functionStack(); 312 const DeclarationStacks::VarStack& varStack = functionNode->varStack(); 313 IdentifierSet test; 314 315 // Captured variables and functions go first so that activations don't have 316 // to step over the non-captured locals to mark them. 317 if (functionNode->hasCapturedVariables() || shouldCaptureAllTheThings) { 318 for (size_t i = 0; i < boundParameterProperties.size(); i++) { 319 const Identifier& ident = boundParameterProperties[i]; 320 if (functionNode->captures(ident) || shouldCaptureAllTheThings) 321 addVar(ident, IsVariable, IsWatchable); 322 } 323 for (size_t i = 0; i < functionStack.size(); ++i) { 324 FunctionBodyNode* function = functionStack[i]; 325 const Identifier& ident = function->ident(); 326 if (functionNode->captures(ident) || shouldCaptureAllTheThings) { 327 m_functions.add(ident.impl()); 328 emitNewFunction(scratch, function); 329 initializeCapturedVariable(addVar(ident, IsVariable, IsWatchable), ident, scratch); 353 354 ScopeOffset offset = m_symbolTable->takeNextScopeOffset(); 355 const Identifier& ident = 356 static_cast<const BindingNode*>(parameters.at(i))->boundProperty(); 357 m_symbolTable->set(name, SymbolTableEntry(VarOffset(offset))); 358 359 emitOpcode(op_put_to_scope); 360 instructions().append(m_lexicalEnvironmentRegister->index()); 361 instructions().append(addConstant(ident)); 362 instructions().append(virtualRegisterForArgument(1 + i).offset()); 363 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand()); 364 instructions().append(0); 365 instructions().append(offset.offset()); 366 } 367 } 368 369 if (needsArguments && codeBlock->isStrictMode()) { 370 // Allocate an out-of-bands arguments object. 371 emitOpcode(op_create_out_of_band_arguments); 372 instructions().append(m_argumentsRegister->index()); 373 } 374 375 // Now declare all variables. 376 for (const Identifier& ident : boundParameterProperties) 377 createVariable(ident, varKind(ident.impl()), IsVariable); 378 for (FunctionBodyNode* function : functionNode->functionStack()) { 379 const Identifier& ident = function->ident(); 380 createVariable(ident, varKind(ident.impl()), IsVariable); 381 m_functionsToInitialize.append(function); 382 } 383 for (auto& entry : functionNode->varStack()) { 384 ConstantMode constantMode = modeForIsConstant(entry.second & DeclarationStacks::IsConstant); 385 // Variables named "arguments" are never const. 386 if (entry.first == propertyNames().arguments) 387 constantMode = IsVariable; 388 createVariable(entry.first, varKind(entry.first.impl()), constantMode, IgnoreExisting); 389 } 390 391 // There are some variables that need to be preinitialized to something other than Undefined: 392 // 393 // - "arguments": unless it's used as a function or parameter, this should refer to the 394 // arguments object. 395 // 396 // - callee: unless it's used as a var, function, or parameter, this should refer to the 397 // callee (i.e. our function). 398 // 399 // - functions: these always override everything else. 400 // 401 // The most logical way to do all of this is to initialize none of the variables until now, 402 // and then initialize them in BytecodeGenerator::generate() in such an order that the rules 403 // for how these things override each other end up holding. We would initialize the callee 404 // first, then "arguments", then all arguments, then the functions. 405 // 406 // But some arguments are already initialized by default, since if they aren't captured and we 407 // don't have "arguments" then we just point the symbol table at the stack slot of those 408 // arguments. We end up initializing the rest of the arguments that have an uncomplicated 409 // binding (i.e. don't involve deconstruction) above when figuring out how to lay them out, 410 // because that's just the simplest thing. This means that when we initialize them, we have to 411 // watch out for the things that override arguments (namely, functions). 412 // 413 // We also initialize callee here as well, just because it's so weird. We know whether we want 414 // to do this because we can just check if it's in the symbol table. 415 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode()) 416 && !functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode()) 417 && m_symbolTable->get(functionNode->ident().impl()).isNull()) { 418 if (captures(functionNode->ident().impl())) { 419 ScopeOffset offset; 420 { 421 ConcurrentJITLocker locker(m_symbolTable->m_lock); 422 offset = m_symbolTable->takeNextScopeOffset(locker); 423 m_symbolTable->add( 424 locker, functionNode->ident().impl(), 425 SymbolTableEntry(VarOffset(offset), ReadOnly)); 330 426 } 331 } 332 for (size_t i = 0; i < varStack.size(); ++i) { 333 const Identifier& ident = varStack[i].first; 334 if (functionNode->captures(ident) || shouldCaptureAllTheThings) 335 addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, IsWatchable); 336 } 337 } 338 339 m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset()); 340 341 bool canLazilyCreateFunctions = !functionNode->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks && !m_vm->typeProfiler() && !m_vm->controlFlowProfiler(); 342 m_firstLazyFunction = codeBlock->m_numVars; 343 if (!shouldCaptureAllTheThings) { 344 for (size_t i = 0; i < functionStack.size(); ++i) { 345 FunctionBodyNode* function = functionStack[i]; 346 const Identifier& ident = function->ident(); 347 if (!functionNode->captures(ident)) { 348 m_functions.add(ident.impl()); 349 RefPtr<RegisterID> reg = addVar(ident, IsVariable, NotWatchable); 350 // Don't lazily create functions that override the name 'arguments' 351 // as this would complicate lazy instantiation of actual arguments. 352 if (!canLazilyCreateFunctions || ident == propertyNames().arguments) 353 emitNewFunction(reg.get(), function); 354 else { 355 emitInitLazyRegister(reg.get()); 356 m_lazyFunctions.set(reg->virtualRegister().toLocal(), function); 357 } 427 428 emitOpcode(op_put_to_scope); 429 instructions().append(m_lexicalEnvironmentRegister->index()); 430 instructions().append(addConstant(functionNode->ident())); 431 instructions().append(m_calleeRegister.index()); 432 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand()); 433 instructions().append(0); 434 instructions().append(offset.offset()); 435 } else { 436 m_symbolTable->add( 437 functionNode->ident().impl(), 438 SymbolTableEntry(VarOffset(m_calleeRegister.virtualRegister()), ReadOnly)); 439 } 440 } 441 442 // This is our final act of weirdness. "arguments" is overridden by everything except the 443 // callee. We add it to the symbol table if it's not already there and it's not an argument. 444 if (needsArguments) { 445 // If "arguments" is overridden by a function or deconstructed parameter name, then it's 446 // OK for us to call createVariable() because it won't change anything. It's also OK for 447 // us to them tell BytecodeGenerator::generate() to write to it because it will do so 448 // before it initializes functions and deconstructed parameters. But if "arguments" is 449 // overridden by a "simple" function parameter, then we have to bail: createVariable() 450 // would assert and BytecodeGenerator::generate() would write the "arguments" after the 451 // argument value had already been properly initialized. 452 453 bool haveParameterNamedArguments = false; 454 for (unsigned i = 0; i < parameters.size(); ++i) { 455 StringImpl* name = visibleNameForParameter(parameters.at(i)); 456 if (name == propertyNames().arguments.impl()) { 457 haveParameterNamedArguments = true; 458 break; 358 459 } 359 460 } 360 m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction; 361 for (size_t i = 0; i < boundParameterProperties.size(); i++) { 362 const Identifier& ident = boundParameterProperties[i]; 363 if (!functionNode->captures(ident)) 364 addVar(ident, IsVariable, IsWatchable); 365 } 366 for (size_t i = 0; i < varStack.size(); ++i) { 367 const Identifier& ident = varStack[i].first; 368 if (!functionNode->captures(ident)) 369 addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, NotWatchable); 370 } 371 } 372 373 if (m_symbolTable->captureCount()) 461 462 if (!haveParameterNamedArguments) { 463 createVariable( 464 propertyNames().arguments, varKind(propertyNames().arguments.impl()), IsVariable); 465 m_needToInitializeArguments = true; 466 } 467 } 468 469 if (m_symbolTable->scopeSize()) 374 470 emitOpcode(op_touch_entry); 375 376 m_parameters.grow(parameters.size() + 1); // reserve space for "this"377 378 // Add "this" as a parameter379 int nextParameterIndex = CallFrame::thisArgumentOffset();380 m_thisRegister.setIndex(nextParameterIndex++);381 m_codeBlock->addParameter();382 383 for (size_t i = 0; i < parameters.size(); ++i, ++nextParameterIndex) {384 int index = nextParameterIndex;385 auto pattern = parameters.at(i);386 if (!pattern->isBindingNode()) {387 m_codeBlock->addParameter();388 RegisterID& parameter = registerFor(index);389 parameter.setIndex(index);390 m_deconstructedParameters.append(std::make_pair(¶meter, pattern));391 continue;392 }393 auto simpleParameter = static_cast<const BindingNode*>(pattern);394 if (capturedArguments.size() && capturedArguments[i] && !m_functions.contains(simpleParameter->boundProperty().impl())) {395 ASSERT((functionNode->hasCapturedVariables() && functionNode->captures(simpleParameter->boundProperty())) || shouldCaptureAllTheThings);396 index = capturedArguments[i]->index();397 RegisterID original(nextParameterIndex);398 initializeCapturedVariable(capturedArguments[i], simpleParameter->boundProperty(), &original);399 }400 addParameter(simpleParameter->boundProperty(), index);401 }402 403 // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration.404 addCallee(functionNode, calleeRegister);405 471 406 472 if (isConstructor()) { … … 420 486 instructions().append(0); 421 487 } 422 m_localArgumentsRegister = localArgumentsRegister;423 488 } 424 489 … … 459 524 } 460 525 461 RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg) 462 { 463 emitOpcode(op_init_lazy_reg); 464 instructions().append(reg->index()); 465 ASSERT(!hasWatchableVariable(reg->index())); 466 return reg; 467 } 468 469 RegisterID* BytecodeGenerator::initializeCapturedVariable(RegisterID* dst, const Identifier& propertyName, RegisterID* value) 470 { 471 472 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 473 emitOpcode(op_put_to_scope); 474 instructions().append(m_lexicalEnvironmentRegister->index()); 475 instructions().append(addConstant(propertyName)); 476 instructions().append(value->index()); 477 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand()); 478 int operand = registerFor(dst->index()).index(); 479 bool isWatchableVariable = hasWatchableVariable(operand); 480 ASSERT(!isWatchableVariable || watchableVariableIdentifier(operand) == propertyName); 481 instructions().append(isWatchableVariable); 482 instructions().append(dst->index()); 483 return dst; 484 } 485 486 RegisterID* BytecodeGenerator::resolveCallee(FunctionNode* functionNode) 487 { 488 if (!functionNameIsInScope(functionNode->ident(), functionNode->functionMode())) 489 return 0; 490 491 if (functionNameScopeIsDynamic(m_codeBlock->usesEval(), m_codeBlock->isStrictMode())) 492 return 0; 493 494 m_calleeRegister.setIndex(JSStack::Callee); 495 if (functionNode->captures(functionNode->ident())) 496 return initializeCapturedVariable(addVar(), functionNode->ident(), &m_calleeRegister); 497 498 return &m_calleeRegister; 499 } 500 501 void BytecodeGenerator::addCallee(FunctionNode* functionNode, RegisterID* calleeRegister) 502 { 503 if (!calleeRegister) 504 return; 505 506 symbolTable().add(functionNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly)); 507 } 508 509 void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex) 510 { 511 // Parameters overwrite var declarations, but not function declarations. 512 StringImpl* rep = ident.impl(); 513 if (!m_functions.contains(rep)) { 514 symbolTable().set(rep, parameterIndex); 515 RegisterID& parameter = registerFor(parameterIndex); 516 parameter.setIndex(parameterIndex); 517 } 518 519 // To maintain the calling convention, we have to allocate unique space for 520 // each parameter, even if the parameter doesn't make it into the symbol table. 526 RegisterID* BytecodeGenerator::initializeNextParameter() 527 { 528 VirtualRegister reg = virtualRegisterForArgument(m_codeBlock->numParameters()); 529 RegisterID& parameter = registerFor(reg); 530 parameter.setIndex(reg.offset()); 521 531 m_codeBlock->addParameter(); 522 } 523 524 bool BytecodeGenerator::willResolveToArgumentsRegister(const Identifier& ident) 525 { 526 if (ident != propertyNames().arguments) 527 return false; 528 529 if (!shouldOptimizeLocals()) 530 return false; 531 532 SymbolTableEntry entry = symbolTable().get(ident.impl()); 533 if (entry.isNull()) 534 return false; 535 536 if (m_localArgumentsRegister && isCaptured(m_localArgumentsRegister->index()) && m_lexicalEnvironmentRegister) 537 return false; 538 539 if (m_codeBlock->usesArguments() && m_codeType == FunctionCode && m_localArgumentsRegister) 540 return true; 541 542 return false; 543 } 544 545 RegisterID* BytecodeGenerator::uncheckedLocalArgumentsRegister() 546 { 547 ASSERT(willResolveToArgumentsRegister(propertyNames().arguments)); 548 ASSERT(m_localArgumentsRegister); 549 return m_localArgumentsRegister; 550 } 551 552 RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg) 553 { 554 if (!reg->virtualRegister().isLocal()) 555 return reg; 556 557 int localVariableNumber = reg->virtualRegister().toLocal(); 558 559 if (m_lastLazyFunction <= localVariableNumber || localVariableNumber < m_firstLazyFunction) 560 return reg; 561 emitLazyNewFunction(reg, m_lazyFunctions.get(localVariableNumber)); 562 return reg; 532 return ¶meter; 533 } 534 535 StringImpl* BytecodeGenerator::visibleNameForParameter(DeconstructionPatternNode* pattern) 536 { 537 if (pattern->isBindingNode()) { 538 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty(); 539 if (!m_functions.contains(ident.impl())) 540 return ident.impl(); 541 } 542 return nullptr; 563 543 } 564 544 … … 965 945 return m_identifierMap.contains(rep); 966 946 } 967 947 968 948 unsigned BytecodeGenerator::addConstant(const Identifier& ident) 969 949 { … … 1016 996 { 1017 997 m_staticPropertyAnalyzer.mov(dst->index(), src->index()); 1018 ASSERT(dst->virtualRegister() == m_codeBlock->argumentsRegister() || !isCaptured(dst->index()));1019 998 emitOpcode(op_mov); 1020 999 instructions().append(dst->index()); … … 1198 1177 } 1199 1178 1200 bool BytecodeGenerator::isCaptured(int operand) 1201 { 1202 return m_symbolTable && m_symbolTable->isCaptured(operand); 1203 } 1204 1205 Local BytecodeGenerator::local(const Identifier& property) 1206 { 1207 if (property == propertyNames().thisIdentifier) 1208 return Local(thisRegister(), ReadOnly, Local::SpecialLocal); 1209 bool isArguments = property == propertyNames().arguments; 1210 if (isArguments) 1211 createArgumentsIfNecessary(); 1212 1179 Variable BytecodeGenerator::variable(const Identifier& property) 1180 { 1181 if (property == propertyNames().thisIdentifier) { 1182 return Variable( 1183 property, VarOffset(thisRegister()->virtualRegister()), thisRegister(), 1184 ReadOnly, Variable::SpecialVariable); 1185 } 1186 1213 1187 if (!shouldOptimizeLocals()) 1214 return Local();1215 1188 return Variable(property); 1189 1216 1190 SymbolTableEntry entry = symbolTable().get(property.impl()); 1217 1191 if (entry.isNull()) 1218 return Local(); 1219 1220 1221 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); 1222 1223 if (isCaptured(local->index()) && m_lexicalEnvironmentRegister) 1224 return Local(); 1225 1226 return Local(local, entry.getAttributes(), isArguments ? Local::SpecialLocal : Local::NormalLocal); 1227 } 1228 1229 Local BytecodeGenerator::constLocal(const Identifier& property) 1230 { 1231 if (m_codeType != FunctionCode) 1232 return Local(); 1233 1192 return Variable(property); 1193 1194 if (entry.varOffset().isScope() && m_localScopeDepth) { 1195 // FIXME: We should be able to statically resolve through our local scopes. 1196 // https://bugs.webkit.org/show_bug.cgi?id=141885 1197 return Variable(property); 1198 } 1199 1200 return variableForLocalEntry(property, entry); 1201 } 1202 1203 Variable BytecodeGenerator::variablePerSymbolTable(const Identifier& property) 1204 { 1234 1205 SymbolTableEntry entry = symbolTable().get(property.impl()); 1235 1206 if (entry.isNull()) 1236 return Local(); 1237 1238 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); 1239 1240 bool isArguments = property == propertyNames().arguments; 1241 if (isCaptured(local->index()) && m_lexicalEnvironmentRegister) 1242 return Local(); 1243 1244 return Local(local, entry.getAttributes(), isArguments ? Local::SpecialLocal : Local::NormalLocal); 1207 return Variable(property); 1208 1209 return variableForLocalEntry(property, entry); 1210 } 1211 1212 Variable BytecodeGenerator::variableForLocalEntry( 1213 const Identifier& property, const SymbolTableEntry& entry) 1214 { 1215 VarOffset offset = entry.varOffset(); 1216 1217 RegisterID* local; 1218 if (offset.isStack()) 1219 local = ®isterFor(offset.stackOffset()); 1220 else 1221 local = nullptr; 1222 1223 return Variable(property, offset, local, entry.getAttributes(), Variable::NormalVariable); 1224 } 1225 1226 void BytecodeGenerator::createVariable( 1227 const Identifier& property, VarKind varKind, ConstantMode constantMode, 1228 ExistingVariableMode existingVariableMode) 1229 { 1230 ASSERT(property != propertyNames().thisIdentifier); 1231 1232 ConcurrentJITLocker locker(symbolTable().m_lock); 1233 SymbolTableEntry entry = symbolTable().get(locker, property.impl()); 1234 1235 if (!entry.isNull()) { 1236 if (existingVariableMode == IgnoreExisting) 1237 return; 1238 1239 // Do some checks to ensure that the variable we're being asked to create is sufficiently 1240 // compatible with the one we have already created. 1241 1242 VarOffset offset = entry.varOffset(); 1243 1244 // We can't change our minds about whether it's captured. 1245 if (offset.kind() != varKind || constantMode != entry.constantMode()) { 1246 dataLog( 1247 "Trying to add variable called ", property, " as ", varKind, "/", constantMode, 1248 " but it was already added as ", offset, "/", entry.constantMode(), ".\n"); 1249 RELEASE_ASSERT_NOT_REACHED(); 1250 } 1251 1252 return; 1253 } 1254 1255 VarOffset varOffset; 1256 if (varKind == VarKind::Scope) 1257 varOffset = VarOffset(symbolTable().takeNextScopeOffset(locker)); 1258 else { 1259 ASSERT(varKind == VarKind::Stack); 1260 varOffset = VarOffset(virtualRegisterForLocal(m_calleeRegisters.size())); 1261 } 1262 SymbolTableEntry newEntry(varOffset, constantMode == IsConstant ? ReadOnly : 0); 1263 symbolTable().add(locker, property.impl(), newEntry); 1264 1265 if (varKind == VarKind::Stack) { 1266 RegisterID* local = addVar(); 1267 RELEASE_ASSERT(local->index() == varOffset.stackOffset().offset()); 1268 } 1245 1269 } 1246 1270 … … 1266 1290 } 1267 1291 1268 RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Identifier& identifier, ResolveScopeInfo& info) 1269 { 1270 if (m_symbolTable && m_codeType == FunctionCode && !m_localScopeDepth) { 1271 SymbolTableEntry entry = m_symbolTable->get(identifier.impl()); 1272 if (!entry.isNull()) { 1273 info = ResolveScopeInfo(entry.getIndex()); 1274 return scopeRegister(); 1275 } 1276 } 1277 1278 ASSERT(!m_symbolTable || !m_symbolTable->contains(identifier.impl()) || resolveType() == Dynamic); 1279 1280 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1281 1282 // resolve_scope dst, id, ResolveType, depth 1283 emitOpcode(op_resolve_scope); 1284 dst = tempDestination(dst); 1285 instructions().append(kill(dst)); 1286 instructions().append(scopeRegister()->index()); 1287 instructions().append(addConstant(identifier)); 1288 instructions().append(resolveType()); 1289 instructions().append(0); 1290 instructions().append(0); 1291 return dst; 1292 } 1293 1294 1295 RegisterID* BytecodeGenerator::emitResolveConstantLocal(RegisterID* dst, const Identifier& identifier, ResolveScopeInfo& info) 1296 { 1297 if (!m_symbolTable || m_codeType != FunctionCode) 1292 RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Variable& variable) 1293 { 1294 switch (variable.offset().kind()) { 1295 case VarKind::Stack: 1298 1296 return nullptr; 1299 1300 SymbolTableEntry entry = m_symbolTable->get(identifier.impl()); 1301 if (entry.isNull()) 1302 return nullptr; 1303 info = ResolveScopeInfo(entry.getIndex()); 1304 return emitMove(dst, m_lexicalEnvironmentRegister); 1305 1306 } 1307 1308 RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier& identifier, ResolveMode resolveMode, const ResolveScopeInfo& info) 1309 { 1310 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1311 1312 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand 1313 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope); 1314 instructions().append(kill(dst)); 1315 instructions().append(scope->index()); 1316 instructions().append(addConstant(identifier)); 1317 instructions().append(ResolveModeAndType(resolveMode, info.isLocal() ? LocalClosureVar : resolveType()).operand()); 1318 instructions().append(0); 1319 instructions().append(info.localIndex()); 1320 instructions().append(profile); 1321 return dst; 1322 } 1323 1324 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode, const ResolveScopeInfo& info) 1325 { 1326 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1327 1328 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand 1329 emitOpcode(op_put_to_scope); 1330 instructions().append(scope->index()); 1331 instructions().append(addConstant(identifier)); 1332 instructions().append(value->index()); 1333 if (info.isLocal()) { 1334 instructions().append(ResolveModeAndType(resolveMode, LocalClosureVar).operand()); 1335 int operand = registerFor(info.localIndex()).index(); 1336 bool isWatchableVariable = hasWatchableVariable(operand); 1337 ASSERT(!isWatchableVariable || watchableVariableIdentifier(operand) == identifier); 1338 instructions().append(isWatchableVariable); 1339 } else { 1340 ASSERT(resolveType() != LocalClosureVar); 1341 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand()); 1342 instructions().append(false); 1343 } 1344 instructions().append(info.localIndex()); 1345 return value; 1297 1298 case VarKind::DirectArgument: 1299 return argumentsRegister(); 1300 1301 case VarKind::Scope: 1302 // This always refers to the activation that *we* allocated, and not the current scope that code 1303 // lives in. Note that this will change once we have proper support for block scoping. Once that 1304 // changes, it will be correct for this code to return scopeRegister(). The only reason why we 1305 // don't do that already is that m_lexicalEnvironment is required by ConstDeclNode. ConstDeclNode 1306 // requires weird things because it is a shameful pile of nonsense, but block scoping would make 1307 // that code sensible and obviate the need for us to do bad things. 1308 return m_lexicalEnvironmentRegister; 1309 1310 case VarKind::Invalid: 1311 // Indicates non-local resolution. 1312 1313 ASSERT(!m_symbolTable || !m_symbolTable->contains(variable.ident().impl()) || resolveType() == Dynamic); 1314 1315 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1316 1317 // resolve_scope dst, id, ResolveType, depth 1318 emitOpcode(op_resolve_scope); 1319 dst = tempDestination(dst); 1320 instructions().append(kill(dst)); 1321 instructions().append(scopeRegister()->index()); 1322 instructions().append(addConstant(variable.ident())); 1323 instructions().append(resolveType()); 1324 instructions().append(0); 1325 instructions().append(0); 1326 return dst; 1327 } 1328 1329 RELEASE_ASSERT_NOT_REACHED(); 1330 return nullptr; 1331 } 1332 1333 RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable& variable, ResolveMode resolveMode) 1334 { 1335 switch (variable.offset().kind()) { 1336 case VarKind::Stack: 1337 return emitMove(dst, variable.local()); 1338 1339 case VarKind::DirectArgument: { 1340 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_arguments); 1341 instructions().append(kill(dst)); 1342 instructions().append(scope->index()); 1343 instructions().append(variable.offset().capturedArgumentsOffset().offset()); 1344 instructions().append(profile); 1345 return dst; 1346 } 1347 1348 case VarKind::Scope: 1349 case VarKind::Invalid: { 1350 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1351 1352 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand 1353 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope); 1354 instructions().append(kill(dst)); 1355 instructions().append(scope->index()); 1356 instructions().append(addConstant(variable.ident())); 1357 instructions().append(ResolveModeAndType(resolveMode, variable.offset().isScope() ? LocalClosureVar : resolveType()).operand()); 1358 instructions().append(0); 1359 instructions().append(variable.offset().isScope() ? variable.offset().scopeOffset().offset() : 0); 1360 instructions().append(profile); 1361 return dst; 1362 } } 1363 1364 RELEASE_ASSERT_NOT_REACHED(); 1365 } 1366 1367 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Variable& variable, RegisterID* value, ResolveMode resolveMode) 1368 { 1369 switch (variable.offset().kind()) { 1370 case VarKind::Stack: 1371 emitMove(variable.local(), value); 1372 return value; 1373 1374 case VarKind::DirectArgument: 1375 emitOpcode(op_put_to_arguments); 1376 instructions().append(scope->index()); 1377 instructions().append(variable.offset().capturedArgumentsOffset().offset()); 1378 instructions().append(value->index()); 1379 return value; 1380 1381 case VarKind::Scope: 1382 case VarKind::Invalid: { 1383 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1384 1385 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand 1386 emitOpcode(op_put_to_scope); 1387 instructions().append(scope->index()); 1388 instructions().append(addConstant(variable.ident())); 1389 instructions().append(value->index()); 1390 ScopeOffset offset; 1391 if (variable.offset().isScope()) { 1392 offset = variable.offset().scopeOffset(); 1393 instructions().append(ResolveModeAndType(resolveMode, LocalClosureVar).operand()); 1394 } else { 1395 ASSERT(resolveType() != LocalClosureVar); 1396 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand()); 1397 } 1398 instructions().append(0); 1399 instructions().append(!!offset ? offset.offset() : 0); 1400 return value; 1401 } } 1402 1403 RELEASE_ASSERT_NOT_REACHED(); 1404 } 1405 1406 RegisterID* BytecodeGenerator::initializeVariable(const Variable& variable, RegisterID* value) 1407 { 1408 RegisterID* scope; 1409 switch (variable.offset().kind()) { 1410 case VarKind::Stack: 1411 scope = nullptr; 1412 break; 1413 1414 case VarKind::DirectArgument: 1415 scope = argumentsRegister(); 1416 break; 1417 1418 case VarKind::Scope: 1419 scope = scopeRegister(); 1420 break; 1421 1422 default: 1423 RELEASE_ASSERT_NOT_REACHED(); 1424 scope = nullptr; 1425 break; 1426 } 1427 1428 return emitPutToScope(scope, variable, value, ThrowIfNotFound); 1346 1429 } 1347 1430 1348 1431 RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype) 1349 { 1432 { 1350 1433 emitOpcode(op_instanceof); 1351 1434 instructions().append(dst->index()); … … 1379 1462 instructions().append(0); 1380 1463 instructions().append(profile); 1381 return dst;1382 }1383 1384 RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterID* base)1385 {1386 emitOpcode(op_get_arguments_length);1387 instructions().append(dst->index());1388 ASSERT(base->virtualRegister() == m_codeBlock->argumentsRegister());1389 instructions().append(base->index());1390 instructions().append(addConstant(propertyNames().length));1391 1464 return dst; 1392 1465 } … … 1452 1525 instructions().append(base->index()); 1453 1526 instructions().append(addConstant(property)); 1454 return dst;1455 }1456 1457 RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)1458 {1459 UnlinkedArrayProfile arrayProfile = newArrayProfile();1460 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_argument_by_val);1461 instructions().append(kill(dst));1462 ASSERT(base->virtualRegister() == m_codeBlock->argumentsRegister());1463 instructions().append(base->index());1464 instructions().append(property->index());1465 instructions().append(m_codeBlock->activationRegister().offset());1466 instructions().append(arrayProfile);1467 instructions().append(profile);1468 1527 return dst; 1469 1528 } … … 1653 1712 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function) 1654 1713 { 1655 return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(function)), false); 1656 } 1657 1658 RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function) 1659 { 1660 FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0); 1661 if (ptr.isNewEntry) 1662 ptr.iterator->value = m_codeBlock->addFunctionDecl(makeFunction(function)); 1663 return emitNewFunctionInternal(dst, ptr.iterator->value, true); 1664 } 1665 1666 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck) 1714 return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(function))); 1715 } 1716 1717 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index) 1667 1718 { 1668 1719 emitOpcode(op_new_func); … … 1670 1721 instructions().append(scopeRegister()->index()); 1671 1722 instructions().append(index); 1672 instructions().append(doNullCheck);1673 1723 return dst; 1674 1724 } … … 1710 1760 { 1711 1761 return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd); 1712 }1713 1714 void BytecodeGenerator::createArgumentsIfNecessary()1715 {1716 if (m_codeType != FunctionCode)1717 return;1718 1719 if (!m_codeBlock->usesArguments())1720 return;1721 1722 if (shouldTearOffArgumentsEagerly() || shouldCreateArgumentsEagerly())1723 return;1724 1725 emitOpcode(op_create_arguments);1726 instructions().append(m_codeBlock->argumentsRegister().offset());1727 ASSERT(!hasWatchableVariable(m_codeBlock->argumentsRegister().offset()));1728 instructions().append(m_codeBlock->activationRegister().offset());1729 1762 } 1730 1763 … … 1825 1858 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression(); 1826 1859 RefPtr<RegisterID> argumentRegister; 1827 if (expression->isResolveNode() && willResolveToArgumentsRegister(static_cast<ResolveNode*>(expression)->identifier()) && !symbolTable().slowArguments()) 1828 argumentRegister = uncheckedLocalArgumentsRegister(); 1829 else 1830 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0)); 1860 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0)); 1831 1861 RefPtr<RegisterID> thisRegister = emitMove(newTemporary(), callArguments.thisRegister()); 1832 1862 return emitCallVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd); … … 1917 1947 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src) 1918 1948 { 1919 if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !isStrictMode()) {1920 RefPtr<RegisterID> scratchRegister;1921 int argumentsIndex = unmodifiedArgumentsRegister(m_codeBlock->argumentsRegister()).offset();1922 if (m_lexicalEnvironmentRegister && m_codeType == FunctionCode) {1923 scratchRegister = newTemporary();1924 ResolveScopeInfo scopeInfo(unmodifiedArgumentsRegister(m_codeBlock->argumentsRegister()).offset());1925 emitGetFromScope(scratchRegister.get(), scopeRegister(), propertyNames().arguments, ThrowIfNotFound, scopeInfo);1926 argumentsIndex = scratchRegister->index();1927 }1928 emitOpcode(op_tear_off_arguments);1929 instructions().append(argumentsIndex);1930 instructions().append(m_lexicalEnvironmentRegister ? m_lexicalEnvironmentRegister->index() : emitLoad(0, JSValue())->index());1931 }1932 1933 1949 if (isConstructor()) { 1934 1950 bool derived = constructorKind() == ConstructorKind::Derived; … … 1979 1995 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression(); 1980 1996 RefPtr<RegisterID> argumentRegister; 1981 if (expression->isResolveNode() && willResolveToArgumentsRegister(static_cast<ResolveNode*>(expression)->identifier()) && !symbolTable().slowArguments()) 1982 argumentRegister = uncheckedLocalArgumentsRegister(); 1983 else 1984 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0)); 1997 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0)); 1985 1998 return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd); 1986 1999 } … … 2544 2557 bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber) 2545 2558 { 2546 RegisterID* registerID = local(ident).get();2547 if (!registerID || registerID->index() >= 0)2548 return 0;2559 RegisterID* registerID = variable(ident).local(); 2560 if (!registerID) 2561 return false; 2549 2562 return registerID->index() == CallFrame::argumentOffset(argumentNumber); 2550 2563 } … … 2561 2574 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack) 2562 2575 { 2563 if (subjectNode->isResolveNode()2564 && willResolveToArgumentsRegister(static_cast<ResolveNode*>(subjectNode)->identifier())2565 && !symbolTable().slowArguments()) {2566 RefPtr<RegisterID> index = emitLoad(newTemporary(), jsNumber(0));2567 2568 LabelScopePtr scope = newLabelScope(LabelScope::Loop);2569 RefPtr<RegisterID> value = emitLoad(newTemporary(), jsUndefined());2570 2571 RefPtr<Label> loopCondition = newLabel();2572 RefPtr<Label> loopStart = newLabel();2573 emitJump(loopCondition.get());2574 emitLabel(loopStart.get());2575 emitLoopHint();2576 emitGetArgumentByVal(value.get(), uncheckedLocalArgumentsRegister(), index.get());2577 callBack(*this, value.get());2578 2579 emitLabel(scope->continueTarget());2580 emitInc(index.get());2581 emitLabel(loopCondition.get());2582 RefPtr<RegisterID> length = emitGetArgumentsLength(newTemporary(), uncheckedLocalArgumentsRegister());2583 emitJumpIfTrue(emitEqualityOp(op_less, newTemporary(), index.get(), length.get()), loopStart.get());2584 emitLabel(scope->breakTarget());2585 return;2586 }2587 2588 2576 LabelScopePtr scope = newLabelScope(LabelScope::Loop); 2589 2577 RefPtr<RegisterID> subject = newTemporary(); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r181891 r181993 1 1 /* 2 * Copyright (C) 2008, 2009, 2012 , 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> 4 4 * Copyright (C) 2012 Igalia, S.L. … … 179 179 }; 180 180 181 enum CaptureMode { 182 NotCaptured, 183 IsCaptured 184 }; 185 186 class Local { 181 class Variable { 187 182 public: 188 Local() 189 : m_local(0) 183 enum VariableKind { NormalVariable, SpecialVariable }; 184 185 Variable() 186 : m_offset() 187 , m_local(nullptr) 190 188 , m_attributes(0) 191 , m_kind(NormalLocal) 192 { 193 } 194 195 enum LocalKind { NormalLocal, SpecialLocal }; 196 197 Local(RegisterID* local, unsigned attributes, LocalKind kind) 198 : m_local(local) 189 , m_kind(NormalVariable) 190 { 191 } 192 193 Variable(const Identifier& ident) 194 : m_ident(ident) 195 , m_local(nullptr) 196 , m_attributes(0) 197 , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable. 198 { 199 } 200 201 Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind) 202 : m_ident(ident) 203 , m_offset(offset) 204 , m_local(local) 199 205 , m_attributes(attributes) 200 206 , m_kind(kind) … … 202 208 } 203 209 204 operator bool() const { return m_local; } 205 206 RegisterID* get() const { return m_local; } 210 // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be 211 // a stack variable, a scoped variable in the local scope, or a variable captured in the 212 // direct arguments object. 213 bool isResolved() const { return !!m_offset; } 214 215 const Identifier& ident() const { return m_ident; } 216 217 VarOffset offset() const { return m_offset; } 218 bool isLocal() const { return m_offset.isStack(); } 219 RegisterID* local() const { return m_local; } 207 220 208 221 bool isReadOnly() const { return m_attributes & ReadOnly; } 209 bool isSpecial() const { return m_kind != Normal Local; }222 bool isSpecial() const { return m_kind != NormalVariable; } 210 223 211 224 private: 225 Identifier m_ident; 226 VarOffset m_offset; 212 227 RegisterID* m_local; 213 228 unsigned m_attributes; 214 LocalKind m_kind; 215 }; 216 217 struct ResolveScopeInfo { 218 ResolveScopeInfo() 219 : m_localIndex(0) 220 , m_resolveScopeKind(NonLocalScope) 221 { 222 } 223 224 ResolveScopeInfo(int index) 225 : m_localIndex(index) 226 , m_resolveScopeKind(LocalScope) 227 { 228 } 229 230 bool isLocal() const { return m_resolveScopeKind == LocalScope; } 231 int localIndex() const { return m_localIndex; } 232 233 private: 234 int m_localIndex; 235 enum { LocalScope, NonLocalScope } m_resolveScopeKind; 229 VariableKind m_kind; 236 230 }; 237 231 … … 283 277 void setIsNumericCompareFunction(bool isNumericCompareFunction); 284 278 285 bool willResolveToArgumentsRegister(const Identifier&); 286 287 bool hasSafeLocalArgumentsRegister() { return m_localArgumentsRegister; } 288 RegisterID* uncheckedLocalArgumentsRegister(); 289 290 bool isCaptured(int operand); 291 CaptureMode captureMode(int operand) { return isCaptured(operand) ? IsCaptured : NotCaptured; } 292 293 Local local(const Identifier&); 294 Local constLocal(const Identifier&); 295 279 Variable variable(const Identifier&); 280 281 // Ignores the possibility of intervening scopes. 282 Variable variablePerSymbolTable(const Identifier&); 283 284 enum ExistingVariableMode { VerifyExisting, IgnoreExisting }; 285 void createVariable(const Identifier&, VarKind, ConstantMode, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible. 286 296 287 // Returns the register storing "this" 297 288 RegisterID* thisRegister() { return &m_thisRegister; } 289 RegisterID* argumentsRegister() { return m_argumentsRegister; } 298 290 RegisterID* newTarget() { return m_newTargetRegister; } 299 291 … … 354 346 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary. 355 347 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount()); 356 // Should never store directly into a captured variable.357 ASSERT(!dst || dst == ignoredResult() || !isCaptured(dst->index()));358 348 if (!m_vm->isSafeToRecurse()) { 359 349 emitThrowExpressionTooDeepException(); … … 372 362 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary. 373 363 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount()); 374 // Should never store directly into a captured variable.375 ASSERT(!dst || dst == ignoredResult() || !isCaptured(dst->index()));376 364 if (!m_vm->isSafeToRecurse()) 377 365 return emitThrowExpressionTooDeepException(); … … 464 452 465 453 RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode*); 466 RegisterID* emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* body); 467 RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index, bool shouldNullCheck); 454 RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index); 468 455 RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func); 469 456 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name); … … 484 471 485 472 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property); 486 RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base);487 473 RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value); 488 474 RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType); … … 511 497 512 498 ResolveType resolveType(); 513 RegisterID* emitResolveConstantLocal(RegisterID* dst, const Identifier&, ResolveScopeInfo&); 514 // Calls tempDestination(dst), so it's safe to pass nullptr. It's also redundant to call 515 // tempDestination(dst) on the thing you pass as the destination. The reason why this 516 // calls tempDestination() for you is that it may not need a spare register. It may return 517 // scopeRegister() directly. So, you cannot rely on this storing to dst. 518 RegisterID* emitResolveScope(RegisterID* dst, const Identifier&, ResolveScopeInfo&); 519 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode, const ResolveScopeInfo&); 520 RegisterID* emitPutToScope(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode, const ResolveScopeInfo&); 499 RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&); 500 RegisterID* emitResolveScope(RegisterID* dst, const Variable&); 501 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable&, ResolveMode); 502 RegisterID* emitPutToScope(RegisterID* scope, const Variable&, RegisterID* value, ResolveMode); 503 RegisterID* initializeVariable(const Variable&, RegisterID* value); 521 504 522 505 PassRefPtr<Label> emitLabel(Label*); … … 598 581 599 582 private: 583 Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&); 584 600 585 void emitOpcode(OpcodeID); 601 586 UnlinkedArrayAllocationProfile newArrayAllocationProfile(); … … 630 615 RegisterID* newRegister(); 631 616 632 // Adds a var slot and maps it to the name ident in symbolTable(). 633 enum WatchMode { IsWatchable, NotWatchable }; 634 RegisterID* addVar(const Identifier&, ConstantMode, WatchMode); 635 636 // Adds an anonymous var slot. To give this slot a name, add it to symbolTable(). 617 // Adds an anonymous local var slot. To give this slot a name, add it to symbolTable(). 637 618 RegisterID* addVar() 638 619 { … … 644 625 } 645 626 646 // Returns the index of the added var. 647 void addParameter(const Identifier&, int parameterIndex); 648 RegisterID* resolveCallee(FunctionNode*); 649 void addCallee(FunctionNode*, RegisterID*); 650 651 void preserveLastVar(); 652 653 RegisterID& registerFor(int index) 654 { 655 if (operandIsLocal(index)) 656 return m_calleeRegisters[VirtualRegister(index).toLocal()]; 657 658 if (index == JSStack::Callee) 627 // Initializes the stack form the parameter; does nothing for the symbol table. 628 RegisterID* initializeNextParameter(); 629 StringImpl* visibleNameForParameter(DeconstructionPatternNode*); 630 631 RegisterID& registerFor(VirtualRegister reg) 632 { 633 if (reg.isLocal()) 634 return m_calleeRegisters[reg.toLocal()]; 635 636 if (reg.offset() == JSStack::Callee) 659 637 return m_calleeRegister; 660 638 661 639 ASSERT(m_parameters.size()); 662 return m_parameters[ VirtualRegister(index).toArgument()];640 return m_parameters[reg.toArgument()]; 663 641 } 664 642 … … 676 654 } 677 655 678 RegisterID* emitInitLazyRegister(RegisterID*);679 680 656 RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); 681 657 RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); 682 RegisterID* initializeCapturedVariable(RegisterID* dst, const Identifier&, RegisterID*);683 658 684 659 public: … … 714 689 } 715 690 716 bool shouldTearOffArgumentsEagerly()717 {718 return m_codeType == FunctionCode && isStrictMode() && m_scopeNode->modifiesParameter();719 }720 721 bool shouldCreateArgumentsEagerly()722 {723 if (m_codeType != FunctionCode)724 return false;725 return m_lexicalEnvironmentRegister && m_codeBlock->usesArguments();726 }727 728 691 RegisterID* emitThrowExpressionTooDeepException(); 729 730 void createArgumentsIfNecessary();731 RegisterID* createLazyRegisterIfNecessary(RegisterID*);732 733 bool hasWatchableVariable(int operand) const734 {735 VirtualRegister reg(operand);736 if (!reg.isLocal())737 return false;738 if (static_cast<size_t>(reg.toLocal()) >= m_watchableVariables.size())739 return false;740 const Identifier& ident = m_watchableVariables[reg.toLocal()];741 if (ident.isNull())742 return false;743 ASSERT(hasConstant(ident)); // Should have already been added.744 return true;745 }746 747 const Identifier& watchableVariableIdentifier(int operand) const748 {749 ASSERT(hasWatchableVariable(operand));750 VirtualRegister reg(operand);751 return m_watchableVariables[reg.toLocal()];752 }753 692 754 693 private: … … 770 709 RegisterID m_calleeRegister; 771 710 RegisterID* m_scopeRegister { nullptr }; 711 RegisterID* m_argumentsRegister { nullptr }; 772 712 RegisterID* m_lexicalEnvironmentRegister { nullptr }; 773 713 RegisterID* m_emptyValueRegister { nullptr }; 774 714 RegisterID* m_globalObjectRegister { nullptr }; 775 RegisterID* m_localArgumentsRegister { nullptr };776 715 RegisterID* m_newTargetRegister { nullptr }; 777 716 778 Vector<Identifier, 16> m_watchableVariables;779 717 SegmentedVector<RegisterID, 32> m_constantPoolRegisters; 780 718 SegmentedVector<RegisterID, 32> m_calleeRegisters; … … 791 729 Vector<TryContext> m_tryContextStack; 792 730 Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters; 731 Vector<FunctionBodyNode*> m_functionsToInitialize; 732 bool m_needToInitializeArguments { false }; 793 733 794 734 Vector<TryRange> m_tryRanges; … … 797 737 int m_nextConstantOffset { 0 }; 798 738 799 int m_firstLazyFunction { 0 };800 int m_lastLazyFunction { 0 };801 HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int>> m_lazyFunctions;802 739 typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap; 803 740 FunctionOffsetMap m_functionOffsets; -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r181891 r181993 2 2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013, 2015 Apple Inc. All rights reserved. 5 5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) 6 6 * Copyright (C) 2007 Maks Orlovich … … 188 188 bool ResolveNode::isPure(BytecodeGenerator& generator) const 189 189 { 190 return generator. local(m_ident).get();190 return generator.variable(m_ident).offset().isStack(); 191 191 } 192 192 193 193 RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 194 194 { 195 if (Local local = generator.local(m_ident)) { 195 Variable var = generator.variable(m_ident); 196 if (RegisterID* local = var.local()) { 196 197 if (dst == generator.ignoredResult()) 197 return 0;198 return nullptr; 198 199 if (generator.vm()->typeProfiler()) { 199 generator.emitProfileType(local .get(), ProfileTypeBytecodeHasGlobalID, nullptr);200 generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr); 200 201 generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1)); 201 202 } 202 return generator.moveToDestinationIfNeeded(dst, local .get());203 return generator.moveToDestinationIfNeeded(dst, local); 203 204 } 204 205 205 206 JSTextPosition divot = m_start + m_ident.length(); 206 207 generator.emitExpressionInfo(divot, m_start, divot); 207 ResolveScopeInfo resolveScopeInfo; 208 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, m_ident, resolveScopeInfo); 208 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var); 209 209 RegisterID* finalDest = generator.finalDestination(dst); 210 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo);210 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound); 211 211 if (generator.vm()->typeProfiler()) { 212 generator.emitProfileType(finalDest, resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);212 generator.emitProfileType(finalDest, var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident); 213 213 generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1)); 214 214 } … … 440 440 } 441 441 442 if (m_base->isResolveNode()443 && generator.willResolveToArgumentsRegister(static_cast<ResolveNode*>(m_base)->identifier())444 && !generator.symbolTable().slowArguments()) {445 RefPtr<RegisterID> property = generator.emitNode(m_subscript);446 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());447 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedLocalArgumentsRegister(), property.get());448 }449 450 442 RegisterID* ret; 451 443 RegisterID* finalDest = generator.finalDestination(dst); … … 473 465 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 474 466 { 475 if (m_ident == generator.propertyNames().length) {476 if (!m_base->isResolveNode())477 goto nonArgumentsPath;478 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);479 if (!generator.willResolveToArgumentsRegister(resolveNode->identifier()))480 goto nonArgumentsPath;481 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());482 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedLocalArgumentsRegister());483 }484 485 nonArgumentsPath:486 467 RefPtr<RegisterID> base = m_base->isSuperNode() ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base); 487 468 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); … … 548 529 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 549 530 { 550 if (Local local = generator.local(generator.propertyNames().eval)) { 551 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get()); 531 Variable var = generator.variable(generator.propertyNames().eval); 532 if (RegisterID* local = var.local()) { 533 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local); 552 534 CallArguments callArguments(generator, m_args); 553 535 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); … … 559 541 JSTextPosition newDivot = divotStart() + 4; 560 542 generator.emitExpressionInfo(newDivot, divotStart(), newDivot); 561 ResolveScopeInfo resolveScopeInfo;562 543 generator.moveToDestinationIfNeeded( 563 544 callArguments.thisRegister(), 564 generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval, resolveScopeInfo));565 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound, resolveScopeInfo);545 generator.emitResolveScope(callArguments.thisRegister(), var)); 546 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound); 566 547 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd()); 567 548 } … … 597 578 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident); 598 579 599 if (Local local = generator.local(m_ident)) { 600 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get()); 580 Variable var = generator.variable(m_ident); 581 if (RegisterID* local = var.local()) { 582 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local); 601 583 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get()); 602 584 CallArguments callArguments(generator, m_args); … … 618 600 JSTextPosition newDivot = divotStart() + m_ident.length(); 619 601 generator.emitExpressionInfo(newDivot, divotStart(), newDivot); 620 ResolveScopeInfo resolveScopeInfo;621 602 generator.moveToDestinationIfNeeded( 622 603 callArguments.thisRegister(), 623 generator.emitResolveScope(callArguments.thisRegister(), m_ident, resolveScopeInfo));624 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound, resolveScopeInfo);604 generator.emitResolveScope(callArguments.thisRegister(), var)); 605 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound); 625 606 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd()); 626 607 if (generator.vm()->typeProfiler()) { … … 676 657 } 677 658 678 static RegisterID* getArgumentByVal(BytecodeGenerator& generator, ExpressionNode* base, RegisterID* property, RegisterID* dst, JSTextPosition divot, JSTextPosition divotStart, JSTextPosition divotEnd)679 {680 if (base->isResolveNode()681 && generator.willResolveToArgumentsRegister(static_cast<ResolveNode*>(base)->identifier())682 && !generator.symbolTable().slowArguments()) {683 generator.emitExpressionInfo(divot, divotStart, divotEnd);684 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedLocalArgumentsRegister(), property);685 }686 return nullptr;687 }688 689 659 RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 690 660 { … … 707 677 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr); 708 678 ExpressionNode* subject = spread->expression(); 709 RefPtr<RegisterID> thisRegister = getArgumentByVal(generator, subject, generator.emitLoad(0, jsNumber(0)), 0, spread->divot(), spread->divotStart(), spread->divotEnd());710 679 RefPtr<RegisterID> argumentsRegister; 711 if (thisRegister) 712 argumentsRegister = generator.uncheckedLocalArgumentsRegister(); 713 else { 714 argumentsRegister = generator.emitNode(subject); 715 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd()); 716 thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0))); 717 } 680 argumentsRegister = generator.emitNode(subject); 681 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd()); 682 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0))); 718 683 generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd()); 719 684 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) { … … 837 802 RefPtr<RegisterID> argsRegister; 838 803 ArgumentListNode* args = m_args->m_listNode->m_next; 839 if (args->m_expr->isResolveNode() && generator.willResolveToArgumentsRegister(static_cast<ResolveNode*>(args->m_expr)->identifier()) && !generator.symbolTable().slowArguments()) 840 argsRegister = generator.uncheckedLocalArgumentsRegister(); 841 else 842 argsRegister = generator.emitNode(args->m_expr); 804 argsRegister = generator.emitNode(args->m_expr); 843 805 844 806 // Function.prototype.apply ignores extra arguments, but we still … … 889 851 const Identifier& ident = resolve->identifier(); 890 852 891 if (Local local = generator.local(ident)) { 892 RefPtr<RegisterID> localReg = local.get(); 893 if (local.isReadOnly()) { 853 Variable var = generator.variable(ident); 854 if (RegisterID* local = var.local()) { 855 RefPtr<RegisterID> localReg = local; 856 if (var.isReadOnly()) { 894 857 generator.emitReadOnlyExceptionIfNeeded(); 895 localReg = generator.emitMove(generator.tempDestination(dst), local Reg.get());858 localReg = generator.emitMove(generator.tempDestination(dst), local); 896 859 } else if (generator.vm()->typeProfiler()) { 897 860 RefPtr<RegisterID> tempDst = generator.finalDestination(dst); … … 910 873 911 874 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 912 ResolveScopeInfo resolveScopeInfo; 913 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, ident, resolveScopeInfo); 914 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo); 875 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 876 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); 915 877 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); 916 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);878 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound); 917 879 if (generator.vm()->typeProfiler()) { 918 generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);880 generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident); 919 881 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); 920 882 } … … 992 954 RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 993 955 { 994 if (generator.local(m_ident).get()) 956 Variable var = generator.variable(m_ident); 957 if (var.local()) 995 958 return generator.emitLoad(generator.finalDestination(dst), false); 996 959 997 960 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 998 ResolveScopeInfo resolveScopeInfo; 999 RefPtr<RegisterID> base = generator.emitResolveScope(dst, m_ident, resolveScopeInfo); 961 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var); 1000 962 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident); 1001 963 } … … 1048 1010 } 1049 1011 1050 // ------------------------------ TypeOf ValueNode -----------------------------------1012 // ------------------------------ TypeOfResolveNode ----------------------------------- 1051 1013 1052 1014 RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1053 1015 { 1054 if (Local local = generator.local(m_ident)) { 1016 Variable var = generator.variable(m_ident); 1017 if (RegisterID* local = var.local()) { 1055 1018 if (dst == generator.ignoredResult()) 1056 1019 return 0; 1057 return generator.emitTypeOf(generator.finalDestination(dst), local.get()); 1058 } 1059 1060 ResolveScopeInfo resolveScopeInfo; 1061 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, m_ident, resolveScopeInfo); 1062 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo); 1020 return generator.emitTypeOf(generator.finalDestination(dst), local); 1021 } 1022 1023 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var); 1024 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound); 1063 1025 if (dst == generator.ignoredResult()) 1064 1026 return 0; … … 1086 1048 const Identifier& ident = resolve->identifier(); 1087 1049 1088 if (Local local = generator.local(ident)) { 1089 RefPtr<RegisterID> localReg = local.get(); 1090 if (local.isReadOnly()) { 1050 Variable var = generator.variable(ident); 1051 if (RegisterID* local = var.local()) { 1052 RefPtr<RegisterID> localReg = local; 1053 if (var.isReadOnly()) { 1091 1054 generator.emitReadOnlyExceptionIfNeeded(); 1092 1055 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get()); … … 1105 1068 1106 1069 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1107 ResolveScopeInfo resolveScopeInfo; 1108 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, ident, resolveScopeInfo); 1109 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo); 1070 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var); 1071 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); 1110 1072 emitIncOrDec(generator, value.get(), m_operator); 1111 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);1073 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound); 1112 1074 if (generator.vm()->typeProfiler()) { 1113 generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);1075 generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident); 1114 1076 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); 1115 1077 } … … 1603 1565 { 1604 1566 JSTextPosition newDivot = divotStart() + m_ident.length(); 1605 if (Local local = generator.local(m_ident)) { 1606 if (local.isReadOnly()) { 1567 Variable var = generator.variable(m_ident); 1568 if (RegisterID* local = var.local()) { 1569 if (var.isReadOnly()) { 1607 1570 generator.emitReadOnlyExceptionIfNeeded(); 1608 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local .get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));1571 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1609 1572 } 1610 1573 … … 1612 1575 || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { 1613 1576 RefPtr<RegisterID> result = generator.newTemporary(); 1614 generator.emitMove(result.get(), local .get());1577 generator.emitMove(result.get(), local); 1615 1578 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1616 generator.emitMove(local .get(), result.get());1617 generator.invalidateForInContextForLocal(local .get());1579 generator.emitMove(local, result.get()); 1580 generator.invalidateForInContextForLocal(local); 1618 1581 if (generator.vm()->typeProfiler()) 1619 1582 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); … … 1621 1584 } 1622 1585 1623 RegisterID* result = emitReadModifyAssignment(generator, local .get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));1624 generator.invalidateForInContextForLocal(local .get());1586 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1587 generator.invalidateForInContextForLocal(local); 1625 1588 return generator.moveToDestinationIfNeeded(dst, result); 1626 1589 } 1627 1590 1628 1591 generator.emitExpressionInfo(newDivot, divotStart(), newDivot); 1629 ResolveScopeInfo resolveScopeInfo; 1630 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, m_ident, resolveScopeInfo); 1631 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo); 1592 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 1593 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); 1632 1594 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); 1633 RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound, resolveScopeInfo);1595 RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound); 1634 1596 if (generator.vm()->typeProfiler()) { 1635 generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);1597 generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident); 1636 1598 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); 1637 1599 } … … 1643 1605 RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1644 1606 { 1645 if (Local local = generator.local(m_ident)) { 1646 if (local.isReadOnly()) { 1607 Variable var = generator.variable(m_ident); 1608 if (RegisterID* local = var.local()) { 1609 if (var.isReadOnly()) { 1647 1610 generator.emitReadOnlyExceptionIfNeeded(); 1648 1611 return generator.emitNode(dst, m_right); 1649 1612 } 1650 if ( local.isSpecial() || generator.vm()->typeProfiler()) {1613 if (var.isSpecial() || generator.vm()->typeProfiler()) { 1651 1614 RefPtr<RegisterID> tempDst = generator.tempDestination(dst); 1652 1615 generator.emitNode(tempDst.get(), m_right); 1653 generator.emitMove(local .get(), tempDst.get());1654 generator.invalidateForInContextForLocal(local .get());1616 generator.emitMove(local, tempDst.get()); 1617 generator.invalidateForInContextForLocal(local); 1655 1618 if (generator.vm()->typeProfiler()) 1656 1619 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); 1657 1620 return generator.moveToDestinationIfNeeded(dst, tempDst.get()); 1658 1621 } 1659 RegisterID* result = generator.emitNode(local .get(), m_right);1660 generator.invalidateForInContextForLocal(local .get());1622 RegisterID* result = generator.emitNode(local, m_right); 1623 generator.invalidateForInContextForLocal(local); 1661 1624 return generator.moveToDestinationIfNeeded(dst, result); 1662 1625 } … … 1664 1627 if (generator.isStrictMode()) 1665 1628 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1666 ResolveScopeInfo resolveScopeInfo; 1667 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, m_ident, resolveScopeInfo); 1629 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 1668 1630 if (dst == generator.ignoredResult()) 1669 1631 dst = 0; 1670 1632 RefPtr<RegisterID> result = generator.emitNode(dst, m_right); 1671 1633 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 1672 RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);1634 RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1673 1635 if (generator.vm()->typeProfiler()) { 1674 generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);1636 generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident); 1675 1637 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); 1676 1638 } … … 1781 1743 { 1782 1744 // FIXME: This code does not match the behavior of const in Firefox. 1783 if (Local local = generator.constLocal(m_ident)) { 1745 Variable var = generator.variable(m_ident); 1746 if (RegisterID* local = var.local()) { 1784 1747 if (!m_init) 1785 return local .get();1748 return local; 1786 1749 1787 1750 // FIXME: Maybe call emitExpressionInfo here. 1788 if ( local.isSpecial() || generator.vm()->typeProfiler()) {1751 if (var.isSpecial() || generator.vm()->typeProfiler()) { 1789 1752 RefPtr<RegisterID> tempDst = generator.newTemporary(); 1790 1753 generator.emitNode(tempDst.get(), m_init); 1791 return generator.emitMove(local .get(), tempDst.get());1754 return generator.emitMove(local, tempDst.get()); 1792 1755 } 1793 1756 1794 return generator.emitNode(local .get(), m_init);1757 return generator.emitNode(local, m_init); 1795 1758 } 1796 1759 … … 1801 1764 1802 1765 if (generator.codeType() != EvalCode) { 1803 1804 ResolveScopeInfo resolveScopeInfo; 1805 if (RefPtr<RegisterID> scope = generator.emitResolveConstantLocal(generator.newTemporary(), m_ident, resolveScopeInfo)) 1806 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo); 1807 1808 return value.get(); 1766 // Do a special kind of resolution. If anything fails, then don't perform the assignment. This is 1767 // pretty shady - particularly how negligent it is with inteleaving scopes - but it's the 1768 // behavior that JSC has had for a long time. 1769 1770 ASSERT(generator.codeType() == FunctinCode); 1771 1772 var = generator.variablePerSymbolTable(m_ident); 1773 if (!var.isResolved()) 1774 return value.get(); 1775 1776 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), var); 1777 return generator.emitPutToScope(scope.get(), var, value.get(), DoNotThrowIfNotFound); 1809 1778 } 1810 1779 1811 1780 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope. 1812 ResolveScopeInfo resolveScopeInfo; 1813 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, m_ident, resolveScopeInfo); 1814 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo); 1781 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 1782 return generator.emitPutToScope(scope.get(), var, value.get(), DoNotThrowIfNotFound); 1815 1783 } 1816 1784 … … 1904 1872 return nullptr; 1905 1873 1906 if (Local local = generator.local(m_ident)) 1907 generator.emitProfileType(local.get(), ProfileTypeBytecodeHasGlobalID, nullptr); 1874 Variable var = generator.variable(m_ident); 1875 if (RegisterID* local = var.local()) 1876 generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr); 1908 1877 else { 1909 ResolveScopeInfo resolveScopeInfo; 1910 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, m_ident, resolveScopeInfo); 1911 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo); 1912 generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident); 1878 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 1879 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound); 1880 generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident); 1913 1881 } 1914 1882 … … 2080 2048 if (m_lexpr->isResolveNode()) { 2081 2049 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); 2082 Local local = generator.local(ident); 2083 return local.get(); 2050 return generator.variable(ident).local(); 2084 2051 } 2085 2052 … … 2092 2059 auto simpleBinding = static_cast<BindingNode*>(binding); 2093 2060 const Identifier& ident = simpleBinding->boundProperty(); 2094 Local local = generator.local(ident);2095 if ( local.isSpecial())2061 Variable var = generator.variable(ident); 2062 if (var.isSpecial()) 2096 2063 return nullptr; 2097 return local.get();2064 return var.local(); 2098 2065 } 2099 2066 … … 2105 2072 if (m_lexpr->isResolveNode()) { 2106 2073 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); 2107 Local local = generator.local(ident);2108 if ( local.get())2109 generator.emitMove(local .get(), propertyName);2074 Variable var = generator.variable(ident); 2075 if (RegisterID* local = var.local()) 2076 generator.emitMove(local, propertyName); 2110 2077 else { 2111 2078 if (generator.isStrictMode()) 2112 2079 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 2113 ResolveScopeInfo resolveScopeInfo; 2114 RegisterID* scope = generator.emitResolveScope(nullptr, ident, resolveScopeInfo); 2080 RegisterID* scope = generator.emitResolveScope(nullptr, var); 2115 2081 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 2116 generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);2082 generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 2117 2083 if (generator.vm()->typeProfiler()) 2118 generator.emitProfileType(propertyName, resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);2084 generator.emitProfileType(propertyName, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident); 2119 2085 } 2120 2086 if (generator.vm()->typeProfiler()) … … 2157 2123 auto simpleBinding = static_cast<BindingNode*>(binding); 2158 2124 const Identifier& ident = simpleBinding->boundProperty(); 2159 Local local = generator.local(ident);2160 if (! local.get() || local.isSpecial()) {2125 Variable var = generator.variable(ident); 2126 if (!var.local() || var.isSpecial()) { 2161 2127 assignNode->bindings()->bindValue(generator, propertyName); 2162 2128 return; 2163 2129 } 2164 generator.emitMove( local.get(), propertyName);2130 generator.emitMove(var.local(), propertyName); 2165 2131 if (generator.vm()->typeProfiler()) 2166 2132 generator.emitTypeProfilerExpressionInfo(simpleBinding->divotStart(), simpleBinding->divotEnd()); … … 2330 2296 if (m_lexpr->isResolveNode()) { 2331 2297 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); 2332 if (Local local = generator.local(ident)) 2333 generator.emitMove(local.get(), value); 2298 Variable var = generator.variable(ident); 2299 if (RegisterID* local = var.local()) 2300 generator.emitMove(local, value); 2334 2301 else { 2335 2302 if (generator.isStrictMode()) 2336 2303 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 2337 ResolveScopeInfo resolveScopeInfo; 2338 RegisterID* scope = generator.emitResolveScope(nullptr, ident, resolveScopeInfo); 2304 RegisterID* scope = generator.emitResolveScope(nullptr, var); 2339 2305 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); 2340 generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);2306 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 2341 2307 if (generator.vm()->typeProfiler()) 2342 generator.emitProfileType(value, resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);2308 generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident); 2343 2309 } 2344 2310 if (generator.vm()->typeProfiler()) … … 2965 2931 RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs) 2966 2932 { 2967 if (rhs->isResolveNode()2968 && generator.willResolveToArgumentsRegister(static_cast<ResolveNode*>(rhs)->identifier())2969 && generator.hasSafeLocalArgumentsRegister()&& !generator.symbolTable().slowArguments()) {2970 for (size_t i = 0; i < m_targetPatterns.size(); i++) {2971 auto target = m_targetPatterns[i];2972 if (!target)2973 continue;2974 2975 RefPtr<RegisterID> temp = generator.newTemporary();2976 generator.emitLoad(temp.get(), jsNumber(i));2977 generator.emitGetArgumentByVal(temp.get(), generator.uncheckedLocalArgumentsRegister(), temp.get());2978 target->bindValue(generator, temp.get());2979 }2980 if (dst == generator.ignoredResult() || !dst)2981 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());2982 Local local = generator.local(generator.vm()->propertyNames->arguments);2983 return generator.moveToDestinationIfNeeded(dst, local.get());2984 }2985 2933 if (!rhs->isSimpleArray()) 2986 2934 return 0; … … 3070 3018 void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const 3071 3019 { 3072 if (Local local = generator.local(m_boundProperty)) { 3073 if (local.isReadOnly()) { 3020 Variable var = generator.variable(m_boundProperty); 3021 if (RegisterID* local = var.local()) { 3022 if (var.isReadOnly()) { 3074 3023 generator.emitReadOnlyExceptionIfNeeded(); 3075 3024 return; 3076 3025 } 3077 generator.emitMove(local .get(), value);3026 generator.emitMove(local, value); 3078 3027 if (generator.vm()->typeProfiler()) 3079 3028 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); … … 3082 3031 if (generator.isStrictMode()) 3083 3032 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd()); 3084 ResolveScopeInfo resolveScopeInfo; 3085 RegisterID* scope = generator.emitResolveScope(nullptr, m_boundProperty, resolveScopeInfo); 3033 RegisterID* scope = generator.emitResolveScope(nullptr, var); 3086 3034 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd()); 3087 generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);3035 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 3088 3036 if (generator.vm()->typeProfiler()) { 3089 generator.emitProfileType(value, resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty);3037 generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty); 3090 3038 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); 3091 3039 } -
trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h
r180656 r181993 48 48 macro(Stack) \ 49 49 macro(Heap) \ 50 macro(Arguments_registers) \51 50 macro(Butterfly_publicLength) \ 52 51 macro(Butterfly_vectorLength) \ … … 58 57 macro(JSCell_typeInfoType) \ 59 58 macro(JSObject_butterfly) \ 60 macro(JSEnvironmentRecord_registers) \61 59 macro(JSPropertyNameEnumerator_cachedPropertyNames) \ 62 60 macro(NamedProperties) \ … … 66 64 macro(IndexedArrayStorageProperties) \ 67 65 macro(ArrayStorageProperties) \ 68 macro(Variables) \ 66 macro(DirectArgumentsProperties) \ 67 macro(ScopeProperties) \ 69 68 macro(TypedArrayProperties) \ 70 69 macro(HeapObjectCount) /* Used to reflect the fact that some allocations reveal object identity */\ -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
r173993 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 149 149 private: 150 150 void clobberWorld(const CodeOrigin&, unsigned indexInBlock); 151 void clobberCapturedVars(const CodeOrigin&);152 151 153 152 template<typename Functor> -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r181891 r181993 132 132 case JSConstant: 133 133 case DoubleConstant: 134 case Int52Constant: 135 case PhantomArguments: { 134 case Int52Constant: { 136 135 setBuiltInConstant(node, *node->constant()); 137 136 break; … … 140 139 case Identity: { 141 140 forNode(node) = forNode(node->child1()); 141 if (forNode(node).value()) 142 m_state.setFoundConstants(true); 142 143 break; 143 144 } … … 208 209 break; 209 210 210 case LoadVarargs: { 211 case LoadVarargs: 212 case ForwardVarargs: { 213 // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn 214 // itself into a straight-line sequence of GetStack/PutStack. 215 // https://bugs.webkit.org/show_bug.cgi?id=143071 211 216 clobberWorld(node->origin.semantic, clobberLimit); 212 217 LoadVarargsData* data = node->loadVarargsData(); … … 880 885 } 881 886 882 if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || is ArgumentsSpeculation(abstractChild.m_type)) {887 if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isDirectArgumentsSpeculation(abstractChild.m_type) || isScopedArgumentsSpeculation(abstractChild.m_type)) { 883 888 setConstant(node, *m_graph.freeze(vm->smallStrings.objectString())); 884 889 break; … … 1032 1037 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); 1033 1038 break; 1034 case Array::Arguments: 1039 case Array::DirectArguments: 1040 case Array::ScopedArguments: 1035 1041 forNode(node).makeHeapTop(); 1036 1042 break; … … 1139 1145 forNode(node).makeHeapTop(); 1140 1146 break; 1147 1148 case GetMyArgumentByVal: { 1149 JSValue index = forNode(node->child2()).m_value; 1150 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame; 1151 1152 if (index && index.isInt32()) { 1153 // This pretends to return TOP for accesses that are actually proven out-of-bounds because 1154 // that's the conservative thing to do. Otherwise we'd need to write more code to mark such 1155 // paths as unreachable, and it's almost certainly not worth the effort. 1156 1157 if (inlineCallFrame) { 1158 if (index.asUInt32() < inlineCallFrame->arguments.size() - 1) { 1159 forNode(node) = m_state.variables().operand( 1160 virtualRegisterForArgument(index.asInt32() + 1) + inlineCallFrame->stackOffset); 1161 m_state.setFoundConstants(true); 1162 break; 1163 } 1164 } else { 1165 if (index.asUInt32() < m_state.variables().numberOfArguments() - 1) { 1166 forNode(node) = m_state.variables().argument(index.asInt32() + 1); 1167 m_state.setFoundConstants(true); 1168 break; 1169 } 1170 } 1171 } 1172 1173 if (inlineCallFrame) { 1174 // We have a bound on the types even though it's random access. Take advantage of this. 1175 1176 AbstractValue result; 1177 for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;) { 1178 result.merge( 1179 m_state.variables().operand( 1180 virtualRegisterForArgument(i) + inlineCallFrame->stackOffset)); 1181 } 1182 1183 if (result.value()) 1184 m_state.setFoundConstants(true); 1185 forNode(node) = result; 1186 break; 1187 } 1188 1189 forNode(node).makeHeapTop(); 1190 break; 1191 } 1141 1192 1142 1193 case RegExpExec: … … 1304 1355 1305 1356 case PhantomNewObject: 1357 case PhantomDirectArguments: 1358 case PhantomClonedArguments: 1306 1359 case BottomValue: 1307 1360 m_state.setDidClobber(true); // Prevent constant folding. … … 1333 1386 break; 1334 1387 1335 case CreateArguments: 1336 forNode(node) = forNode(node->child1()); 1337 forNode(node).filter(~SpecEmpty); 1338 forNode(node).merge(SpecArguments); 1339 break; 1340 1341 case TearOffArguments: 1342 // Does nothing that is user-visible. 1343 break; 1344 1345 case CheckArgumentsNotCreated: 1346 if (isEmptySpeculation( 1347 m_state.variables().operand( 1348 m_graph.argumentsRegisterFor(node->origin.semantic).offset()).m_type)) 1349 m_state.setFoundConstants(true); 1350 break; 1351 1352 case GetMyArgumentsLength: 1353 // We know that this executable does not escape its arguments, so we can optimize 1354 // the arguments a bit. Note that this is not sufficient to force constant folding 1355 // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation. 1356 // We perform further optimizations on this later on. 1357 if (node->origin.semantic.inlineCallFrame 1358 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 1359 setConstant( 1360 node, jsNumber(node->origin.semantic.inlineCallFrame->arguments.size() - 1)); 1361 m_state.setDidClobber(true); // Pretend that we clobbered to prevent constant folding. 1362 } else 1363 forNode(node).setType(SpecInt32); 1364 break; 1365 1366 case GetMyArgumentsLengthSafe: 1367 // This potentially clobbers all structures if the arguments object had a getter 1368 // installed on the length property. 1369 clobberWorld(node->origin.semantic, clobberLimit); 1370 // We currently make no guarantee about what this returns because it does not 1371 // speculate that the length property is actually a length. 1372 forNode(node).makeHeapTop(); 1373 break; 1374 1375 case GetMyArgumentByVal: { 1376 InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame; 1377 JSValue value = forNode(node->child1()).m_value; 1378 if (inlineCallFrame && value && value.isInt32()) { 1379 int32_t index = value.asInt32(); 1380 if (index >= 0 1381 && static_cast<size_t>(index + 1) < inlineCallFrame->arguments.size()) { 1382 forNode(node) = m_state.variables().operand( 1383 inlineCallFrame->stackOffset + 1384 m_graph.baselineCodeBlockFor(inlineCallFrame)->argumentIndexAfterCapture(index)); 1385 m_state.setFoundConstants(true); 1386 break; 1387 } 1388 } 1389 forNode(node).makeHeapTop(); 1390 break; 1391 } 1392 1393 case GetMyArgumentByValSafe: 1394 // This potentially clobbers all structures if the property we're accessing has 1395 // a getter. We don't speculate against this. 1396 clobberWorld(node->origin.semantic, clobberLimit); 1397 // And the result is unknown. 1398 forNode(node).makeHeapTop(); 1399 break; 1400 1401 case NewFunction: { 1402 AbstractValue& value = forNode(node); 1403 value = forNode(node->child1()); 1404 1405 if (!(value.m_type & SpecEmpty)) { 1406 m_state.setFoundConstants(true); 1407 break; 1408 } 1409 1410 value.setType((value.m_type & ~SpecEmpty) | SpecFunction); 1411 break; 1412 } 1413 1414 case NewFunctionExpression: 1415 case NewFunctionNoCheck: 1388 case CreateDirectArguments: 1389 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure()); 1390 break; 1391 1392 case CreateScopedArguments: 1393 forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure()); 1394 break; 1395 1396 case CreateClonedArguments: 1397 forNode(node).setType(SpecObjectOther); 1398 break; 1399 1400 case NewFunction: 1416 1401 forNode(node).set( 1417 1402 m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->functionStructure()); … … 1420 1405 case GetCallee: 1421 1406 forNode(node).setType(SpecFunction); 1407 break; 1408 1409 case GetArgumentCount: 1410 forNode(node).setType(SpecInt32); 1422 1411 break; 1423 1412 … … 1470 1459 } 1471 1460 1472 case GetClosureRegisters:1473 forNode(node).clear(); // The result is not a JS value.1474 break;1475 1476 1461 case GetClosureVar: 1477 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), VirtualRegister(node->varNumber()))) {1462 if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) { 1478 1463 setConstant(node, *m_graph.freeze(value)); 1479 1464 break; … … 1483 1468 1484 1469 case PutClosureVar: 1485 clobberCapturedVars(node->origin.semantic); 1470 break; 1471 1472 case GetFromArguments: 1473 forNode(node).makeHeapTop(); 1474 break; 1475 1476 case PutToArguments: 1486 1477 break; 1487 1478 … … 1627 1618 case Array::SlowPutArrayStorage: 1628 1619 break; 1629 case Array::Arguments: 1630 filter(node->child1(), SpecArguments); 1620 case Array::DirectArguments: 1621 filter(node->child1(), SpecDirectArguments); 1622 break; 1623 case Array::ScopedArguments: 1624 filter(node->child1(), SpecScopedArguments); 1631 1625 break; 1632 1626 case Array::Int8Array: … … 2027 2021 case CallForwardVarargs: 2028 2022 case ConstructVarargs: 2023 case ConstructForwardVarargs: 2029 2024 clobberWorld(node->origin.semantic, clobberLimit); 2030 2025 forNode(node).makeHeapTop(); … … 2121 2116 template<typename AbstractStateType> 2122 2117 void AbstractInterpreter<AbstractStateType>::clobberWorld( 2123 const CodeOrigin& codeOrigin, unsigned clobberLimit) 2124 { 2125 clobberCapturedVars(codeOrigin); 2118 const CodeOrigin&, unsigned clobberLimit) 2119 { 2126 2120 clobberStructures(clobberLimit); 2127 }2128 2129 template<typename AbstractStateType>2130 void AbstractInterpreter<AbstractStateType>::clobberCapturedVars(const CodeOrigin& codeOrigin)2131 {2132 SamplingRegion samplingRegion("DFG AI Clobber Captured Vars");2133 if (codeOrigin.inlineCallFrame) {2134 const BitVector& capturedVars = codeOrigin.inlineCallFrame->capturedVars;2135 for (size_t i = capturedVars.size(); i--;) {2136 if (!capturedVars.quickGet(i))2137 continue;2138 m_state.variables().local(i).makeHeapTop();2139 }2140 } else {2141 for (size_t i = m_codeBlock->m_numVars; i--;) {2142 if (m_codeBlock->isCaptured(virtualRegisterForLocal(i)))2143 m_state.variables().local(i).makeHeapTop();2144 }2145 }2146 2147 for (size_t i = m_state.variables().numberOfArguments(); i--;) {2148 if (m_codeBlock->isCaptured(virtualRegisterForArgument(i)))2149 m_state.variables().argument(i).makeHeapTop();2150 }2151 2121 } 2152 2122 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r172737 r181993 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 347 347 // This is a proven constraint on the possible types that this value can have 348 348 // now or any time in the future, unless it is reassigned. This field is 349 // impervious to side-effects unless the side-effect can reassign the value 350 // (for example if we're talking about a captured variable). The relationship 351 // between this field, and the structure fields above, is as follows. The 352 // fields above constraint the structures that a cell may have, but they say 353 // nothing about whether or not the value is known to be a cell. More formally, 354 // the m_structure is itself an abstract value that consists of the 355 // union of the set of all non-cell values and the set of cell values that have 356 // the given structure. This abstract value is then the intersection of the 357 // m_structure and the set of values whose type is m_type. So, for 358 // example if m_type is SpecFinal|SpecInt32 and m_structure is 359 // [0x12345] then this abstract value corresponds to the set of all integers 360 // unified with the set of all objects with structure 0x12345. 349 // impervious to side-effects. The relationship between this field, and the 350 // structure fields above, is as follows. The fields above constraint the 351 // structures that a cell may have, but they say nothing about whether or not 352 // the value is known to be a cell. More formally, the m_structure is itself an 353 // abstract value that consists of the union of the set of all non-cell values 354 // and the set of cell values that have the given structure. This abstract 355 // value is then the intersection of the m_structure and the set of values 356 // whose type is m_type. So, for example if m_type is SpecFinal|SpecInt32 and 357 // m_structure is [0x12345] then this abstract value corresponds to the set of 358 // all integers unified with the set of all objects with structure 0x12345. 361 359 SpeculatedType m_type; 362 360 -
trunk/Source/JavaScriptCore/dfg/DFGArgumentPosition.h
r179503 r181993 47 47 { 48 48 m_variables.append(variable); 49 50 // We may set this early. Merging it here saves us time in prediction propagation. 51 variable->mergeShouldNeverUnbox(m_shouldNeverUnbox); 49 52 } 50 53 -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
r180703 r181993 198 198 return withType(Array::String); 199 199 200 if (isArgumentsSpeculation(base)) 201 return withType(Array::Arguments); 200 if (isDirectArgumentsSpeculation(base) || isScopedArgumentsSpeculation(base)) { 201 // Handle out-of-bounds accesses as generic accesses. 202 if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds()) 203 return ArrayMode(Array::Generic); 204 205 if (isDirectArgumentsSpeculation(base)) 206 return withType(Array::DirectArguments); 207 return withType(Array::ScopedArguments); 208 } 202 209 203 210 ArrayMode result; … … 397 404 } } 398 405 399 case Array::Arguments: 400 return speculationChecked(value.m_type, SpecArguments); 406 case Array::DirectArguments: 407 return speculationChecked(value.m_type, SpecDirectArguments); 408 409 case Array::ScopedArguments: 410 return speculationChecked(value.m_type, SpecScopedArguments); 401 411 402 412 case Array::Int8Array: … … 462 472 case Array::SlowPutArrayStorage: 463 473 return "SlowPutArrayStorage"; 464 case Array::Arguments: 465 return "Arguments"; 474 case Array::DirectArguments: 475 return "DirectArguments"; 476 case Array::ScopedArguments: 477 return "ScopedArguments"; 466 478 case Array::Int8Array: 467 479 return "Int8Array"; -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h
r176972 r181993 1 1 /* 2 * Copyright (C) 2012 , 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 66 66 SlowPutArrayStorage, 67 67 68 Arguments, 68 DirectArguments, 69 ScopedArguments, 70 69 71 Int8Array, 70 72 Int16Array, … … 295 297 case Array::ForceExit: 296 298 case Array::Generic: 297 case Array::Arguments: 299 case Array::DirectArguments: 300 case Array::ScopedArguments: 298 301 return false; 299 302 default: … … 321 324 switch (type()) { 322 325 case Array::String: 326 case Array::DirectArguments: 327 case Array::ScopedArguments: 323 328 return ArrayMode(Array::Generic); 324 #if USE(JSVALUE32_64)325 case Array::Arguments:326 return ArrayMode(Array::Generic);327 #endif328 329 default: 329 330 return *this; -
trunk/Source/JavaScriptCore/dfg/DFGAvailabilityMap.cpp
r181348 r181993 46 46 } 47 47 48 unsigned oldPossibleNodesSize; 49 do { 50 oldPossibleNodesSize = possibleNodes.size(); 51 for (auto pair : m_heap) { 52 if (pair.value.hasNode() && possibleNodes.contains(pair.key.base())) 53 possibleNodes.add(pair.value.node()); 54 } 55 } while (oldPossibleNodesSize != possibleNodes.size()); 48 closeOverNodes( 49 [&] (Node* node) -> bool { 50 return possibleNodes.contains(node); 51 }, 52 [&] (Node* node) -> bool { 53 return possibleNodes.add(node).isNewEntry; 54 }); 56 55 57 56 HashMap<PromotedHeapLocation, Availability> newHeap; -
trunk/Source/JavaScriptCore/dfg/DFGAvailabilityMap.h
r173993 r181993 53 53 } 54 54 55 template<typename HasFunctor, typename AddFunctor> 56 void closeOverNodes(const HasFunctor& has, const AddFunctor& add) 57 { 58 bool changed; 59 do { 60 changed = false; 61 for (auto pair : m_heap) { 62 if (pair.value.hasNode() && has(pair.key.base())) 63 changed |= add(pair.value.node()); 64 } 65 } while (changed); 66 } 67 68 template<typename HasFunctor, typename AddFunctor> 69 void closeStartingWithLocal(VirtualRegister reg, const HasFunctor& has, const AddFunctor& add) 70 { 71 Availability availability = m_locals.operand(reg); 72 if (!availability.hasNode()) 73 return; 74 75 if (!add(availability.node())) 76 return; 77 78 closeOverNodes(has, add); 79 } 80 55 81 Operands<Availability> m_locals; 56 82 HashMap<PromotedHeapLocation, Availability> m_heap; -
trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
r180813 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 324 324 node->child1()->mergeFlags(NodeBytecodeUsesAsValue); 325 325 node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); 326 break;327 }328 329 case GetMyArgumentByValSafe: {330 node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex);331 326 break; 332 327 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r181891 r181993 226 226 void linkBlocks(Vector<UnlinkedBlock>& unlinkedBlocks, Vector<BasicBlock*>& possibleTargets); 227 227 228 VariableAccessData* newVariableAccessData(VirtualRegister operand , bool isCaptured)228 VariableAccessData* newVariableAccessData(VirtualRegister operand) 229 229 { 230 230 ASSERT(!operand.isConstant()); 231 231 232 m_graph.m_variableAccessData.append(VariableAccessData(operand , isCaptured));232 m_graph.m_variableAccessData.append(VariableAccessData(operand)); 233 233 return &m_graph.m_variableAccessData.last(); 234 234 } … … 347 347 348 348 Node* node = m_currentBlock->variablesAtTail.local(local); 349 bool isCaptured = m_codeBlock->isCaptured(operand, inlineCallFrame());350 349 351 350 // This has two goals: 1) link together variable access datas, and 2) … … 359 358 if (node) { 360 359 variable = node->variableAccessData(); 361 variable->mergeIsCaptured(isCaptured); 362 363 if (!isCaptured) { 364 switch (node->op()) { 365 case GetLocal: 366 return node; 367 case SetLocal: 368 return node->child1().node(); 369 default: 370 break; 371 } 360 361 switch (node->op()) { 362 case GetLocal: 363 return node; 364 case SetLocal: 365 return node->child1().node(); 366 default: 367 break; 372 368 } 373 369 } else 374 variable = newVariableAccessData(operand , isCaptured);370 variable = newVariableAccessData(operand); 375 371 376 372 node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable))); … … 385 381 386 382 unsigned local = operand.toLocal(); 387 bool isCaptured = m_codeBlock->isCaptured(operand, inlineCallFrame());388 383 389 384 if (setMode != ImmediateNakedSet) { 390 385 ArgumentPosition* argumentPosition = findArgumentPositionForLocal(operand); 391 if ( isCaptured ||argumentPosition)386 if (argumentPosition) 392 387 flushDirect(operand, argumentPosition); 393 388 } 394 389 395 VariableAccessData* variableAccessData = newVariableAccessData(operand , isCaptured);390 VariableAccessData* variableAccessData = newVariableAccessData(operand); 396 391 variableAccessData->mergeStructureCheckHoistingFailed( 397 392 m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadCache)); … … 412 407 413 408 Node* node = m_currentBlock->variablesAtTail.argument(argument); 414 bool isCaptured = m_codeBlock->isCaptured(operand);415 409 416 410 VariableAccessData* variable; … … 418 412 if (node) { 419 413 variable = node->variableAccessData(); 420 variable->mergeIsCaptured(isCaptured); 421 422 if (!isCaptured) { 423 switch (node->op()) { 424 case GetLocal: 425 return node; 426 case SetLocal: 427 return node->child1().node(); 428 default: 429 break; 430 } 414 415 switch (node->op()) { 416 case GetLocal: 417 return node; 418 case SetLocal: 419 return node->child1().node(); 420 default: 421 break; 431 422 } 432 423 } else 433 variable = newVariableAccessData(operand , isCaptured);424 variable = newVariableAccessData(operand); 434 425 435 426 node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable))); … … 445 436 ASSERT(argument < m_numArguments); 446 437 447 bool isCaptured = m_codeBlock->isCaptured(operand); 448 449 VariableAccessData* variableAccessData = newVariableAccessData(operand, isCaptured); 438 VariableAccessData* variableAccessData = newVariableAccessData(operand); 450 439 451 440 // Always flush arguments, except for 'this'. If 'this' is created by us, … … 513 502 void flushDirect(VirtualRegister operand, ArgumentPosition* argumentPosition) 514 503 { 515 bool isCaptured = m_codeBlock->isCaptured(operand, inlineCallFrame());516 517 504 ASSERT(!operand.isConstant()); 518 505 … … 521 508 VariableAccessData* variable; 522 509 523 if (node) {510 if (node) 524 511 variable = node->variableAccessData(); 525 variable->mergeIsCaptured(isCaptured); 526 } else 527 variable = newVariableAccessData(operand, isCaptured); 512 else 513 variable = newVariableAccessData(operand); 528 514 529 515 node = addToGraph(Flush, OpInfo(variable)); … … 546 532 for (unsigned argument = numArguments; argument-- > 1;) 547 533 flushDirect(inlineStackEntry->remapOperand(virtualRegisterForArgument(argument))); 548 for (int local = 0; local < inlineStackEntry->m_codeBlock->m_numVars; ++local) {549 if (!inlineStackEntry->m_codeBlock->isCaptured(virtualRegisterForLocal(local)))550 continue;551 flushDirect(inlineStackEntry->remapOperand(virtualRegisterForLocal(local)));552 }553 534 } 554 535 … … 843 824 844 825 return node; 826 } 827 828 void noticeArgumentsUse() 829 { 830 // All of the arguments in this function need to be formatted as JSValues because we will 831 // load from them in a random-access fashion and we don't want to have to switch on 832 // format. 833 834 for (ArgumentPosition* argument : m_inlineStackTop->m_argumentPositions) 835 argument->mergeShouldNeverUnbox(true); 845 836 } 846 837 … … 1123 1114 if (callTarget->isCellConstant()) 1124 1115 callLinkStatus.setProvenConstantCallee(CallVariant(callTarget->asCell())); 1116 1117 if (Options::verboseDFGByteCodeParsing()) 1118 dataLog(" Varargs call link status at ", currentCodeOrigin(), ": ", callLinkStatus, "\n"); 1125 1119 1126 1120 if (callLinkStatus.canOptimize() … … 1432 1426 dataLog(" Considering callee ", callee, "\n"); 1433 1427 1434 if (InternalFunction* function = callee.internalFunction()) { 1435 if (handleConstantInternalFunction(resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, insertChecksWithAccounting)) { 1436 RELEASE_ASSERT(didInsertChecks); 1437 addToGraph(Phantom, callTargetNode); 1438 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis); 1439 inliningBalance--; 1440 return true; 1441 } 1442 RELEASE_ASSERT(!didInsertChecks); 1443 return false; 1444 } 1445 1446 Intrinsic intrinsic = callee.intrinsicFor(specializationKind); 1447 if (intrinsic != NoIntrinsic) { 1448 if (handleIntrinsic(resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) { 1449 RELEASE_ASSERT(didInsertChecks); 1450 addToGraph(Phantom, callTargetNode); 1451 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis); 1452 inliningBalance--; 1453 return true; 1454 } 1455 RELEASE_ASSERT(!didInsertChecks); 1456 return false; 1428 // Intrinsics and internal functions can only be inlined if we're not doing varargs. This is because 1429 // we currently don't have any way of getting profiling information for arguments to non-JS varargs 1430 // calls. The prediction propagator won't be of any help because LoadVarargs obscures the data flow, 1431 // and there are no callsite value profiles and native function won't have callee value profiles for 1432 // those arguments. Even worse, if the intrinsic decides to exit, it won't really have anywhere to 1433 // exit to: LoadVarargs is effectful and it's part of the op_call_varargs, so we can't exit without 1434 // calling LoadVarargs twice. 1435 if (!InlineCallFrame::isVarargs(kind)) { 1436 if (InternalFunction* function = callee.internalFunction()) { 1437 if (handleConstantInternalFunction(resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, insertChecksWithAccounting)) { 1438 RELEASE_ASSERT(didInsertChecks); 1439 addToGraph(Phantom, callTargetNode); 1440 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis); 1441 inliningBalance--; 1442 return true; 1443 } 1444 RELEASE_ASSERT(!didInsertChecks); 1445 return false; 1446 } 1447 1448 Intrinsic intrinsic = callee.intrinsicFor(specializationKind); 1449 if (intrinsic != NoIntrinsic) { 1450 if (handleIntrinsic(resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) { 1451 RELEASE_ASSERT(didInsertChecks); 1452 addToGraph(Phantom, callTargetNode); 1453 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis); 1454 inliningBalance--; 1455 return true; 1456 } 1457 RELEASE_ASSERT(!didInsertChecks); 1458 return false; 1459 } 1457 1460 } 1458 1461 … … 1541 1544 m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset(); 1542 1545 1546 ensureLocals(VirtualRegister(remappedRegisterOffset).toLocal()); 1547 1543 1548 int argumentStart = registerOffset + JSStack::CallFrameHeaderSize; 1544 1549 int remappedArgumentStart = … … 1560 1565 1561 1566 VariableAccessData* countVariable = newVariableAccessData( 1562 VirtualRegister(remappedRegisterOffset + JSStack::ArgumentCount) , false);1567 VirtualRegister(remappedRegisterOffset + JSStack::ArgumentCount)); 1563 1568 // This is pretty lame, but it will force the count to be flushed as an int. This doesn't 1564 1569 // matter very much, since our use of a SetArgument and Flushes for this local slot is … … 1572 1577 for (unsigned argument = 1; argument < maxNumArguments; ++argument) { 1573 1578 VariableAccessData* variable = newVariableAccessData( 1574 VirtualRegister(remappedArgumentStart + argument) , false);1579 VirtualRegister(remappedArgumentStart + argument)); 1575 1580 variable->mergeShouldNeverUnbox(true); // We currently have nowhere to put the type check on the LoadVarargs. LoadVarargs is effectful, so after it finishes, we cannot exit. 1576 1581 … … 2535 2540 for (unsigned argument = 0; argument < m_numArguments; ++argument) { 2536 2541 VariableAccessData* variable = newVariableAccessData( 2537 virtualRegisterForArgument(argument) , m_codeBlock->isCaptured(virtualRegisterForArgument(argument)));2542 virtualRegisterForArgument(argument)); 2538 2543 variable->mergeStructureCheckHoistingFailed( 2539 2544 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); … … 3085 3090 addToGraph( 3086 3091 PutGlobalVar, 3087 OpInfo(m_inlineStackTop->m_codeBlock->globalObject()->assert RegisterIsInThisObject(currentInstruction[1].u.registerPointer)),3092 OpInfo(m_inlineStackTop->m_codeBlock->globalObject()->assertVariableIsInThisObject(currentInstruction[1].u.variablePointer)), 3088 3093 value); 3089 3094 NEXT_OPCODE(op_init_global_const); … … 3328 3333 3329 3334 case op_call_varargs: { 3330 int result = currentInstruction[1].u.operand;3331 int callee = currentInstruction[2].u.operand;3332 int thisReg = currentInstruction[3].u.operand;3333 int arguments = currentInstruction[4].u.operand;3334 int firstFreeReg = currentInstruction[5].u.operand;3335 int firstVarArgOffset = currentInstruction[6].u.operand;3336 3337 if (arguments == m_inlineStackTop->m_codeBlock->uncheckedArgumentsRegister().offset()3338 && !m_inlineStackTop->m_codeBlock->symbolTable()->slowArguments()) {3339 if (inlineCallFrame()3340 && !inlineCallFrame()->isVarargs()3341 && !firstVarArgOffset) {3342 addToGraph(CheckArgumentsNotCreated);3343 3344 unsigned argCount = inlineCallFrame()->arguments.size();3345 3346 // Let's compute the register offset. We start with the last used register, and3347 // then adjust for the things we want in the call frame.3348 int registerOffset = firstFreeReg + 1;3349 registerOffset -= argCount; // We will be passing some arguments.3350 registerOffset -= JSStack::CallFrameHeaderSize; // We will pretend to have a call frame header.3351 3352 // Get the alignment right.3353 registerOffset = -WTF::roundUpToMultipleOf(3354 stackAlignmentRegisters(),3355 -registerOffset);3356 3357 ensureLocals(3358 m_inlineStackTop->remapOperand(3359 VirtualRegister(registerOffset)).toLocal());3360 3361 // The bytecode wouldn't have set up the arguments. But we'll do it and make it3362 // look like the bytecode had done it.3363 int nextRegister = registerOffset + JSStack::CallFrameHeaderSize;3364 set(VirtualRegister(nextRegister++), get(VirtualRegister(thisReg)), ImmediateNakedSet);3365 for (unsigned argument = 1; argument < argCount; ++argument)3366 set(VirtualRegister(nextRegister++), get(virtualRegisterForArgument(argument)), ImmediateNakedSet);3367 3368 handleCall(3369 result, Call, CodeForCall, OPCODE_LENGTH(op_call_varargs),3370 callee, argCount, registerOffset);3371 NEXT_OPCODE(op_call_varargs);3372 }3373 3374 // Emit CallForwardVarargs3375 // FIXME: This means we cannot inline forwarded varargs calls inside a varargs3376 // call frame. We will probably fix that once we finally get rid of the3377 // arguments object special-casing.3378 CallVarargsData* data = m_graph.m_callVarargsData.add();3379 data->firstVarArgOffset = firstVarArgOffset;3380 3381 Node* call = addToGraph(3382 CallForwardVarargs, OpInfo(data), OpInfo(getPrediction()),3383 get(VirtualRegister(callee)), get(VirtualRegister(thisReg)));3384 VirtualRegister resultReg(result);3385 if (resultReg.isValid())3386 set(resultReg, call);3387 NEXT_OPCODE(op_call_varargs);3388 }3389 3390 3335 handleVarargsCall(currentInstruction, CallVarargs, CodeForCall); 3391 3336 NEXT_OPCODE(op_call_varargs); … … 3512 3457 case ClosureVarWithVarInjectionChecks: { 3513 3458 Node* scopeNode = get(VirtualRegister(scope)); 3514 if (JSValue value = m_graph.tryGetConstantClosureVar(scopeNode, VirtualRegister(operand))) { 3515 addToGraph(Phantom, scopeNode); 3459 3460 // Ideally we wouldn't have to do this Phantom. But: 3461 // 3462 // For the constant case: we must do it because otherwise we would have no way of knowing 3463 // that the scope is live at OSR here. 3464 // 3465 // For the non-constant case: GetClosureVar could be DCE'd, but baseline's implementation 3466 // won't be able to handle an Undefined scope. 3467 addToGraph(Phantom, scopeNode); 3468 3469 if (JSValue value = m_graph.tryGetConstantClosureVar(scopeNode, ScopeOffset(operand))) { 3516 3470 set(VirtualRegister(dst), weakJSConstant(value)); 3517 3471 break; … … 3519 3473 SpeculatedType prediction = getPrediction(); 3520 3474 set(VirtualRegister(dst), 3521 addToGraph( 3522 GetClosureVar, OpInfo(operand), OpInfo(prediction), 3523 scopeNode, addToGraph(GetClosureRegisters, scopeNode))); 3475 addToGraph(GetClosureVar, OpInfo(operand), OpInfo(prediction), scopeNode)); 3524 3476 break; 3525 3477 } … … 3533 3485 case op_put_to_scope: { 3534 3486 unsigned scope = currentInstruction[1].u.operand; 3535 unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand]; 3487 unsigned identifierNumber = currentInstruction[2].u.operand; 3488 if (identifierNumber != UINT_MAX) 3489 identifierNumber = m_inlineStackTop->m_identifierRemap[identifierNumber]; 3536 3490 unsigned value = currentInstruction[3].u.operand; 3537 3491 ResolveType resolveType = ResolveModeAndType(currentInstruction[4].u.operand).type(); 3538 AtomicStringImpl* uid = m_graph.identifiers()[identifierNumber]; 3539 3540 Structure* structure = 0; 3541 VariableWatchpointSet* watchpoints = 0; 3492 AtomicStringImpl* uid; 3493 if (identifierNumber != UINT_MAX) 3494 uid = m_graph.identifiers()[identifierNumber]; 3495 else 3496 uid = nullptr; 3497 3498 Structure* structure = nullptr; 3499 VariableWatchpointSet* watchpoints = nullptr; 3542 3500 uintptr_t operand; 3543 3501 { … … 3555 3513 case GlobalProperty: 3556 3514 case GlobalPropertyWithVarInjectionChecks: { 3557 PutByIdStatus status = PutByIdStatus::computeFor(globalObject, structure, uid, false); 3515 PutByIdStatus status; 3516 if (uid) 3517 status = PutByIdStatus::computeFor(globalObject, structure, uid, false); 3518 else 3519 status = PutByIdStatus(PutByIdStatus::TakesSlowPath); 3558 3520 if (status.numVariants() != 1 3559 3521 || status[0].kind() != PutByIdVariant::Replace … … 3572 3534 case GlobalVar: 3573 3535 case GlobalVarWithVarInjectionChecks: { 3574 SymbolTableEntry entry = globalObject->symbolTable()->get(uid); 3575 ASSERT(watchpoints == entry.watchpointSet()); 3536 if (watchpoints) { 3537 SymbolTableEntry entry = globalObject->symbolTable()->get(uid); 3538 ASSERT_UNUSED(entry, watchpoints == entry.watchpointSet()); 3539 } 3576 3540 Node* valueNode = get(VirtualRegister(value)); 3577 3541 addToGraph(PutGlobalVar, OpInfo(operand), valueNode); 3578 if (watchpoints ->state() != IsInvalidated)3542 if (watchpoints && watchpoints->state() != IsInvalidated) 3579 3543 addToGraph(NotifyWrite, OpInfo(watchpoints), valueNode); 3580 3544 // Keep scope alive until after put. … … 3586 3550 case ClosureVarWithVarInjectionChecks: { 3587 3551 Node* scopeNode = get(VirtualRegister(scope)); 3588 Node* scopeRegisters = addToGraph(GetClosureRegisters, scopeNode);3589 3552 Node* valueNode = get(VirtualRegister(value)); 3590 3553 … … 3592 3555 addToGraph(NotifyWrite, OpInfo(watchpoints), valueNode); 3593 3556 3594 addToGraph(PutClosureVar, OpInfo(operand), scopeNode, scopeRegisters,valueNode);3557 addToGraph(PutClosureVar, OpInfo(operand), scopeNode, valueNode); 3595 3558 break; 3596 3559 } … … 3622 3585 } 3623 3586 3624 case op_init_lazy_reg: {3625 set(VirtualRegister(currentInstruction[1].u.operand), jsConstant(JSValue()));3626 ASSERT(operandIsLocal(currentInstruction[1].u.operand));3627 m_graph.m_lazyVars.set(VirtualRegister(currentInstruction[1].u.operand).toLocal());3628 NEXT_OPCODE(op_init_lazy_reg);3629 }3630 3631 3587 case op_create_lexical_environment: { 3632 Node* lexicalEnvironment = addToGraph(CreateActivation, get(VirtualRegister(currentInstruction[ 1].u.operand)), get(VirtualRegister(currentInstruction[2].u.operand)));3588 Node* lexicalEnvironment = addToGraph(CreateActivation, get(VirtualRegister(currentInstruction[2].u.operand))); 3633 3589 set(VirtualRegister(currentInstruction[1].u.operand), lexicalEnvironment); 3634 3590 set(VirtualRegister(currentInstruction[2].u.operand), lexicalEnvironment); … … 3651 3607 } 3652 3608 3653 case op_create_ arguments: {3654 m_graph.m_hasArguments = true;3655 Node* createArguments = addToGraph(Create Arguments, get(VirtualRegister(currentInstruction[1].u.operand)));3609 case op_create_direct_arguments: { 3610 noticeArgumentsUse(); 3611 Node* createArguments = addToGraph(CreateDirectArguments); 3656 3612 set(VirtualRegister(currentInstruction[1].u.operand), createArguments); 3657 set(unmodifiedArgumentsRegister(VirtualRegister(currentInstruction[1].u.operand)), createArguments);3658 NEXT_OPCODE(op_create_arguments);3659 }3660 3661 case op_tear_off_arguments: {3662 m_graph.m_hasArguments = true;3663 addToGraph(TearOffArguments, get(VirtualRegister(currentInstruction[1].u.operand)), get(VirtualRegister(currentInstruction[2].u.operand)));3664 NEXT_OPCODE(op_ tear_off_arguments);3665 } 3666 3667 case op_ get_arguments_length: {3668 m_graph.m_hasArguments = true;3669 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetMyArgumentsLengthSafe));3670 NEXT_OPCODE(op_get_arguments_length);3671 }3672 3673 case op_get_argument_by_val: {3674 m_graph.m_hasArguments = true;3613 NEXT_OPCODE(op_create_direct_arguments); 3614 } 3615 3616 case op_create_scoped_arguments: { 3617 noticeArgumentsUse(); 3618 Node* createArguments = addToGraph(CreateScopedArguments, get(VirtualRegister(currentInstruction[2].u.operand))); 3619 set(VirtualRegister(currentInstruction[1].u.operand), createArguments); 3620 NEXT_OPCODE(op_create_scoped_arguments); 3621 } 3622 3623 case op_create_out_of_band_arguments: { 3624 noticeArgumentsUse(); 3625 Node* createArguments = addToGraph(CreateClonedArguments); 3626 set(VirtualRegister(currentInstruction[1].u.operand), createArguments); 3627 NEXT_OPCODE(op_create_out_of_band_arguments); 3628 } 3629 3630 case op_get_from_arguments: { 3675 3631 set(VirtualRegister(currentInstruction[1].u.operand), 3676 3632 addToGraph( 3677 GetMyArgumentByValSafe, OpInfo(0), OpInfo(getPrediction()), 3678 get(VirtualRegister(currentInstruction[3].u.operand)))); 3679 NEXT_OPCODE(op_get_argument_by_val); 3633 GetFromArguments, 3634 OpInfo(currentInstruction[3].u.operand), 3635 OpInfo(getPrediction()), 3636 get(VirtualRegister(currentInstruction[2].u.operand)))); 3637 NEXT_OPCODE(op_get_from_arguments); 3638 } 3639 3640 case op_put_to_arguments: { 3641 addToGraph( 3642 PutToArguments, 3643 OpInfo(currentInstruction[2].u.operand), 3644 get(VirtualRegister(currentInstruction[1].u.operand)), 3645 get(VirtualRegister(currentInstruction[3].u.operand))); 3646 NEXT_OPCODE(op_put_to_arguments); 3680 3647 } 3681 3648 … … 3683 3650 FunctionExecutable* decl = m_inlineStackTop->m_profiledBlock->functionDecl(currentInstruction[3].u.operand); 3684 3651 FrozenValue* frozen = m_graph.freezeStrong(decl); 3685 if (!currentInstruction[4].u.operand) { 3686 set(VirtualRegister(currentInstruction[1].u.operand), 3687 addToGraph(NewFunctionNoCheck, OpInfo(frozen), get(VirtualRegister(currentInstruction[2].u.operand)))); 3688 } else { 3689 set(VirtualRegister(currentInstruction[1].u.operand), 3690 addToGraph( 3691 NewFunction, 3692 OpInfo(frozen), 3693 get(VirtualRegister(currentInstruction[1].u.operand)), get(VirtualRegister(currentInstruction[2].u.operand)))); 3694 } 3652 set(VirtualRegister(currentInstruction[1].u.operand), 3653 addToGraph(NewFunction, OpInfo(frozen), get(VirtualRegister(currentInstruction[2].u.operand)))); 3695 3654 NEXT_OPCODE(op_new_func); 3696 3655 } … … 3700 3659 FrozenValue* frozen = m_graph.freezeStrong(expr); 3701 3660 set(VirtualRegister(currentInstruction[1].u.operand), 3702 addToGraph(NewFunction Expression, OpInfo(frozen), get(VirtualRegister(currentInstruction[2].u.operand))));3661 addToGraph(NewFunction, OpInfo(frozen), get(VirtualRegister(currentInstruction[2].u.operand)))); 3703 3662 NEXT_OPCODE(op_new_func_exp); 3704 3663 } … … 3907 3866 } 3908 3867 3909 // Track the code-block-global exit sites.3910 if (m_exitProfile.hasExitSite(ArgumentsEscaped)) {3911 byteCodeParser->m_graph.m_executablesWhoseArgumentsEscaped.add(3912 codeBlock->ownerExecutable());3913 }3914 3915 3868 if (m_caller) { 3916 3869 // Inline case. … … 3937 3890 m_inlineCallFrame->kind = kind; 3938 3891 3939 if (m_inlineCallFrame->caller.inlineCallFrame)3940 m_inlineCallFrame->capturedVars = m_inlineCallFrame->caller.inlineCallFrame->capturedVars;3941 else3942 m_inlineCallFrame->capturedVars = byteCodeParser->m_graph.m_outermostCapturedVars;3943 3944 for (int i = argumentCountIncludingThis; i--;) {3945 VirtualRegister argument = virtualRegisterForArgument(i);3946 if (codeBlock->isCaptured(argument))3947 m_inlineCallFrame->capturedVars.set(VirtualRegister(argument.offset() + m_inlineCallFrame->stackOffset).toLocal());3948 }3949 for (size_t i = codeBlock->m_numVars; i--;) {3950 VirtualRegister local = virtualRegisterForLocal(i);3951 if (codeBlock->isCaptured(local))3952 m_inlineCallFrame->capturedVars.set(VirtualRegister(local.offset() + m_inlineCallFrame->stackOffset).toLocal());3953 }3954 3955 3892 byteCodeParser->buildOperandMapsIfNecessary(); 3956 3893 … … 4030 3967 } 4031 3968 dataLog( 4032 ": captureCount = ", codeBlock->symbolTable() ? codeBlock->symbolTable()->captureCount() : 0, 4033 ", needsActivation = ", codeBlock->needsActivation(), 3969 ": needsActivation = ", codeBlock->needsActivation(), 4034 3970 ", isStrictMode = ", codeBlock->ownerExecutable()->isStrictMode(), "\n"); 4035 3971 codeBlock->baselineVersion()->dumpBytecode(); -
trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
r179756 r181993 193 193 } 194 194 195 if (variable->isCaptured()) {196 variable->setIsLoadedFrom(true);197 if (otherNode->op() == GetLocal)198 otherNode = otherNode->child1().node();199 else200 ASSERT(otherNode->op() == SetLocal || otherNode->op() == SetArgument);201 202 ASSERT(otherNode->op() == Phi || otherNode->op() == SetLocal || otherNode->op() == SetArgument);203 204 // Keep this GetLocal but link it to the prior ones.205 node->children.setChild1(Edge(otherNode));206 m_block->variablesAtTail.atFor<operandKind>(idx) = node;207 return;208 }209 210 195 if (otherNode->op() == GetLocal) { 211 196 // Replace all references to this GetLocal with otherNode. … … 336 321 // variable will be a SetLocal and not those subsequent Flushes. 337 322 // 338 // Child of GetLocal: the operation that the GetLocal keeps alive. For 339 // uncaptured locals, it may be a Phi from the current block. For arguments, 340 // it may be a SetArgument. For captured locals and arguments it may also be 341 // a SetLocal. 323 // Child of GetLocal: the operation that the GetLocal keeps alive. It may be 324 // a Phi from the current block. For arguments, it may be a SetArgument. 342 325 // 343 326 // Child of SetLocal: must be a value producing node. -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r173413 r181993 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 327 327 328 328 if (m_node->op() == GetLocal) { 329 // For uncaptured locals, usually the CPS rethreading phase does this. But it's OK330 // for us to mess with locals - regardless of their capturedness -so long as:329 // Usually the CPS rethreading phase does this. But it's OK for us to mess with 330 // locals so long as: 331 331 // 332 332 // - We dethread the graph. Any changes we make may invalidate the assumptions of … … 467 467 // computed. We pick one that is in a block that dominates ours. Note that this means that 468 468 // a PureValue will map to a list of nodes, since there may be many places in the control 469 // flow graph that compute a value but only one of them that dominates us. we may build up469 // flow graph that compute a value but only one of them that dominates us. We may build up 470 470 // a large list of nodes that compute some value in the case of gnarly control flow. This 471 471 // is probably OK. -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r181891 r181993 45 45 bool isSupportedForInlining(CodeBlock* codeBlock) 46 46 { 47 return !codeBlock->ownerExecutable()->needsActivation() 48 && codeBlock->ownerExecutable()->isInliningCandidate(); 47 return codeBlock->ownerExecutable()->isInliningCandidate(); 49 48 } 50 49 … … 185 184 case op_call_varargs: 186 185 case op_construct_varargs: 187 case op_ init_lazy_reg:188 case op_create_ arguments:189 case op_ tear_off_arguments:190 case op_get_ argument_by_val:191 case op_ get_arguments_length:186 case op_create_direct_arguments: 187 case op_create_scoped_arguments: 188 case op_create_out_of_band_arguments: 189 case op_get_from_arguments: 190 case op_put_to_arguments: 192 191 case op_jneq_ptr: 193 192 case op_typeof: … … 209 208 case op_new_func: 210 209 case op_new_func_exp: 210 case op_create_lexical_environment: 211 211 return CanCompileAndInline; 212 212 … … 228 228 } 229 229 230 case op_new_regexp: 231 case op_create_lexical_environment: 230 case op_new_regexp: 232 231 case op_switch_string: // Don't inline because we don't want to copy string tables in the concurrent JIT. 233 232 return CanCompile; -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r181891 r181993 271 271 case PhantomLocal: 272 272 case SetArgument: 273 case PhantomArguments:274 273 case Jump: 275 274 case Branch: … … 301 300 302 301 case Flush: 303 read(AbstractHeap( Variables, node->local()));302 read(AbstractHeap(Stack, node->local())); 304 303 write(SideState); 305 304 return; … … 318 317 read(HeapObjectCount); 319 318 write(HeapObjectCount); 320 write(SideState);321 write(Watchpoint_fire);322 return;323 324 case Create Arguments:325 read( Variables);319 return; 320 321 case CreateDirectArguments: 322 case CreateScopedArguments: 323 case CreateClonedArguments: 324 read(Stack); 326 325 read(HeapObjectCount); 327 326 write(HeapObjectCount); 328 write(SideState); 329 write(Watchpoint_fire); 327 return; 328 329 case PhantomDirectArguments: 330 case PhantomClonedArguments: 331 // DFG backend requires that the locals that this reads are flushed. FTL backend can handle those 332 // locals being promoted. 333 if (!isFTL(graph.m_plan.mode)) 334 read(Stack); 335 336 // Even though it's phantom, it still has the property that one can't be replaced with another. 337 read(HeapObjectCount); 338 write(HeapObjectCount); 330 339 return; 331 340 … … 376 385 case CallForwardVarargs: 377 386 case ConstructVarargs: 387 case ConstructForwardVarargs: 378 388 case ToPrimitive: 379 389 case In: 380 case GetMyArgumentsLengthSafe:381 case GetMyArgumentByValSafe:382 390 case ValueAdd: 383 391 read(World); … … 396 404 397 405 case GetCallee: 398 read(AbstractHeap(Variables, JSStack::Callee)); 399 def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::Callee)), node); 406 read(AbstractHeap(Stack, JSStack::Callee)); 407 def(HeapLocation(StackLoc, AbstractHeap(Stack, JSStack::Callee)), node); 408 return; 409 410 case GetArgumentCount: 411 read(AbstractHeap(Stack, JSStack::ArgumentCount)); 412 def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), node); 400 413 return; 401 414 402 415 case GetLocal: 403 read(AbstractHeap( Variables, node->local()));404 def(HeapLocation( VariableLoc, AbstractHeap(Variables, node->local())), node);416 read(AbstractHeap(Stack, node->local())); 417 def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), node); 405 418 return; 406 419 407 420 case SetLocal: 408 write(AbstractHeap( Variables, node->local()));409 def(HeapLocation( VariableLoc, AbstractHeap(Variables, node->local())), node->child1().node());421 write(AbstractHeap(Stack, node->local())); 422 def(HeapLocation(StackLoc, AbstractHeap(Stack, node->local())), node->child1().node()); 410 423 return; 411 424 412 425 case GetStack: { 413 AbstractHeap heap( Variables, node->stackAccessData()->local);426 AbstractHeap heap(Stack, node->stackAccessData()->local); 414 427 read(heap); 415 def(HeapLocation( VariableLoc, heap), node);428 def(HeapLocation(StackLoc, heap), node); 416 429 return; 417 430 } 418 431 419 432 case PutStack: { 420 AbstractHeap heap( Variables, node->stackAccessData()->local);433 AbstractHeap heap(Stack, node->stackAccessData()->local); 421 434 write(heap); 422 def(HeapLocation(VariableLoc, heap), node->child1().node()); 423 return; 424 } 425 426 case LoadVarargs: 427 // This actually writes to local variables as well. But when it reads the array, it does 428 // so in a way that may trigger getters or various traps. 435 def(HeapLocation(StackLoc, heap), node->child1().node()); 436 return; 437 } 438 439 case LoadVarargs: { 429 440 read(World); 430 write(World); 431 return; 441 write(Heap); 442 LoadVarargsData* data = node->loadVarargsData(); 443 write(AbstractHeap(Stack, data->count.offset())); 444 for (unsigned i = data->limit; i--;) 445 write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i))); 446 return; 447 } 448 449 case ForwardVarargs: { 450 // We could be way more precise here. 451 read(Stack); 452 453 LoadVarargsData* data = node->loadVarargsData(); 454 write(AbstractHeap(Stack, data->count.offset())); 455 for (unsigned i = data->limit; i--;) 456 write(AbstractHeap(Stack, data->start.offset() + static_cast<int>(i))); 457 return; 458 } 432 459 433 460 case GetLocalUnlinked: 434 read(AbstractHeap( Variables, node->unlinkedLocal()));435 def(HeapLocation( VariableLoc, AbstractHeap(Variables, node->unlinkedLocal())), node);461 read(AbstractHeap(Stack, node->unlinkedLocal())); 462 def(HeapLocation(StackLoc, AbstractHeap(Stack, node->unlinkedLocal())), node); 436 463 return; 437 464 … … 466 493 return; 467 494 468 case Array::Arguments: 469 read(Arguments_registers); 470 read(Variables); 471 def(HeapLocation(IndexedPropertyLoc, Variables, node->child1(), node->child2()), node); 495 case Array::DirectArguments: 496 read(DirectArgumentsProperties); 497 def(HeapLocation(IndexedPropertyLoc, DirectArgumentsProperties, node->child1(), node->child2()), node); 498 return; 499 500 case Array::ScopedArguments: 501 read(ScopeProperties); 502 def(HeapLocation(IndexedPropertyLoc, ScopeProperties, node->child1(), node->child2()), node); 472 503 return; 473 504 … … 533 564 return; 534 565 } 566 567 case GetMyArgumentByVal: { 568 read(Stack); 569 // FIXME: It would be trivial to have a def here. 570 // https://bugs.webkit.org/show_bug.cgi?id=143077 571 return; 572 } 535 573 536 574 case PutByValDirect: … … 545 583 case Array::Unprofiled: 546 584 case Array::Undecided: 547 case Array::String:548 585 // Assume the worst since we don't have profiling yet. 549 586 read(World); … … 558 595 read(World); 559 596 write(Heap); 560 return;561 562 case Array::Arguments:563 read(Arguments_registers);564 read(MiscFields);565 write(Variables);566 def(HeapLocation(IndexedPropertyLoc, Variables, base, index), value);567 597 return; 568 598 … … 633 663 // https://bugs.webkit.org/show_bug.cgi?id=134737 634 664 return; 665 case Array::String: 666 case Array::DirectArguments: 667 case Array::ScopedArguments: 668 DFG_CRASH(graph, node, "impossible array mode for put"); 669 return; 635 670 } 636 671 RELEASE_ASSERT_NOT_REACHED(); … … 761 796 return; 762 797 763 case Array::Arguments: 798 case Array::DirectArguments: 799 case Array::ScopedArguments: 764 800 read(MiscFields); 765 801 def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node); … … 774 810 } 775 811 776 case GetClosureRegisters:777 read(JSEnvironmentRecord_registers);778 def(HeapLocation(ClosureRegistersLoc, JSEnvironmentRecord_registers, node->child1()), node);779 return;780 781 812 case GetClosureVar: 782 read(AbstractHeap( Variables, node->varNumber()));783 def(HeapLocation(ClosureVariableLoc, AbstractHeap( Variables, node->varNumber()), node->child1()), node);813 read(AbstractHeap(ScopeProperties, node->scopeOffset().offset())); 814 def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child1()), node); 784 815 return; 785 816 786 817 case PutClosureVar: 787 write(AbstractHeap(Variables, node->varNumber())); 788 def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child1()), node->child3().node()); 789 return; 818 write(AbstractHeap(ScopeProperties, node->scopeOffset().offset())); 819 def(HeapLocation(ClosureVariableLoc, AbstractHeap(ScopeProperties, node->scopeOffset().offset()), node->child2()), node->child2().node()); 820 return; 821 822 case GetFromArguments: { 823 AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset()); 824 read(heap); 825 def(HeapLocation(DirectArgumentsLoc, heap), node); 826 return; 827 } 828 829 case PutToArguments: { 830 AbstractHeap heap(DirectArgumentsProperties, node->capturedArgumentsOffset().offset()); 831 write(heap); 832 def(HeapLocation(DirectArgumentsLoc, heap), node->child2().node()); 833 return; 834 } 790 835 791 836 case GetGlobalVar: 792 read(AbstractHeap(Absolute, node-> registerPointer()));793 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node-> registerPointer())), node);837 read(AbstractHeap(Absolute, node->variablePointer())); 838 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), node); 794 839 return; 795 840 796 841 case PutGlobalVar: 797 write(AbstractHeap(Absolute, node-> registerPointer()));798 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node-> registerPointer())), node->child1().node());842 write(AbstractHeap(Absolute, node->variablePointer())); 843 def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->variablePointer())), node->child1().node()); 799 844 return; 800 845 … … 816 861 case PhantomNewObject: 817 862 case MaterializeNewObject: 818 case NewFunctionNoCheck:819 863 case NewFunction: 820 case NewFunctionExpression:821 864 read(HeapObjectCount); 822 865 write(HeapObjectCount); … … 870 913 } 871 914 872 case TearOffArguments:873 read(Variables);874 write(Arguments_registers);875 return;876 877 case GetMyArgumentsLength:878 read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));879 read(AbstractHeap(Variables, JSStack::ArgumentCount));880 // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we881 // have for PureValue.882 // https://bugs.webkit.org/show_bug.cgi?id=134797883 return;884 885 case GetMyArgumentByVal:886 read(Variables);887 // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we888 // have for PureValue.889 // https://bugs.webkit.org/show_bug.cgi?id=134797890 return;891 892 case CheckArgumentsNotCreated:893 read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));894 return;895 896 915 case ThrowReferenceError: 897 916 write(SideState); -
trunk/Source/JavaScriptCore/dfg/DFGCommon.h
r180813 r181993 31 31 #if ENABLE(DFG_JIT) 32 32 33 #include "CodeOrigin.h"34 33 #include "Options.h" 35 34 #include "VirtualRegister.h" … … 194 193 // tail. ThreadedCPS form also implies that: 195 194 // 196 // - GetLocals and SetLocals to uncaptured variables are not redundant within 197 // a basic block. 195 // - GetLocals and SetLocals are not redundant within a basic block. 198 196 // 199 197 // - All GetLocals and Flushes are linked directly to the last access point 200 // of the variable, which must not be another GetLocal if the variable is 201 // uncaptured. 198 // of the variable, which must not be another GetLocal. 202 199 // 203 200 // - Phantom(Phi) is not legal, but PhantomLocal is. -
trunk/Source/JavaScriptCore/dfg/DFGCommonData.h
r172129 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 72 72 CommonData() 73 73 : isStillValid(true) 74 , machineCaptureStart(std::numeric_limits<int>::max())75 74 , frameRegisterCount(std::numeric_limits<unsigned>::max()) 76 75 , requiredRegisterCountForExit(std::numeric_limits<unsigned>::max()) … … 104 103 bool isStillValid; 105 104 106 int machineCaptureStart;107 std::unique_ptr<SlowArgument[]> slowArguments;108 109 105 #if USE(JSVALUE32_64) 110 106 std::unique_ptr<Bag<double>> doubleConstants; -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r181817 r181993 1 1 /* 2 * Copyright (C) 2012 , 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 31 31 #include "DFGAbstractInterpreterInlines.h" 32 #include "DFGArgumentsUtilities.h" 32 33 #include "DFGBasicBlock.h" 33 34 #include "DFGGraph.h" … … 98 99 } 99 100 100 case CheckArgumentsNotCreated: {101 if (!isEmptySpeculation(102 m_state.variables().operand(103 m_graph.argumentsRegisterFor(node->origin.semantic)).m_type))104 break;105 node->convertToPhantom();106 eliminated = true;107 break;108 }109 110 101 case CheckStructure: 111 102 case ArrayifyToStructure: { … … 205 196 } 206 197 198 break; 199 } 200 201 case GetMyArgumentByVal: { 202 JSValue index = m_state.forNode(node->child2()).value(); 203 if (!index || !index.isInt32()) 204 break; 205 206 Node* arguments = node->child1().node(); 207 InlineCallFrame* inlineCallFrame = arguments->origin.semantic.inlineCallFrame; 208 209 // Don't try to do anything if the index is known to be outside our static bounds. Note 210 // that our static bounds are usually strictly larger than the dynamic bounds. The 211 // exception is something like this, assuming foo() is not inlined: 212 // 213 // function foo() { return arguments[5]; } 214 // 215 // Here the static bound on number of arguments is 0, and we're accessing index 5. We 216 // will not strength-reduce this to GetStack because GetStack is otherwise assumed by the 217 // compiler to access those variables that are statically accounted for; for example if 218 // we emitted a GetStack on arg6 we would have out-of-bounds access crashes anywhere that 219 // uses an Operands<> map. There is not much cost to continuing to use a 220 // GetMyArgumentByVal in such statically-out-of-bounds accesses; we just lose CFA unless 221 // GCSE removes the access entirely. 222 if (inlineCallFrame) { 223 if (index.isUInt32() >= inlineCallFrame->arguments.size() - 1) 224 break; 225 } else { 226 if (index.isUInt32() >= m_state.variables().numberOfArguments() - 1) 227 break; 228 } 229 230 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before. 231 232 StackAccessData* data; 233 if (inlineCallFrame) { 234 data = m_graph.m_stackAccessData.add( 235 inlineCallFrame->arguments[index.asInt32() + 1].virtualRegister(), FlushedJSValue); 236 } else { 237 data = m_graph.m_stackAccessData.add( 238 virtualRegisterForArgument(index.asInt32() + 1), FlushedJSValue); 239 } 240 241 if (inlineCallFrame && !inlineCallFrame->isVarargs() 242 && index.asUInt32() < inlineCallFrame->arguments.size() - 1) { 243 node->convertToGetStack(data); 244 eliminated = true; 245 break; 246 } 247 248 Node* length = emitCodeToGetArgumentsArrayLength( 249 m_insertionSet, arguments, indexInBlock, node->origin); 250 m_insertionSet.insertNode( 251 indexInBlock, SpecNone, CheckInBounds, node->origin, 252 node->child2(), Edge(length, Int32Use)); 253 node->convertToGetStack(data); 254 eliminated = true; 207 255 break; 208 256 } … … 386 434 } 387 435 388 case GetMyArgumentByVal: {389 InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame;390 JSValue value = m_state.forNode(node->child1()).m_value;391 if (inlineCallFrame && value && value.isInt32()) {392 int32_t index = value.asInt32();393 if (index >= 0394 && static_cast<size_t>(index + 1) < inlineCallFrame->arguments.size()) {395 // Roll the interpreter over this.396 m_interpreter.execute(indexInBlock);397 eliminated = true;398 399 int operand =400 inlineCallFrame->stackOffset +401 m_graph.baselineCodeBlockFor(inlineCallFrame)->argumentIndexAfterCapture(index);402 403 m_insertionSet.insertNode(404 indexInBlock, SpecNone, CheckArgumentsNotCreated, node->origin);405 m_insertionSet.insertNode(406 indexInBlock, SpecNone, Phantom, node->origin, node->children);407 408 if (m_graph.m_form == SSA)409 node->convertToGetStack(m_graph.m_stackAccessData.add(VirtualRegister(operand), FlushedJSValue));410 else411 node->convertToGetLocalUnlinked(VirtualRegister(operand));412 break;413 }414 }415 416 break;417 }418 419 436 case Check: { 420 437 alreadyHandled = true; -
trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp
r180160 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 206 206 node = node->child1().node(); 207 207 208 // FIXME: In the case that the variable is captured, we really want to be able 209 // to replace the variable-at-tail with the last use of the variable in the same 210 // way that CPS rethreading would do. The child of the GetLocal isn't necessarily 211 // the same as what CPS rethreading would do. For example, we may have: 212 // 213 // a: SetLocal(...) // live 214 // b: GetLocal(@a) // live 215 // c: GetLocal(@a) // dead 216 // 217 // When killing @c, the code below will set the variable-at-tail to @a, while CPS 218 // rethreading would have set @b. This is a benign bug, since all clients of CPS 219 // only use the variable-at-tail of captured variables to get the 220 // VariableAccessData and observe that it is in fact captured. But, this feels 221 // like it could cause bugs in the future. 222 // 223 // It's tempting to just dethread and then invoke CPS rethreading, but CPS 224 // rethreading fails to preserve exact ref-counts. So we would need a fixpoint. 225 // It's probably the case that this fixpoint will be guaranteed to converge after 226 // the second iteration (i.e. the second run of DCE will not kill anything and so 227 // will not need to dethread), but for now the safest approach is probably just to 228 // allow for this tiny bit of sloppiness. 229 // 230 // Another possible solution would be to simply say that DCE dethreads but then 231 // we never rethread before going to the backend. That feels intuitively right 232 // because it's unlikely that any of the phases after DCE in the backend rely on 233 // ThreadedCPS. 234 // 235 // https://bugs.webkit.org/show_bug.cgi?id=130115 236 ASSERT( 237 node->op() == Phi || node->op() == SetArgument 238 || node->variableAccessData()->isCaptured()); 208 ASSERT(node->op() == Phi || node->op() == SetArgument); 239 209 240 210 if (node->shouldGenerate()) { -
trunk/Source/JavaScriptCore/dfg/DFGDisassembler.h
r170876 r181993 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "CodeOrigin.h" 31 32 #include "DFGCommon.h" 32 33 #include "DumpContext.h" -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r181891 r181993 50 50 case Identity: 51 51 case GetCallee: 52 case GetArgumentCount: 52 53 case GetLocal: 53 54 case SetLocal: … … 99 100 case GetScope: 100 101 case SkipScope: 101 case GetClosureRegisters:102 102 case GetClosureVar: 103 103 case PutClosureVar: … … 123 123 case LoadVarargs: 124 124 case CallForwardVarargs: 125 case ConstructForwardVarargs: 125 126 case NativeCall: 126 127 case NativeConstruct: … … 144 145 case ToString: 145 146 case In: 146 case PhantomArguments:147 case TearOffArguments:148 case GetMyArgumentsLength:149 case GetMyArgumentByVal:150 case GetMyArgumentsLengthSafe:151 case GetMyArgumentByValSafe:152 case CheckArgumentsNotCreated:153 147 case Jump: 154 148 case Branch: … … 205 199 case BottomValue: 206 200 case PhantomNewObject: 201 case PhantomDirectArguments: 202 case PhantomClonedArguments: 203 case GetMyArgumentByVal: 204 case ForwardVarargs: 207 205 case PutHint: 208 206 case CheckStructureImmediate: … … 210 208 case KillStack: 211 209 case GetStack: 210 case GetFromArguments: 211 case PutToArguments: 212 212 return false; 213 213 214 214 case CreateActivation: 215 case CreateArguments: 215 case CreateDirectArguments: 216 case CreateScopedArguments: 217 case CreateClonedArguments: 216 218 case ToThis: 217 219 case CreateThis: … … 227 229 case NewStringObject: 228 230 case MakeRope: 229 case NewFunctionNoCheck:230 231 case NewFunction: 231 case NewFunctionExpression:232 232 case NewTypedArray: 233 233 case ThrowReferenceError: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r181891 r181993 659 659 case Array::ArrayStorage: 660 660 case Array::SlowPutArrayStorage: 661 case Array::Arguments:662 661 fixEdge<KnownCellUse>(child1); 663 662 fixEdge<Int32Use>(child2); … … 858 857 } 859 858 860 case GetMyArgumentByVal:861 case GetMyArgumentByValSafe: {862 fixEdge<Int32Use>(node->child1());863 break;864 }865 866 859 case PutStructure: { 867 860 fixEdge<KnownCellUse>(node->child1()); … … 869 862 break; 870 863 } 871 872 case GetClosureVar: { 864 865 case GetClosureVar: 866 case GetFromArguments: { 873 867 fixEdge<KnownCellUse>(node->child1()); 874 868 break; 875 869 } 876 870 877 case PutClosureVar: { 871 case PutClosureVar: 872 case PutToArguments: { 878 873 fixEdge<KnownCellUse>(node->child1()); 879 insertStoreBarrier(m_indexInBlock, node->child1(), node->child3()); 880 break; 881 } 882 883 case GetClosureRegisters: 874 insertStoreBarrier(m_indexInBlock, node->child1(), node->child2()); 875 break; 876 } 877 884 878 case SkipScope: 885 879 case GetScope: … … 1042 1036 case BooleanToNumber: 1043 1037 case PhantomNewObject: 1038 case PhantomDirectArguments: 1039 case PhantomClonedArguments: 1040 case ForwardVarargs: 1041 case GetMyArgumentByVal: 1044 1042 case PutHint: 1045 1043 case CheckStructureImmediate: … … 1181 1179 } 1182 1180 1181 case CreateScopedArguments: 1183 1182 case CreateActivation: 1184 1183 case NewFunction: { 1185 fixEdge<CellUse>(node->child2());1186 break;1187 }1188 1189 case NewFunctionNoCheck:1190 case NewFunctionExpression: {1191 1184 fixEdge<CellUse>(node->child1()); 1192 1185 break; … … 1200 1193 case GetLocal: 1201 1194 case GetCallee: 1195 case GetArgumentCount: 1202 1196 case Flush: 1203 1197 case PhantomLocal: … … 1212 1206 case ConstructVarargs: 1213 1207 case CallForwardVarargs: 1208 case ConstructForwardVarargs: 1214 1209 case LoadVarargs: 1215 1210 case ProfileControlFlow: … … 1227 1222 case IsObjectOrNull: 1228 1223 case IsFunction: 1229 case CreateArguments: 1230 case PhantomArguments: 1231 case TearOffArguments: 1232 case GetMyArgumentsLength: 1233 case GetMyArgumentsLengthSafe: 1234 case CheckArgumentsNotCreated: 1224 case CreateDirectArguments: 1225 case CreateClonedArguments: 1235 1226 case Jump: 1236 1227 case Return: -
trunk/Source/JavaScriptCore/dfg/DFGFlushFormat.cpp
r164229 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 59 59 out.print("FlushedJSValue"); 60 60 return; 61 case FlushedArguments:62 out.print("FlushedArguments");63 return;64 61 case ConflictingFlush: 65 62 out.print("ConflictingFlush"); -
trunk/Source/JavaScriptCore/dfg/DFGFlushFormat.h
r180691 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 45 45 FlushedBoolean, 46 46 FlushedJSValue, 47 FlushedArguments,48 47 ConflictingFlush 49 48 }; … … 56 55 case FlushedCell: 57 56 case ConflictingFlush: 58 case FlushedArguments:59 57 return NodeResultJS; 60 58 case FlushedInt32: … … 77 75 case FlushedJSValue: 78 76 case ConflictingFlush: 79 case FlushedArguments:80 77 return UntypedUse; 81 78 case FlushedCell: … … 117 114 case FlushedBoolean: 118 115 return DataFormatBoolean; 119 case FlushedArguments:120 return DataFormatArguments;121 116 } 122 117 RELEASE_ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r181650 r181993 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "BytecodeKills.h" 31 32 #include "BytecodeLivenessAnalysisInlines.h" 32 33 #include "CodeBlock.h" … … 63 64 , m_allocator(longLivedState.m_allocator) 64 65 , m_mustHandleValues(OperandsLike, plan.mustHandleValues) 65 , m_hasArguments(false)66 66 , m_nextMachineLocal(0) 67 , m_machineCaptureStart(std::numeric_limits<int>::max())68 67 , m_fixpointState(BeforeFixpoint) 69 68 , m_structureRegistrationState(HaveNotStartedRegistering) … … 76 75 for (unsigned i = m_mustHandleValues.size(); i--;) 77 76 m_mustHandleValues[i] = freezeFragile(plan.mustHandleValues[i]); 78 79 for (unsigned i = m_codeBlock->m_numVars; i--;) {80 if (m_codeBlock->isCaptured(virtualRegisterForLocal(i)))81 m_outermostCapturedVars.set(i);82 }83 77 } 84 78 … … 217 211 if (node->hasArithMode()) 218 212 out.print(comma, node->arithMode()); 219 if (node->hasVarNumber()) 220 out.print(comma, node->varNumber()); 213 if (node->hasScopeOffset()) 214 out.print(comma, node->scopeOffset()); 215 if (node->hasDirectArgumentsOffset()) 216 out.print(comma, node->capturedArgumentsOffset()); 221 217 if (node->hasRegisterPointer()) 222 out.print(comma, "global", globalObjectFor(node->origin.semantic)->find RegisterIndex(node->registerPointer()), "(", RawPointer(node->registerPointer()), ")");218 out.print(comma, "global", globalObjectFor(node->origin.semantic)->findVariableIndex(node->variablePointer()), "(", RawPointer(node->variablePointer()), ")"); 223 219 if (node->hasIdentifier()) 224 220 out.print(comma, "id", node->identifierNumber(), "{", identifiers()[node->identifierNumber()], "}"); … … 229 225 if (node->hasStructure()) 230 226 out.print(comma, inContext(*node->structure(), context)); 231 if (node->hasTransition()) 227 if (node->hasTransition()) { 232 228 out.print(comma, pointerDumpInContext(node->transition(), context)); 229 #if USE(JSVALUE64) 230 out.print(", ID:", node->transition()->next->id()); 231 #else 232 out.print(", ID:", RawPointer(node->transition()->next)); 233 #endif 234 } 233 235 if (node->hasCellOperand()) { 234 236 if (!node->cellOperand()->value() || !node->cellOperand()->value().isCell()) … … 749 751 void Graph::substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal) 750 752 { 751 if (variableAccessData->isCaptured()) {752 // Let CSE worry about this one.753 return;754 }755 753 for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) { 756 754 Node* node = block[indexInBlock]; … … 870 868 { 871 869 return livenessFor(baselineCodeBlockFor(inlineCallFrame)); 870 } 871 872 BytecodeKills& Graph::killsFor(CodeBlock* codeBlock) 873 { 874 HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>>::iterator iter = m_bytecodeKills.find(codeBlock); 875 if (iter != m_bytecodeKills.end()) 876 return *iter->value; 877 878 std::unique_ptr<BytecodeKills> kills = std::make_unique<BytecodeKills>(); 879 codeBlock->livenessAnalysis().computeKills(*kills); 880 BytecodeKills& result = *kills; 881 m_bytecodeKills.add(codeBlock, WTF::move(kills)); 882 return result; 883 } 884 885 BytecodeKills& Graph::killsFor(InlineCallFrame* inlineCallFrame) 886 { 887 return killsFor(baselineCodeBlockFor(inlineCallFrame)); 872 888 } 873 889 … … 1008 1024 } 1009 1025 1010 JSValue Graph::tryGetConstantClosureVar(JSValue base, VirtualRegister reg)1026 JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset) 1011 1027 { 1012 1028 if (!base) … … 1023 1039 return JSValue(); 1024 1040 1025 SymbolTableEntry* entry = symbolTable->entryFor(locker, reg);1041 SymbolTableEntry* entry = symbolTable->entryFor(locker, offset); 1026 1042 if (!entry) 1027 1043 return JSValue(); … … 1041 1057 } 1042 1058 1043 JSValue Graph::tryGetConstantClosureVar(const AbstractValue& value, VirtualRegister reg)1044 { 1045 return tryGetConstantClosureVar(value.m_value, reg);1046 } 1047 1048 JSValue Graph::tryGetConstantClosureVar(Node* node, VirtualRegister reg)1059 JSValue Graph::tryGetConstantClosureVar(const AbstractValue& value, ScopeOffset offset) 1060 { 1061 return tryGetConstantClosureVar(value.m_value, offset); 1062 } 1063 1064 JSValue Graph::tryGetConstantClosureVar(Node* node, ScopeOffset offset) 1049 1065 { 1050 1066 if (!node->hasConstant()) 1051 1067 return JSValue(); 1052 return tryGetConstantClosureVar(node->asJSValue(), reg); 1053 } 1054 1055 WriteBarrierBase<Unknown>* Graph::tryGetRegisters(Node* node) 1056 { 1057 JSLexicalEnvironment* lexicalEnvironment = node->dynamicCastConstant<JSLexicalEnvironment*>(); 1058 if (!lexicalEnvironment) 1059 return 0; 1060 return lexicalEnvironment->registers(); 1068 return tryGetConstantClosureVar(node->asJSValue(), offset); 1061 1069 } 1062 1070 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r180989 r181993 316 316 } 317 317 318 VirtualRegister bytecodeRegisterForArgument(CodeOrigin codeOrigin, int argument)319 {320 return VirtualRegister(321 codeOrigin.inlineCallFrame->stackOffset +322 baselineCodeBlockFor(codeOrigin)->argumentIndexAfterCapture(argument));323 }324 325 318 static const char *opName(NodeType); 326 319 … … 368 361 } 369 362 370 const BitVector& capturedVarsFor(InlineCallFrame* inlineCallFrame) 371 { 372 if (!inlineCallFrame) 373 return m_outermostCapturedVars; 374 return inlineCallFrame->capturedVars; 363 SymbolTable* symbolTableFor(InlineCallFrame* inlineCallFrame) 364 { 365 return baselineCodeBlockFor(inlineCallFrame)->symbolTable(); 366 } 367 368 SymbolTable* symbolTableFor(const CodeOrigin& codeOrigin) 369 { 370 return symbolTableFor(codeOrigin.inlineCallFrame); 375 371 } 376 372 … … 407 403 } 408 404 409 bool usesArguments(InlineCallFrame* inlineCallFrame)410 {411 if (!inlineCallFrame)412 return m_profiledBlock->usesArguments();413 414 return baselineCodeBlockForInlineCallFrame(inlineCallFrame)->usesArguments();415 }416 417 VirtualRegister argumentsRegisterFor(InlineCallFrame* inlineCallFrame)418 {419 if (!inlineCallFrame)420 return m_profiledBlock->argumentsRegister();421 422 return VirtualRegister(baselineCodeBlockForInlineCallFrame(423 inlineCallFrame)->argumentsRegister().offset() +424 inlineCallFrame->stackOffset);425 }426 427 VirtualRegister argumentsRegisterFor(const CodeOrigin& codeOrigin)428 {429 return argumentsRegisterFor(codeOrigin.inlineCallFrame);430 }431 432 VirtualRegister machineArgumentsRegisterFor(InlineCallFrame* inlineCallFrame)433 {434 if (!inlineCallFrame)435 return m_codeBlock->argumentsRegister();436 437 return inlineCallFrame->argumentsRegister;438 }439 440 VirtualRegister machineArgumentsRegisterFor(const CodeOrigin& codeOrigin)441 {442 return machineArgumentsRegisterFor(codeOrigin.inlineCallFrame);443 }444 445 VirtualRegister uncheckedArgumentsRegisterFor(InlineCallFrame* inlineCallFrame)446 {447 if (!inlineCallFrame)448 return m_profiledBlock->uncheckedArgumentsRegister();449 450 CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);451 if (!codeBlock->usesArguments())452 return VirtualRegister();453 454 return VirtualRegister(codeBlock->argumentsRegister().offset() +455 inlineCallFrame->stackOffset);456 }457 458 VirtualRegister uncheckedArgumentsRegisterFor(const CodeOrigin& codeOrigin)459 {460 return uncheckedArgumentsRegisterFor(codeOrigin.inlineCallFrame);461 }462 463 405 VirtualRegister activationRegister() 464 406 { … … 483 425 ValueProfile* valueProfileFor(Node*); 484 426 MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node*); 485 486 bool usesArguments() const487 {488 return m_codeBlock->usesArguments();489 }490 427 491 428 BlockIndex numBlocks() const { return m_blocks.size(); } … … 723 660 } 724 661 662 bool uses(Node* node, Node* child) 663 { 664 bool result = false; 665 doToChildren(node, [&] (Edge edge) { result |= edge == child; }); 666 return result; 667 } 668 725 669 Profiler::Compilation* compilation() { return m_plan.compilation.get(); } 726 670 … … 731 675 FullBytecodeLiveness& livenessFor(InlineCallFrame*); 732 676 bool isLiveInBytecode(VirtualRegister, CodeOrigin); 677 678 BytecodeKills& killsFor(CodeBlock*); 679 BytecodeKills& killsFor(InlineCallFrame*); 733 680 734 681 unsigned frameRegisterCount(); … … 742 689 JSValue tryGetConstantProperty(const AbstractValue&, PropertyOffset); 743 690 744 JSValue tryGetConstantClosureVar(JSValue base, VirtualRegister); 745 JSValue tryGetConstantClosureVar(const AbstractValue&, VirtualRegister); 746 JSValue tryGetConstantClosureVar(Node*, VirtualRegister); 747 WriteBarrierBase<Unknown>* tryGetRegisters(Node*); 691 JSValue tryGetConstantClosureVar(JSValue base, ScopeOffset); 692 JSValue tryGetConstantClosureVar(const AbstractValue&, ScopeOffset); 693 JSValue tryGetConstantClosureVar(Node*, ScopeOffset); 748 694 749 695 JSArrayBufferView* tryGetFoldableView(Node*); … … 827 773 Vector<InlineVariableData, 4> m_inlineVariableData; 828 774 HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness; 829 bool m_hasArguments; 830 HashSet<ExecutableBase*> m_executablesWhoseArgumentsEscaped; 831 BitVector m_lazyVars; 775 HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills; 832 776 Dominators m_dominators; 833 777 PrePostNumbering m_prePostNumbering; … … 836 780 unsigned m_nextMachineLocal; 837 781 unsigned m_parameterSlots; 838 int m_machineCaptureStart;839 std::unique_ptr<SlowArgument[]> m_slowArguments;840 BitVector m_outermostCapturedVars;841 782 842 783 #if USE(JSVALUE32_64) -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp
r180587 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 81 81 return; 82 82 83 case VariableLoc: 84 out.print("VariableLoc"); 83 case StackLoc: 84 out.print("StackLoc"); 85 return; 86 87 case StackPayloadLoc: 88 out.print("StackPayloadLoc"); 85 89 return; 86 90 … … 97 101 return; 98 102 99 case Closure RegistersLoc:100 out.print("Closure RegistersLoc");103 case ClosureVariableLoc: 104 out.print("ClosureVariableLoc"); 101 105 return; 102 106 103 case ClosureVariableLoc:104 out.print(" ClosureVariableLoc");107 case DirectArgumentsLoc: 108 out.print("DirectArgumentsLoc"); 105 109 return; 106 110 … … 123 127 case InstanceOfLoc: 124 128 out.print("InstanceOfLoc"); 125 return;126 127 case MyArgumentByValLoc:128 out.print("MyArgumentByValLoc");129 return;130 131 case MyArgumentsLengthLoc:132 out.print("MyArgumentsLengthLoc");133 129 return; 134 130 -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h
r180587 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 41 41 ButterflyLoc, 42 42 CheckHasInstanceLoc, 43 ClosureRegistersLoc,44 43 ClosureVariableLoc, 44 DirectArgumentsLoc, 45 45 GetterLoc, 46 46 GlobalVariableLoc, … … 52 52 IsFunctionLoc, 53 53 IsObjectOrNullLoc, 54 MyArgumentByValLoc,55 MyArgumentsLengthLoc,56 54 NamedPropertyLoc, 57 55 SetterLoc, … … 60 58 TypedArrayByteOffsetLoc, 61 59 VarInjectionWatchpointLoc, 62 VariableLoc 60 StackLoc, 61 StackPayloadLoc 63 62 }; 64 63 -
trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp
r180160 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 130 130 } 131 131 for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) { 132 Node* node = root->variablesAtHead.local(i); 133 if (node && node->variableAccessData()->isCaptured()) 134 root->valuesAtHead.local(i).makeHeapTop(); 135 else 136 root->valuesAtHead.local(i).clear(); 132 root->valuesAtHead.local(i).clear(); 137 133 root->valuesAtTail.local(i).clear(); 138 134 } … … 264 260 AbstractValue source; 265 261 266 if (node->variableAccessData()->isCaptured()) {267 // If it's captured then we know that whatever value was stored into the variable last is the268 // one we care about. This is true even if the variable at tail is dead, which might happen if269 // the last thing we did to the variable was a GetLocal and then ended up not using the270 // GetLocal's result.271 262 switch (node->op()) { 263 case Phi: 264 case SetArgument: 265 case PhantomLocal: 266 case Flush: 267 // The block transfers the value from head to tail. 272 268 source = inVariable; 273 } else { 274 switch (node->op()) { 275 case Phi: 276 case SetArgument: 277 case PhantomLocal: 278 case Flush: 279 // The block transfers the value from head to tail. 280 source = inVariable; 281 break; 282 283 case GetLocal: 284 // The block refines the value with additional speculations. 285 source = forNode(node); 286 break; 287 288 case SetLocal: 289 // The block sets the variable, and potentially refines it, both 290 // before and after setting it. 291 source = forNode(node->child1()); 292 if (node->variableAccessData()->flushFormat() == FlushedDouble) 293 RELEASE_ASSERT(!(source.m_type & ~SpecFullDouble)); 294 break; 295 296 default: 297 RELEASE_ASSERT_NOT_REACHED(); 298 break; 299 } 269 break; 270 271 case GetLocal: 272 // The block refines the value with additional speculations. 273 source = forNode(node); 274 break; 275 276 case SetLocal: 277 // The block sets the variable, and potentially refines it, both 278 // before and after setting it. 279 source = forNode(node->child1()); 280 if (node->variableAccessData()->flushFormat() == FlushedDouble) 281 RELEASE_ASSERT(!(source.m_type & ~SpecFullDouble)); 282 break; 283 284 default: 285 RELEASE_ASSERT_NOT_REACHED(); 286 break; 300 287 } 301 288 -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r181990 r181993 162 162 m_jitCode->common.inlineCallFrames = m_graph.m_plan.inlineCallFrames; 163 163 164 m_jitCode->common.machineCaptureStart = m_graph.m_machineCaptureStart;165 m_jitCode->common.slowArguments = WTF::move(m_graph.m_slowArguments);166 167 164 #if USE(JSVALUE32_64) 168 165 m_jitCode->common.doubleConstants = WTF::move(m_graph.m_doubleConstants); -
trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp
r181650 r181993 72 72 case GetLocal: 73 73 case LoopHint: 74 case PhantomArguments:75 74 case Phi: 76 75 case Upsilon: … … 83 82 case GetStack: 84 83 case GetCallee: 84 case GetArgumentCount: 85 85 case GetScope: 86 86 case PhantomLocal: -
trunk/Source/JavaScriptCore/dfg/DFGMinifiedID.h
r164424 r181993 38 38 class MinifiedNode; 39 39 class ValueSource; 40 struct Node; 40 41 41 42 class MinifiedID { … … 99 100 100 101 template<typename T> struct HashTraits; 101 template<> struct HashTraits<JSC::DFG::MinifiedID> : SimpleClassHashTraits<JSC::DFG::MinifiedID> { }; 102 template<> struct HashTraits<JSC::DFG::MinifiedID> : SimpleClassHashTraits<JSC::DFG::MinifiedID> { 103 static const bool emptyValueIsZero = false; 104 }; 102 105 103 106 } // namespace WTF -
trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp
r171613 r181993 1 1 /* 2 * Copyright (C) 2012 , 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 43 43 result.m_info = JSValue::encode(node->asJSValue()); 44 44 else { 45 ASSERT(node->op() == Phantom Arguments);46 result.m_info = 0;45 ASSERT(node->op() == PhantomDirectArguments || node->op() == PhantomClonedArguments); 46 result.m_info = bitwise_cast<uintptr_t>(node->origin.semantic.inlineCallFrame); 47 47 } 48 48 return result; -
trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h
r171613 r181993 1 1 /* 2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 43 43 case Int52Constant: 44 44 case DoubleConstant: 45 case PhantomArguments: 45 case PhantomDirectArguments: 46 case PhantomClonedArguments: 46 47 return true; 47 48 default: … … 66 67 } 67 68 69 bool hasInlineCallFrame() const { return hasInlineCallFrame(m_op); } 70 71 InlineCallFrame* inlineCallFrame() const 72 { 73 return bitwise_cast<InlineCallFrame*>(static_cast<uintptr_t>(m_info)); 74 } 75 68 76 static MinifiedID getID(MinifiedNode* node) { return node->id(); } 69 77 static bool compareByNodeIndex(const MinifiedNode& a, const MinifiedNode& b) … … 76 84 { 77 85 return type == JSConstant || type == Int52Constant || type == DoubleConstant; 86 } 87 88 static bool hasInlineCallFrame(NodeType type) 89 { 90 return type == PhantomDirectArguments || type == PhantomClonedArguments; 78 91 } 79 92 -
trunk/Source/JavaScriptCore/dfg/DFGNode.cpp
r181650 r181993 95 95 } 96 96 97 void Node::convertToIdentityOn(Node* child) 98 { 99 children.reset(); 100 child1() = child->defaultEdge(); 101 NodeFlags output = canonicalResultRepresentation(this->result()); 102 NodeFlags input = canonicalResultRepresentation(child->result()); 103 if (output == input) { 104 setOpAndDefaultFlags(Identity); 105 setResult(output); 106 return; 107 } 108 switch (output) { 109 case NodeResultDouble: 110 RELEASE_ASSERT(input == NodeResultInt52 || input == NodeResultJS); 111 setOpAndDefaultFlags(DoubleRep); 112 return; 113 case NodeResultInt52: 114 RELEASE_ASSERT(input == NodeResultDouble || input == NodeResultJS); 115 setOpAndDefaultFlags(Int52Rep); 116 return; 117 case NodeResultJS: 118 RELEASE_ASSERT(input == NodeResultDouble || input == NodeResultInt52); 119 setOpAndDefaultFlags(ValueRep); 120 return; 121 default: 122 RELEASE_ASSERT_NOT_REACHED(); 123 return; 124 } 125 } 126 97 127 void Node::convertToPutHint(const PromotedLocationDescriptor& descriptor, Node* base, Node* value) 98 128 { -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r181650 r181993 430 430 431 431 void convertToIdentity(); 432 void convertToIdentityOn(Node*); 432 433 433 434 bool mustGenerate() … … 448 449 } 449 450 450 bool isPhantomArguments()451 {452 return op() == PhantomArguments;453 }454 455 451 bool hasConstant() 456 452 { … … 459 455 case DoubleConstant: 460 456 case Int52Constant: 461 case PhantomArguments: 462 return true; 457 return true; 458 459 case PhantomDirectArguments: 460 case PhantomClonedArguments: 461 // These pretend to be the empty value constant for the benefit of the DFG backend, which 462 // otherwise wouldn't take kindly to a node that doesn't compute a value. 463 return true; 464 463 465 default: 464 466 return false; … … 469 471 { 470 472 ASSERT(hasConstant()); 471 if (op() == PhantomArguments) 473 474 if (op() == PhantomDirectArguments || op() == PhantomClonedArguments) { 475 // These pretend to be the empty value constant for the benefit of the DFG backend, which 476 // otherwise wouldn't take kindly to a node that doesn't compute a value. 472 477 return FrozenValue::emptySingleton(); 478 } 479 473 480 return bitwise_cast<FrozenValue*>(m_opInfo); 474 481 } … … 935 942 } 936 943 937 bool has VarNumber()944 bool hasScopeOffset() 938 945 { 939 946 return op() == GetClosureVar || op() == PutClosureVar; 940 947 } 941 948 942 int varNumber() 943 { 944 ASSERT(hasVarNumber()); 945 return m_opInfo; 949 ScopeOffset scopeOffset() 950 { 951 ASSERT(hasScopeOffset()); 952 return ScopeOffset(m_opInfo); 953 } 954 955 bool hasDirectArgumentsOffset() 956 { 957 return op() == GetFromArguments || op() == PutToArguments; 958 } 959 960 DirectArgumentsOffset capturedArgumentsOffset() 961 { 962 ASSERT(hasDirectArgumentsOffset()); 963 return DirectArgumentsOffset(m_opInfo); 946 964 } 947 965 … … 951 969 } 952 970 953 WriteBarrier<Unknown>* registerPointer()971 WriteBarrier<Unknown>* variablePointer() 954 972 { 955 973 return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo); … … 962 980 case CallForwardVarargs: 963 981 case ConstructVarargs: 982 case ConstructForwardVarargs: 964 983 return true; 965 984 default: … … 976 995 bool hasLoadVarargsData() 977 996 { 978 return op() == LoadVarargs ;997 return op() == LoadVarargs || op() == ForwardVarargs; 979 998 } 980 999 … … 1135 1154 case GetByIdFlush: 1136 1155 case GetByVal: 1137 case GetMyArgumentByVal:1138 case GetMyArgumentByValSafe:1139 1156 case Call: 1140 1157 case Construct: … … 1147 1164 case MultiGetByOffset: 1148 1165 case GetClosureVar: 1166 case GetFromArguments: 1149 1167 case ArrayPop: 1150 1168 case ArrayPush: … … 1177 1195 case NativeConstruct: 1178 1196 case NativeCall: 1179 case NewFunctionNoCheck:1180 1197 case NewFunction: 1181 case NewFunctionExpression:1182 1198 return true; 1183 1199 default: … … 1331 1347 ObjectMaterializationData& objectMaterializationData() 1332 1348 { 1349 ASSERT(hasObjectMaterializationData()); 1333 1350 return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo); 1334 1351 } … … 1338 1355 switch (op()) { 1339 1356 case PhantomNewObject: 1357 return true; 1358 default: 1359 return false; 1360 } 1361 } 1362 1363 bool isPhantomAllocation() 1364 { 1365 switch (op()) { 1366 case PhantomNewObject: 1367 case PhantomDirectArguments: 1368 case PhantomClonedArguments: 1340 1369 return true; 1341 1370 default: … … 1452 1481 case MovHint: 1453 1482 case ZombieHint: 1454 case PhantomArguments:1455 1483 return true; 1456 1484 case Phantom: … … 1672 1700 } 1673 1701 1674 bool shouldSpeculateArguments() 1675 { 1676 return isArgumentsSpeculation(prediction()); 1702 bool shouldSpeculateDirectArguments() 1703 { 1704 return isDirectArgumentsSpeculation(prediction()); 1705 } 1706 1707 bool shouldSpeculateScopedArguments() 1708 { 1709 return isScopedArgumentsSpeculation(prediction()); 1677 1710 } 1678 1711 -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r181891 r181993 51 51 macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \ 52 52 macro(GetCallee, NodeResultJS) \ 53 macro(GetArgumentCount, NodeResultInt32) \ 53 54 \ 54 55 /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\ … … 152 153 /* opcodes use VarArgs beause they may have up to 4 children. */\ 153 154 macro(GetByVal, NodeResultJS | NodeMustGenerate) \ 155 macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \ 154 156 macro(LoadVarargs, NodeMustGenerate) \ 157 macro(ForwardVarargs, NodeMustGenerate) \ 155 158 macro(PutByValDirect, NodeMustGenerate | NodeHasVarArgs) \ 156 159 macro(PutByVal, NodeMustGenerate | NodeHasVarArgs) \ … … 184 187 macro(GetScope, NodeResultJS) \ 185 188 macro(SkipScope, NodeResultJS) \ 186 macro(GetClosureRegisters, NodeResultStorage) \187 189 macro(GetClosureVar, NodeResultJS) \ 188 190 macro(PutClosureVar, NodeMustGenerate) \ … … 225 227 macro(CallForwardVarargs, NodeResultJS | NodeMustGenerate) \ 226 228 macro(ConstructVarargs, NodeResultJS | NodeMustGenerate) \ 229 macro(ConstructForwardVarargs, NodeResultJS | NodeMustGenerate) \ 227 230 macro(NativeCall, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ 228 231 macro(NativeConstruct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ … … 265 268 macro(ProfileControlFlow, NodeMustGenerate) \ 266 269 \ 267 /* Nodes used for activations. Activation support works by having it anchored at */\268 /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\269 /* being threaded with each other. */\270 270 macro(CreateActivation, NodeResultJS) \ 271 271 \ 272 /* Nodes used for arguments. Similar to lexical environment support, only it makes even less */\ 273 /* sense. */\ 274 macro(CreateArguments, NodeResultJS) \ 275 macro(PhantomArguments, NodeResultJS) \ 276 macro(TearOffArguments, NodeMustGenerate) \ 277 macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \ 278 macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \ 279 macro(GetMyArgumentsLengthSafe, NodeResultJS | NodeMustGenerate) \ 280 macro(GetMyArgumentByValSafe, NodeResultJS | NodeMustGenerate) \ 281 macro(CheckArgumentsNotCreated, NodeMustGenerate) \ 282 \ 283 /* Nodes for creating functions. */\ 284 macro(NewFunctionNoCheck, NodeResultJS) \ 272 macro(CreateDirectArguments, NodeResultJS) \ 273 macro(PhantomDirectArguments, NodeResultJS) \ 274 macro(CreateScopedArguments, NodeResultJS) \ 275 macro(CreateClonedArguments, NodeResultJS) \ 276 macro(PhantomClonedArguments, NodeResultJS) \ 277 macro(GetFromArguments, NodeResultJS) \ 278 macro(PutToArguments, NodeMustGenerate) \ 279 \ 285 280 macro(NewFunction, NodeResultJS) \ 286 macro(NewFunctionExpression, NodeResultJS) \287 281 \ 288 282 /* These aren't terminals but always exit */ \ -
trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp
r181650 r181993 83 83 calculator.executeNode(block->at(nodeIndex)); 84 84 85 // FIXME: we should probably prune by liveness here. 86 // https://bugs.webkit.org/show_bug.cgi?id=143078 85 87 calculator.m_availability.prune(); 86 88 87 89 if (calculator.m_availability == block->ssa->availabilityAtTail) 88 90 continue; … … 156 158 } 157 159 158 case LoadVarargs: { 160 case LoadVarargs: 161 case ForwardVarargs: { 159 162 LoadVarargsData* data = node->loadVarargsData(); 160 163 m_availability.m_locals.operand(data->count) = … … 167 170 } 168 171 172 case PhantomDirectArguments: 173 case PhantomClonedArguments: { 174 InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame; 175 if (!inlineCallFrame) { 176 // We don't need to record anything about how the arguments are to be recovered. It's just a 177 // given that we can read them from the stack. 178 break; 179 } 180 181 if (inlineCallFrame->isVarargs()) { 182 // Record how to read each argument and the argument count. 183 Availability argumentCount = 184 m_availability.m_locals.operand(inlineCallFrame->stackOffset + JSStack::ArgumentCount); 185 186 m_availability.m_heap.set(PromotedHeapLocation(ArgumentCountPLoc, node), argumentCount); 187 } 188 189 if (inlineCallFrame->isClosureCall) { 190 Availability callee = m_availability.m_locals.operand( 191 inlineCallFrame->stackOffset + JSStack::Callee); 192 m_availability.m_heap.set(PromotedHeapLocation(ArgumentsCalleePLoc, node), callee); 193 } 194 195 for (unsigned i = 0; i < inlineCallFrame->arguments.size() - 1; ++i) { 196 Availability argument = m_availability.m_locals.operand( 197 inlineCallFrame->stackOffset + CallFrame::argumentOffset(i)); 198 199 m_availability.m_heap.set(PromotedHeapLocation(ArgumentPLoc, node, i), argument); 200 } 201 break; 202 } 203 169 204 case PutHint: { 170 205 m_availability.m_heap.set( -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
r181841 r181993 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013Apple Inc. All rights reserved.2 * Copyright (C) 2011-2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 40 40 41 41 namespace JSC { namespace DFG { 42 43 void OSRExitCompiler::emitRestoreArguments(const Operands<ValueRecovery>& operands) 44 { 45 HashMap<MinifiedID, int> alreadyAllocatedArguments; // Maps phantom arguments node ID to operand. 46 for (size_t index = 0; index < operands.size(); ++index) { 47 const ValueRecovery& recovery = operands[index]; 48 int operand = operands.operandForIndex(index); 49 50 if (recovery.technique() != DirectArgumentsThatWereNotCreated 51 && recovery.technique() != ClonedArgumentsThatWereNotCreated) 52 continue; 53 54 MinifiedID id = recovery.nodeID(); 55 auto iter = alreadyAllocatedArguments.find(id); 56 if (iter != alreadyAllocatedArguments.end()) { 57 JSValueRegs regs = JSValueRegs::withTwoAvailableRegs(GPRInfo::regT0, GPRInfo::regT1); 58 m_jit.loadValue(CCallHelpers::addressFor(iter->value), regs); 59 m_jit.storeValue(regs, CCallHelpers::addressFor(operand)); 60 continue; 61 } 62 63 InlineCallFrame* inlineCallFrame = 64 m_jit.codeBlock()->jitCode()->dfg()->minifiedDFG.at(id)->inlineCallFrame(); 65 66 int stackOffset; 67 if (inlineCallFrame) 68 stackOffset = inlineCallFrame->stackOffset; 69 else 70 stackOffset = 0; 71 72 if (!inlineCallFrame || inlineCallFrame->isClosureCall) { 73 m_jit.loadPtr( 74 AssemblyHelpers::addressFor(stackOffset + JSStack::Callee), 75 GPRInfo::regT0); 76 } else { 77 m_jit.move( 78 AssemblyHelpers::TrustedImmPtr(inlineCallFrame->calleeRecovery.constant().asCell()), 79 GPRInfo::regT0); 80 } 81 82 if (!inlineCallFrame || inlineCallFrame->isVarargs()) { 83 m_jit.load32( 84 AssemblyHelpers::payloadFor(stackOffset + JSStack::ArgumentCount), 85 GPRInfo::regT1); 86 } else { 87 m_jit.move( 88 AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), 89 GPRInfo::regT1); 90 } 91 92 m_jit.setupArgumentsWithExecState( 93 AssemblyHelpers::TrustedImmPtr(inlineCallFrame), GPRInfo::regT0, GPRInfo::regT1); 94 switch (recovery.technique()) { 95 case DirectArgumentsThatWereNotCreated: 96 m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(operationCreateDirectArgumentsDuringExit)), GPRInfo::nonArgGPR0); 97 break; 98 case ClonedArgumentsThatWereNotCreated: 99 m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(operationCreateClonedArgumentsDuringExit)), GPRInfo::nonArgGPR0); 100 break; 101 default: 102 RELEASE_ASSERT_NOT_REACHED(); 103 break; 104 } 105 m_jit.call(GPRInfo::nonArgGPR0); 106 m_jit.storeCell(GPRInfo::returnValueGPR, AssemblyHelpers::addressFor(operand)); 107 108 alreadyAllocatedArguments.add(id, operand); 109 } 110 } 42 111 43 112 extern "C" { -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h
r164424 r181993 1 1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 50 50 51 51 private: 52 #if !ASSERT_DISABLED 53 static unsigned badIndex() { return static_cast<unsigned>(-1); }; 54 #endif 55 56 void initializePoisoned(unsigned size) 57 { 58 #if ASSERT_DISABLED 59 m_poisonScratchIndices.resize(size); 60 #else 61 m_poisonScratchIndices.fill(badIndex(), size); 62 #endif 63 } 64 65 unsigned poisonIndex(unsigned index) 66 { 67 unsigned result = m_poisonScratchIndices[index]; 68 ASSERT(result != badIndex()); 69 return result; 70 } 52 void emitRestoreArguments(const Operands<ValueRecovery>&); 71 53 72 54 CCallHelpers& m_jit; 73 Vector<unsigned> m_poisonScratchIndices;74 55 }; 75 56 -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
r181835 r181993 1 1 /* 2 * Copyright (C) 2011, 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 39 39 void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecovery>& operands, SpeculationRecovery* recovery) 40 40 { 41 // 1)Pro-forma stuff.41 // Pro-forma stuff. 42 42 if (Options::printEachOSRExit()) { 43 43 SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo; … … 49 49 } 50 50 51 // 2)Perform speculation recovery. This only comes into play when an operation52 // 51 // Perform speculation recovery. This only comes into play when an operation 52 // starts mutating state before verifying the speculation it has already made. 53 53 54 54 if (recovery) { … … 66 66 } 67 67 68 // 3)Refine some value profile, if appropriate.68 // Refine some value profile, if appropriate. 69 69 70 70 if (!!exit.m_jsValueSource) { … … 103 103 scratch2 = AssemblyHelpers::selectScratchGPR(usedRegister1, usedRegister2, scratch1); 104 104 105 #if CPU(ARM64)106 m_jit.pushToSave(scratch1);107 m_jit.pushToSave(scratch2);108 #else109 105 m_jit.push(scratch1); 110 106 m_jit.push(scratch2); 111 #endif112 107 113 108 GPRReg value; … … 125 120 m_jit.or32(scratch2, AssemblyHelpers::AbsoluteAddress(arrayProfile->addressOfArrayModes())); 126 121 127 #if CPU(ARM64)128 m_jit.popToRestore(scratch2);129 m_jit.popToRestore(scratch1);130 #else131 122 m_jit.pop(scratch2); 132 123 m_jit.pop(scratch1); 133 #endif134 124 } 135 125 } … … 142 132 GPRReg scratch = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base()); 143 133 144 #if CPU(ARM64)145 m_jit.pushToSave(scratch);146 #else147 134 m_jit.push(scratch); 148 #endif149 135 150 136 m_jit.load32(exit.m_jsValueSource.asAddress(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), scratch); … … 153 139 m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload); 154 140 155 #if CPU(ARM64)156 m_jit.popToRestore(scratch);157 #else158 141 m_jit.pop(scratch); 159 #endif160 142 } else if (exit.m_jsValueSource.hasKnownTag()) { 161 143 m_jit.store32(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag); … … 171 153 // do this simple approach. 172 154 173 // 4)Save all state from GPRs into the scratch buffer.155 // Save all state from GPRs into the scratch buffer. 174 156 175 157 ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(sizeof(EncodedJSValue) * operands.size()); … … 204 186 // Now all GPRs are free to reuse. 205 187 206 // 5)Save all state from FPRs into the scratch buffer.188 // Save all state from FPRs into the scratch buffer. 207 189 208 190 for (size_t index = 0; index < operands.size(); ++index) { … … 222 204 // Now all FPRs are free to reuse. 223 205 224 // 6)Save all state from the stack into the scratch buffer. For simplicity we225 // 226 // 206 // Save all state from the stack into the scratch buffer. For simplicity we 207 // do this even for state that's already in the right place on the stack. 208 // It makes things simpler later. 227 209 228 210 for (size_t index = 0; index < operands.size(); ++index) { … … 262 244 CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister); 263 245 264 // 7) Do all data format conversions and store the results into the stack. 265 266 bool haveArguments = false; 246 // Do all data format conversions and store the results into the stack. 267 247 268 248 for (size_t index = 0; index < operands.size(); ++index) { … … 343 323 break; 344 324 345 case ArgumentsThatWereNotCreated: 346 haveArguments = true; 347 m_jit.store32( 348 AssemblyHelpers::TrustedImm32(JSValue().tag()), 349 AssemblyHelpers::tagFor(operand)); 350 m_jit.store32( 351 AssemblyHelpers::TrustedImm32(JSValue().payload()), 352 AssemblyHelpers::payloadFor(operand)); 353 break; 354 355 default: 356 break; 357 } 358 } 359 360 // 8) Adjust the old JIT's execute counter. Since we are exiting OSR, we know 361 // that all new calls into this code will go to the new JIT, so the execute 362 // counter only affects call frames that performed OSR exit and call frames 363 // that were still executing the old JIT at the time of another call frame's 364 // OSR exit. We want to ensure that the following is true: 365 // 366 // (a) Code the performs an OSR exit gets a chance to reenter optimized 367 // code eventually, since optimized code is faster. But we don't 368 // want to do such reentery too aggressively (see (c) below). 369 // 370 // (b) If there is code on the call stack that is still running the old 371 // JIT's code and has never OSR'd, then it should get a chance to 372 // perform OSR entry despite the fact that we've exited. 373 // 374 // (c) Code the performs an OSR exit should not immediately retry OSR 375 // entry, since both forms of OSR are expensive. OSR entry is 376 // particularly expensive. 377 // 378 // (d) Frequent OSR failures, even those that do not result in the code 379 // running in a hot loop, result in recompilation getting triggered. 380 // 381 // To ensure (c), we'd like to set the execute counter to 382 // counterValueForOptimizeAfterWarmUp(). This seems like it would endanger 383 // (a) and (b), since then every OSR exit would delay the opportunity for 384 // every call frame to perform OSR entry. Essentially, if OSR exit happens 385 // frequently and the function has few loops, then the counter will never 386 // become non-negative and OSR entry will never be triggered. OSR entry 387 // will only happen if a loop gets hot in the old JIT, which does a pretty 388 // good job of ensuring (a) and (b). But that doesn't take care of (d), 389 // since each speculation failure would reset the execute counter. 390 // So we check here if the number of speculation failures is significantly 391 // larger than the number of successes (we want 90% success rate), and if 392 // there have been a large enough number of failures. If so, we set the 393 // counter to 0; otherwise we set the counter to 394 // counterValueForOptimizeAfterWarmUp(). 325 case DirectArgumentsThatWereNotCreated: 326 case ClonedArgumentsThatWereNotCreated: 327 // Don't do this, yet. 328 break; 329 330 default: 331 break; 332 } 333 } 334 335 // Now that things on the stack are recovered, do the arguments recovery. We assume that arguments 336 // recoveries don't recursively refer to each other. But, we don't try to assume that they only 337 // refer to certain ranges of locals. Hence why we need to do this here, once the stack is sensible. 338 // Note that we also roughly assume that the arguments might still be materialized outside of its 339 // inline call frame scope - but for now the DFG wouldn't do that. 340 341 emitRestoreArguments(operands); 342 343 // Adjust the old JIT's execute counter. Since we are exiting OSR, we know 344 // that all new calls into this code will go to the new JIT, so the execute 345 // counter only affects call frames that performed OSR exit and call frames 346 // that were still executing the old JIT at the time of another call frame's 347 // OSR exit. We want to ensure that the following is true: 348 // 349 // (a) Code the performs an OSR exit gets a chance to reenter optimized 350 // code eventually, since optimized code is faster. But we don't 351 // want to do such reentery too aggressively (see (c) below). 352 // 353 // (b) If there is code on the call stack that is still running the old 354 // JIT's code and has never OSR'd, then it should get a chance to 355 // perform OSR entry despite the fact that we've exited. 356 // 357 // (c) Code the performs an OSR exit should not immediately retry OSR 358 // entry, since both forms of OSR are expensive. OSR entry is 359 // particularly expensive. 360 // 361 // (d) Frequent OSR failures, even those that do not result in the code 362 // running in a hot loop, result in recompilation getting triggered. 363 // 364 // To ensure (c), we'd like to set the execute counter to 365 // counterValueForOptimizeAfterWarmUp(). This seems like it would endanger 366 // (a) and (b), since then every OSR exit would delay the opportunity for 367 // every call frame to perform OSR entry. Essentially, if OSR exit happens 368 // frequently and the function has few loops, then the counter will never 369 // become non-negative and OSR entry will never be triggered. OSR entry 370 // will only happen if a loop gets hot in the old JIT, which does a pretty 371 // good job of ensuring (a) and (b). But that doesn't take care of (d), 372 // since each speculation failure would reset the execute counter. 373 // So we check here if the number of speculation failures is significantly 374 // larger than the number of successes (we want 90% success rate), and if 375 // there have been a large enough number of failures. If so, we set the 376 // counter to 0; otherwise we set the counter to 377 // counterValueForOptimizeAfterWarmUp(). 395 378 396 379 handleExitCounts(m_jit, exit); 397 380 398 // 9)Reify inlined call frames.381 // Reify inlined call frames. 399 382 400 383 reifyInlinedCallFrames(m_jit, exit); 401 384 402 // 10) Create arguments if necessary and place them into the appropriate aliased 403 // registers. 404 405 if (haveArguments) { 406 ArgumentsRecoveryGenerator argumentsRecovery; 407 408 for (size_t index = 0; index < operands.size(); ++index) { 409 const ValueRecovery& recovery = operands[index]; 410 if (recovery.technique() != ArgumentsThatWereNotCreated) 411 continue; 412 argumentsRecovery.generateFor( 413 operands.operandForIndex(index), exit.m_codeOrigin, m_jit); 414 } 415 } 416 417 // 12) And finish. 385 // And finish. 418 386 adjustAndJumpToTarget(m_jit, exit); 419 387 } -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
r181835 r181993 43 43 m_jit.jitAssertTagsInPlace(); 44 44 45 // 1)Pro-forma stuff.45 // Pro-forma stuff. 46 46 if (Options::printEachOSRExit()) { 47 47 SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo; … … 53 53 } 54 54 55 // 2)Perform speculation recovery. This only comes into play when an operation56 // 55 // Perform speculation recovery. This only comes into play when an operation 56 // starts mutating state before verifying the speculation it has already made. 57 57 58 58 if (recovery) { … … 72 72 } 73 73 74 // 3)Refine some array and/or value profile, if appropriate.74 // Refine some array and/or value profile, if appropriate. 75 75 76 76 if (!!exit.m_jsValueSource) { … … 98 98 scratch2 = AssemblyHelpers::selectScratchGPR(usedRegister, scratch1); 99 99 100 #if CPU(ARM64) 101 m_jit.pushToSave(scratch1);102 m_jit.pushToSave(scratch2);103 #else 104 m_jit.push(scratch1);105 m_jit.push(scratch2);106 #endif 100 if (isARM64()) { 101 m_jit.pushToSave(scratch1); 102 m_jit.pushToSave(scratch2); 103 } else { 104 m_jit.push(scratch1); 105 m_jit.push(scratch2); 106 } 107 107 108 108 GPRReg value; … … 120 120 m_jit.or32(scratch2, AssemblyHelpers::AbsoluteAddress(arrayProfile->addressOfArrayModes())); 121 121 122 #if CPU(ARM64) 123 m_jit.popToRestore(scratch2);124 m_jit.popToRestore(scratch1);125 #else 126 m_jit.pop(scratch2);127 m_jit.pop(scratch1);128 #endif 122 if (isARM64()) { 123 m_jit.popToRestore(scratch2); 124 m_jit.popToRestore(scratch1); 125 } else { 126 m_jit.pop(scratch2); 127 m_jit.pop(scratch1); 128 } 129 129 } 130 130 } … … 180 180 // features in the future and it will make it harder to reason about bugs. 181 181 182 // 4)Save all state from GPRs into the scratch buffer.182 // Save all state from GPRs into the scratch buffer. 183 183 184 184 ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(sizeof(EncodedJSValue) * operands.size()); … … 204 204 // And voila, all GPRs are free to reuse. 205 205 206 // 5)Save all state from FPRs into the scratch buffer.206 // Save all state from FPRs into the scratch buffer. 207 207 208 208 for (size_t index = 0; index < operands.size(); ++index) { … … 222 222 // Now, all FPRs are also free. 223 223 224 // 6)Save all state from the stack into the scratch buffer. For simplicity we225 // 226 // 224 // Save all state from the stack into the scratch buffer. For simplicity we 225 // do this even for state that's already in the right place on the stack. 226 // It makes things simpler later. 227 227 228 228 for (size_t index = 0; index < operands.size(); ++index) { … … 254 254 CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister); 255 255 256 // 7) Do all data format conversions and store the results into the stack. 257 258 bool haveArguments = false; 256 // Do all data format conversions and store the results into the stack. 259 257 260 258 for (size_t index = 0; index < operands.size(); ++index) { … … 311 309 break; 312 310 313 case ArgumentsThatWereNotCreated: 314 haveArguments = true; 315 // We can't restore this yet but we can make sure that the stack appears 316 // sane. 317 m_jit.store64( 318 AssemblyHelpers::TrustedImm64(JSValue::encode(JSValue())), 319 AssemblyHelpers::addressFor(operand)); 320 break; 321 322 default: 323 break; 324 } 325 } 326 327 // 8) Adjust the old JIT's execute counter. Since we are exiting OSR, we know 328 // that all new calls into this code will go to the new JIT, so the execute 329 // counter only affects call frames that performed OSR exit and call frames 330 // that were still executing the old JIT at the time of another call frame's 331 // OSR exit. We want to ensure that the following is true: 332 // 333 // (a) Code the performs an OSR exit gets a chance to reenter optimized 334 // code eventually, since optimized code is faster. But we don't 335 // want to do such reentery too aggressively (see (c) below). 336 // 337 // (b) If there is code on the call stack that is still running the old 338 // JIT's code and has never OSR'd, then it should get a chance to 339 // perform OSR entry despite the fact that we've exited. 340 // 341 // (c) Code the performs an OSR exit should not immediately retry OSR 342 // entry, since both forms of OSR are expensive. OSR entry is 343 // particularly expensive. 344 // 345 // (d) Frequent OSR failures, even those that do not result in the code 346 // running in a hot loop, result in recompilation getting triggered. 347 // 348 // To ensure (c), we'd like to set the execute counter to 349 // counterValueForOptimizeAfterWarmUp(). This seems like it would endanger 350 // (a) and (b), since then every OSR exit would delay the opportunity for 351 // every call frame to perform OSR entry. Essentially, if OSR exit happens 352 // frequently and the function has few loops, then the counter will never 353 // become non-negative and OSR entry will never be triggered. OSR entry 354 // will only happen if a loop gets hot in the old JIT, which does a pretty 355 // good job of ensuring (a) and (b). But that doesn't take care of (d), 356 // since each speculation failure would reset the execute counter. 357 // So we check here if the number of speculation failures is significantly 358 // larger than the number of successes (we want 90% success rate), and if 359 // there have been a large enough number of failures. If so, we set the 360 // counter to 0; otherwise we set the counter to 361 // counterValueForOptimizeAfterWarmUp(). 311 case DirectArgumentsThatWereNotCreated: 312 case ClonedArgumentsThatWereNotCreated: 313 // Don't do this, yet. 314 break; 315 316 default: 317 RELEASE_ASSERT_NOT_REACHED(); 318 break; 319 } 320 } 321 322 // Now that things on the stack are recovered, do the arguments recovery. We assume that arguments 323 // recoveries don't recursively refer to each other. But, we don't try to assume that they only 324 // refer to certain ranges of locals. Hence why we need to do this here, once the stack is sensible. 325 // Note that we also roughly assume that the arguments might still be materialized outside of its 326 // inline call frame scope - but for now the DFG wouldn't do that. 327 328 emitRestoreArguments(operands); 329 330 // Adjust the old JIT's execute counter. Since we are exiting OSR, we know 331 // that all new calls into this code will go to the new JIT, so the execute 332 // counter only affects call frames that performed OSR exit and call frames 333 // that were still executing the old JIT at the time of another call frame's 334 // OSR exit. We want to ensure that the following is true: 335 // 336 // (a) Code the performs an OSR exit gets a chance to reenter optimized 337 // code eventually, since optimized code is faster. But we don't 338 // want to do such reentery too aggressively (see (c) below). 339 // 340 // (b) If there is code on the call stack that is still running the old 341 // JIT's code and has never OSR'd, then it should get a chance to 342 // perform OSR entry despite the fact that we've exited. 343 // 344 // (c) Code the performs an OSR exit should not immediately retry OSR 345 // entry, since both forms of OSR are expensive. OSR entry is 346 // particularly expensive. 347 // 348 // (d) Frequent OSR failures, even those that do not result in the code 349 // running in a hot loop, result in recompilation getting triggered. 350 // 351 // To ensure (c), we'd like to set the execute counter to 352 // counterValueForOptimizeAfterWarmUp(). This seems like it would endanger 353 // (a) and (b), since then every OSR exit would delay the opportunity for 354 // every call frame to perform OSR entry. Essentially, if OSR exit happens 355 // frequently and the function has few loops, then the counter will never 356 // become non-negative and OSR entry will never be triggered. OSR entry 357 // will only happen if a loop gets hot in the old JIT, which does a pretty 358 // good job of ensuring (a) and (b). But that doesn't take care of (d), 359 // since each speculation failure would reset the execute counter. 360 // So we check here if the number of speculation failures is significantly 361 // larger than the number of successes (we want 90% success rate), and if 362 // there have been a large enough number of failures. If so, we set the 363 // counter to 0; otherwise we set the counter to 364 // counterValueForOptimizeAfterWarmUp(). 362 365 363 366 handleExitCounts(m_jit, exit); 364 367 365 // 9)Reify inlined call frames.368 // Reify inlined call frames. 366 369 367 370 reifyInlinedCallFrames(m_jit, exit); 368 371 369 // 10) Create arguments if necessary and place them into the appropriate aliased 370 // registers. 371 372 if (haveArguments) { 373 ArgumentsRecoveryGenerator argumentsRecovery; 374 375 for (size_t index = 0; index < operands.size(); ++index) { 376 const ValueRecovery& recovery = operands[index]; 377 if (recovery.technique() != ArgumentsThatWereNotCreated) 378 continue; 379 argumentsRecovery.generateFor( 380 operands.operandForIndex(index), exit.m_codeOrigin, m_jit); 381 } 382 } 383 384 // 12) And finish. 372 // And finish. 385 373 adjustAndJumpToTarget(m_jit, exit); 386 374 } -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
r181835 r181993 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "Arguments.h"32 31 #include "DFGJITCode.h" 33 32 #include "DFGOperations.h" … … 207 206 if (!inlineCallFrame->isClosureCall) 208 207 jit.store64(AssemblyHelpers::TrustedImm64(JSValue::encode(JSValue(inlineCallFrame->calleeConstant()))), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee))); 209 210 // Leave the captured arguments in regT3.211 if (baselineCodeBlock->usesArguments())212 jit.loadPtr(AssemblyHelpers::addressFor(VirtualRegister(inlineCallFrame->stackOffset + unmodifiedArgumentsRegister(baselineCodeBlock->argumentsRegister()).offset())), GPRInfo::regT3);213 208 #else // USE(JSVALUE64) // so this is the 32-bit part 214 209 jit.storePtr(callerFrameGPR, AssemblyHelpers::addressForByteOffset(inlineCallFrame->callerFrameOffset())); … … 219 214 if (!inlineCallFrame->isClosureCall) 220 215 jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->calleeConstant()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee))); 221 222 // Leave the captured arguments in regT3.223 if (baselineCodeBlock->usesArguments())224 jit.loadPtr(AssemblyHelpers::payloadFor(VirtualRegister(inlineCallFrame->stackOffset + unmodifiedArgumentsRegister(baselineCodeBlock->argumentsRegister()).offset())), GPRInfo::regT3);225 216 #endif // USE(JSVALUE64) // ending the #else part, so directly above is the 32-bit part 226 227 if (baselineCodeBlock->usesArguments()) {228 AssemblyHelpers::Jump noArguments = jit.branchTestPtr(AssemblyHelpers::Zero, GPRInfo::regT3);229 jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT0);230 jit.storePtr(GPRInfo::regT0, AssemblyHelpers::Address(GPRInfo::regT3, Arguments::offsetOfRegisters()));231 noArguments.link(&jit);232 }233 217 } 234 218 … … 300 284 } 301 285 302 ArgumentsRecoveryGenerator::ArgumentsRecoveryGenerator() { }303 ArgumentsRecoveryGenerator::~ArgumentsRecoveryGenerator() { }304 305 void ArgumentsRecoveryGenerator::generateFor(306 int operand, CodeOrigin codeOrigin, CCallHelpers& jit)307 {308 // Find the right inline call frame.309 InlineCallFrame* inlineCallFrame = 0;310 for (InlineCallFrame* current = codeOrigin.inlineCallFrame;311 current;312 current = current->caller.inlineCallFrame) {313 if (current->stackOffset >= operand) {314 inlineCallFrame = current;315 break;316 }317 }318 319 if (!jit.baselineCodeBlockFor(inlineCallFrame)->usesArguments())320 return;321 VirtualRegister argumentsRegister = jit.baselineArgumentsRegisterFor(inlineCallFrame);322 if (m_didCreateArgumentsObject.add(inlineCallFrame).isNewEntry) {323 // We know this call frame optimized out an arguments object that324 // the baseline JIT would have created. Do that creation now.325 if (inlineCallFrame) {326 jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT0);327 jit.setupArguments(GPRInfo::regT0);328 } else329 jit.setupArgumentsExecState();330 jit.move(331 AssemblyHelpers::TrustedImmPtr(332 bitwise_cast<void*>(operationCreateArgumentsDuringOSRExit)),333 GPRInfo::nonArgGPR0);334 #if USE(JSVALUE64)335 jit.call(GPRInfo::nonArgGPR0);336 jit.store64(GPRInfo::returnValueGPR, AssemblyHelpers::addressFor(argumentsRegister));337 jit.store64(338 GPRInfo::returnValueGPR,339 AssemblyHelpers::addressFor(unmodifiedArgumentsRegister(argumentsRegister)));340 jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.341 #else // USE(JSVALUE64) -> so the 32_64 part342 jit.call(GPRInfo::nonArgGPR0);343 jit.store32(344 AssemblyHelpers::TrustedImm32(JSValue::CellTag),345 AssemblyHelpers::tagFor(argumentsRegister));346 jit.store32(347 GPRInfo::returnValueGPR,348 AssemblyHelpers::payloadFor(argumentsRegister));349 jit.store32(350 AssemblyHelpers::TrustedImm32(JSValue::CellTag),351 AssemblyHelpers::tagFor(unmodifiedArgumentsRegister(argumentsRegister)));352 jit.store32(353 GPRInfo::returnValueGPR,354 AssemblyHelpers::payloadFor(unmodifiedArgumentsRegister(argumentsRegister)));355 jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); // no-op move on almost all platforms.356 #endif // USE(JSVALUE64)357 }358 359 #if USE(JSVALUE64)360 jit.load64(AssemblyHelpers::addressFor(argumentsRegister), GPRInfo::regT0);361 jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));362 #else // USE(JSVALUE64) -> so the 32_64 part363 jit.load32(AssemblyHelpers::payloadFor(argumentsRegister), GPRInfo::regT0);364 jit.store32(365 AssemblyHelpers::TrustedImm32(JSValue::CellTag),366 AssemblyHelpers::tagFor(operand));367 jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(operand));368 #endif // USE(JSVALUE64)369 }370 371 286 } } // namespace JSC::DFG 372 287 -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h
r164923 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 38 38 void adjustAndJumpToTarget(CCallHelpers&, const OSRExitBase&); 39 39 40 class ArgumentsRecoveryGenerator {41 public:42 ArgumentsRecoveryGenerator();43 ~ArgumentsRecoveryGenerator();44 45 void generateFor(int operand, CodeOrigin, CCallHelpers&);46 47 private:48 HashSet<InlineCallFrame*, DefaultHash<InlineCallFrame*>::Hash,49 NullableHashTraits<InlineCallFrame*>> m_didCreateArgumentsObject;50 };51 52 40 } } // namespace JSC::DFG 53 41 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r181814 r181993 27 27 #include "DFGOperations.h" 28 28 29 #include "Arguments.h"30 29 #include "ButterflyInlines.h" 30 #include "ClonedArguments.h" 31 31 #include "CodeBlock.h" 32 32 #include "CommonSlowPaths.h" … … 39 39 #include "DFGToFTLForOSREntryDeferredCompilationCallback.h" 40 40 #include "DFGWorklist.h" 41 #include "DirectArguments.h" 41 42 #include "FTLForOSREntryJITCode.h" 42 43 #include "FTLOSREntry.h" … … 46 47 #include "JIT.h" 47 48 #include "JITExceptions.h" 49 #include "JSCInlines.h" 48 50 #include "JSLexicalEnvironment.h" 49 #include "VM.h"50 51 #include "JSNameScope.h" 51 52 #include "ObjectConstructor.h" 52 #include "JSCInlines.h"53 53 #include "Repatch.h" 54 #include "ScopedArguments.h" 54 55 #include "StringConstructor.h" 55 56 #include "Symbol.h" 56 57 #include "TypeProfilerLog.h" 57 58 #include "TypedArrayInlines.h" 59 #include "VM.h" 58 60 #include <wtf/InlineASM.h> 59 61 … … 747 749 } 748 750 749 JSCell* JIT_OPERATION operationCreateInlinedArguments( 750 ExecState* exec, InlineCallFrame* inlineCallFrame) 751 { 752 VM& vm = exec->vm(); 753 NativeCallFrameTracer tracer(&vm, exec); 754 // NB: This needs to be exceedingly careful with top call frame tracking, since it 755 // may be called from OSR exit, while the state of the call stack is bizarre. 756 Arguments* result = Arguments::create(vm, exec, inlineCallFrame); 757 ASSERT(!vm.exception()); 751 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table) 752 { 753 VM& vm = exec->vm(); 754 NativeCallFrameTracer tracer(&vm, exec); 755 return JSLexicalEnvironment::create(vm, structure, scope, table); 756 } 757 758 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity) 759 { 760 VM& vm = exec->vm(); 761 NativeCallFrameTracer target(&vm, exec); 762 DirectArguments* result = DirectArguments::create( 763 vm, structure, length, std::max(length, minCapacity)); 764 // The caller will store to this object without barriers. Most likely, at this point, this is 765 // still a young object and so no barriers are needed. But it's good to be careful anyway, 766 // since the GC should be allowed to do crazy (like pretenuring, for example). 767 vm.heap.writeBarrier(result); 758 768 return result; 759 769 } 760 770 761 void JIT_OPERATION operationTearOffInlinedArguments( 762 ExecState* exec, JSCell* argumentsCell, JSCell* activationCell, InlineCallFrame* inlineCallFrame) 763 { 764 ASSERT_UNUSED(activationCell, !activationCell); // Currently, we don't inline functions with activations. 765 jsCast<Arguments*>(argumentsCell)->tearOff(exec, inlineCallFrame); 766 } 767 768 EncodedJSValue JIT_OPERATION operationGetArgumentByVal(ExecState* exec, int32_t argumentsRegister, int32_t index) 769 { 770 VM& vm = exec->vm(); 771 NativeCallFrameTracer tracer(&vm, exec); 772 773 JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue(); 774 775 // If there are no arguments, and we're accessing out of bounds, then we have to create the 776 // arguments in case someone has installed a getter on a numeric property. 777 if (!argumentsValue) { 778 JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr(); 779 exec->uncheckedR(argumentsRegister) = argumentsValue = Arguments::create(exec->vm(), exec, lexicalEnvironment); 780 } 781 782 return JSValue::encode(argumentsValue.get(exec, index)); 783 } 784 785 EncodedJSValue JIT_OPERATION operationGetInlinedArgumentByVal( 786 ExecState* exec, int32_t argumentsRegister, InlineCallFrame* inlineCallFrame, int32_t index) 787 { 788 VM& vm = exec->vm(); 789 NativeCallFrameTracer tracer(&vm, exec); 790 791 JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue(); 792 793 // If there are no arguments, and we're accessing out of bounds, then we have to create the 794 // arguments in case someone has installed a getter on a numeric property. 795 if (!argumentsValue) { 796 exec->uncheckedR(argumentsRegister) = argumentsValue = 797 Arguments::create(exec->vm(), exec, inlineCallFrame); 798 } 799 800 return JSValue::encode(argumentsValue.get(exec, index)); 801 } 802 803 JSCell* JIT_OPERATION operationNewFunctionNoCheck(ExecState* exec, JSScope* scope, JSCell* functionExecutable) 804 { 805 ASSERT(functionExecutable->inherits(FunctionExecutable::info())); 806 VM& vm = exec->vm(); 807 NativeCallFrameTracer tracer(&vm, exec); 808 return JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope); 771 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope) 772 { 773 VM& vm = exec->vm(); 774 NativeCallFrameTracer target(&vm, exec); 775 776 // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I 777 // didn't feel like changing the max number of arguments for a slow path call from 6 to 7. 778 ScopedArgumentsTable* table = scope->symbolTable()->arguments(); 779 780 return ScopedArguments::createByCopyingFrom( 781 vm, structure, argumentStart, length, callee, table, scope); 782 } 783 784 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee) 785 { 786 VM& vm = exec->vm(); 787 NativeCallFrameTracer target(&vm, exec); 788 return ClonedArguments::createByCopyingFrom( 789 exec, structure, argumentStart, length, callee); 790 } 791 792 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount) 793 { 794 VM& vm = exec->vm(); 795 NativeCallFrameTracer target(&vm, exec); 796 797 DeferGCForAWhile deferGC(vm.heap); 798 799 CodeBlock* codeBlock; 800 if (inlineCallFrame) 801 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame); 802 else 803 codeBlock = exec->codeBlock(); 804 805 unsigned length = argumentCount - 1; 806 unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1)); 807 DirectArguments* result = DirectArguments::create( 808 vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity); 809 810 result->callee().set(vm, result, callee); 811 812 Register* arguments = 813 exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) + 814 CallFrame::argumentOffset(0); 815 for (unsigned i = length; i--;) 816 result->setIndexQuickly(vm, i, arguments[i].jsValue()); 817 818 return result; 819 } 820 821 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount) 822 { 823 VM& vm = exec->vm(); 824 NativeCallFrameTracer target(&vm, exec); 825 826 DeferGCForAWhile deferGC(vm.heap); 827 828 CodeBlock* codeBlock; 829 if (inlineCallFrame) 830 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame); 831 else 832 codeBlock = exec->codeBlock(); 833 834 unsigned length = argumentCount - 1; 835 ClonedArguments* result = ClonedArguments::createEmpty( 836 vm, codeBlock->globalObject()->outOfBandArgumentsStructure(), callee); 837 838 Register* arguments = 839 exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) + 840 CallFrame::argumentOffset(0); 841 for (unsigned i = length; i--;) 842 result->putDirectIndex(exec, i, arguments[i].jsValue()); 843 844 result->putDirect(vm, vm.propertyNames->length, jsNumber(length)); 845 846 return result; 809 847 } 810 848 … … 1017 1055 1018 1056 set->notifyWrite(vm, value, "Executed NotifyWrite"); 1057 } 1058 1059 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec) 1060 { 1061 VM& vm = exec->vm(); 1062 NativeCallFrameTracer tracer(&vm, exec); 1063 throwStackOverflowError(exec); 1019 1064 } 1020 1065 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r180587 r181993 97 97 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 98 98 size_t JIT_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 99 JSCell* JIT_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL; 100 void JIT_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, JSCell*, InlineCallFrame*) WTF_INTERNAL; 101 EncodedJSValue JIT_OPERATION operationGetInlinedArgumentByVal(ExecState*, int32_t, InlineCallFrame*, int32_t) WTF_INTERNAL; 102 EncodedJSValue JIT_OPERATION operationGetArgumentByVal(ExecState*, int32_t, int32_t) WTF_INTERNAL; 103 JSCell* JIT_OPERATION operationNewFunctionNoCheck(ExecState*, JSScope*, JSCell*) WTF_INTERNAL; 99 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState*, Structure*, JSScope*, SymbolTable*); 100 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState*, Structure*, int32_t length, int32_t minCapacity); 101 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount); 102 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment*); 103 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount); 104 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee); 104 105 double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL; 105 106 size_t JIT_OPERATION operationIsObjectOrNull(ExecState*, EncodedJSValue) WTF_INTERNAL; … … 126 127 char* JIT_OPERATION operationSwitchString(ExecState*, size_t tableIndex, JSString*); 127 128 void JIT_OPERATION operationNotifyWrite(ExecState*, VariableWatchpointSet*, EncodedJSValue); 129 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState*) WTF_INTERNAL; 128 130 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState*, EncodedJSValue arguments, int32_t firstVarArgOffset); 129 131 void JIT_OPERATION operationLoadVarargs(ExecState*, int32_t firstElementDest, EncodedJSValue arguments, int32_t offset, int32_t length, int32_t mandatoryMinimum); -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r181990 r181993 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "DFGArguments SimplificationPhase.h"31 #include "DFGArgumentsEliminationPhase.h" 32 32 #include "DFGBackwardsPropagationPhase.h" 33 33 #include "DFGByteCodeParser.h" … … 68 68 #include "DFGUnificationPhase.h" 69 69 #include "DFGValidate.h" 70 #include "DFGVarargsForwardingPhase.h" 70 71 #include "DFGVirtualRegisterAllocationPhase.h" 71 72 #include "DFGWatchpointCollectionPhase.h" … … 221 222 validate(dfg); 222 223 224 if (Options::dumpGraphAfterParsing()) { 225 dataLog("Graph after parsing:\n"); 226 dfg.dump(); 227 } 228 223 229 performCPSRethreading(dfg); 224 230 performUnification(dfg); … … 258 264 performStrengthReduction(dfg); 259 265 performLocalCSE(dfg); 260 performCPSRethreading(dfg); // Canonicalize PhantomLocal to Phantom 261 performArgumentsSimplification(dfg); 262 performCPSRethreading(dfg); // This should do nothing, if arguments simplification did nothing. 266 performCPSRethreading(dfg); 263 267 performCFA(dfg); 264 268 performConstantFolding(dfg); … … 271 275 272 276 performCPSRethreading(dfg); 277 if (!isFTL(mode)) { 278 // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and 279 // in a non-varargs inlined call frame, this will generate ForwardVarargs while the FTL 280 // ArgumentsEliminationPhase will create a sequence of GetStack+PutStacks. The GetStack+PutStack 281 // sequence then gets sunk, eliminating anything that looks like an escape for subsequent phases, 282 // while the ForwardVarargs doesn't get simplified until later (or not at all) and looks like an 283 // escape for all of the arguments. This then disables object allocation sinking. 284 // 285 // So, for now, we just disable this phase for the FTL. 286 // 287 // If we wanted to enable it, we'd have to do any of the following: 288 // - Enable ForwardVarargs->GetStack+PutStack strength reduction, and have that run before 289 // PutStack sinking and object allocation sinking. 290 // - Make VarargsForwarding emit a GetLocal+SetLocal sequence, that we can later turn into 291 // GetStack+PutStack. 292 // 293 // But, it's not super valuable to enable those optimizations, since the FTL 294 // ArgumentsEliminationPhase does everything that this phase does, and it doesn't introduce this 295 // pathology. 296 297 changed |= performVarargsForwarding(dfg); // Do this after CFG simplification and CPS rethreading. 298 } 273 299 if (changed) { 274 300 performCFA(dfg); … … 322 348 performSSAConversion(dfg); 323 349 performSSALowering(dfg); 350 351 // Ideally, these would be run to fixpoint with the object allocation sinking phase. 352 performArgumentsElimination(dfg); 324 353 performPutStackSinking(dfg); 354 325 355 performGlobalCSE(dfg); 326 356 performLivenessAnalysis(dfg); … … 341 371 performConstantFolding(dfg); 342 372 } 373 374 // Currently, this relies on pre-headers still being valid. That precludes running CFG 375 // simplification before it, unless we re-created the pre-headers. There wouldn't be anything 376 // wrong with running LICM earlier, if we wanted to put other CFG transforms above this point. 377 // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that 378 // then we'd need to do some simple SSA fix-up. 343 379 performLICM(dfg); 380 344 381 performPhantomCanonicalization(dfg); 345 382 performIntegerCheckCombining(dfg); -
trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h
r180279 r181993 50 50 void read(AbstractHeap heap) 51 51 { 52 if (heap.kind() == Variables) {52 if (heap.kind() == Stack) { 53 53 if (heap.payload().isTop()) { 54 54 readTop(); … … 60 60 } 61 61 62 if (heap.overlaps( Variables)) {62 if (heap.overlaps(Stack)) { 63 63 readTop(); 64 64 return; … … 68 68 void write(AbstractHeap heap) 69 69 { 70 if (heap.kind() == Variables) { 71 if (heap.payload().isTop()) { 72 writeTop(); 73 return; 74 } 75 70 // We expect stack writes to already be precisely characterized by DFG::clobberize(). 71 if (heap.kind() == Stack) { 72 RELEASE_ASSERT(!heap.payload().isTop()); 76 73 callIfAppropriate(m_write, VirtualRegister(heap.payload().value32())); 77 74 return; 78 75 } 79 76 80 if (heap.overlaps(Variables)) { 81 writeTop(); 82 return; 83 } 77 RELEASE_ASSERT(!heap.overlaps(Stack)); 84 78 } 85 79 … … 91 85 void def(HeapLocation location, Node* node) 92 86 { 93 if (location.kind() != VariableLoc)87 if (location.kind() != StackLoc) 94 88 return; 95 89 96 RELEASE_ASSERT(location.heap().kind() == Variables);90 RELEASE_ASSERT(location.heap().kind() == Stack); 97 91 98 92 m_def(VirtualRegister(location.heap().payload().value32()), node); … … 122 116 m_read(VirtualRegister(i)); 123 117 124 // Read all of the captured variables.125 const BitVector& capturedVars =126 m_graph.capturedVarsFor(m_node->origin.semantic.inlineCallFrame);127 for (unsigned i : capturedVars.setBits())128 m_read(virtualRegisterForLocal(i));129 130 118 // Read all of the inline arguments and call frame headers that we didn't already capture. 131 119 for (InlineCallFrame* inlineCallFrame = m_node->origin.semantic.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) { … … 137 125 m_read(VirtualRegister(inlineCallFrame->stackOffset + JSStack::ArgumentCount)); 138 126 } 139 } 140 141 void writeTop() 142 { 143 if (m_node->op() == LoadVarargs) { 144 // Make sure we note the writes to the locals that will store the array elements and 145 // count. 146 LoadVarargsData* data = m_node->loadVarargsData(); 147 m_write(data->count); 148 for (unsigned i = data->limit; i--;) 149 m_write(VirtualRegister(data->start.offset() + i)); 150 } 151 127 152 128 // Note that we don't need to do anything special for CallForwardVarargs, since it reads 153 129 // our arguments the same way that any effectful thing might. 154 155 if (m_graph.m_codeBlock->usesArguments()) {156 for (unsigned i = m_graph.m_codeBlock->numParameters(); i-- > 1;)157 m_write(virtualRegisterForArgument(i));158 }159 160 const BitVector& capturedVars =161 m_graph.capturedVarsFor(m_node->origin.semantic.inlineCallFrame);162 for (unsigned i : capturedVars.setBits())163 m_write(virtualRegisterForLocal(i));164 130 } 165 131 … … 171 137 }; 172 138 173 template<typename ReadFunctor>174 void forEachLocalReadByUnwind(Graph& graph, CodeOrigin codeOrigin, const ReadFunctor& read)175 {176 if (graph.uncheckedActivationRegister().isValid())177 read(graph.activationRegister());178 if (graph.m_codeBlock->usesArguments())179 read(unmodifiedArgumentsRegister(graph.argumentsRegisterFor(nullptr)));180 181 for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) {182 if (inlineCallFrame->executable->usesArguments())183 read(unmodifiedArgumentsRegister(graph.argumentsRegisterFor(inlineCallFrame)));184 }185 }186 187 139 template<typename ReadFunctor, typename WriteFunctor, typename DefFunctor> 188 140 void preciseLocalClobberize( … … 193 145 adaptor(graph, node, read, write, def); 194 146 clobberize(graph, node, adaptor); 195 if (mayExit(graph, node))196 forEachLocalReadByUnwind(graph, node->origin.forExit, read);197 147 } 198 148 -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r181891 r181993 58 58 ASSERT(m_graph.m_unificationState == GloballyUnified); 59 59 60 propagateThroughArgumentPositions(); 61 60 62 m_pass = PrimaryPass; 61 63 propagateToFixpoint(); … … 188 190 case GetById: 189 191 case GetByIdFlush: 190 case GetMyArgumentByValSafe:191 192 case GetByOffset: 192 193 case MultiGetByOffset: … … 197 198 case ConstructVarargs: 198 199 case CallForwardVarargs: 200 case ConstructForwardVarargs: 199 201 case NativeCall: 200 202 case NativeConstruct: 201 203 case GetGlobalVar: 202 case GetClosureVar: { 204 case GetClosureVar: 205 case GetFromArguments: { 203 206 changed |= setPrediction(node->getHeapPrediction()); 204 207 break; … … 214 217 case GetSetter: 215 218 case GetCallee: 216 case NewFunctionNoCheck: 217 case NewFunctionExpression: { 219 case NewFunction: { 218 220 changed |= setPrediction(SpecFunction); 221 break; 222 } 223 224 case GetArgumentCount: { 225 changed |= setPrediction(SpecInt32); 219 226 break; 220 227 } … … 419 426 } 420 427 421 case GetMyArgumentsLengthSafe: {422 changed |= setPrediction(SpecInt32);423 break;424 }425 426 case GetClosureRegisters:427 428 case GetButterfly: 428 429 case GetIndexedPropertyStorage: … … 498 499 } 499 500 500 case CreateArguments: { 501 changed |= setPrediction(SpecArguments); 502 break; 503 } 504 505 case NewFunction: { 506 SpeculatedType child = node->child1()->prediction(); 507 if (child & SpecEmpty) 508 changed |= mergePrediction((child & ~SpecEmpty) | SpecFunction); 509 else 510 changed |= mergePrediction(child); 501 case CreateDirectArguments: { 502 changed |= setPrediction(SpecDirectArguments); 503 break; 504 } 505 506 case CreateScopedArguments: { 507 changed |= setPrediction(SpecScopedArguments); 508 break; 509 } 510 511 case CreateClonedArguments: { 512 changed |= setPrediction(SpecObjectOther); 511 513 break; 512 514 } … … 523 525 case DoubleAsInt32: 524 526 case GetLocalUnlinked: 525 case GetMyArgumentsLength:526 case GetMyArgumentByVal:527 case PhantomArguments:528 527 case CheckArray: 529 528 case Arrayify: … … 543 542 case BooleanToNumber: 544 543 case PhantomNewObject: 544 case PhantomDirectArguments: 545 case PhantomClonedArguments: 546 case GetMyArgumentByVal: 547 case ForwardVarargs: 545 548 case PutHint: 546 549 case CheckStructureImmediate: … … 608 611 case PutByVal: 609 612 case PutClosureVar: 613 case PutToArguments: 610 614 case Return: 611 615 case Throw: … … 632 636 case CheckBadCell: 633 637 case PutStructure: 634 case TearOffArguments:635 case CheckArgumentsNotCreated:636 638 case VarInjectionWatchpoint: 637 639 case AllocationProfileWatchpoint: … … 855 857 m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat(); 856 858 } 857 for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i) 858 m_changed |= m_graph.m_argumentPositions[i].mergeArgumentPredictionAwareness(); 859 propagateThroughArgumentPositions(); 859 860 for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) { 860 861 VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i]; … … 865 866 } 866 867 868 void propagateThroughArgumentPositions() 869 { 870 for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i) 871 m_changed |= m_graph.m_argumentPositions[i].mergeArgumentPredictionAwareness(); 872 } 873 867 874 Node* m_currentNode; 868 875 bool m_changed; -
trunk/Source/JavaScriptCore/dfg/DFGPromoteHeapAccess.h
r181650 r181993 62 62 63 63 case PutHint: { 64 ASSERT(node->child1()->isPhantom ObjectAllocation());64 ASSERT(node->child1()->isPhantomAllocation()); 65 65 write( 66 66 PromotedHeapLocation(node->child1().node(), node->promotedLocationDescriptor()), -
trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp
r181650 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 71 71 out.print("NamedPropertyPLoc"); 72 72 return; 73 74 case ArgumentPLoc: 75 out.print("ArgumentPLoc"); 76 return; 77 78 case ArgumentCountPLoc: 79 out.print("ArgumentCountPLoc"); 80 return; 81 82 case ArgumentsCalleePLoc: 83 out.print("ArgumentsCalleePLoc"); 84 return; 73 85 } 74 86 -
trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h
r181650 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 38 38 39 39 StructurePLoc, 40 NamedPropertyPLoc 40 NamedPropertyPLoc, 41 ArgumentPLoc, 42 ArgumentCountPLoc, 43 ArgumentsCalleePLoc 41 44 }; 42 45 -
trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp
r180691 r181993 64 64 // Create a SSACalculator::Variable for every root VariableAccessData. 65 65 for (VariableAccessData& variable : m_graph.m_variableAccessData) { 66 if (!variable.isRoot() || variable.isCaptured())66 if (!variable.isRoot()) 67 67 continue; 68 68 … … 88 88 89 89 VariableAccessData* variable = node->variableAccessData(); 90 if (variable->isCaptured())91 continue;92 90 93 91 Node* childNode; … … 191 189 // - MovHint has KillLocal prepended to it. 192 190 // 193 // - GetLocal over captured variables lose their phis and become GetStack. 194 // 195 // - GetLocal over uncaptured variables die and get replaced with references to the node 196 // specified by valueForOperand. 191 // - GetLocal die and get replaced with references to the node specified by 192 // valueForOperand. 197 193 // 198 194 // - SetLocal turns into PutStack if it's flushed, or turns into a Check otherwise. … … 219 215 220 216 VariableAccessData* variable = nodeAtHead->variableAccessData(); 221 if (variable->isCaptured())222 continue;223 217 224 218 if (verbose) … … 284 278 VariableAccessData* variable = node->variableAccessData(); 285 279 286 if ( variable->isCaptured() ||!!(node->flags() & NodeIsFlushed)) {280 if (!!(node->flags() & NodeIsFlushed)) { 287 281 node->convertToPutStack( 288 282 m_graph.m_stackAccessData.add( … … 291 285 node->setOpAndDefaultFlags(Check); 292 286 293 if (!variable->isCaptured()) { 294 if (verbose) 295 dataLog("Mapping: ", variable->local(), " -> ", node->child1().node(), "\n"); 296 valueForOperand.operand(variable->local()) = node->child1().node(); 297 } 287 if (verbose) 288 dataLog("Mapping: ", variable->local(), " -> ", node->child1().node(), "\n"); 289 valueForOperand.operand(variable->local()) = node->child1().node(); 298 290 break; 299 291 } … … 308 300 VariableAccessData* variable = node->variableAccessData(); 309 301 node->children.reset(); 310 311 if (variable->isCaptured()) {312 node->convertToGetStack(m_graph.m_stackAccessData.add(variable->local(), variable->flushFormat()));313 break;314 }315 302 316 303 node->convertToPhantom(); … … 330 317 ASSERT(node->child1().useKind() == UntypedUse); 331 318 VariableAccessData* variable = node->variableAccessData(); 332 if (variable->isCaptured()) { 333 // This is a fun case. We could have a captured variable that had some 334 // or all of its uses strength reduced to phantoms rather than flushes. 335 // SSA conversion will currently still treat it as flushed, in the sense 336 // that it will just keep the SetLocal. Therefore, there is nothing that 337 // needs to be done here: we don't need to also keep the source value 338 // alive. And even if we did want to keep the source value alive, we 339 // wouldn't be able to, because the variablesAtHead value for a captured 340 // local wouldn't have been computed by the Phi reduction algorithm 341 // above. 342 node->children.reset(); 343 } else 344 node->child1() = valueForOperand.operand(variable->local())->defaultEdge(); 319 node->child1() = valueForOperand.operand(variable->local())->defaultEdge(); 345 320 node->convertToPhantom(); 346 321 break; … … 403 378 404 379 Node* node = m_argumentMapping.get(m_graph.m_arguments[i]); 405 406 // m_argumentMapping.get could return null for a captured local. That's fine. We only 407 // track the argument loads of those arguments for which we speculate type. We don't 408 // speculate type for captured arguments. 409 if (node) 410 format = node->stackAccessData()->format; 380 381 RELEASE_ASSERT(node); 382 format = node->stackAccessData()->format; 411 383 412 384 m_graph.m_argumentFormats[i] = format; -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r181891 r181993 117 117 case CreateThis: 118 118 case GetCallee: 119 case GetArgumentCount: 119 120 case GetLocal: 120 121 case SetLocal: … … 171 172 case GetScope: 172 173 case SkipScope: 173 case GetClosureRegisters:174 174 case GetClosureVar: 175 175 case PutClosureVar: … … 196 196 case LoadVarargs: 197 197 case CallForwardVarargs: 198 case ConstructForwardVarargs: 198 199 case NewObject: 199 200 case NewArray: … … 223 224 case In: 224 225 case CreateActivation: 225 case CreateArguments: 226 case PhantomArguments: 227 case TearOffArguments: 228 case GetMyArgumentsLength: 229 case GetMyArgumentByVal: 230 case GetMyArgumentsLengthSafe: 231 case GetMyArgumentByValSafe: 232 case CheckArgumentsNotCreated: 233 case NewFunctionNoCheck: 226 case CreateDirectArguments: 227 case CreateScopedArguments: 228 case CreateClonedArguments: 229 case GetFromArguments: 230 case PutToArguments: 234 231 case NewFunction: 235 case NewFunctionExpression:236 232 case Jump: 237 233 case Branch: … … 281 277 case CheckStructureImmediate: 282 278 case MaterializeNewObject: 279 case PhantomDirectArguments: 280 case PhantomClonedArguments: 281 case GetMyArgumentByVal: 282 case ForwardVarargs: 283 283 return true; 284 284 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r181570 r181993 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "Arguments.h"32 31 #include "BinarySwitch.h" 33 32 #include "DFGAbstractInterpreterInlines.h" 34 33 #include "DFGArrayifySlowPathGenerator.h" 35 34 #include "DFGCallArrayAllocatorSlowPathGenerator.h" 35 #include "DFGCallCreateDirectArgumentsSlowPathGenerator.h" 36 36 #include "DFGMayExit.h" 37 37 #include "DFGSaneStringGetByValSlowPathGenerator.h" 38 38 #include "DFGSlowPathGenerator.h" 39 #include "DirectArguments.h" 40 #include "JSCInlines.h" 41 #include "JSEnvironmentRecord.h" 42 #include "JSLexicalEnvironment.h" 39 43 #include "LinkBuffer.h" 40 #include " JSCInlines.h"44 #include "ScopedArguments.h" 41 45 #include "ScratchRegisterAllocator.h" 42 46 #include "WriteBarrierBuffer.h" … … 104 108 // of work for a very small piece of functionality. :-/ 105 109 addSlowPathGenerator(std::make_unique<CallArrayAllocatorSlowPathGenerator>( 106 slowCases, this, operationNewArrayWithSize, resultGPR, storageGPR, 107 structure, numElements)); 108 } 109 110 void SpeculativeJIT::emitAllocateArguments(GPRReg resultGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath) 111 { 112 Structure* structure = m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)->argumentsStructure(); 113 114 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), scratchGPR1); 115 m_jit.lshift32(TrustedImm32(3), scratchGPR1); 116 m_jit.add32(TrustedImm32(Arguments::offsetOfInlineRegisterArray()), scratchGPR1); 117 emitAllocateVariableSizedJSObject<Arguments>(resultGPR, TrustedImmPtr(structure), scratchGPR1, scratchGPR1, scratchGPR2, slowPath); 118 119 m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfActivation())); 120 121 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), scratchGPR1); 122 m_jit.sub32(TrustedImm32(1), scratchGPR1); 123 m_jit.store32(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfNumArguments())); 124 125 m_jit.store32(TrustedImm32(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfOverrodeLength())); 126 if (m_jit.isStrictModeFor(m_currentNode->origin.semantic)) 127 m_jit.store8(TrustedImm32(1), MacroAssembler::Address(resultGPR, Arguments::offsetOfIsStrictMode())); 128 129 m_jit.storePtr(GPRInfo::callFrameRegister, MacroAssembler::Address(resultGPR, Arguments::offsetOfRegisters())); 130 m_jit.storePtr(TrustedImmPtr(0), MacroAssembler::Address(resultGPR, Arguments::offsetOfSlowArgumentData())); 131 132 m_jit.loadPtr(JITCompiler::addressFor(JSStack::Callee), scratchGPR1); 133 m_jit.storePtr(scratchGPR1, MacroAssembler::Address(resultGPR, Arguments::offsetOfCallee())); 134 110 slowCases, this, operationNewArrayWithSize, resultGPR, storageGPR, 111 structure, numElements)); 112 } 113 114 void SpeculativeJIT::emitGetLength(InlineCallFrame* inlineCallFrame, GPRReg lengthGPR, bool includeThis) 115 { 116 if (inlineCallFrame && !inlineCallFrame->isVarargs()) 117 m_jit.move(TrustedImm32(inlineCallFrame->arguments.size() - !includeThis), lengthGPR); 118 else { 119 VirtualRegister argumentCountRegister; 120 if (!inlineCallFrame) 121 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 122 else 123 argumentCountRegister = inlineCallFrame->argumentCountRegister; 124 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), lengthGPR); 125 if (!includeThis) 126 m_jit.sub32(TrustedImm32(1), lengthGPR); 127 } 128 } 129 130 void SpeculativeJIT::emitGetLength(CodeOrigin origin, GPRReg lengthGPR, bool includeThis) 131 { 132 emitGetLength(origin.inlineCallFrame, lengthGPR, includeThis); 133 } 134 135 void SpeculativeJIT::emitGetCallee(CodeOrigin origin, GPRReg calleeGPR) 136 { 137 if (origin.inlineCallFrame) { 138 if (origin.inlineCallFrame->isClosureCall) { 139 m_jit.loadPtr( 140 JITCompiler::addressFor(origin.inlineCallFrame->calleeRecovery.virtualRegister()), 141 calleeGPR); 142 } else { 143 m_jit.move( 144 TrustedImmPtr(origin.inlineCallFrame->calleeRecovery.constant().asCell()), 145 calleeGPR); 146 } 147 } else 148 m_jit.loadPtr(JITCompiler::addressFor(JSStack::Callee), calleeGPR); 149 } 150 151 void SpeculativeJIT::emitGetArgumentStart(CodeOrigin origin, GPRReg startGPR) 152 { 153 m_jit.addPtr( 154 TrustedImm32( 155 JITCompiler::argumentsStart(origin).offset() * static_cast<int>(sizeof(Register))), 156 GPRInfo::callFrameRegister, startGPR); 135 157 } 136 158 … … 723 745 return; 724 746 } 725 case Array::Arguments: 726 speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, ArgumentsType); 727 747 case Array::DirectArguments: 748 speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, DirectArgumentsType); 749 noResult(m_currentNode); 750 return; 751 case Array::ScopedArguments: 752 speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, ScopedArgumentsType); 728 753 noResult(m_currentNode); 729 754 return; … … 4099 4124 } 4100 4125 4101 void SpeculativeJIT::compileGetByValOnArguments(Node* node) 4126 void SpeculativeJIT::compileGetByValOnDirectArguments(Node* node) 4127 { 4128 SpeculateCellOperand base(this, node->child1()); 4129 SpeculateStrictInt32Operand property(this, node->child2()); 4130 GPRTemporary result(this); 4131 #if USE(JSVALUE32_64) 4132 GPRTemporary resultTag(this); 4133 #endif 4134 4135 GPRReg baseReg = base.gpr(); 4136 GPRReg propertyReg = property.gpr(); 4137 GPRReg resultReg = result.gpr(); 4138 #if USE(JSVALUE32_64) 4139 GPRReg resultTagReg = resultTag.gpr(); 4140 JSValueRegs resultRegs = JSValueRegs(resultTagReg, resultReg); 4141 #else 4142 JSValueRegs resultRegs = JSValueRegs(resultReg); 4143 #endif 4144 4145 if (!m_compileOkay) 4146 return; 4147 4148 ASSERT(ArrayMode(Array::DirectArguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))); 4149 4150 speculationCheck( 4151 ExoticObjectMode, JSValueSource(), 0, 4152 m_jit.branchTestPtr( 4153 MacroAssembler::NonZero, 4154 MacroAssembler::Address(baseReg, DirectArguments::offsetOfOverrides()))); 4155 speculationCheck( 4156 ExoticObjectMode, JSValueSource(), 0, 4157 m_jit.branch32( 4158 MacroAssembler::AboveOrEqual, propertyReg, 4159 MacroAssembler::Address(baseReg, DirectArguments::offsetOfLength()))); 4160 4161 m_jit.loadValue( 4162 MacroAssembler::BaseIndex( 4163 baseReg, propertyReg, MacroAssembler::TimesEight, DirectArguments::storageOffset()), 4164 resultRegs); 4165 4166 jsValueResult(resultRegs, node); 4167 } 4168 4169 void SpeculativeJIT::compileGetByValOnScopedArguments(Node* node) 4102 4170 { 4103 4171 SpeculateCellOperand base(this, node->child1()); … … 4108 4176 #endif 4109 4177 GPRTemporary scratch(this); 4178 GPRTemporary scratch2(this); 4110 4179 4111 4180 GPRReg baseReg = base.gpr(); … … 4114 4183 #if USE(JSVALUE32_64) 4115 4184 GPRReg resultTagReg = resultTag.gpr(); 4185 JSValueRegs resultRegs = JSValueRegs(resultTagReg, resultReg); 4186 #else 4187 JSValueRegs resultRegs = JSValueRegs(resultReg); 4116 4188 #endif 4117 4189 GPRReg scratchReg = scratch.gpr(); 4190 GPRReg scratch2Reg = scratch2.gpr(); 4118 4191 4119 4192 if (!m_compileOkay) 4120 4193 return; 4121 4122 ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))); 4123 4124 // Two really lame checks. 4194 4195 ASSERT(ArrayMode(Array::ScopedArguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))); 4196 4125 4197 speculationCheck( 4126 ExoticObjectMode, JSValueSource(), 0,4198 ExoticObjectMode, JSValueSource(), nullptr, 4127 4199 m_jit.branch32( 4128 4200 MacroAssembler::AboveOrEqual, propertyReg, 4129 MacroAssembler::Address(baseReg, Arguments::offsetOfNumArguments()))); 4201 MacroAssembler::Address(baseReg, ScopedArguments::offsetOfTotalLength()))); 4202 4203 m_jit.loadPtr(MacroAssembler::Address(baseReg, ScopedArguments::offsetOfTable()), scratchReg); 4204 m_jit.load32( 4205 MacroAssembler::Address(scratchReg, ScopedArgumentsTable::offsetOfLength()), scratch2Reg); 4206 4207 MacroAssembler::Jump overflowArgument = m_jit.branch32( 4208 MacroAssembler::AboveOrEqual, propertyReg, scratch2Reg); 4209 4210 m_jit.loadPtr(MacroAssembler::Address(baseReg, ScopedArguments::offsetOfScope()), scratch2Reg); 4211 4212 m_jit.loadPtr( 4213 MacroAssembler::Address(scratchReg, ScopedArgumentsTable::offsetOfArguments()), 4214 scratchReg); 4215 m_jit.load32( 4216 MacroAssembler::BaseIndex(scratchReg, propertyReg, MacroAssembler::TimesFour), 4217 scratchReg); 4218 4130 4219 speculationCheck( 4131 ExoticObjectMode, JSValueSource(), 0, 4132 m_jit.branchTestPtr( 4133 MacroAssembler::NonZero, 4134 MacroAssembler::Address( 4135 baseReg, Arguments::offsetOfSlowArgumentData()))); 4136 4137 m_jit.move(propertyReg, resultReg); 4138 m_jit.signExtend32ToPtr(resultReg, resultReg); 4139 m_jit.loadPtr( 4140 MacroAssembler::Address(baseReg, Arguments::offsetOfRegisters()), 4141 scratchReg); 4142 4143 #if USE(JSVALUE32_64) 4144 m_jit.load32( 4220 ExoticObjectMode, JSValueSource(), nullptr, 4221 m_jit.branch32( 4222 MacroAssembler::Equal, scratchReg, TrustedImm32(ScopeOffset::invalidOffset))); 4223 4224 m_jit.loadValue( 4145 4225 MacroAssembler::BaseIndex( 4146 scratchReg, resultReg, MacroAssembler::TimesEight, 4147 CallFrame::thisArgumentOffset() * sizeof(Register) + sizeof(Register) + 4148 OBJECT_OFFSETOF(JSValue, u.asBits.tag)), 4149 resultTagReg); 4150 m_jit.load32( 4226 scratch2Reg, propertyReg, MacroAssembler::TimesEight, 4227 JSEnvironmentRecord::offsetOfVariables()), 4228 resultRegs); 4229 4230 MacroAssembler::Jump done = m_jit.jump(); 4231 overflowArgument.link(&m_jit); 4232 4233 m_jit.sub32(propertyReg, scratch2Reg); 4234 m_jit.neg32(scratch2Reg); 4235 4236 m_jit.loadValue( 4151 4237 MacroAssembler::BaseIndex( 4152 scratchReg, resultReg, MacroAssembler::TimesEight, 4153 CallFrame::thisArgumentOffset() * sizeof(Register) + sizeof(Register) + 4154 OBJECT_OFFSETOF(JSValue, u.asBits.payload)), 4155 resultReg); 4156 jsValueResult(resultTagReg, resultReg, node); 4157 #else 4158 m_jit.load64( 4159 MacroAssembler::BaseIndex( 4160 scratchReg, resultReg, MacroAssembler::TimesEight, 4161 CallFrame::thisArgumentOffset() * sizeof(Register) + sizeof(Register)), 4162 resultReg); 4163 jsValueResult(resultReg, node); 4164 #endif 4165 } 4166 4167 void SpeculativeJIT::compileGetArgumentsLength(Node* node) 4168 { 4169 SpeculateCellOperand base(this, node->child1()); 4170 GPRTemporary result(this, Reuse, base); 4171 4172 GPRReg baseReg = base.gpr(); 4173 GPRReg resultReg = result.gpr(); 4174 4175 if (!m_compileOkay) 4176 return; 4177 4178 ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))); 4179 4180 speculationCheck( 4181 ExoticObjectMode, JSValueSource(), 0, 4182 m_jit.branchTest8( 4183 MacroAssembler::NonZero, 4184 MacroAssembler::Address(baseReg, Arguments::offsetOfOverrodeLength()))); 4185 4186 m_jit.load32( 4187 MacroAssembler::Address(baseReg, Arguments::offsetOfNumArguments()), 4188 resultReg); 4189 int32Result(resultReg, node); 4238 baseReg, scratch2Reg, MacroAssembler::TimesEight, 4239 ScopedArguments::overflowStorageOffset()), 4240 resultRegs); 4241 speculationCheck(ExoticObjectMode, JSValueSource(), nullptr, m_jit.branchIsEmpty(resultRegs)); 4242 4243 done.link(&m_jit); 4244 4245 jsValueResult(resultRegs, node); 4190 4246 } 4191 4247 … … 4243 4299 break; 4244 4300 } 4245 case Array::Arguments: { 4246 compileGetArgumentsLength(node); 4301 case Array::DirectArguments: { 4302 SpeculateCellOperand base(this, node->child1()); 4303 GPRTemporary result(this, Reuse, base); 4304 4305 GPRReg baseReg = base.gpr(); 4306 GPRReg resultReg = result.gpr(); 4307 4308 if (!m_compileOkay) 4309 return; 4310 4311 ASSERT(ArrayMode(Array::DirectArguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))); 4312 4313 speculationCheck( 4314 ExoticObjectMode, JSValueSource(), 0, 4315 m_jit.branchTestPtr( 4316 MacroAssembler::NonZero, 4317 MacroAssembler::Address(baseReg, DirectArguments::offsetOfOverrides()))); 4318 4319 m_jit.load32( 4320 MacroAssembler::Address(baseReg, DirectArguments::offsetOfLength()), resultReg); 4321 4322 int32Result(resultReg, node); 4323 break; 4324 } 4325 case Array::ScopedArguments: { 4326 SpeculateCellOperand base(this, node->child1()); 4327 GPRTemporary result(this, Reuse, base); 4328 4329 GPRReg baseReg = base.gpr(); 4330 GPRReg resultReg = result.gpr(); 4331 4332 if (!m_compileOkay) 4333 return; 4334 4335 ASSERT(ArrayMode(Array::ScopedArguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))); 4336 4337 speculationCheck( 4338 ExoticObjectMode, JSValueSource(), 0, 4339 m_jit.branchTest8( 4340 MacroAssembler::NonZero, 4341 MacroAssembler::Address(baseReg, ScopedArguments::offsetOfOverrodeThings()))); 4342 4343 m_jit.load32( 4344 MacroAssembler::Address(baseReg, ScopedArguments::offsetOfTotalLength()), resultReg); 4345 4346 int32Result(resultReg, node); 4247 4347 break; 4248 4348 } … … 4259 4359 } 4260 4360 4261 void SpeculativeJIT::compileNewFunction NoCheck(Node* node)4361 void SpeculativeJIT::compileNewFunction(Node* node) 4262 4362 { 4263 4363 GPRFlushedCallResult result(this); … … 4267 4367 flushRegisters(); 4268 4368 callOperation( 4269 operationNewFunctionNoCheck, resultGPR, scopeGPR, 4270 node->castOperand<FunctionExecutable*>()); 4369 operationNewFunction, resultGPR, scopeGPR, node->castOperand<FunctionExecutable*>()); 4271 4370 cellResult(resultGPR, node); 4272 4371 } 4273 4372 4274 void SpeculativeJIT::compileNewFunctionExpression(Node* node) 4275 { 4373 void SpeculativeJIT::compileForwardVarargs(Node* node) 4374 { 4375 LoadVarargsData* data = node->loadVarargsData(); 4376 InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame; 4377 4378 GPRTemporary length(this); 4379 JSValueRegsTemporary temp(this); 4380 GPRReg lengthGPR = length.gpr(); 4381 JSValueRegs tempRegs = temp.regs(); 4382 4383 emitGetLength(inlineCallFrame, lengthGPR, /* includeThis = */ true); 4384 if (data->offset) 4385 m_jit.sub32(TrustedImm32(data->offset), lengthGPR); 4386 4387 speculationCheck( 4388 VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32( 4389 MacroAssembler::Above, 4390 lengthGPR, TrustedImm32(data->limit))); 4391 4392 m_jit.store32(lengthGPR, JITCompiler::payloadFor(data->machineCount)); 4393 4394 VirtualRegister sourceStart = JITCompiler::argumentsStart(inlineCallFrame) + data->offset; 4395 VirtualRegister targetStart = data->machineStart; 4396 4397 m_jit.sub32(TrustedImm32(1), lengthGPR); 4398 4399 // First have a loop that fills in the undefined slots in case of an arity check failure. 4400 m_jit.move(TrustedImm32(data->mandatoryMinimum), tempRegs.payloadGPR()); 4401 JITCompiler::Jump done = m_jit.branch32(JITCompiler::BelowOrEqual, tempRegs.payloadGPR(), lengthGPR); 4402 4403 JITCompiler::Label loop = m_jit.label(); 4404 m_jit.sub32(TrustedImm32(1), tempRegs.payloadGPR()); 4405 m_jit.storeTrustedValue( 4406 jsUndefined(), 4407 JITCompiler::BaseIndex( 4408 GPRInfo::callFrameRegister, tempRegs.payloadGPR(), JITCompiler::TimesEight, 4409 targetStart.offset() * sizeof(EncodedJSValue))); 4410 m_jit.branch32(JITCompiler::Above, tempRegs.payloadGPR(), lengthGPR).linkTo(loop, &m_jit); 4411 done.link(&m_jit); 4412 4413 // And then fill in the actual argument values. 4414 done = m_jit.branchTest32(JITCompiler::Zero, lengthGPR); 4415 4416 loop = m_jit.label(); 4417 m_jit.sub32(TrustedImm32(1), lengthGPR); 4418 m_jit.loadValue( 4419 JITCompiler::BaseIndex( 4420 GPRInfo::callFrameRegister, lengthGPR, JITCompiler::TimesEight, 4421 sourceStart.offset() * sizeof(EncodedJSValue)), 4422 tempRegs); 4423 m_jit.storeValue( 4424 tempRegs, 4425 JITCompiler::BaseIndex( 4426 GPRInfo::callFrameRegister, lengthGPR, JITCompiler::TimesEight, 4427 targetStart.offset() * sizeof(EncodedJSValue))); 4428 m_jit.branchTest32(JITCompiler::NonZero, lengthGPR).linkTo(loop, &m_jit); 4429 4430 done.link(&m_jit); 4431 4432 noResult(node); 4433 } 4434 4435 void SpeculativeJIT::compileCreateActivation(Node* node) 4436 { 4437 SpeculateCellOperand scope(this, node->child1()); 4438 GPRTemporary result(this); 4439 GPRTemporary scratch1(this); 4440 GPRTemporary scratch2(this); 4441 GPRReg scopeGPR = scope.gpr(); 4442 GPRReg resultGPR = result.gpr(); 4443 GPRReg scratch1GPR = scratch1.gpr(); 4444 GPRReg scratch2GPR = scratch2.gpr(); 4445 4446 SymbolTable* table = m_jit.graph().symbolTableFor(node->origin.semantic); 4447 Structure* structure = m_jit.graph().globalObjectFor( 4448 node->origin.semantic)->activationStructure(); 4449 4450 JITCompiler::JumpList slowPath; 4451 emitAllocateJSObjectWithKnownSize<JSLexicalEnvironment>( 4452 resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratch1GPR, scratch2GPR, 4453 slowPath, JSLexicalEnvironment::allocationSize(table)); 4454 4455 // Don't need a memory barriers since we just fast-created the activation, so the 4456 // activation must be young. 4457 m_jit.storePtr(scopeGPR, JITCompiler::Address(resultGPR, JSScope::offsetOfNext())); 4458 m_jit.storePtr( 4459 TrustedImmPtr(table), 4460 JITCompiler::Address(resultGPR, JSLexicalEnvironment::offsetOfSymbolTable())); 4461 4462 // Must initialize all members to undefined. 4463 for (unsigned i = 0; i < table->scopeSize(); ++i) { 4464 m_jit.storeTrustedValue( 4465 jsUndefined(), 4466 JITCompiler::Address( 4467 resultGPR, JSLexicalEnvironment::offsetOfVariable(ScopeOffset(i)))); 4468 } 4469 4470 addSlowPathGenerator( 4471 slowPathCall( 4472 slowPath, this, operationCreateActivationDirect, resultGPR, structure, scopeGPR, table)); 4473 4474 cellResult(resultGPR, node); 4475 } 4476 4477 void SpeculativeJIT::compileCreateDirectArguments(Node* node) 4478 { 4479 // FIXME: A more effective way of dealing with the argument count and callee is to have 4480 // them be explicit arguments to this node. 4481 // https://bugs.webkit.org/show_bug.cgi?id=142207 4482 4483 GPRTemporary result(this); 4484 GPRTemporary scratch1(this); 4485 GPRTemporary scratch2(this); 4486 GPRTemporary length; 4487 GPRReg resultGPR = result.gpr(); 4488 GPRReg scratch1GPR = scratch1.gpr(); 4489 GPRReg scratch2GPR = scratch2.gpr(); 4490 GPRReg lengthGPR = InvalidGPRReg; 4491 JSValueRegs valueRegs = JSValueRegs::withTwoAvailableRegs(scratch1GPR, scratch2GPR); 4492 4493 unsigned minCapacity = m_jit.graph().baselineCodeBlockFor(node->origin.semantic)->numParameters() - 1; 4494 4495 unsigned knownLength; 4496 bool lengthIsKnown; // if false, lengthGPR will have the length. 4497 if (node->origin.semantic.inlineCallFrame 4498 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4499 knownLength = node->origin.semantic.inlineCallFrame->arguments.size() - 1; 4500 lengthIsKnown = true; 4501 } else { 4502 knownLength = UINT_MAX; 4503 lengthIsKnown = false; 4504 4505 GPRTemporary realLength(this); 4506 length.adopt(realLength); 4507 lengthGPR = length.gpr(); 4508 4509 VirtualRegister argumentCountRegister; 4510 if (!node->origin.semantic.inlineCallFrame) 4511 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4512 else 4513 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4514 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), lengthGPR); 4515 m_jit.sub32(TrustedImm32(1), lengthGPR); 4516 } 4517 4518 Structure* structure = 4519 m_jit.graph().globalObjectFor(node->origin.semantic)->directArgumentsStructure(); 4520 4521 // Use a different strategy for allocating the object depending on whether we know its 4522 // size statically. 4523 JITCompiler::JumpList slowPath; 4524 if (lengthIsKnown) { 4525 emitAllocateJSObjectWithKnownSize<DirectArguments>( 4526 resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratch1GPR, scratch2GPR, 4527 slowPath, DirectArguments::allocationSize(std::max(knownLength, minCapacity))); 4528 4529 m_jit.store32( 4530 TrustedImm32(knownLength), 4531 JITCompiler::Address(resultGPR, DirectArguments::offsetOfLength())); 4532 } else { 4533 JITCompiler::Jump tooFewArguments; 4534 if (minCapacity) { 4535 tooFewArguments = 4536 m_jit.branch32(JITCompiler::Below, lengthGPR, TrustedImm32(minCapacity)); 4537 } 4538 m_jit.lshift32(lengthGPR, TrustedImm32(3), scratch1GPR); 4539 m_jit.add32(TrustedImm32(DirectArguments::storageOffset()), scratch1GPR); 4540 if (minCapacity) { 4541 JITCompiler::Jump done = m_jit.jump(); 4542 tooFewArguments.link(&m_jit); 4543 m_jit.move(TrustedImm32(DirectArguments::allocationSize(minCapacity)), scratch1GPR); 4544 done.link(&m_jit); 4545 } 4546 4547 emitAllocateVariableSizedJSObject<DirectArguments>( 4548 resultGPR, TrustedImmPtr(structure), scratch1GPR, scratch1GPR, scratch2GPR, 4549 slowPath); 4550 4551 m_jit.store32( 4552 lengthGPR, JITCompiler::Address(resultGPR, DirectArguments::offsetOfLength())); 4553 } 4554 4555 m_jit.store32( 4556 TrustedImm32(minCapacity), 4557 JITCompiler::Address(resultGPR, DirectArguments::offsetOfMinCapacity())); 4558 4559 m_jit.storePtr( 4560 TrustedImmPtr(0), JITCompiler::Address(resultGPR, DirectArguments::offsetOfOverrides())); 4561 4562 if (lengthIsKnown) { 4563 addSlowPathGenerator( 4564 slowPathCall( 4565 slowPath, this, operationCreateDirectArguments, resultGPR, structure, 4566 knownLength, minCapacity)); 4567 } else { 4568 auto generator = std::make_unique<CallCreateDirectArgumentsSlowPathGenerator>( 4569 slowPath, this, resultGPR, structure, lengthGPR, minCapacity); 4570 addSlowPathGenerator(WTF::move(generator)); 4571 } 4572 4573 if (node->origin.semantic.inlineCallFrame) { 4574 if (node->origin.semantic.inlineCallFrame->isClosureCall) { 4575 m_jit.loadPtr( 4576 JITCompiler::addressFor( 4577 node->origin.semantic.inlineCallFrame->calleeRecovery.virtualRegister()), 4578 scratch1GPR); 4579 } else { 4580 m_jit.move( 4581 TrustedImmPtr( 4582 node->origin.semantic.inlineCallFrame->calleeRecovery.constant().asCell()), 4583 scratch1GPR); 4584 } 4585 } else 4586 m_jit.loadPtr(JITCompiler::addressFor(JSStack::Callee), scratch1GPR); 4587 4588 // Don't need a memory barriers since we just fast-created the activation, so the 4589 // activation must be young. 4590 m_jit.storePtr( 4591 scratch1GPR, JITCompiler::Address(resultGPR, DirectArguments::offsetOfCallee())); 4592 4593 VirtualRegister start = m_jit.argumentsStart(node->origin.semantic); 4594 if (lengthIsKnown) { 4595 for (unsigned i = 0; i < std::max(knownLength, minCapacity); ++i) { 4596 m_jit.loadValue(JITCompiler::addressFor(start + i), valueRegs); 4597 m_jit.storeValue( 4598 valueRegs, JITCompiler::Address(resultGPR, DirectArguments::offsetOfSlot(i))); 4599 } 4600 } else { 4601 JITCompiler::Jump done; 4602 if (minCapacity) { 4603 JITCompiler::Jump startLoop = m_jit.branch32( 4604 JITCompiler::AboveOrEqual, lengthGPR, TrustedImm32(minCapacity)); 4605 m_jit.move(TrustedImm32(minCapacity), lengthGPR); 4606 startLoop.link(&m_jit); 4607 } else 4608 done = m_jit.branchTest32(MacroAssembler::Zero, lengthGPR); 4609 JITCompiler::Label loop = m_jit.label(); 4610 m_jit.sub32(TrustedImm32(1), lengthGPR); 4611 m_jit.loadValue( 4612 JITCompiler::BaseIndex( 4613 GPRInfo::callFrameRegister, lengthGPR, JITCompiler::TimesEight, 4614 start.offset() * static_cast<int>(sizeof(Register))), 4615 valueRegs); 4616 m_jit.storeValue( 4617 valueRegs, 4618 JITCompiler::BaseIndex( 4619 resultGPR, lengthGPR, JITCompiler::TimesEight, 4620 DirectArguments::storageOffset())); 4621 m_jit.branchTest32(MacroAssembler::NonZero, lengthGPR).linkTo(loop, &m_jit); 4622 if (done.isSet()) 4623 done.link(&m_jit); 4624 } 4625 4626 cellResult(resultGPR, node); 4627 } 4628 4629 void SpeculativeJIT::compileGetFromArguments(Node* node) 4630 { 4631 SpeculateCellOperand arguments(this, node->child1()); 4632 JSValueRegsTemporary result(this); 4633 4634 GPRReg argumentsGPR = arguments.gpr(); 4635 JSValueRegs resultRegs = result.regs(); 4636 4637 m_jit.loadValue(JITCompiler::Address(argumentsGPR, DirectArguments::offsetOfSlot(node->capturedArgumentsOffset().offset())), resultRegs); 4638 jsValueResult(resultRegs, node); 4639 } 4640 4641 void SpeculativeJIT::compilePutToArguments(Node* node) 4642 { 4643 SpeculateCellOperand arguments(this, node->child1()); 4644 JSValueOperand value(this, node->child2()); 4645 4646 GPRReg argumentsGPR = arguments.gpr(); 4647 JSValueRegs valueRegs = value.jsValueRegs(); 4648 4649 m_jit.storeValue(valueRegs, JITCompiler::Address(argumentsGPR, DirectArguments::offsetOfSlot(node->capturedArgumentsOffset().offset()))); 4650 noResult(node); 4651 } 4652 4653 void SpeculativeJIT::compileCreateScopedArguments(Node* node) 4654 { 4655 SpeculateCellOperand scope(this, node->child1()); 4656 GPRReg scopeGPR = scope.gpr(); 4657 4276 4658 GPRFlushedCallResult result(this); 4277 4659 GPRReg resultGPR = result.gpr(); 4278 SpeculateCellOperand scope(this, node->child1());4279 GPRReg scopeGPR = scope.gpr();4280 4660 flushRegisters(); 4281 callOperation( 4282 operationNewFunctionNoCheck, 4283 resultGPR, scopeGPR, node->castOperand<FunctionExecutable*>()); 4661 4662 // We set up the arguments ourselves, because we have the whole register file and we can 4663 // set them up directly into the argument registers. This also means that we don't have to 4664 // invent a four-argument-register shuffle. 4665 4666 // Arguments: 0:exec, 1:structure, 2:start, 3:length, 4:callee, 5:scope 4667 4668 // Do the scopeGPR first, since it might alias an argument register. 4669 m_jit.setupArgument(5, [&] (GPRReg destGPR) { m_jit.move(scopeGPR, destGPR); }); 4670 4671 // These other things could be done in any order. 4672 m_jit.setupArgument(4, [&] (GPRReg destGPR) { emitGetCallee(node->origin.semantic, destGPR); }); 4673 m_jit.setupArgument(3, [&] (GPRReg destGPR) { emitGetLength(node->origin.semantic, destGPR); }); 4674 m_jit.setupArgument(2, [&] (GPRReg destGPR) { emitGetArgumentStart(node->origin.semantic, destGPR); }); 4675 m_jit.setupArgument( 4676 1, [&] (GPRReg destGPR) { 4677 m_jit.move( 4678 TrustedImmPtr(m_jit.globalObjectFor(node->origin.semantic)->scopedArgumentsStructure()), 4679 destGPR); 4680 }); 4681 m_jit.setupArgument(0, [&] (GPRReg destGPR) { m_jit.move(GPRInfo::callFrameRegister, destGPR); }); 4682 4683 appendCallWithExceptionCheckSetResult(operationCreateScopedArguments, resultGPR); 4684 4685 cellResult(resultGPR, node); 4686 } 4687 4688 void SpeculativeJIT::compileCreateClonedArguments(Node* node) 4689 { 4690 GPRFlushedCallResult result(this); 4691 GPRReg resultGPR = result.gpr(); 4692 flushRegisters(); 4693 4694 // We set up the arguments ourselves, because we have the whole register file and we can 4695 // set them up directly into the argument registers. 4696 4697 // Arguments: 0:exec, 1:structure, 2:start, 3:length, 4:callee 4698 m_jit.setupArgument(4, [&] (GPRReg destGPR) { emitGetCallee(node->origin.semantic, destGPR); }); 4699 m_jit.setupArgument(3, [&] (GPRReg destGPR) { emitGetLength(node->origin.semantic, destGPR); }); 4700 m_jit.setupArgument(2, [&] (GPRReg destGPR) { emitGetArgumentStart(node->origin.semantic, destGPR); }); 4701 m_jit.setupArgument( 4702 1, [&] (GPRReg destGPR) { 4703 m_jit.move( 4704 TrustedImmPtr( 4705 m_jit.globalObjectFor(node->origin.semantic)->outOfBandArgumentsStructure()), 4706 destGPR); 4707 }); 4708 m_jit.setupArgument(0, [&] (GPRReg destGPR) { m_jit.move(GPRInfo::callFrameRegister, destGPR); }); 4709 4710 appendCallWithExceptionCheckSetResult(operationCreateClonedArguments, resultGPR); 4711 4284 4712 cellResult(resultGPR, node); 4285 4713 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r181035 r181993 718 718 void emitCall(Node*); 719 719 720 int32_t framePointerOffsetToGetActivationRegisters()721 {722 return m_jit.codeBlock()->framePointerOffsetToGetActivationRegisters(723 m_jit.graph().m_machineCaptureStart);724 }725 726 720 // Called once a node has completed code generation but prior to setting 727 721 // its result, to free up its children. (This must happen prior to setting … … 903 897 { 904 898 m_jit.setupArgumentsExecState(); 905 return appendCall (operation);899 return appendCallWithExceptionCheck(operation); 906 900 } 907 901 JITCompiler::Call callOperation(P_JITOperation_E operation, GPRReg result) … … 1018 1012 { 1019 1013 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure)); 1014 return appendCallWithExceptionCheckSetResult(operation, result); 1015 } 1016 JITCompiler::Call callOperation(C_JITOperation_EStJscSymtab operation, GPRReg result, Structure* structure, GPRReg scope, SymbolTable* table) 1017 { 1018 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), scope, TrustedImmPtr(table)); 1019 return appendCallWithExceptionCheckSetResult(operation, result); 1020 } 1021 JITCompiler::Call callOperation(C_JITOperation_EStZ operation, GPRReg result, Structure* structure, unsigned knownLength) 1022 { 1023 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(knownLength)); 1024 return appendCallWithExceptionCheckSetResult(operation, result); 1025 } 1026 JITCompiler::Call callOperation(C_JITOperation_EStZZ operation, GPRReg result, Structure* structure, unsigned knownLength, unsigned minCapacity) 1027 { 1028 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(knownLength), TrustedImm32(minCapacity)); 1029 return appendCallWithExceptionCheckSetResult(operation, result); 1030 } 1031 JITCompiler::Call callOperation(C_JITOperation_EStZ operation, GPRReg result, Structure* structure, GPRReg length) 1032 { 1033 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), length); 1034 return appendCallWithExceptionCheckSetResult(operation, result); 1035 } 1036 JITCompiler::Call callOperation(C_JITOperation_EStZZ operation, GPRReg result, Structure* structure, GPRReg length, unsigned minCapacity) 1037 { 1038 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), length, TrustedImm32(minCapacity)); 1020 1039 return appendCallWithExceptionCheckSetResult(operation, result); 1021 1040 } … … 1173 1192 { 1174 1193 m_jit.setupArgumentsWithExecState(TrustedImm32(arg1)); 1194 return appendCallWithExceptionCheckSetResult(operation, result); 1195 } 1196 1197 JITCompiler::Call callOperation(J_JITOperation_EJscC operation, GPRReg result, GPRReg arg1, JSCell* cell) 1198 { 1199 m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell)); 1175 1200 return appendCallWithExceptionCheckSetResult(operation, result); 1176 1201 } … … 1247 1272 { 1248 1273 m_jit.setupArgumentsWithExecState(arg1, arg2); 1249 return appendCallWithExceptionCheckSetResult(operation, result);1250 }1251 JITCompiler::Call callOperation(J_JITOperation_EJscC operation, GPRReg result, GPRReg arg1, JSCell* cell)1252 {1253 m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));1254 1274 return appendCallWithExceptionCheckSetResult(operation, result); 1255 1275 } … … 2153 2173 void compileFromCharCode(Node*); 2154 2174 2155 void compileGetByValOnArguments(Node*); 2156 void compileGetArgumentsLength(Node*); 2175 void compileGetByValOnDirectArguments(Node*); 2176 void compileGetByValOnScopedArguments(Node*); 2177 2157 2178 void compileGetScope(Node*); 2158 2179 void compileSkipScope(Node*); … … 2185 2206 void compileGetByValOnFloatTypedArray(Node*, TypedArrayType); 2186 2207 void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType); 2187 void compileNewFunctionNoCheck(Node*); 2188 void compileNewFunctionExpression(Node*); 2208 void compileNewFunction(Node*); 2209 void compileForwardVarargs(Node*); 2210 void compileCreateActivation(Node*); 2211 void compileCreateDirectArguments(Node*); 2212 void compileGetFromArguments(Node*); 2213 void compilePutToArguments(Node*); 2214 void compileCreateScopedArguments(Node*); 2215 void compileCreateClonedArguments(Node*); 2189 2216 bool compileRegExpExec(Node*); 2190 2217 … … 2255 2282 } 2256 2283 2284 template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr. 2285 void emitAllocateJSObjectWithKnownSize( 2286 GPRReg resultGPR, StructureType structure, StorageType storage, GPRReg scratchGPR1, 2287 GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath, size_t size) 2288 { 2289 MarkedAllocator* allocator = &m_jit.vm()->heap.allocatorForObjectOfType<ClassType>(size); 2290 m_jit.move(TrustedImmPtr(allocator), scratchGPR1); 2291 emitAllocateJSObject(resultGPR, scratchGPR1, structure, storage, scratchGPR2, slowPath); 2292 } 2293 2257 2294 // Convenience allocator for a built-in object. 2258 2295 template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr. … … 2260 2297 GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath) 2261 2298 { 2262 size_t size = ClassType::allocationSize(0); 2263 MarkedAllocator* allocator = &m_jit.vm()->heap.allocatorForObjectOfType<ClassType>(size); 2264 m_jit.move(TrustedImmPtr(allocator), scratchGPR1); 2265 emitAllocateJSObject(resultGPR, scratchGPR1, structure, storage, scratchGPR2, slowPath); 2299 emitAllocateJSObjectWithKnownSize<ClassType>( 2300 resultGPR, structure, storage, scratchGPR1, scratchGPR2, slowPath, 2301 ClassType::allocationSize(0)); 2266 2302 } 2267 2303 … … 2300 2336 2301 2337 void emitAllocateJSArray(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements); 2302 void emitAllocateArguments(GPRReg resultGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath); 2303 2338 2339 void emitGetLength(InlineCallFrame*, GPRReg lengthGPR, bool includeThis = false); 2340 void emitGetLength(CodeOrigin, GPRReg lengthGPR, bool includeThis = false); 2341 void emitGetCallee(CodeOrigin, GPRReg calleeGPR); 2342 void emitGetArgumentStart(CodeOrigin, GPRReg startGPR); 2343 2304 2344 // Add a speculation check. 2305 2345 void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r181891 r181993 36 36 #include "DFGSlowPathGenerator.h" 37 37 #include "Debugger.h" 38 #include "DirectArguments.h" 38 39 #include "GetterSetter.h" 40 #include "JSEnvironmentRecord.h" 39 41 #include "JSLexicalEnvironment.h" 40 42 #include "JSPropertyNameEnumerator.h" … … 641 643 { 642 644 CallLinkInfo::CallType callType; 643 bool isVarargs; 645 bool isVarargs = false; 646 bool isForwardVarargs = false; 644 647 switch (node->op()) { 645 648 case Call: 646 649 callType = CallLinkInfo::Call; 647 isVarargs = false;648 650 break; 649 651 case Construct: 650 652 callType = CallLinkInfo::Construct; 651 isVarargs = false;652 653 break; 653 654 case CallVarargs: 654 case CallForwardVarargs:655 655 callType = CallLinkInfo::CallVarargs; 656 656 isVarargs = true; … … 660 660 isVarargs = true; 661 661 break; 662 case CallForwardVarargs: 663 callType = CallLinkInfo::CallVarargs; 664 isForwardVarargs = true; 665 break; 666 case ConstructForwardVarargs: 667 callType = CallLinkInfo::ConstructVarargs; 668 isForwardVarargs = true; 669 break; 662 670 default: 663 671 DFG_CRASH(m_jit.graph(), node, "bad node type"); … … 668 676 669 677 // Gotta load the arguments somehow. Varargs is trickier. 670 if (isVarargs ) {678 if (isVarargs || isForwardVarargs) { 671 679 CallVarargsData* data = node->callVarargsData(); 672 680 673 GPRReg argumentsPayloadGPR; 674 GPRReg argumentsTagGPR; 675 GPRReg scratchGPR1; 676 GPRReg scratchGPR2; 677 GPRReg scratchGPR3; 678 679 if (node->op() == CallForwardVarargs) { 680 // We avoid calling flushRegisters() inside the control flow of CallForwardVarargs. 681 GPRReg resultGPR; 682 unsigned numUsedStackSlots = m_jit.graph().m_nextMachineLocal; 683 684 if (isForwardVarargs) { 681 685 flushRegisters(); 682 } 683 684 auto loadArgumentsGPR = [&] (GPRReg reservedGPR) { 685 if (node->op() == CallForwardVarargs) { 686 argumentsTagGPR = JITCompiler::selectScratchGPR(reservedGPR); 687 argumentsPayloadGPR = JITCompiler::selectScratchGPR(reservedGPR, argumentsTagGPR); 688 m_jit.load32( 689 JITCompiler::tagFor( 690 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 691 argumentsTagGPR); 692 m_jit.load32( 693 JITCompiler::payloadFor( 694 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 695 argumentsPayloadGPR); 696 } else { 686 use(node->child2()); 687 688 GPRReg scratchGPR1; 689 GPRReg scratchGPR2; 690 GPRReg scratchGPR3; 691 692 scratchGPR1 = JITCompiler::selectScratchGPR(); 693 scratchGPR2 = JITCompiler::selectScratchGPR(scratchGPR1); 694 scratchGPR3 = JITCompiler::selectScratchGPR(scratchGPR1, scratchGPR2); 695 696 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2); 697 JITCompiler::JumpList slowCase; 698 emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node->child2()->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); 699 JITCompiler::Jump done = m_jit.jump(); 700 slowCase.link(&m_jit); 701 callOperation(operationThrowStackOverflowForVarargs); 702 m_jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow); 703 done.link(&m_jit); 704 resultGPR = scratchGPR2; 705 } else { 706 GPRReg argumentsPayloadGPR; 707 GPRReg argumentsTagGPR; 708 GPRReg scratchGPR1; 709 GPRReg scratchGPR2; 710 GPRReg scratchGPR3; 711 712 auto loadArgumentsGPR = [&] (GPRReg reservedGPR) { 697 713 if (reservedGPR != InvalidGPRReg) 698 714 lock(reservedGPR); … … 703 719 unlock(reservedGPR); 704 720 flushRegisters(); 705 } 706 707 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, reservedGPR); 708 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, reservedGPR); 709 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, scratchGPR2, reservedGPR); 710 }; 711 712 loadArgumentsGPR(InvalidGPRReg); 713 714 // At this point we have the whole register file to ourselves, and argumentsGPR has the 715 // arguments register. Select some scratch registers. 716 717 // We will use scratchGPR2 to point to our stack frame. 718 719 unsigned numUsedStackSlots = m_jit.graph().m_nextMachineLocal; 720 721 JITCompiler::Jump haveArguments; 722 GPRReg resultGPR = GPRInfo::regT0; 723 if (node->op() == CallForwardVarargs) { 724 // Do the horrific foo.apply(this, arguments) optimization. 725 // FIXME: do this optimization at the IR level instead of dynamically by testing the 726 // arguments register. This will happen once we get rid of the arguments lazy creation and 727 // lazy tear-off. 728 729 JITCompiler::JumpList slowCase; 730 slowCase.append( 731 m_jit.branch32( 732 JITCompiler::NotEqual, 733 argumentsTagGPR, TrustedImm32(JSValue::EmptyValueTag))); 734 735 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2); 736 emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); 737 resultGPR = scratchGPR2; 738 739 haveArguments = m_jit.jump(); 740 slowCase.link(&m_jit); 741 } 742 721 722 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, reservedGPR); 723 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, reservedGPR); 724 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, scratchGPR2, reservedGPR); 725 }; 726 727 loadArgumentsGPR(InvalidGPRReg); 728 729 DFG_ASSERT(m_jit.graph(), node, isFlushed()); 730 731 // Right now, arguments is in argumentsTagGPR/argumentsPayloadGPR and the register file is 732 // flushed. 733 callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, argumentsTagGPR, argumentsPayloadGPR, numUsedStackSlots, data->firstVarArgOffset); 734 735 // Now we have the argument count of the callee frame, but we've lost the arguments operand. 736 // Reconstruct the arguments operand while preserving the callee frame. 737 loadArgumentsGPR(GPRInfo::returnValueGPR); 738 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1); 739 emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1); 740 m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister); 741 742 callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, argumentsTagGPR, argumentsPayloadGPR, data->firstVarArgOffset, GPRInfo::returnValueGPR); 743 resultGPR = GPRInfo::returnValueGPR; 744 } 745 746 m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), resultGPR, JITCompiler::stackPointerRegister); 747 743 748 DFG_ASSERT(m_jit.graph(), node, isFlushed()); 744 749 745 // Right now, arguments is in argumentsTagGPR/argumentsPayloadGPR and the register file is746 // flushed.747 callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, argumentsTagGPR, argumentsPayloadGPR, numUsedStackSlots, data->firstVarArgOffset);748 749 // Now we have the argument count of the callee frame, but we've lost the arguments operand.750 // Reconstruct the arguments operand while preserving the callee frame.751 loadArgumentsGPR(GPRInfo::returnValueGPR);752 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1);753 emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1);754 m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister);755 756 callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, argumentsTagGPR, argumentsPayloadGPR, data->firstVarArgOffset, GPRInfo::returnValueGPR);757 m_jit.move(GPRInfo::returnValueGPR, resultGPR);758 759 if (node->op() == CallForwardVarargs)760 haveArguments.link(&m_jit);761 762 m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), resultGPR, JITCompiler::stackPointerRegister);763 764 DFG_ASSERT(m_jit.graph(), node, isFlushed());765 766 if (node->op() != CallForwardVarargs)767 use(node->child2());768 769 750 // Now set up the "this" argument. 770 JSValueOperand thisArgument(this, node-> op() == CallForwardVarargs ? node->child2() : node->child3());751 JSValueOperand thisArgument(this, node->child3()); 771 752 GPRReg thisArgumentTagGPR = thisArgument.tagGPR(); 772 753 GPRReg thisArgumentPayloadGPR = thisArgument.payloadGPR(); … … 1754 1735 case JSConstant: 1755 1736 case DoubleConstant: 1756 initConstantInfo(node); 1757 break; 1758 1759 case PhantomArguments: 1737 case PhantomDirectArguments: 1738 case PhantomClonedArguments: 1760 1739 initConstantInfo(node); 1761 1740 break; … … 1841 1820 } 1842 1821 1843 case FlushedJSValue: 1844 case FlushedArguments: { 1822 case FlushedJSValue: { 1845 1823 GPRTemporary result(this); 1846 1824 GPRTemporary tag(this); … … 1917 1895 } 1918 1896 1919 case FlushedJSValue: 1920 case FlushedArguments: { 1897 case FlushedJSValue: { 1921 1898 JSValueOperand value(this, node->child1()); 1922 1899 m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal())); … … 2501 2478 compileGetByValOnString(node); 2502 2479 break; 2503 case Array::Arguments: 2504 compileGetByValOnArguments(node); 2480 case Array::DirectArguments: 2481 compileGetByValOnDirectArguments(node); 2482 break; 2483 case Array::ScopedArguments: 2484 compileGetByValOnScopedArguments(node); 2505 2485 break; 2506 2486 default: { … … 2680 2660 break; 2681 2661 } 2682 2683 case Array::Arguments:2684 // FIXME: we could at some point make this work. Right now we're assuming that the register2685 // pressure would be too great.2686 RELEASE_ASSERT_NOT_REACHED();2687 break;2688 2662 2689 2663 default: { … … 3587 3561 } 3588 3562 3563 case GetArgumentCount: { 3564 GPRTemporary result(this); 3565 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), result.gpr()); 3566 int32Result(result.gpr(), node); 3567 break; 3568 } 3569 3589 3570 case GetScope: 3590 3571 compileGetScope(node); … … 3595 3576 break; 3596 3577 3597 case GetClosureRegisters: {3598 if (WriteBarrierBase<Unknown>* registers = m_jit.graph().tryGetRegisters(node->child1().node())) {3599 GPRTemporary result(this);3600 GPRReg resultGPR = result.gpr();3601 m_jit.move(TrustedImmPtr(registers), resultGPR);3602 storageResult(resultGPR, node);3603 break;3604 }3605 3606 SpeculateCellOperand scope(this, node->child1());3607 GPRTemporary result(this);3608 GPRReg scopeGPR = scope.gpr();3609 GPRReg resultGPR = result.gpr();3610 3611 m_jit.loadPtr(JITCompiler::Address(scopeGPR, JSEnvironmentRecord::offsetOfRegisters()), resultGPR);3612 storageResult(resultGPR, node);3613 break;3614 }3615 3578 case GetClosureVar: { 3616 speculate(node, node->child1()); 3617 3618 StorageOperand registers(this, node->child2()); 3579 SpeculateCellOperand base(this, node->child1()); 3619 3580 GPRTemporary resultTag(this); 3620 3581 GPRTemporary resultPayload(this); 3621 GPRReg registersGPR = registers.gpr();3582 GPRReg baseGPR = base.gpr(); 3622 3583 GPRReg resultTagGPR = resultTag.gpr(); 3623 3584 GPRReg resultPayloadGPR = resultPayload.gpr(); 3624 m_jit.load32(JITCompiler::Address( registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);3625 m_jit.load32(JITCompiler::Address( registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);3585 m_jit.load32(JITCompiler::Address(baseGPR, JSEnvironmentRecord::offsetOfVariable(node->scopeOffset()) + TagOffset), resultTagGPR); 3586 m_jit.load32(JITCompiler::Address(baseGPR, JSEnvironmentRecord::offsetOfVariable(node->scopeOffset()) + PayloadOffset), resultPayloadGPR); 3626 3587 jsValueResult(resultTagGPR, resultPayloadGPR, node); 3627 3588 break; 3628 3589 } 3590 3629 3591 case PutClosureVar: { 3630 speculate(node, node->child1()); 3631 3632 StorageOperand registers(this, node->child2()); 3633 JSValueOperand value(this, node->child3()); 3634 GPRTemporary scratchRegister(this); 3635 3636 GPRReg registersGPR = registers.gpr(); 3592 SpeculateCellOperand base(this, node->child1()); 3593 JSValueOperand value(this, node->child2()); 3594 3595 GPRReg baseGPR = base.gpr(); 3637 3596 GPRReg valueTagGPR = value.tagGPR(); 3638 3597 GPRReg valuePayloadGPR = value.payloadGPR(); 3639 3598 3640 m_jit.store32(valueTagGPR, JITCompiler::Address( registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));3641 m_jit.store32(valuePayloadGPR, JITCompiler::Address( registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));3599 m_jit.store32(valueTagGPR, JITCompiler::Address(baseGPR, JSEnvironmentRecord::offsetOfVariable(node->scopeOffset()) + TagOffset)); 3600 m_jit.store32(valuePayloadGPR, JITCompiler::Address(baseGPR, JSEnvironmentRecord::offsetOfVariable(node->scopeOffset()) + PayloadOffset)); 3642 3601 noResult(node); 3643 3602 break; … … 3997 3956 GPRTemporary resultTag(this); 3998 3957 3999 m_jit.move(TrustedImmPtr(node-> registerPointer()), resultPayload.gpr());3958 m_jit.move(TrustedImmPtr(node->variablePointer()), resultPayload.gpr()); 4000 3959 m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTag.gpr()); 4001 3960 m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayload.gpr()); … … 4012 3971 // a register and then do a zero offset store followed by a four-offset store (or 4013 3972 // vice-versa depending on endianness). 4014 m_jit.store32(value.tagGPR(), node-> registerPointer()->tagPointer());4015 m_jit.store32(value.payloadGPR(), node-> registerPointer()->payloadPointer());3973 m_jit.store32(value.tagGPR(), node->variablePointer()->tagPointer()); 3974 m_jit.store32(value.payloadGPR(), node->variablePointer()->payloadPointer()); 4016 3975 4017 3976 noResult(node); … … 4263 4222 case CallForwardVarargs: 4264 4223 case ConstructVarargs: 4224 case ConstructForwardVarargs: 4265 4225 emitCall(node); 4266 4226 break; … … 4313 4273 } 4314 4274 4275 case ForwardVarargs: { 4276 compileForwardVarargs(node); 4277 break; 4278 } 4279 4315 4280 case CreateActivation: { 4316 GPRTemporary result(this); 4317 GPRReg resultGPR = result.gpr(); 4318 SpeculateCellOperand scope(this, node->child2()); 4319 GPRReg scopeGPR = scope.gpr(); 4320 4321 flushRegisters(); 4322 callOperation(operationCreateActivation, resultGPR, scopeGPR, framePointerOffsetToGetActivationRegisters()); 4323 4324 cellResult(resultGPR, node); 4325 break; 4326 } 4327 4328 case CreateArguments: { 4329 JSValueOperand value(this, node->child1()); 4330 GPRTemporary scratch1(this); 4331 GPRTemporary scratch2(this); 4332 GPRTemporary result(this, Reuse, value, PayloadWord); 4333 4334 GPRReg valueTagGPR = value.tagGPR(); 4335 GPRReg valuePayloadGPR = value.payloadGPR(); 4336 GPRReg scratch1GPR = scratch1.gpr(); 4337 GPRReg scratch2GPR = scratch2.gpr(); 4338 GPRReg resultGPR = result.gpr(); 4339 4340 m_jit.move(valuePayloadGPR, resultGPR); 4341 4342 if (node->origin.semantic.inlineCallFrame) { 4343 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4344 addSlowPathGenerator( 4345 slowPathCall( 4346 notCreated, this, operationCreateInlinedArguments, resultGPR, 4347 node->origin.semantic.inlineCallFrame)); 4348 cellResult(resultGPR, node); 4349 break; 4350 } 4351 4352 FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic)); 4353 if (m_jit.codeBlock()->hasSlowArguments() 4354 || executable->isStrictMode() 4355 || !executable->parameterCount()) { 4356 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4357 addSlowPathGenerator( 4358 slowPathCall(notCreated, this, operationCreateArgumentsForDFG, resultGPR)); 4359 cellResult(resultGPR, node); 4360 break; 4361 } 4362 4363 JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4364 4365 MacroAssembler::JumpList slowPaths; 4366 emitAllocateArguments(resultGPR, scratch1GPR, scratch2GPR, slowPaths); 4367 addSlowPathGenerator( 4368 slowPathCall(slowPaths, this, operationCreateArgumentsForDFG, resultGPR)); 4369 4370 alreadyCreated.link(&m_jit); 4371 cellResult(resultGPR, node); 4372 break; 4373 } 4374 4375 case TearOffArguments: { 4376 JSValueOperand unmodifiedArgumentsValue(this, node->child1()); 4377 JSValueOperand activationValue(this, node->child2()); 4378 GPRReg unmodifiedArgumentsValuePayloadGPR = unmodifiedArgumentsValue.payloadGPR(); 4379 GPRReg activationValuePayloadGPR = activationValue.payloadGPR(); 4380 4381 JITCompiler::Jump created = m_jit.branchTest32( 4382 JITCompiler::NonZero, unmodifiedArgumentsValuePayloadGPR); 4383 4384 if (node->origin.semantic.inlineCallFrame) { 4385 addSlowPathGenerator( 4386 slowPathCall( 4387 created, this, operationTearOffInlinedArguments, NoResult, 4388 unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR, node->origin.semantic.inlineCallFrame)); 4389 } else { 4390 addSlowPathGenerator( 4391 slowPathCall( 4392 created, this, operationTearOffArguments, NoResult, 4393 unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR)); 4394 } 4395 4396 noResult(node); 4397 break; 4398 } 4399 4400 case CheckArgumentsNotCreated: { 4401 ASSERT(!isEmptySpeculation( 4402 m_state.variables().operand( 4403 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)); 4404 speculationCheck( 4405 Uncountable, JSValueRegs(), 0, 4406 m_jit.branch32( 4407 JITCompiler::NotEqual, 4408 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4409 TrustedImm32(JSValue::EmptyValueTag))); 4410 noResult(node); 4411 break; 4412 } 4413 4414 case GetMyArgumentsLength: { 4415 GPRTemporary result(this); 4416 GPRReg resultGPR = result.gpr(); 4417 4418 if (!isEmptySpeculation( 4419 m_state.variables().operand( 4420 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) { 4421 speculationCheck( 4422 ArgumentsEscaped, JSValueRegs(), 0, 4423 m_jit.branch32( 4424 JITCompiler::NotEqual, 4425 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4426 TrustedImm32(JSValue::EmptyValueTag))); 4427 } 4428 4429 if (node->origin.semantic.inlineCallFrame 4430 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4431 m_jit.move( 4432 TrustedImm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1), 4433 resultGPR); 4434 } else { 4435 VirtualRegister argumentCountRegister; 4436 if (!node->origin.semantic.inlineCallFrame) 4437 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4438 else 4439 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4440 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultGPR); 4441 m_jit.sub32(TrustedImm32(1), resultGPR); 4442 } 4443 int32Result(resultGPR, node); 4444 break; 4445 } 4446 4447 case GetMyArgumentsLengthSafe: { 4448 GPRTemporary resultPayload(this); 4449 GPRTemporary resultTag(this); 4450 GPRReg resultPayloadGPR = resultPayload.gpr(); 4451 GPRReg resultTagGPR = resultTag.gpr(); 4452 4453 JITCompiler::Jump created = m_jit.branch32( 4454 JITCompiler::NotEqual, 4455 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4456 TrustedImm32(JSValue::EmptyValueTag)); 4457 4458 if (node->origin.semantic.inlineCallFrame 4459 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4460 m_jit.move( 4461 TrustedImm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1), 4462 resultPayloadGPR); 4463 } else { 4464 VirtualRegister argumentCountRegister; 4465 if (!node->origin.semantic.inlineCallFrame) 4466 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4467 else 4468 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4469 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultPayloadGPR); 4470 m_jit.sub32(TrustedImm32(1), resultPayloadGPR); 4471 } 4472 4473 m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR); 4474 4475 // FIXME: the slow path generator should perform a forward speculation that the 4476 // result is an integer. For now we postpone the speculation by having this return 4477 // a JSValue. 4478 4479 addSlowPathGenerator( 4480 slowPathCall( 4481 created, this, operationGetArgumentsLength, 4482 JSValueRegs(resultTagGPR, resultPayloadGPR), 4483 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset())); 4484 4485 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4486 break; 4487 } 4488 4489 case GetMyArgumentByVal: { 4490 SpeculateStrictInt32Operand index(this, node->child1()); 4491 GPRTemporary resultPayload(this); 4492 GPRTemporary resultTag(this); 4493 GPRReg indexGPR = index.gpr(); 4494 GPRReg resultPayloadGPR = resultPayload.gpr(); 4495 GPRReg resultTagGPR = resultTag.gpr(); 4496 4497 if (!isEmptySpeculation( 4498 m_state.variables().operand( 4499 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) { 4500 speculationCheck( 4501 ArgumentsEscaped, JSValueRegs(), 0, 4502 m_jit.branch32( 4503 JITCompiler::NotEqual, 4504 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4505 TrustedImm32(JSValue::EmptyValueTag))); 4506 } 4507 4508 if (node->origin.semantic.inlineCallFrame 4509 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4510 speculationCheck( 4511 Uncountable, JSValueRegs(), 0, 4512 m_jit.branch32( 4513 JITCompiler::AboveOrEqual, 4514 indexGPR, 4515 Imm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1))); 4516 } else { 4517 VirtualRegister argumentCountRegister; 4518 if (!node->origin.semantic.inlineCallFrame) 4519 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4520 else 4521 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4522 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultPayloadGPR); 4523 m_jit.sub32(TrustedImm32(1), resultPayloadGPR); 4524 speculationCheck( 4525 Uncountable, JSValueRegs(), 0, 4526 m_jit.branch32(JITCompiler::AboveOrEqual, indexGPR, resultPayloadGPR)); 4527 } 4528 4529 JITCompiler::JumpList slowArgument; 4530 JITCompiler::JumpList slowArgumentOutOfBounds; 4531 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4532 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4533 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4534 slowArgumentOutOfBounds.append( 4535 m_jit.branch32( 4536 JITCompiler::AboveOrEqual, indexGPR, 4537 Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount()))); 4538 4539 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4540 m_jit.move(ImmPtr(slowArguments), resultPayloadGPR); 4541 m_jit.load32( 4542 JITCompiler::BaseIndex( 4543 resultPayloadGPR, indexGPR, JITCompiler::TimesEight, 4544 OBJECT_OFFSETOF(SlowArgument, index)), 4545 resultPayloadGPR); 4546 4547 m_jit.load32( 4548 JITCompiler::BaseIndex( 4549 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4550 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4551 resultTagGPR); 4552 m_jit.load32( 4553 JITCompiler::BaseIndex( 4554 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4555 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4556 resultPayloadGPR); 4557 slowArgument.append(m_jit.jump()); 4558 } 4559 slowArgumentOutOfBounds.link(&m_jit); 4560 4561 m_jit.load32( 4562 JITCompiler::BaseIndex( 4563 GPRInfo::callFrameRegister, indexGPR, JITCompiler::TimesEight, 4564 m_jit.offsetOfArguments(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4565 resultTagGPR); 4566 m_jit.load32( 4567 JITCompiler::BaseIndex( 4568 GPRInfo::callFrameRegister, indexGPR, JITCompiler::TimesEight, 4569 m_jit.offsetOfArguments(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4570 resultPayloadGPR); 4571 4572 slowArgument.link(&m_jit); 4573 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4574 break; 4575 } 4576 case GetMyArgumentByValSafe: { 4577 SpeculateStrictInt32Operand index(this, node->child1()); 4578 GPRTemporary resultPayload(this); 4579 GPRTemporary resultTag(this); 4580 GPRReg indexGPR = index.gpr(); 4581 GPRReg resultPayloadGPR = resultPayload.gpr(); 4582 GPRReg resultTagGPR = resultTag.gpr(); 4583 4584 JITCompiler::JumpList slowPath; 4585 slowPath.append( 4586 m_jit.branch32( 4587 JITCompiler::NotEqual, 4588 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4589 TrustedImm32(JSValue::EmptyValueTag))); 4590 4591 if (node->origin.semantic.inlineCallFrame 4592 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4593 slowPath.append( 4594 m_jit.branch32( 4595 JITCompiler::AboveOrEqual, 4596 indexGPR, 4597 Imm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1))); 4598 } else { 4599 VirtualRegister argumentCountRegister; 4600 if (!node->origin.semantic.inlineCallFrame) 4601 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4602 else 4603 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4604 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultPayloadGPR); 4605 m_jit.sub32(TrustedImm32(1), resultPayloadGPR); 4606 slowPath.append( 4607 m_jit.branch32(JITCompiler::AboveOrEqual, indexGPR, resultPayloadGPR)); 4608 } 4609 4610 JITCompiler::JumpList slowArgument; 4611 JITCompiler::JumpList slowArgumentOutOfBounds; 4612 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4613 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4614 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4615 slowArgumentOutOfBounds.append( 4616 m_jit.branch32( 4617 JITCompiler::AboveOrEqual, indexGPR, 4618 Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount()))); 4619 4620 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4621 m_jit.move(ImmPtr(slowArguments), resultPayloadGPR); 4622 m_jit.load32( 4623 JITCompiler::BaseIndex( 4624 resultPayloadGPR, indexGPR, JITCompiler::TimesEight, 4625 OBJECT_OFFSETOF(SlowArgument, index)), 4626 resultPayloadGPR); 4627 m_jit.load32( 4628 JITCompiler::BaseIndex( 4629 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4630 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4631 resultTagGPR); 4632 m_jit.load32( 4633 JITCompiler::BaseIndex( 4634 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4635 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4636 resultPayloadGPR); 4637 slowArgument.append(m_jit.jump()); 4638 } 4639 slowArgumentOutOfBounds.link(&m_jit); 4640 4641 m_jit.load32( 4642 JITCompiler::BaseIndex( 4643 GPRInfo::callFrameRegister, indexGPR, JITCompiler::TimesEight, 4644 m_jit.offsetOfArguments(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4645 resultTagGPR); 4646 m_jit.load32( 4647 JITCompiler::BaseIndex( 4648 GPRInfo::callFrameRegister, indexGPR, JITCompiler::TimesEight, 4649 m_jit.offsetOfArguments(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4650 resultPayloadGPR); 4651 4652 if (node->origin.semantic.inlineCallFrame) { 4653 addSlowPathGenerator( 4654 slowPathCall( 4655 slowPath, this, operationGetInlinedArgumentByVal, 4656 JSValueRegs(resultTagGPR, resultPayloadGPR), 4657 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(), 4658 node->origin.semantic.inlineCallFrame, indexGPR)); 4659 } else { 4660 addSlowPathGenerator( 4661 slowPathCall( 4662 slowPath, this, operationGetArgumentByVal, 4663 JSValueRegs(resultTagGPR, resultPayloadGPR), 4664 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(), 4665 indexGPR)); 4666 } 4667 4668 slowArgument.link(&m_jit); 4669 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4670 break; 4671 } 4672 4673 case NewFunctionNoCheck: 4674 compileNewFunctionNoCheck(node); 4675 break; 4676 4677 case NewFunction: { 4678 JSValueOperand value(this, node->child1()); 4679 GPRTemporary resultTag(this, Reuse, value, TagWord); 4680 GPRTemporary resultPayload(this, Reuse, value, PayloadWord); 4681 4682 GPRReg valueTagGPR = value.tagGPR(); 4683 GPRReg valuePayloadGPR = value.payloadGPR(); 4684 GPRReg resultTagGPR = resultTag.gpr(); 4685 GPRReg resultPayloadGPR = resultPayload.gpr(); 4686 SpeculateCellOperand scope(this, node->child2()); 4687 GPRReg scopeGPR = scope.gpr(); 4688 4689 m_jit.move(valuePayloadGPR, resultPayloadGPR); 4690 m_jit.move(valueTagGPR, resultTagGPR); 4691 4692 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4693 4694 addSlowPathGenerator( 4695 slowPathCall( 4696 notCreated, this, operationNewFunction, JSValueRegs(resultTagGPR, resultPayloadGPR), scopeGPR, 4697 node->castOperand<FunctionExecutable*>())); 4698 4699 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4700 break; 4701 } 4702 4703 case NewFunctionExpression: 4704 compileNewFunctionExpression(node); 4281 compileCreateActivation(node); 4282 break; 4283 } 4284 4285 case CreateDirectArguments: { 4286 compileCreateDirectArguments(node); 4287 break; 4288 } 4289 4290 case GetFromArguments: { 4291 compileGetFromArguments(node); 4292 break; 4293 } 4294 4295 case PutToArguments: { 4296 compilePutToArguments(node); 4297 break; 4298 } 4299 4300 case CreateScopedArguments: { 4301 compileCreateScopedArguments(node); 4302 break; 4303 } 4304 4305 case CreateClonedArguments: { 4306 compileCreateClonedArguments(node); 4307 break; 4308 } 4309 4310 case NewFunction: 4311 compileNewFunction(node); 4705 4312 break; 4706 4313 … … 5088 4695 case KillStack: 5089 4696 case GetStack: 5090 RELEASE_ASSERT_NOT_REACHED(); 4697 case GetMyArgumentByVal: 4698 DFG_CRASH(m_jit.graph(), node, "unexpected node in DFG backend"); 5091 4699 break; 5092 4700 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r181891 r181993 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "Arguments.h"32 31 #include "ArrayPrototype.h" 33 32 #include "DFGAbstractInterpreterInlines.h" … … 36 35 #include "DFGSlowPathGenerator.h" 37 36 #include "Debugger.h" 37 #include "DirectArguments.h" 38 38 #include "GetterSetter.h" 39 39 #include "JSCInlines.h" 40 #include "JSEnvironmentRecord.h" 41 #include "JSLexicalEnvironment.h" 40 42 #include "JSPropertyNameEnumerator.h" 41 43 #include "ObjectPrototype.h" … … 627 629 { 628 630 CallLinkInfo::CallType callType; 629 bool isVarargs; 631 bool isVarargs = false; 632 bool isForwardVarargs = false; 630 633 switch (node->op()) { 631 634 case Call: 632 635 callType = CallLinkInfo::Call; 633 isVarargs = false;634 636 break; 635 637 case Construct: 636 638 callType = CallLinkInfo::Construct; 637 isVarargs = false;638 639 break; 639 640 case CallVarargs: 640 case CallForwardVarargs:641 641 callType = CallLinkInfo::CallVarargs; 642 642 isVarargs = true; … … 646 646 isVarargs = true; 647 647 break; 648 case CallForwardVarargs: 649 callType = CallLinkInfo::CallVarargs; 650 isForwardVarargs = true; 651 break; 652 case ConstructForwardVarargs: 653 callType = CallLinkInfo::ConstructVarargs; 654 isForwardVarargs = true; 655 break; 648 656 default: 649 657 DFG_CRASH(m_jit.graph(), node, "bad node type"); … … 654 662 655 663 // Gotta load the arguments somehow. Varargs is trickier. 656 if (isVarargs ) {664 if (isVarargs || isForwardVarargs) { 657 665 CallVarargsData* data = node->callVarargsData(); 658 666 659 GPRReg argumentsGPR; 660 GPRReg scratchGPR1; 661 GPRReg scratchGPR2; 662 GPRReg scratchGPR3; 663 664 if (node->op() == CallForwardVarargs) { 665 // We avoid calling flushRegisters() inside the control flow of CallForwardVarargs. 667 GPRReg resultGPR; 668 unsigned numUsedStackSlots = m_jit.graph().m_nextMachineLocal; 669 670 if (isForwardVarargs) { 666 671 flushRegisters(); 667 } 668 669 auto loadArgumentsGPR = [&] (GPRReg reservedGPR) { 670 if (node->op() == CallForwardVarargs) { 671 argumentsGPR = JITCompiler::selectScratchGPR(reservedGPR); 672 m_jit.load64( 673 JITCompiler::addressFor( 674 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 675 argumentsGPR); 676 } else { 672 use(node->child2()); 673 674 GPRReg scratchGPR1; 675 GPRReg scratchGPR2; 676 GPRReg scratchGPR3; 677 678 scratchGPR1 = JITCompiler::selectScratchGPR(); 679 scratchGPR2 = JITCompiler::selectScratchGPR(scratchGPR1); 680 scratchGPR3 = JITCompiler::selectScratchGPR(scratchGPR1, scratchGPR2); 681 682 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2); 683 JITCompiler::JumpList slowCase; 684 emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node->child2()->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); 685 JITCompiler::Jump done = m_jit.jump(); 686 slowCase.link(&m_jit); 687 callOperation(operationThrowStackOverflowForVarargs); 688 m_jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow); 689 done.link(&m_jit); 690 resultGPR = scratchGPR2; 691 } else { 692 GPRReg argumentsGPR; 693 GPRReg scratchGPR1; 694 GPRReg scratchGPR2; 695 GPRReg scratchGPR3; 696 697 auto loadArgumentsGPR = [&] (GPRReg reservedGPR) { 677 698 if (reservedGPR != InvalidGPRReg) 678 699 lock(reservedGPR); … … 682 703 unlock(reservedGPR); 683 704 flushRegisters(); 684 } 685 686 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsGPR, reservedGPR); 687 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, reservedGPR); 688 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, scratchGPR2, reservedGPR); 689 }; 690 691 loadArgumentsGPR(InvalidGPRReg); 692 693 // At this point we have the whole register file to ourselves, and argumentsGPR has the 694 // arguments register. Select some scratch registers. 695 696 // We will use scratchGPR2 to point to our stack frame. 697 698 unsigned numUsedStackSlots = m_jit.graph().m_nextMachineLocal; 699 700 JITCompiler::Jump haveArguments; 701 GPRReg resultGPR = GPRInfo::regT0; 702 if (node->op() == CallForwardVarargs) { 703 // Do the horrific foo.apply(this, arguments) optimization. 704 // FIXME: do this optimization at the IR level instead of dynamically by testing the 705 // arguments register. This will happen once we get rid of the arguments lazy creation and 706 // lazy tear-off. 707 708 JITCompiler::JumpList slowCase; 709 slowCase.append(m_jit.branchTest64(JITCompiler::NonZero, argumentsGPR)); 710 711 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2); 712 emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); 713 resultGPR = scratchGPR2; 714 715 haveArguments = m_jit.jump(); 716 slowCase.link(&m_jit); 717 } 718 705 706 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsGPR, reservedGPR); 707 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, reservedGPR); 708 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, scratchGPR2, reservedGPR); 709 }; 710 711 loadArgumentsGPR(InvalidGPRReg); 712 713 DFG_ASSERT(m_jit.graph(), node, isFlushed()); 714 715 // Right now, arguments is in argumentsGPR and the register file is flushed. 716 callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, argumentsGPR, numUsedStackSlots, data->firstVarArgOffset); 717 718 // Now we have the argument count of the callee frame, but we've lost the arguments operand. 719 // Reconstruct the arguments operand while preserving the callee frame. 720 loadArgumentsGPR(GPRInfo::returnValueGPR); 721 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1); 722 emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1); 723 m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister); 724 725 callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, argumentsGPR, data->firstVarArgOffset, GPRInfo::returnValueGPR); 726 resultGPR = GPRInfo::returnValueGPR; 727 } 728 729 m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), resultGPR, JITCompiler::stackPointerRegister); 730 719 731 DFG_ASSERT(m_jit.graph(), node, isFlushed()); 720 732 721 // Right now, arguments is in argumentsGPR and the register file is flushed.722 callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, argumentsGPR, numUsedStackSlots, data->firstVarArgOffset);723 724 // Now we have the argument count of the callee frame, but we've lost the arguments operand.725 // Reconstruct the arguments operand while preserving the callee frame.726 loadArgumentsGPR(GPRInfo::returnValueGPR);727 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1);728 emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1);729 m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister);730 731 callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, argumentsGPR, data->firstVarArgOffset, GPRInfo::returnValueGPR);732 m_jit.move(GPRInfo::returnValueGPR, resultGPR);733 734 if (node->op() == CallForwardVarargs)735 haveArguments.link(&m_jit);736 737 m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), resultGPR, JITCompiler::stackPointerRegister);738 739 DFG_ASSERT(m_jit.graph(), node, isFlushed());740 741 733 // We don't need the arguments array anymore. 742 if ( node->op() != CallForwardVarargs)734 if (isVarargs) 743 735 use(node->child2()); 744 736 745 737 // Now set up the "this" argument. 746 JSValueOperand thisArgument(this, node-> op() == CallForwardVarargs ? node->child2() : node->child3());738 JSValueOperand thisArgument(this, node->child3()); 747 739 GPRReg thisArgumentGPR = thisArgument.gpr(); 748 740 thisArgument.use(); … … 1847 1839 case DoubleConstant: 1848 1840 case Int52Constant: 1849 initConstantInfo(node); 1850 break; 1851 1852 case PhantomArguments: 1841 case PhantomDirectArguments: 1842 case PhantomClonedArguments: 1853 1843 initConstantInfo(node); 1854 1844 break; … … 2010 2000 } 2011 2001 2012 case FlushedJSValue: 2013 case FlushedArguments: { 2002 case FlushedJSValue: { 2014 2003 JSValueOperand value(this, node->child1()); 2015 2004 m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal())); … … 2603 2592 compileGetByValOnString(node); 2604 2593 break; 2605 case Array::Arguments: 2606 compileGetByValOnArguments(node); 2594 case Array::DirectArguments: 2595 compileGetByValOnDirectArguments(node); 2596 break; 2597 case Array::ScopedArguments: 2598 compileGetByValOnScopedArguments(node); 2607 2599 break; 2608 2600 default: { … … 2831 2823 2832 2824 noResult(node, UseChildrenCalledExplicitly); 2833 break;2834 }2835 2836 case Array::Arguments: {2837 JSValueOperand value(this, child3);2838 GPRTemporary scratch(this);2839 GPRTemporary scratch2(this);2840 2841 GPRReg valueReg = value.gpr();2842 GPRReg scratchReg = scratch.gpr();2843 GPRReg scratch2Reg = scratch2.gpr();2844 2845 if (!m_compileOkay)2846 return;2847 2848 // Two really lame checks.2849 speculationCheck(2850 Uncountable, JSValueSource(), 0,2851 m_jit.branch32(2852 MacroAssembler::AboveOrEqual, propertyReg,2853 MacroAssembler::Address(baseReg, Arguments::offsetOfNumArguments())));2854 speculationCheck(2855 Uncountable, JSValueSource(), 0,2856 m_jit.branchTestPtr(2857 MacroAssembler::NonZero,2858 MacroAssembler::Address(2859 baseReg, Arguments::offsetOfSlowArgumentData())));2860 2861 m_jit.move(propertyReg, scratch2Reg);2862 m_jit.signExtend32ToPtr(scratch2Reg, scratch2Reg);2863 m_jit.loadPtr(2864 MacroAssembler::Address(baseReg, Arguments::offsetOfRegisters()),2865 scratchReg);2866 2867 m_jit.store64(2868 valueReg,2869 MacroAssembler::BaseIndex(2870 scratchReg, scratch2Reg, MacroAssembler::TimesEight,2871 CallFrame::thisArgumentOffset() * sizeof(Register) + sizeof(Register)));2872 2873 noResult(node);2874 2825 break; 2875 2826 } … … 3640 3591 3641 3592 MacroAssembler::JumpList slowPath; 3642 3593 3643 3594 m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR); 3644 3595 m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR); … … 3689 3640 } 3690 3641 3642 case GetArgumentCount: { 3643 GPRTemporary result(this); 3644 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), result.gpr()); 3645 int32Result(result.gpr(), node); 3646 break; 3647 } 3648 3691 3649 case GetScope: 3692 3650 compileGetScope(node); … … 3697 3655 break; 3698 3656 3699 case GetClosureRegisters: { 3700 if (WriteBarrierBase<Unknown>* registers = m_jit.graph().tryGetRegisters(node->child1().node())) { 3701 GPRTemporary result(this); 3702 GPRReg resultGPR = result.gpr(); 3703 m_jit.move(TrustedImmPtr(registers), resultGPR); 3704 storageResult(resultGPR, node); 3705 break; 3706 } 3707 3708 SpeculateCellOperand scope(this, node->child1()); 3657 case GetClosureVar: { 3658 SpeculateCellOperand base(this, node->child1()); 3709 3659 GPRTemporary result(this); 3710 GPRReg scopeGPR = scope.gpr();3660 GPRReg baseGPR = base.gpr(); 3711 3661 GPRReg resultGPR = result.gpr(); 3712 3662 3713 m_jit.loadPtr(JITCompiler::Address(scopeGPR, JSEnvironmentRecord::offsetOfRegisters()), resultGPR); 3714 storageResult(resultGPR, node); 3715 break; 3716 } 3717 case GetClosureVar: { 3718 speculate(node, node->child1()); 3719 3720 StorageOperand registers(this, node->child2()); 3721 GPRTemporary result(this); 3722 GPRReg registersGPR = registers.gpr(); 3723 GPRReg resultGPR = result.gpr(); 3724 3725 m_jit.load64(JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register)), resultGPR); 3663 m_jit.load64(JITCompiler::Address(baseGPR, JSEnvironmentRecord::offsetOfVariable(node->scopeOffset())), resultGPR); 3726 3664 jsValueResult(resultGPR, node); 3727 3665 break; 3728 3666 } 3729 3667 case PutClosureVar: { 3730 speculate(node, node->child1()); 3731 3732 StorageOperand registers(this, node->child2()); 3733 JSValueOperand value(this, node->child3()); 3734 3735 GPRReg registersGPR = registers.gpr(); 3668 SpeculateCellOperand base(this, node->child1()); 3669 JSValueOperand value(this, node->child2()); 3670 3671 GPRReg baseGPR = base.gpr(); 3736 3672 GPRReg valueGPR = value.gpr(); 3737 3673 3738 m_jit.store64(valueGPR, JITCompiler::Address( registersGPR, node->varNumber() * sizeof(Register)));3674 m_jit.store64(valueGPR, JITCompiler::Address(baseGPR, JSEnvironmentRecord::offsetOfVariable(node->scopeOffset()))); 3739 3675 noResult(node); 3740 3676 break; … … 4063 3999 GPRTemporary result(this); 4064 4000 4065 m_jit.load64(node-> registerPointer(), result.gpr());4001 m_jit.load64(node->variablePointer(), result.gpr()); 4066 4002 4067 4003 jsValueResult(result.gpr(), node); … … 4072 4008 JSValueOperand value(this, node->child1()); 4073 4009 4074 m_jit.store64(value.gpr(), node-> registerPointer());4010 m_jit.store64(value.gpr(), node->variablePointer()); 4075 4011 4076 4012 noResult(node); … … 4319 4255 case CallForwardVarargs: 4320 4256 case ConstructVarargs: 4257 case ConstructForwardVarargs: 4321 4258 emitCall(node); 4322 4259 break; … … 4366 4303 } 4367 4304 4305 case ForwardVarargs: { 4306 compileForwardVarargs(node); 4307 break; 4308 } 4309 4368 4310 case CreateActivation: { 4369 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4370 4371 GPRTemporary result(this); 4372 GPRReg resultGPR = result.gpr(); 4373 SpeculateCellOperand scope(this, node->child2()); 4374 GPRReg scopeGPR = scope.gpr(); 4375 4376 flushRegisters(); 4377 callOperation(operationCreateActivation, resultGPR, scopeGPR, framePointerOffsetToGetActivationRegisters()); 4378 4379 cellResult(resultGPR, node); 4380 break; 4381 } 4382 4383 case CreateArguments: { 4384 JSValueOperand value(this, node->child1()); 4385 GPRTemporary scratch1(this); 4386 GPRTemporary scratch2(this); 4387 GPRTemporary result(this, Reuse, value); 4388 4389 GPRReg valueGPR = value.gpr(); 4390 GPRReg scratchGPR1 = scratch1.gpr(); 4391 GPRReg scratchGPR2 = scratch2.gpr(); 4392 GPRReg resultGPR = result.gpr(); 4393 4394 m_jit.move(valueGPR, resultGPR); 4395 4396 if (node->origin.semantic.inlineCallFrame) { 4397 JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR); 4398 addSlowPathGenerator( 4399 slowPathCall( 4400 notCreated, this, operationCreateInlinedArguments, resultGPR, 4401 node->origin.semantic.inlineCallFrame)); 4402 cellResult(resultGPR, node); 4403 break; 4404 } 4405 4406 FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic)); 4407 if (m_jit.codeBlock()->hasSlowArguments() 4408 || executable->isStrictMode() 4409 || !executable->parameterCount()) { 4410 JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR); 4411 addSlowPathGenerator( 4412 slowPathCall(notCreated, this, operationCreateArgumentsForDFG, resultGPR)); 4413 cellResult(resultGPR, node); 4414 break; 4415 } 4416 4417 JITCompiler::Jump alreadyCreated = m_jit.branchTest64(JITCompiler::NonZero, resultGPR); 4418 4419 MacroAssembler::JumpList slowPaths; 4420 emitAllocateArguments(resultGPR, scratchGPR1, scratchGPR2, slowPaths); 4421 addSlowPathGenerator( 4422 slowPathCall(slowPaths, this, operationCreateArgumentsForDFG, resultGPR)); 4423 4424 alreadyCreated.link(&m_jit); 4425 cellResult(resultGPR, node); 4426 break; 4427 } 4428 4429 case TearOffArguments: { 4430 JSValueOperand unmodifiedArgumentsValue(this, node->child1()); 4431 JSValueOperand activationValue(this, node->child2()); 4432 GPRReg unmodifiedArgumentsValueGPR = unmodifiedArgumentsValue.gpr(); 4433 GPRReg activationValueGPR = activationValue.gpr(); 4434 4435 JITCompiler::Jump created = m_jit.branchTest64(JITCompiler::NonZero, unmodifiedArgumentsValueGPR); 4436 4437 if (node->origin.semantic.inlineCallFrame) { 4438 addSlowPathGenerator( 4439 slowPathCall( 4440 created, this, operationTearOffInlinedArguments, NoResult, 4441 unmodifiedArgumentsValueGPR, activationValueGPR, node->origin.semantic.inlineCallFrame)); 4442 } else { 4443 addSlowPathGenerator( 4444 slowPathCall( 4445 created, this, operationTearOffArguments, NoResult, unmodifiedArgumentsValueGPR, activationValueGPR)); 4446 } 4447 4448 noResult(node); 4449 break; 4450 } 4451 4452 case GetMyArgumentsLength: { 4453 GPRTemporary result(this); 4454 GPRReg resultGPR = result.gpr(); 4455 4456 if (!isEmptySpeculation( 4457 m_state.variables().operand( 4458 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) { 4459 speculationCheck( 4460 ArgumentsEscaped, JSValueRegs(), 0, 4461 m_jit.branchTest64( 4462 JITCompiler::NonZero, 4463 JITCompiler::addressFor( 4464 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)))); 4465 } 4466 4467 if (node->origin.semantic.inlineCallFrame 4468 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4469 m_jit.move( 4470 TrustedImm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1), 4471 resultGPR); 4472 } else { 4473 VirtualRegister argumentCountRegister; 4474 if (!node->origin.semantic.inlineCallFrame) 4475 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4476 else 4477 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4478 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultGPR); 4479 m_jit.sub32(TrustedImm32(1), resultGPR); 4480 } 4481 int32Result(resultGPR, node); 4482 break; 4483 } 4484 4485 case GetMyArgumentsLengthSafe: { 4486 GPRTemporary result(this); 4487 GPRReg resultGPR = result.gpr(); 4488 4489 JITCompiler::Jump created = m_jit.branchTest64( 4490 JITCompiler::NonZero, 4491 JITCompiler::addressFor( 4492 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic))); 4493 4494 if (node->origin.semantic.inlineCallFrame 4495 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4496 m_jit.move( 4497 Imm64(JSValue::encode(jsNumber(node->origin.semantic.inlineCallFrame->arguments.size() - 1))), 4498 resultGPR); 4499 } else { 4500 VirtualRegister argumentCountRegister; 4501 if (!node->origin.semantic.inlineCallFrame) 4502 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4503 else 4504 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4505 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultGPR); 4506 m_jit.sub32(TrustedImm32(1), resultGPR); 4507 m_jit.or64(GPRInfo::tagTypeNumberRegister, resultGPR); 4508 } 4509 4510 addSlowPathGenerator( 4511 slowPathCall( 4512 created, this, operationGetArgumentsLength, resultGPR, 4513 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset())); 4514 4515 jsValueResult(resultGPR, node); 4516 break; 4517 } 4518 4519 case GetMyArgumentByVal: { 4520 SpeculateStrictInt32Operand index(this, node->child1()); 4521 GPRTemporary result(this); 4522 GPRReg indexGPR = index.gpr(); 4523 GPRReg resultGPR = result.gpr(); 4524 4525 if (!isEmptySpeculation( 4526 m_state.variables().operand( 4527 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) { 4528 speculationCheck( 4529 ArgumentsEscaped, JSValueRegs(), 0, 4530 m_jit.branchTest64( 4531 JITCompiler::NonZero, 4532 JITCompiler::addressFor( 4533 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)))); 4534 } 4535 4536 if (node->origin.semantic.inlineCallFrame 4537 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4538 speculationCheck( 4539 Uncountable, JSValueRegs(), 0, 4540 m_jit.branch32( 4541 JITCompiler::AboveOrEqual, 4542 indexGPR, 4543 Imm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1))); 4544 } else { 4545 VirtualRegister argumentCountRegister; 4546 if (!node->origin.semantic.inlineCallFrame) 4547 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4548 else 4549 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4550 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultGPR); 4551 m_jit.sub32(TrustedImm32(1), resultGPR); 4552 speculationCheck( 4553 Uncountable, JSValueRegs(), 0, 4554 m_jit.branch32(JITCompiler::AboveOrEqual, indexGPR, resultGPR)); 4555 } 4556 4557 JITCompiler::JumpList slowArgument; 4558 JITCompiler::JumpList slowArgumentOutOfBounds; 4559 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4560 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4561 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4562 4563 slowArgumentOutOfBounds.append( 4564 m_jit.branch32( 4565 JITCompiler::AboveOrEqual, indexGPR, 4566 Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount()))); 4567 4568 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4569 m_jit.move(ImmPtr(slowArguments), resultGPR); 4570 m_jit.load32( 4571 JITCompiler::BaseIndex( 4572 resultGPR, indexGPR, JITCompiler::TimesEight, 4573 OBJECT_OFFSETOF(SlowArgument, index)), 4574 resultGPR); 4575 m_jit.signExtend32ToPtr(resultGPR, resultGPR); 4576 m_jit.load64( 4577 JITCompiler::BaseIndex( 4578 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight), 4579 resultGPR); 4580 slowArgument.append(m_jit.jump()); 4581 } 4582 slowArgumentOutOfBounds.link(&m_jit); 4583 4584 m_jit.load64( 4585 JITCompiler::BaseIndex( 4586 GPRInfo::callFrameRegister, indexGPR, JITCompiler::TimesEight, m_jit.offsetOfArguments(node->origin.semantic)), 4587 resultGPR); 4588 4589 slowArgument.link(&m_jit); 4590 jsValueResult(resultGPR, node); 4591 break; 4592 } 4593 4594 case GetMyArgumentByValSafe: { 4595 SpeculateStrictInt32Operand index(this, node->child1()); 4596 GPRTemporary result(this); 4597 GPRReg indexGPR = index.gpr(); 4598 GPRReg resultGPR = result.gpr(); 4599 4600 JITCompiler::JumpList slowPath; 4601 slowPath.append( 4602 m_jit.branchTest64( 4603 JITCompiler::NonZero, 4604 JITCompiler::addressFor( 4605 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)))); 4606 4607 if (node->origin.semantic.inlineCallFrame 4608 && !node->origin.semantic.inlineCallFrame->isVarargs()) { 4609 slowPath.append( 4610 m_jit.branch32( 4611 JITCompiler::AboveOrEqual, 4612 resultGPR, 4613 Imm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1))); 4614 } else { 4615 VirtualRegister argumentCountRegister; 4616 if (!node->origin.semantic.inlineCallFrame) 4617 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 4618 else 4619 argumentCountRegister = node->origin.semantic.inlineCallFrame->argumentCountRegister; 4620 m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), resultGPR); 4621 m_jit.sub32(TrustedImm32(1), resultGPR); 4622 slowPath.append( 4623 m_jit.branch32(JITCompiler::AboveOrEqual, indexGPR, resultGPR)); 4624 } 4625 4626 JITCompiler::JumpList slowArgument; 4627 JITCompiler::JumpList slowArgumentOutOfBounds; 4628 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4629 DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame); 4630 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4631 4632 slowArgumentOutOfBounds.append( 4633 m_jit.branch32( 4634 JITCompiler::AboveOrEqual, indexGPR, 4635 Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount()))); 4636 4637 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4638 m_jit.move(ImmPtr(slowArguments), resultGPR); 4639 m_jit.load32( 4640 JITCompiler::BaseIndex( 4641 resultGPR, indexGPR, JITCompiler::TimesEight, 4642 OBJECT_OFFSETOF(SlowArgument, index)), 4643 resultGPR); 4644 m_jit.signExtend32ToPtr(resultGPR, resultGPR); 4645 m_jit.load64( 4646 JITCompiler::BaseIndex( 4647 GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight), 4648 resultGPR); 4649 slowArgument.append(m_jit.jump()); 4650 } 4651 slowArgumentOutOfBounds.link(&m_jit); 4652 4653 m_jit.load64( 4654 JITCompiler::BaseIndex( 4655 GPRInfo::callFrameRegister, indexGPR, JITCompiler::TimesEight, m_jit.offsetOfArguments(node->origin.semantic)), 4656 resultGPR); 4657 4658 if (node->origin.semantic.inlineCallFrame) { 4659 addSlowPathGenerator( 4660 slowPathCall( 4661 slowPath, this, operationGetInlinedArgumentByVal, resultGPR, 4662 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(), 4663 node->origin.semantic.inlineCallFrame, 4664 indexGPR)); 4665 } else { 4666 addSlowPathGenerator( 4667 slowPathCall( 4668 slowPath, this, operationGetArgumentByVal, resultGPR, 4669 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(), 4670 indexGPR)); 4671 } 4672 4673 slowArgument.link(&m_jit); 4674 jsValueResult(resultGPR, node); 4675 break; 4676 } 4677 4678 case CheckArgumentsNotCreated: { 4679 ASSERT(!isEmptySpeculation( 4680 m_state.variables().operand( 4681 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)); 4682 speculationCheck( 4683 ArgumentsEscaped, JSValueRegs(), 0, 4684 m_jit.branchTest64( 4685 JITCompiler::NonZero, 4686 JITCompiler::addressFor( 4687 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)))); 4688 noResult(node); 4689 break; 4690 } 4691 4692 case NewFunctionNoCheck: 4693 compileNewFunctionNoCheck(node); 4694 break; 4695 4696 case NewFunction: { 4697 JSValueOperand value(this, node->child1()); 4698 GPRTemporary result(this, Reuse, value); 4699 SpeculateCellOperand scope(this, node->child2()); 4700 GPRReg scopeGPR = scope.gpr(); 4701 4702 GPRReg valueGPR = value.gpr(); 4703 GPRReg resultGPR = result.gpr(); 4704 4705 m_jit.move(valueGPR, resultGPR); 4706 4707 JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR); 4708 4709 addSlowPathGenerator( 4710 slowPathCall( 4711 notCreated, this, operationNewFunction, 4712 resultGPR, scopeGPR, node->castOperand<FunctionExecutable*>())); 4713 4714 jsValueResult(resultGPR, node); 4715 break; 4716 } 4717 4718 case NewFunctionExpression: 4719 compileNewFunctionExpression(node); 4311 compileCreateActivation(node); 4312 break; 4313 } 4314 4315 case CreateDirectArguments: { 4316 compileCreateDirectArguments(node); 4317 break; 4318 } 4319 4320 case GetFromArguments: { 4321 compileGetFromArguments(node); 4322 break; 4323 } 4324 4325 case PutToArguments: { 4326 compilePutToArguments(node); 4327 break; 4328 } 4329 4330 case CreateScopedArguments: { 4331 compileCreateScopedArguments(node); 4332 break; 4333 } 4334 4335 case CreateClonedArguments: { 4336 compileCreateClonedArguments(node); 4337 break; 4338 } 4339 4340 case NewFunction: 4341 compileNewFunction(node); 4720 4342 break; 4721 4343 … … 5153 4775 case BottomValue: 5154 4776 case PhantomNewObject: 4777 case GetMyArgumentByVal: 5155 4778 case PutHint: 5156 4779 case CheckStructureImmediate: -
trunk/Source/JavaScriptCore/dfg/DFGStackLayoutPhase.cpp
r180691 r181993 47 47 bool run() 48 48 { 49 SymbolTable* symbolTable = codeBlock()->symbolTable();50 51 49 // This enumerates the locals that we actually care about and packs them. So for example 52 50 // if we use local 1, 3, 4, 5, 7, then we remap them: 1->0, 3->1, 4->2, 5->3, 7->4. We … … 85 83 } 86 84 87 case LoadVarargs: { 85 case LoadVarargs: 86 case ForwardVarargs: { 88 87 LoadVarargsData* data = node->loadVarargsData(); 89 88 if (data->count.isLocal()) … … 115 114 } 116 115 117 // Ensure that captured variables and captured inline arguments are pinned down.118 // They should have been because of flushes, except that the flushes can be optimized119 // away.120 if (symbolTable) {121 for (int i = symbolTable->captureStart(); i > symbolTable->captureEnd(); i--)122 usedLocals.set(VirtualRegister(i).toLocal());123 }124 if (codeBlock()->usesArguments()) {125 usedLocals.set(codeBlock()->argumentsRegister().toLocal());126 usedLocals.set(unmodifiedArgumentsRegister(codeBlock()->argumentsRegister()).toLocal());127 }128 if (codeBlock()->uncheckedActivationRegister().isValid())129 usedLocals.set(codeBlock()->activationRegister().toLocal());130 116 for (InlineCallFrameSet::iterator iter = m_graph.m_plan.inlineCallFrames->begin(); !!iter; ++iter) { 131 117 InlineCallFrame* inlineCallFrame = *iter; 132 if (!m_graph.usesArguments(inlineCallFrame))133 continue;134 135 VirtualRegister argumentsRegister = m_graph.argumentsRegisterFor(inlineCallFrame);136 usedLocals.set(argumentsRegister.toLocal());137 usedLocals.set(unmodifiedArgumentsRegister(argumentsRegister).toLocal());138 118 139 119 if (inlineCallFrame->isVarargs()) { … … 194 174 } 195 175 196 if (codeBlock()->usesArguments()) {197 VirtualRegister argumentsRegister =198 assign(allocation, codeBlock()->argumentsRegister());199 RELEASE_ASSERT(200 assign(allocation, unmodifiedArgumentsRegister(codeBlock()->argumentsRegister()))201 == unmodifiedArgumentsRegister(argumentsRegister));202 codeBlock()->setArgumentsRegister(argumentsRegister);203 }204 205 if (codeBlock()->uncheckedActivationRegister().isValid()) {206 codeBlock()->setActivationRegister(207 assign(allocation, codeBlock()->activationRegister()));208 }209 210 176 // This register is never valid for DFG code blocks. 177 codeBlock()->setActivationRegister(VirtualRegister()); 211 178 codeBlock()->setScopeRegister(VirtualRegister()); 212 179 … … 214 181 InlineVariableData data = m_graph.m_inlineVariableData[i]; 215 182 InlineCallFrame* inlineCallFrame = data.inlineCallFrame; 216 217 if (m_graph.usesArguments(inlineCallFrame)) {218 inlineCallFrame->argumentsRegister = assign(219 allocation, m_graph.argumentsRegisterFor(inlineCallFrame));220 221 RELEASE_ASSERT(222 assign(allocation, unmodifiedArgumentsRegister(m_graph.argumentsRegisterFor(inlineCallFrame)))223 == unmodifiedArgumentsRegister(inlineCallFrame->argumentsRegister));224 }225 183 226 184 if (inlineCallFrame->isVarargs()) { … … 252 210 } else 253 211 RELEASE_ASSERT(inlineCallFrame->calleeRecovery.isConstant()); 254 }255 256 if (symbolTable) {257 if (symbolTable->captureCount()) {258 unsigned captureStartLocal = allocation[259 VirtualRegister(codeBlock()->symbolTable()->captureStart()).toLocal()];260 ASSERT(captureStartLocal != UINT_MAX);261 m_graph.m_machineCaptureStart = virtualRegisterForLocal(captureStartLocal).offset();262 } else263 m_graph.m_machineCaptureStart = virtualRegisterForLocal(0).offset();264 265 // This is an abomination. If we had captured an argument then the argument ends266 // up being "slow", meaning that loads of the argument go through an extra lookup267 // table.268 if (const SlowArgument* slowArguments = symbolTable->slowArguments()) {269 auto newSlowArguments = std::make_unique<SlowArgument[]>(270 symbolTable->parameterCount());271 for (size_t i = symbolTable->parameterCount(); i--;) {272 newSlowArguments[i] = slowArguments[i];273 newSlowArguments[i].index = assign(allocation, VirtualRegister(slowArguments[i].index)).offset();274 }275 276 m_graph.m_slowArguments = WTF::move(newSlowArguments);277 }278 212 } 279 213 … … 292 226 } 293 227 294 case LoadVarargs: { 228 case LoadVarargs: 229 case ForwardVarargs: { 295 230 LoadVarargsData* data = node->loadVarargsData(); 296 231 data->machineCount = assign(allocation, data->count); -
trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
r180279 r181993 238 238 VirtualRegister local = m_node->local(); 239 239 240 if (m_node->variableAccessData()->isCaptured()) { 241 for (unsigned i = m_nodeIndex; i--;) { 242 Node* node = m_block->at(i); 243 bool done = false; 244 switch (node->op()) { 245 case GetLocal: 246 case Flush: 247 if (node->local() == local) 248 done = true; 249 break; 250 251 case GetLocalUnlinked: 252 if (node->unlinkedLocal() == local) 253 done = true; 254 break; 255 256 case SetLocal: { 257 if (node->local() != local) 258 break; 259 setLocal = node; 260 done = true; 261 break; 262 } 263 264 case Phantom: 265 case Check: 266 case HardPhantom: 267 case MovHint: 268 case JSConstant: 269 case DoubleConstant: 270 case Int52Constant: 271 case GetScope: 272 case PhantomLocal: 273 case GetCallee: 274 case CountExecution: 275 break; 276 277 default: 278 done = true; 279 break; 280 } 281 if (done) 282 break; 283 } 284 } else { 285 for (unsigned i = m_nodeIndex; i--;) { 286 Node* node = m_block->at(i); 287 if (node->op() == SetLocal && node->local() == local) { 288 setLocal = node; 289 break; 290 } 291 if (accessesOverlap(m_graph, node, AbstractHeap(Variables, local))) 292 break; 293 } 240 for (unsigned i = m_nodeIndex; i--;) { 241 Node* node = m_block->at(i); 242 if (node->op() == SetLocal && node->local() == local) { 243 setLocal = node; 244 break; 245 } 246 if (accessesOverlap(m_graph, node, AbstractHeap(Stack, local))) 247 break; 294 248 } 295 249 -
trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp
r173993 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 119 119 break; 120 120 121 case CreateDirectArguments: 122 registerStructure(m_graph.globalObjectFor(node->origin.semantic)->directArgumentsStructure()); 123 break; 124 125 case CreateScopedArguments: 126 registerStructure(m_graph.globalObjectFor(node->origin.semantic)->scopedArgumentsStructure()); 127 break; 128 121 129 case NewRegexp: 122 130 registerStructure(m_graph.globalObjectFor(node->origin.semantic)->regExpStructure()); 123 131 break; 124 132 125 case NewFunctionExpression: 126 case NewFunctionNoCheck: 133 case NewFunction: 127 134 registerStructure(m_graph.globalObjectFor(node->origin.semantic)->functionStructure()); 128 135 break; -
trunk/Source/JavaScriptCore/dfg/DFGUnificationPhase.cpp
r164229 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 71 71 VariableAccessData* data = &m_graph.m_variableAccessData[i]; 72 72 data->find()->predict(data->nonUnifiedPrediction()); 73 data->find()->mergeIsCaptured(data->isCaptured());74 73 data->find()->mergeStructureCheckHoistingFailed(data->structureCheckHoistingFailed()); 75 74 data->find()->mergeCheckArrayHoistingFailed(data->checkArrayHoistingFailed()); -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r181650 r181993 439 439 case CheckInBounds: 440 440 case PhantomNewObject: 441 case GetMyArgumentByVal: 441 442 case PutHint: 442 443 case CheckStructureImmediate: … … 455 456 switch (node->op()) { 456 457 case GetLocal: 457 if (node->variableAccessData()->isCaptured())458 break;459 458 // Ignore GetLocal's that we know to be dead, but that the graph 460 459 // doesn't yet know to be dead. … … 466 465 break; 467 466 case SetLocal: 468 if (node->variableAccessData()->isCaptured())469 break;470 467 // Only record the first SetLocal. There may be multiple SetLocals 471 468 // because of flushing. … … 475 472 break; 476 473 case SetArgument: 477 if (node->variableAccessData()->isCaptured())478 break;479 474 // This acts like a reset. It's ok to have a second GetLocal for a local in the same 480 475 // block if we had a SetArgument for that local. -
trunk/Source/JavaScriptCore/dfg/DFGValueSource.cpp
r179503 r181993 1 1 /* 2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 60 60 out.print("Double:", virtualRegister()); 61 61 break; 62 case ArgumentsSource:63 out.print("Arguments");64 break;65 62 case HaveNode: 66 63 out.print("Node(", m_value, ")"); -
trunk/Source/JavaScriptCore/dfg/DFGValueSource.h
r168051 r181993 1 1 /* 2 * Copyright (C) 2011, 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 46 46 BooleanInJSStack, 47 47 DoubleInJSStack, 48 ArgumentsSource,49 48 SourceIsDead, 50 49 HaveNode … … 66 65 case DataFormatDead: 67 66 return SourceIsDead; 68 case DataFormatArguments:69 return ArgumentsSource;70 67 default: 71 68 RELEASE_ASSERT(dataFormat & DataFormatJS); … … 89 86 case DoubleInJSStack: 90 87 return DataFormatDouble; 91 case ArgumentsSource:92 return DataFormatArguments;93 88 case SourceIsDead: 94 89 return DataFormatDead; … … 121 116 : m_kind(valueSourceKind) 122 117 { 123 ASSERT(kind() == ArgumentsSource || kind() == SourceIsDead || kind() == ArgumentsSource);118 ASSERT(kind() == SourceIsDead); 124 119 } 125 120 … … 158 153 case FlushedBoolean: 159 154 return ValueSource(BooleanInJSStack, where); 160 case FlushedArguments:161 return ValueSource(ArgumentsSource);162 155 } 163 156 RELEASE_ASSERT_NOT_REACHED(); … … 197 190 return ValueRecovery::constant(jsUndefined()); 198 191 199 case ArgumentsSource:200 return ValueRecovery::argumentsThatWereNotCreated();201 202 192 default: 203 193 return ValueRecovery::displacedInJSStack(virtualRegister(), dataFormat()); -
trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.cpp
r174371 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 36 36 , m_argumentAwarePrediction(SpecNone) 37 37 , m_flags(0) 38 , m_isCaptured(false)39 38 , m_shouldNeverUnbox(false) 40 , m_isArgumentsAlias(false)41 39 , m_structureCheckHoistingFailed(false) 42 40 , m_checkArrayHoistingFailed(false) … … 48 46 } 49 47 50 VariableAccessData::VariableAccessData(VirtualRegister local , bool isCaptured)48 VariableAccessData::VariableAccessData(VirtualRegister local) 51 49 : m_local(local) 52 50 , m_prediction(SpecNone) 53 51 , m_argumentAwarePrediction(SpecNone) 54 52 , m_flags(0) 55 , m_isCaptured(isCaptured) 56 , m_shouldNeverUnbox(isCaptured) 57 , m_isArgumentsAlias(false) 53 , m_shouldNeverUnbox(false) 58 54 , m_structureCheckHoistingFailed(false) 59 55 , m_checkArrayHoistingFailed(false) … … 63 59 { 64 60 clearVotes(); 65 }66 67 bool VariableAccessData::mergeIsCaptured(bool isCaptured)68 {69 return checkAndSet(m_shouldNeverUnbox, m_shouldNeverUnbox || isCaptured)70 | checkAndSet(m_isCaptured, m_isCaptured || isCaptured);71 61 } 72 62 … … 199 189 ASSERT(find() == this); 200 190 201 if (isArgumentsAlias())202 return FlushedArguments;203 204 191 if (!shouldUnboxIfPossible()) 205 192 return FlushedJSValue; -
trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
r174371 r181993 1 1 /* 2 * Copyright (C) 2011-201 4Apple Inc. All rights reserved.2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 49 49 public: 50 50 VariableAccessData(); 51 VariableAccessData(VirtualRegister local , bool isCaptured);51 VariableAccessData(VirtualRegister local); 52 52 53 53 VirtualRegister local() … … 63 63 } 64 64 65 bool mergeIsCaptured(bool isCaptured);66 67 bool isCaptured()68 {69 return m_isCaptured;70 }71 72 65 bool mergeIsProfitableToUnbox(bool isProfitableToUnbox) 73 66 { … … 87 80 bool shouldNeverUnbox() 88 81 { 89 ASSERT(!(m_isCaptured && !m_shouldNeverUnbox));90 82 return m_shouldNeverUnbox; 91 83 } … … 119 111 } 120 112 121 bool mergeIsArgumentsAlias(bool isArgumentsAlias)122 {123 return checkAndSet(m_isArgumentsAlias, m_isArgumentsAlias || isArgumentsAlias);124 }125 126 bool isArgumentsAlias()127 {128 return m_isArgumentsAlias;129 }130 131 113 bool mergeIsLoadedFrom(bool isLoadedFrom) 132 114 { … … 194 176 bool doubleState = m_doubleFormatState == UsingDoubleFormat; 195 177 ASSERT(!(doubleState && shouldNeverUnbox())); 196 ASSERT(!(doubleState && isCaptured()));197 178 return doubleState && isProfitableToUnbox(); 198 179 } … … 234 215 NodeFlags m_flags; 235 216 236 bool m_isCaptured;237 217 bool m_shouldNeverUnbox; 238 bool m_isArgumentsAlias;239 218 bool m_structureCheckHoistingFailed; 240 219 bool m_checkArrayHoistingFailed; -
trunk/Source/JavaScriptCore/dfg/DFGVariableAccessDataDump.cpp
r164229 r181993 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 63 63 } 64 64 65 if (m_data->isCaptured()) 66 out.print("*"); 67 else if (m_data->shouldNeverUnbox()) 65 if (m_data->shouldNeverUnbox()) 68 66 out.print("!"); 69 67 else if (!m_data->shouldUnboxIfPossible()) -
trunk/Source/JavaScriptCore/dfg/DFGVariableAccessDataDump.h
r164424 r181993 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without -
trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
r171613 r181993 1 1 /* 2 * Copyright (C) 2012 , 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 92 92 } 93 93 94 if (node->op() == PhantomArguments) { 95 recovery = ValueRecovery::argumentsThatWereNotCreated(); 94 if (node->op() == PhantomDirectArguments) { 95 recovery = ValueRecovery::directArgumentsThatWereNotCreated(node->id()); 96 return true; 97 } 98 99 if (node->op() == PhantomClonedArguments) { 100 recovery = ValueRecovery::outOfBandArgumentsThatWereNotCreated(node->id()); 96 101 return true; 97 102 } -
trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.h
r171613 r181993 33 33 #include "DFGVariableEvent.h" 34 34 #include "Operands.h" 35 #include "ValueRecovery.h" 35 36 #include <wtf/Vector.h> 36 37 -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeap.cpp
r177222 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 54 54 } 55 55 56 void AbstractHeap::dump(PrintStream& out) const 57 { 58 out.print(heapName()); 59 if (m_parent) 60 out.print("->", *m_parent); 61 } 62 63 void AbstractField::dump(PrintStream& out) const 64 { 65 out.print(heapName(), "(", m_offset, ")"); 66 if (parent()) 67 out.print("->", *parent()); 68 } 69 56 70 IndexedAbstractHeap::IndexedAbstractHeap(LContext context, AbstractHeap* parent, const char* heapName, ptrdiff_t offset, size_t elementSize) 57 71 : m_heapForAnyIndex(parent, heapName) … … 177 191 } 178 192 193 void IndexedAbstractHeap::dump(PrintStream& out) const 194 { 195 out.print("Indexed:", atAnyIndex()); 196 } 197 179 198 NumberedAbstractHeap::NumberedAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName) 180 199 : m_indexedHeap(context, heap, heapName, 0, 1) … … 186 205 } 187 206 207 void NumberedAbstractHeap::dump(PrintStream& out) const 208 { 209 out.print("Numbered: ", atAnyNumber()); 210 } 211 188 212 AbsoluteAbstractHeap::AbsoluteAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName) 189 213 : m_indexedHeap(context, heap, heapName, 0, 1) … … 195 219 } 196 220 221 void AbsoluteAbstractHeap::dump(PrintStream& out) const 222 { 223 out.print("Absolute:", atAnyAddress()); 224 } 225 197 226 } } // namespace JSC::FTL 198 227 -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeap.h
r177222 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 100 100 void decorateInstruction(LValue instruction, const AbstractHeapRepository&) const; 101 101 102 void dump(PrintStream&) const; 103 102 104 private: 103 105 friend class AbstractHeapRepository; … … 136 138 } 137 139 140 void dump(PrintStream&) const; 141 138 142 private: 139 143 ptrdiff_t m_offset; … … 158 162 TypedPointer baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0); 159 163 164 void dump(PrintStream&) const; 165 160 166 private: 161 167 const AbstractField& returnInitialized(AbstractField& field, ptrdiff_t index) … … 202 208 const AbstractHeap& operator[](unsigned number) { return at(number); } 203 209 210 void dump(PrintStream&) const; 211 204 212 private: 205 213 … … 222 230 223 231 const AbstractHeap& operator[](void* address) { return at(address); } 232 233 void dump(PrintStream&) const; 224 234 225 235 private: -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp
r173837 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(FTL_JIT) 30 30 31 #include "DirectArguments.h" 31 32 #include "GetterSetter.h" 32 33 #include "JSEnvironmentRecord.h" … … 34 35 #include "JSScope.h" 35 36 #include "JSCInlines.h" 37 #include "ScopedArguments.h" 38 #include "ScopedArgumentsTable.h" 36 39 37 40 namespace JSC { namespace FTL { -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r181891 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 36 36 37 37 #define FOR_EACH_ABSTRACT_HEAP(macro) \ 38 macro(length) \ 39 macro(structureTable) \ 40 macro(typedArrayProperties) \ 41 macro(WriteBarrierBuffer_bufferContents) 38 macro(typedArrayProperties) 42 39 43 40 #define FOR_EACH_ABSTRACT_FIELD(macro) \ … … 47 44 macro(Butterfly_vectorLength, Butterfly::offsetOfVectorLength()) \ 48 45 macro(CallFrame_callerFrame, CallFrame::callerFrameOffset()) \ 46 macro(DirectArguments_callee, DirectArguments::offsetOfCallee()) \ 47 macro(DirectArguments_length, DirectArguments::offsetOfLength()) \ 48 macro(DirectArguments_minCapacity, DirectArguments::offsetOfMinCapacity()) \ 49 macro(DirectArguments_overrides, DirectArguments::offsetOfOverrides()) \ 49 50 macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \ 50 51 macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \ … … 71 72 macro(JSString_length, JSString::offsetOfLength()) \ 72 73 macro(JSString_value, JSString::offsetOfValue()) \ 73 macro(JS EnvironmentRecord_registers, JSEnvironmentRecord::offsetOfRegisters()) \74 macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \ 74 75 macro(JSWrapperObject_internalValue, JSWrapperObject::internalValueOffset()) \ 75 76 macro(MarkedAllocator_freeListHead, MarkedAllocator::offsetOfFreeListHead()) \ 76 77 macro(MarkedBlock_markBits, MarkedBlock::offsetOfMarks()) \ 78 macro(ScopedArguments_overrodeThings, ScopedArguments::offsetOfOverrodeThings()) \ 79 macro(ScopedArguments_scope, ScopedArguments::offsetOfScope()) \ 80 macro(ScopedArguments_table, ScopedArguments::offsetOfTable()) \ 81 macro(ScopedArguments_totalLength, ScopedArguments::offsetOfTotalLength()) \ 82 macro(ScopedArgumentsTable_arguments, ScopedArgumentsTable::offsetOfArguments()) \ 83 macro(ScopedArgumentsTable_length, ScopedArgumentsTable::offsetOfLength()) \ 77 84 macro(StringImpl_data, StringImpl::dataOffset()) \ 78 85 macro(StringImpl_hashAndFlags, StringImpl::flagsOffset()) \ … … 83 90 84 91 #define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \ 92 macro(DirectArguments_storage, DirectArguments::storageOffset(), sizeof(EncodedJSValue)) \ 93 macro(JSEnvironmentRecord_variables, JSEnvironmentRecord::offsetOfVariables(), sizeof(EncodedJSValue)) \ 94 macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier<JSString>)) \ 85 95 macro(JSRopeString_fibers, JSRopeString::offsetOfFibers(), sizeof(WriteBarrier<JSString>)) \ 96 macro(MarkedSpace_Subspace_impreciseAllocators, OBJECT_OFFSETOF(MarkedSpace::Subspace, impreciseAllocators), sizeof(MarkedAllocator)) \ 97 macro(MarkedSpace_Subspace_preciseAllocators, OBJECT_OFFSETOF(MarkedSpace::Subspace, preciseAllocators), sizeof(MarkedAllocator)) \ 98 macro(ScopedArguments_overflowStorage, ScopedArguments::overflowStorageOffset(), sizeof(EncodedJSValue)) \ 99 macro(WriteBarrierBuffer_bufferContents, 0, sizeof(JSCell*)) \ 86 100 macro(characters8, 0, sizeof(LChar)) \ 87 101 macro(characters16, 0, sizeof(UChar)) \ … … 90 104 macro(indexedContiguousProperties, 0, sizeof(EncodedJSValue)) \ 91 105 macro(indexedArrayStorageProperties, 0, sizeof(EncodedJSValue)) \ 106 macro(scopedArgumentsTableArguments, 0, sizeof(int32_t)) \ 92 107 macro(singleCharacterStrings, 0, sizeof(JSString*)) \ 108 macro(structureTable, 0, sizeof(Structure*)) \ 93 109 macro(variables, 0, sizeof(Register)) 94 110 -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r181891 r181993 45 45 switch (node->op()) { 46 46 case JSConstant: 47 case GetMyArgumentsLength:48 47 case GetLocal: 49 48 case SetLocal: … … 104 103 case LoopHint: 105 104 case SkipScope: 106 case GetClosureRegisters: 105 case CreateActivation: 106 case NewFunction: 107 107 case GetClosureVar: 108 108 case PutClosureVar: 109 case CreateDirectArguments: 110 case CreateScopedArguments: 111 case CreateClonedArguments: 112 case GetFromArguments: 113 case PutToArguments: 109 114 case InvalidationPoint: 110 115 case StringCharAt: … … 125 130 case CallForwardVarargs: 126 131 case ConstructVarargs: 132 case ConstructForwardVarargs: 127 133 case LoadVarargs: 128 134 case NativeCall: … … 138 144 case GetScope: 139 145 case AllocationProfileWatchpoint: 140 case CheckArgumentsNotCreated:141 146 case GetCallee: 147 case GetArgumentCount: 142 148 case ToString: 143 149 case MakeRope: … … 148 154 case MultiPutByOffset: 149 155 case ToPrimitive: 150 case PhantomArguments:151 156 case Throw: 152 157 case ThrowReferenceError: 153 158 case Unreachable: 154 case GetMyArgumentByVal:155 159 case IsUndefined: 156 160 case IsBoolean: … … 181 185 case CheckStructureImmediate: 182 186 case MaterializeNewObject: 187 case PhantomDirectArguments: 188 case PhantomClonedArguments: 189 case GetMyArgumentByVal: 190 case ForwardVarargs: 183 191 // These are OK. 184 192 break; … … 209 217 case Array::Double: 210 218 case Array::Contiguous: 219 case Array::DirectArguments: 220 case Array::ScopedArguments: 211 221 break; 212 222 default: … … 222 232 case Array::Contiguous: 223 233 case Array::String: 234 case Array::DirectArguments: 235 case Array::ScopedArguments: 224 236 break; 225 237 default: … … 248 260 case Array::Double: 249 261 case Array::Contiguous: 262 case Array::DirectArguments: 263 case Array::ScopedArguments: 250 264 break; 251 265 default: … … 365 379 if (verboseCapabilities()) 366 380 dataLog("FTL rejecting ", *graph.m_codeBlock, " because it doesn't belong to a function.\n"); 367 return CannotCompile;368 }369 370 if (graph.m_codeBlock->needsActivation()) {371 // Need this because although we also don't support372 // CreateActivation, we might not see those nodes in case of373 // OSR entry.374 // FIXME: Support activations.375 // https://bugs.webkit.org/show_bug.cgi?id=129576376 if (verboseCapabilities())377 dataLog("FTL rejecting ", *graph.m_codeBlock, " because it uses activations.\n");378 381 return CannotCompile; 379 382 } -
trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp
r181990 r181993 141 141 static int offsetOfStackRegion(StackMaps::RecordMap& recordMap, uint32_t stackmapID) 142 142 { 143 if (stackmapID == UINT_MAX) 144 return 0; 145 143 146 StackMaps::RecordMap::iterator iter = recordMap.find(stackmapID); 144 147 RELEASE_ASSERT(iter != recordMap.end()); … … 302 305 StackMaps stackmaps = jitCode->stackmaps; 303 306 304 int localsOffset = 305 offsetOfStackRegion(recordMap, state.capturedStackmapID) + graph.m_nextMachineLocal; 306 307 int varargsSpillSlotsOffset; 308 if (state.varargsSpillSlotsStackmapID != UINT_MAX) 309 varargsSpillSlotsOffset = offsetOfStackRegion(recordMap, state.varargsSpillSlotsStackmapID); 310 else 311 varargsSpillSlotsOffset = 0; 307 int localsOffset = offsetOfStackRegion(recordMap, state.capturedStackmapID) + graph.m_nextMachineLocal; 308 int varargsSpillSlotsOffset = offsetOfStackRegion(recordMap, state.varargsSpillSlotsStackmapID); 312 309 313 310 for (unsigned i = graph.m_inlineVariableData.size(); i--;) { 314 311 InlineCallFrame* inlineCallFrame = graph.m_inlineVariableData[i].inlineCallFrame; 315 316 if (inlineCallFrame->argumentsRegister.isValid())317 inlineCallFrame->argumentsRegister += localsOffset;318 312 319 313 if (inlineCallFrame->argumentCountRegister.isValid()) … … 331 325 } 332 326 333 if (codeBlock->usesArguments()) {334 codeBlock->setArgumentsRegister(335 VirtualRegister(codeBlock->argumentsRegister().offset() + localsOffset));336 }337 338 327 MacroAssembler::Label stackOverflowException; 339 328 … … 397 386 exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump); 398 387 399 for (unsigned j = exit.m_values.size(); j--;) { 400 ExitValue value = exit.m_values[j]; 401 if (!value.isInJSStackSomehow()) 402 continue; 403 if (!value.virtualRegister().isLocal()) 404 continue; 405 exit.m_values[j] = value.withVirtualRegister( 406 VirtualRegister(value.virtualRegister().offset() + localsOffset)); 407 } 388 for (unsigned j = exit.m_values.size(); j--;) 389 exit.m_values[j] = exit.m_values[j].withLocalsOffset(localsOffset); 390 for (ExitTimeObjectMaterialization* materialization : exit.m_materializations) 391 materialization->accountForLocalsOffset(localsOffset); 408 392 409 393 if (verboseCompilationEnabled()) { … … 589 573 590 574 CCallHelpers fastPathJIT(&vm, codeBlock); 591 call.emit(fastPathJIT, graph,varargsSpillSlotsOffset);575 call.emit(fastPathJIT, varargsSpillSlotsOffset); 592 576 593 577 char* startOfIC = bitwise_cast<char*>(generatedFunction) + call.m_instructionOffset; -
trunk/Source/JavaScriptCore/ftl/FTLExitArgument.cpp
r153121 r181993 33 33 void ExitArgument::dump(PrintStream& out) const 34 34 { 35 out.print(" arg", argument(), " as ", format());35 out.print("#", argument(), " as ", format()); 36 36 } 37 37 -
trunk/Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp
r173993 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 31 31 namespace JSC { namespace FTL { 32 32 33 ExitPropertyValue ExitPropertyValue::withLocalsOffset(int offset) const 34 { 35 return ExitPropertyValue(m_location, m_value.withLocalsOffset(offset)); 36 } 37 33 38 void ExitPropertyValue::dump(PrintStream& out) const 34 39 { -
trunk/Source/JavaScriptCore/ftl/FTLExitPropertyValue.h
r173993 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 52 52 const ExitValue& value() const { return m_value; } 53 53 54 ExitPropertyValue withLocalsOffset(int offset) const; 55 54 56 void dump(PrintStream& out) const; 55 57 -
trunk/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp
r173993 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 35 35 using namespace JSC::DFG; 36 36 37 ExitTimeObjectMaterialization::ExitTimeObjectMaterialization(NodeType type )37 ExitTimeObjectMaterialization::ExitTimeObjectMaterialization(NodeType type, CodeOrigin codeOrigin) 38 38 : m_type(type) 39 , m_origin(codeOrigin) 39 40 { 40 41 } … … 59 60 } 60 61 62 void ExitTimeObjectMaterialization::accountForLocalsOffset(int offset) 63 { 64 for (ExitPropertyValue& property : m_properties) 65 property = property.withLocalsOffset(offset); 66 } 67 61 68 void ExitTimeObjectMaterialization::dump(PrintStream& out) const 62 69 { -
trunk/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h
r173993 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 39 39 WTF_MAKE_NONCOPYABLE(ExitTimeObjectMaterialization) 40 40 public: 41 ExitTimeObjectMaterialization(DFG::NodeType );41 ExitTimeObjectMaterialization(DFG::NodeType, CodeOrigin); 42 42 ~ExitTimeObjectMaterialization(); 43 43 … … 45 45 46 46 DFG::NodeType type() const { return m_type; } 47 CodeOrigin origin() const { return m_origin; } 47 48 48 49 ExitValue get(DFG::PromotedLocationDescriptor) const; 49 50 const Vector<ExitPropertyValue>& properties() const { return m_properties; } 51 52 void accountForLocalsOffset(int offset); 50 53 51 54 void dump(PrintStream& out) const; … … 53 56 private: 54 57 DFG::NodeType m_type; 58 CodeOrigin m_origin; 55 59 Vector<ExitPropertyValue> m_properties; 56 60 }; -
trunk/Source/JavaScriptCore/ftl/FTLExitValue.cpp
r179503 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 42 42 } 43 43 44 ExitValue ExitValue::withLocalsOffset(int offset) const 45 { 46 if (!isInJSStackSomehow()) 47 return *this; 48 if (!virtualRegister().isLocal()) 49 return *this; 50 return withVirtualRegister(virtualRegister() + offset); 51 } 52 53 ValueFormat ExitValue::valueFormat() const 54 { 55 switch (kind()) { 56 case InvalidExitValue: 57 RELEASE_ASSERT_NOT_REACHED(); 58 return InvalidValueFormat; 59 60 case ExitValueDead: 61 case ExitValueConstant: 62 case ExitValueInJSStack: 63 case ExitValueMaterializeNewObject: 64 return ValueFormatJSValue; 65 66 case ExitValueArgument: 67 return exitArgument().format(); 68 69 case ExitValueInJSStackAsInt32: 70 return ValueFormatInt32; 71 72 case ExitValueInJSStackAsInt52: 73 return ValueFormatInt52; 74 75 case ExitValueInJSStackAsDouble: 76 return ValueFormatDouble; 77 78 case ExitValueRecovery: 79 return recoveryFormat(); 80 } 81 82 RELEASE_ASSERT_NOT_REACHED(); 83 return InvalidValueFormat; 84 } 85 44 86 void ExitValue::dumpInContext(PrintStream& out, DumpContext* context) const 45 87 { … … 69 111 out.print("InJSStackAsDouble:", virtualRegister()); 70 112 return; 71 case ExitValueArgumentsObjectThatWasNotCreated:72 out.print("ArgumentsObjectThatWasNotCreated");73 return;74 113 case ExitValueRecovery: 75 114 out.print("Recovery(", recoveryOpcode(), ", arg", leftRecoveryArgument(), ", arg", rightRecoveryArgument(), ", ", recoveryFormat(), ")"); -
trunk/Source/JavaScriptCore/ftl/FTLExitValue.h
r173993 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 52 52 ExitValueInJSStackAsInt52, 53 53 ExitValueInJSStackAsDouble, 54 ExitValueArgumentsObjectThatWasNotCreated,55 54 ExitValueRecovery, 56 55 ExitValueMaterializeNewObject … … 120 119 result.m_kind = ExitValueArgument; 121 120 result.u.argument = argument.representation(); 122 return result;123 }124 125 static ExitValue argumentsObjectThatWasNotCreated()126 {127 ExitValue result;128 result.m_kind = ExitValueArgumentsObjectThatWasNotCreated;129 121 return result; 130 122 } … … 160 152 bool isConstant() const { return kind() == ExitValueConstant; } 161 153 bool isArgument() const { return kind() == ExitValueArgument; } 162 bool isArgumentsObjectThatWasNotCreated() const { return kind() == ExitValueArgumentsObjectThatWasNotCreated; }163 154 bool isRecovery() const { return kind() == ExitValueRecovery; } 164 155 bool isObjectMaterialization() const { return kind() == ExitValueMaterializeNewObject; } … … 220 211 return result; 221 212 } 213 214 ExitValue withLocalsOffset(int offset) const; 222 215 223 216 // If it's in the JSStack somehow, this will tell you what format it's in, in a manner … … 225 218 // will claim to be a JSValue. If it's an argument then it will tell you the argument's 226 219 // format. 227 ValueFormat valueFormat() const 228 { 229 switch (kind()) { 230 case InvalidExitValue: 231 RELEASE_ASSERT_NOT_REACHED(); 232 return InvalidValueFormat; 233 234 case ExitValueDead: 235 case ExitValueConstant: 236 case ExitValueInJSStack: 237 case ExitValueArgumentsObjectThatWasNotCreated: 238 case ExitValueMaterializeNewObject: 239 return ValueFormatJSValue; 240 241 case ExitValueArgument: 242 return exitArgument().format(); 243 244 case ExitValueInJSStackAsInt32: 245 return ValueFormatInt32; 246 247 case ExitValueInJSStackAsInt52: 248 return ValueFormatInt52; 249 250 case ExitValueInJSStackAsDouble: 251 return ValueFormatDouble; 252 253 case ExitValueRecovery: 254 return recoveryFormat(); 255 } 256 257 RELEASE_ASSERT_NOT_REACHED(); 258 return InvalidValueFormat; 259 } 220 ValueFormat valueFormat() const; 260 221 261 222 void dump(PrintStream&) const; -
trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp
r181195 r181993 86 86 { 87 87 #if CPU(ARM64) 88 return 460;88 return 312; 89 89 #else 90 return 372;90 return 250; 91 91 #endif 92 92 } … … 95 95 { 96 96 #if CPU(ARM64) 97 return 3 00;97 return 332; 98 98 #else 99 99 return 275; 100 #endif 101 } 102 103 size_t sizeOfConstructForwardVarargs() 104 { 105 #if CPU(ARM64) 106 return 312; 107 #else 108 return 250; 100 109 #endif 101 110 } … … 126 135 case ConstructVarargs: 127 136 return sizeOfConstructVarargs(); 137 case ConstructForwardVarargs: 138 return sizeOfConstructForwardVarargs(); 128 139 case In: 129 140 return sizeOfIn(); -
trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h
r180279 r181993 43 43 size_t sizeOfCallForwardVarargs(); 44 44 size_t sizeOfConstructVarargs(); 45 size_t sizeOfConstructForwardVarargs(); 45 46 size_t sizeOfIn(); 46 47 -
trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
r181035 r181993 64 64 macro(C_JITOperation_EJssJssJss, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \ 65 65 macro(C_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \ 66 macro(C_JITOperation_EStJscSymtab, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \ 67 macro(C_JITOperation_EStRZJsf, functionType(intPtr, intPtr, intPtr, intPtr, int32, intPtr)) \ 68 macro(C_JITOperation_EStRZJsfL, functionType(intPtr, intPtr, intPtr, intPtr, int32, intPtr, intPtr)) \ 69 macro(C_JITOperation_EStZ, functionType(intPtr, intPtr, intPtr, int32)) \ 70 macro(C_JITOperation_EStZZ, functionType(intPtr, intPtr, intPtr, int32, int32)) \ 66 71 macro(C_JITOperation_EZ, functionType(intPtr, intPtr, int32)) \ 67 72 macro(D_JITOperation_D, functionType(doubleType, doubleType)) \ … … 77 82 macro(J_JITOperation_EJC, functionType(int64, intPtr, int64, intPtr)) \ 78 83 macro(J_JITOperation_EJJ, functionType(int64, intPtr, int64, int64)) \ 84 macro(J_JITOperation_EJscC, functionType(intPtr, intPtr, intPtr, intPtr)) \ 79 85 macro(J_JITOperation_EJssZ, functionType(int64, intPtr, intPtr, int32)) \ 80 86 macro(J_JITOperation_ESsiJI, functionType(int64, intPtr, intPtr, int64, intPtr)) \ -
trunk/Source/JavaScriptCore/ftl/FTLJSCallVarargs.cpp
r180595 r181993 29 29 #if ENABLE(FTL_JIT) 30 30 31 #include "DFGGraph.h"32 31 #include "DFGNode.h" 33 32 #include "DFGOperations.h" … … 52 51 , m_node(node) 53 52 , m_callBase( 54 node->op() == ConstructVarargs ? CallLinkInfo::ConstructVarargs : CallLinkInfo::CallVarargs, 53 (node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs) 54 ? CallLinkInfo::ConstructVarargs : CallLinkInfo::CallVarargs, 55 55 node->origin.semantic) 56 56 , m_instructionOffset(0) 57 57 { 58 ASSERT(node->op() == CallVarargs || node->op() == CallForwardVarargs || node->op() == ConstructVarargs); 58 ASSERT( 59 node->op() == CallVarargs || node->op() == CallForwardVarargs 60 || node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs); 59 61 } 60 62 … … 64 66 } 65 67 66 void JSCallVarargs::emit(CCallHelpers& jit, Graph& graph,int32_t spillSlotsOffset)68 void JSCallVarargs::emit(CCallHelpers& jit, int32_t spillSlotsOffset) 67 69 { 68 70 // We are passed three pieces of information: 69 71 // - The callee. 70 // - The arguments object .72 // - The arguments object, if it's not a forwarding call. 71 73 // - The "this" value, if it's a constructor call. 72 74 … … 77 79 GPRReg argumentsGPR = InvalidGPRReg; 78 80 GPRReg thisGPR = InvalidGPRReg; 79 bool argumentsOnStack = false; 81 82 bool forwarding = false; 80 83 81 84 switch (m_node->op()) { 82 85 case CallVarargs: 86 case ConstructVarargs: 83 87 argumentsGPR = GPRInfo::argumentGPR1; 84 88 thisGPR = GPRInfo::argumentGPR2; 85 89 break; 86 90 case CallForwardVarargs: 91 case ConstructForwardVarargs: 87 92 thisGPR = GPRInfo::argumentGPR1; 88 argumentsOnStack = true; 89 break; 90 case ConstructVarargs: 91 argumentsGPR = GPRInfo::argumentGPR1; 92 thisGPR = GPRInfo::argumentGPR2; 93 forwarding = true; 93 94 break; 94 95 default: … … 116 117 GPRReg scratchGPR2 = allocator.allocateScratchGPR(); 117 118 GPRReg scratchGPR3 = allocator.allocateScratchGPR(); 118 if (argumentsOnStack) 119 argumentsGPR = allocator.allocateScratchGPR(); 119 120 120 RELEASE_ASSERT(!allocator.numberOfReusedRegisters()); 121 122 auto loadArguments = [&] (bool clobbered) {123 if (argumentsOnStack) {124 jit.load64(125 CCallHelpers::addressFor(graph.machineArgumentsRegisterFor(m_node->origin.semantic)),126 argumentsGPR);127 } else if (clobbered) {128 jit.load64(129 CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot), argumentsGPR);130 }131 };132 121 133 122 auto computeUsedStack = [&] (GPRReg targetGPR, unsigned extra) { … … 152 141 }; 153 142 154 loadArguments(false);155 156 143 if (isARM64()) { 157 144 jit.move(CCallHelpers::stackPointerRegister, scratchGPR1); … … 159 146 } else 160 147 jit.storePtr(CCallHelpers::stackPointerRegister, CCallHelpers::addressFor(spillSlotsOffset + stackPointerSpillSlot)); 161 162 // Attempt the forwarding fast path, if it's been requested. 163 CCallHelpers::Jump haveArguments; 164 if (m_node->op() == CallForwardVarargs) { 165 // Do the horrific foo.apply(this, arguments) optimization. 166 // FIXME: do this optimization at the IR level. 167 168 CCallHelpers::JumpList slowCase; 169 slowCase.append(jit.branchTest64(CCallHelpers::NonZero, argumentsGPR)); 170 171 computeUsedStack(scratchGPR2, 0); 172 emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, m_node->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); 173 174 jit.move(calleeGPR, GPRInfo::regT0); 175 haveArguments = jit.jump(); 176 slowCase.link(&jit); 177 } 178 179 // Gotta spill the callee, arguments, and this because we will need them later and we will have some 180 // calls that clobber them. 181 jit.store64(calleeGPR, CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot)); 182 if (!argumentsOnStack) 183 jit.store64(argumentsGPR, CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot)); 184 jit.store64(thisGPR, CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot)); 185 148 186 149 unsigned extraStack = sizeof(CallerFrameAndPC) + 187 150 WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)); 188 computeUsedStack(scratchGPR1, 0); 189 jit.subPtr(CCallHelpers::TrustedImm32(extraStack), CCallHelpers::stackPointerRegister); 190 jit.setupArgumentsWithExecState(argumentsGPR, scratchGPR1, CCallHelpers::TrustedImm32(data->firstVarArgOffset)); 191 callWithExceptionCheck(bitwise_cast<void*>(operationSizeFrameForVarargs)); 192 193 jit.move(GPRInfo::returnValueGPR, scratchGPR1); 194 computeUsedStack(scratchGPR2, extraStack); 195 loadArguments(true); 196 emitSetVarargsFrame(jit, scratchGPR1, false, scratchGPR2, scratchGPR2); 197 jit.addPtr(CCallHelpers::TrustedImm32(-extraStack), scratchGPR2, CCallHelpers::stackPointerRegister); 198 jit.setupArgumentsWithExecState(scratchGPR2, argumentsGPR, CCallHelpers::TrustedImm32(data->firstVarArgOffset), scratchGPR1); 199 callWithExceptionCheck(bitwise_cast<void*>(operationSetupVarargsFrame)); 200 201 jit.move(GPRInfo::returnValueGPR, scratchGPR2); 202 203 jit.load64(CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot), thisGPR); 204 jit.load64(CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot), GPRInfo::regT0); 205 206 if (m_node->op() == CallForwardVarargs) 207 haveArguments.link(&jit); 151 152 if (forwarding) { 153 CCallHelpers::JumpList slowCase; 154 computeUsedStack(scratchGPR2, 0); 155 emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, m_node->child2()->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); 156 157 CCallHelpers::Jump done = jit.jump(); 158 slowCase.link(&jit); 159 jit.subPtr(CCallHelpers::TrustedImm32(extraStack), CCallHelpers::stackPointerRegister); 160 jit.setupArgumentsExecState(); 161 callWithExceptionCheck(bitwise_cast<void*>(operationThrowStackOverflowForVarargs)); 162 jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow); 163 164 done.link(&jit); 165 jit.move(calleeGPR, GPRInfo::regT0); 166 } else { 167 // Gotta spill the callee, arguments, and this because we will need them later and we will have some 168 // calls that clobber them. 169 jit.store64(calleeGPR, CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot)); 170 jit.store64(argumentsGPR, CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot)); 171 jit.store64(thisGPR, CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot)); 172 173 computeUsedStack(scratchGPR1, 0); 174 jit.subPtr(CCallHelpers::TrustedImm32(extraStack), CCallHelpers::stackPointerRegister); 175 jit.setupArgumentsWithExecState(argumentsGPR, scratchGPR1, CCallHelpers::TrustedImm32(data->firstVarArgOffset)); 176 callWithExceptionCheck(bitwise_cast<void*>(operationSizeFrameForVarargs)); 177 178 jit.move(GPRInfo::returnValueGPR, scratchGPR1); 179 computeUsedStack(scratchGPR2, extraStack); 180 jit.load64(CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot), argumentsGPR); 181 emitSetVarargsFrame(jit, scratchGPR1, false, scratchGPR2, scratchGPR2); 182 jit.addPtr(CCallHelpers::TrustedImm32(-extraStack), scratchGPR2, CCallHelpers::stackPointerRegister); 183 jit.setupArgumentsWithExecState(scratchGPR2, argumentsGPR, CCallHelpers::TrustedImm32(data->firstVarArgOffset), scratchGPR1); 184 callWithExceptionCheck(bitwise_cast<void*>(operationSetupVarargsFrame)); 185 186 jit.move(GPRInfo::returnValueGPR, scratchGPR2); 187 188 jit.load64(CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot), thisGPR); 189 jit.load64(CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot), GPRInfo::regT0); 190 } 208 191 209 192 jit.addPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), scratchGPR2, CCallHelpers::stackPointerRegister); -
trunk/Source/JavaScriptCore/ftl/FTLJSCallVarargs.h
r180279 r181993 36 36 37 37 namespace DFG { 38 class Graph;39 38 struct Node; 40 39 } … … 51 50 static unsigned numSpillSlotsNeeded(); 52 51 53 void emit(CCallHelpers&, DFG::Graph&,int32_t spillSlotsOffset);52 void emit(CCallHelpers&, int32_t spillSlotsOffset); 54 53 void link(VM&, LinkBuffer&, CodeLocationLabel exceptionHandler); 55 54 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r181891 r181993 33 33 #include "DFGInPlaceAbstractState.h" 34 34 #include "DFGOSRAvailabilityAnalysisPhase.h" 35 #include "DirectArguments.h" 35 36 #include "FTLAbstractHeapRepository.h" 36 37 #include "FTLAvailableRecovery.h" … … 44 45 #include "FTLWeightedTarget.h" 45 46 #include "JSCInlines.h" 47 #include "JSLexicalEnvironment.h" 46 48 #include "OperandsInlines.h" 49 #include "ScopedArguments.h" 50 #include "ScopedArgumentsTable.h" 47 51 #include "VirtualRegister.h" 48 52 #include <atomic> … … 168 172 } 169 173 } 170 171 LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal)); 172 174 173 175 if (maxNumberOfArguments >= 0) { 174 176 m_execState = m_out.alloca(arrayType(m_out.int64, JSStack::CallFrameHeaderSize + maxNumberOfArguments)); … … 176 178 } 177 179 180 LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal)); 181 178 182 m_captured = m_out.add( 179 183 m_out.ptrToInt(capturedAlloca, m_out.intPtr), 180 184 m_out.constIntPtr(m_graph.m_nextMachineLocal * sizeof(Register))); 181 182 // We should not create any alloca's after this point, since they will cease to183 // be mem2reg candidates.184 185 185 186 m_ftlState.capturedStackmapID = m_stackmapIDs++; … … 196 197 case CallForwardVarargs: 197 198 case ConstructVarargs: 199 case ConstructForwardVarargs: 198 200 hasVarargs = true; 199 201 break; … … 211 213 m_out.int32Zero, varargsSpillSlots); 212 214 } 215 216 // We should not create any alloca's after this point, since they will cease to 217 // be mem2reg candidates. 213 218 214 219 m_callFrame = m_out.ptrToInt( … … 435 440 compileInt52Constant(); 436 441 break; 437 case PhantomArguments:438 compilePhantomArguments();439 break;440 442 case DoubleRep: 441 443 compileDoubleRep(); … … 461 463 case PutStack: 462 464 compilePutStack(); 463 break;464 case GetMyArgumentsLength:465 compileGetMyArgumentsLength();466 break;467 case GetMyArgumentByVal:468 compileGetMyArgumentByVal();469 465 break; 470 466 case Phantom: … … 593 589 compileGetByVal(); 594 590 break; 591 case GetMyArgumentByVal: 592 compileGetMyArgumentByVal(); 593 break; 595 594 case PutByVal: 596 595 case PutByValAlias: … … 604 603 compileArrayPop(); 605 604 break; 605 case CreateActivation: 606 compileCreateActivation(); 607 break; 608 case NewFunction: 609 compileNewFunction(); 610 break; 611 case CreateDirectArguments: 612 compileCreateDirectArguments(); 613 break; 614 case CreateScopedArguments: 615 compileCreateScopedArguments(); 616 break; 617 case CreateClonedArguments: 618 compileCreateClonedArguments(); 619 break; 606 620 case NewObject: 607 621 compileNewObject(); … … 671 685 compileGetCallee(); 672 686 break; 687 case GetArgumentCount: 688 compileGetArgumentCount(); 689 break; 673 690 case GetScope: 674 691 compileGetScope(); … … 677 694 compileSkipScope(); 678 695 break; 679 case GetClosureRegisters:680 compileGetClosureRegisters();681 break;682 696 case GetClosureVar: 683 697 compileGetClosureVar(); … … 685 699 case PutClosureVar: 686 700 compilePutClosureVar(); 701 break; 702 case GetFromArguments: 703 compileGetFromArguments(); 704 break; 705 case PutToArguments: 706 compilePutToArguments(); 687 707 break; 688 708 case CompareEq: … … 717 737 case CallForwardVarargs: 718 738 case ConstructVarargs: 739 case ConstructForwardVarargs: 719 740 compileCallOrConstructVarargs(); 720 741 break; 721 742 case LoadVarargs: 722 743 compileLoadVarargs(); 744 break; 745 case ForwardVarargs: 746 compileForwardVarargs(); 723 747 break; 724 748 #if ENABLE(FTL_NATIVE_CALL_INLINING) … … 749 773 case InvalidationPoint: 750 774 compileInvalidationPoint(); 751 break;752 case CheckArgumentsNotCreated:753 compileCheckArgumentsNotCreated();754 775 break; 755 776 case IsUndefined: … … 830 851 case ZombieHint: 831 852 case PhantomNewObject: 853 case PhantomDirectArguments: 854 case PhantomClonedArguments: 832 855 case PutHint: 833 856 case BottomValue: … … 839 862 } 840 863 841 if (!m_state.isValid() ) {864 if (!m_state.isValid() && !m_node->isTerminal()) { 842 865 safelyInvalidateAfterTermination(); 843 866 return false; … … 918 941 } 919 942 920 void compilePhantomArguments()921 {922 setJSValue(m_out.constInt64(JSValue::encode(JSValue())));923 }924 925 943 void compileDoubleRep() 926 944 { … … 1096 1114 StackAccessData* data = m_node->stackAccessData(); 1097 1115 switch (data->format) { 1098 case FlushedJSValue: 1099 case FlushedArguments: { 1116 case FlushedJSValue: { 1100 1117 LValue value = lowJSValue(m_node->child1()); 1101 1118 m_out.store64(value, addressFor(data->machineLocal)); … … 2117 2134 } 2118 2135 2119 void compileGetMyArgumentsLength()2120 {2121 checkArgumentsNotCreated();2122 2123 if (m_node->origin.semantic.inlineCallFrame2124 && !m_node->origin.semantic.inlineCallFrame->isVarargs()) {2125 setInt32(2126 m_out.constInt32(2127 m_node->origin.semantic.inlineCallFrame->arguments.size() - 1));2128 } else {2129 VirtualRegister argumentCountRegister;2130 if (!m_node->origin.semantic.inlineCallFrame)2131 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);2132 else2133 argumentCountRegister = m_node->origin.semantic.inlineCallFrame->argumentCountRegister;2134 setInt32(2135 m_out.add(2136 m_out.load32NonNegative(payloadFor(argumentCountRegister)),2137 m_out.constInt32(-1)));2138 }2139 }2140 2141 void compileGetMyArgumentByVal()2142 {2143 checkArgumentsNotCreated();2144 2145 CodeOrigin codeOrigin = m_node->origin.semantic;2146 2147 LValue index = lowInt32(m_node->child1());2148 2149 LValue limit;2150 if (codeOrigin.inlineCallFrame2151 && !codeOrigin.inlineCallFrame->isVarargs())2152 limit = m_out.constInt32(codeOrigin.inlineCallFrame->arguments.size() - 1);2153 else {2154 VirtualRegister argumentCountRegister;2155 if (!codeOrigin.inlineCallFrame)2156 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);2157 else2158 argumentCountRegister = codeOrigin.inlineCallFrame->argumentCountRegister;2159 limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);2160 }2161 2162 speculate(Uncountable, noValue(), 0, m_out.aboveOrEqual(index, limit));2163 2164 SymbolTable* symbolTable = m_graph.baselineCodeBlockFor(codeOrigin)->symbolTable();2165 if (symbolTable->slowArguments()) {2166 // FIXME: FTL should support activations.2167 // https://bugs.webkit.org/show_bug.cgi?id=1295762168 2169 DFG_CRASH(m_graph, m_node, "Unimplemented");2170 }2171 2172 TypedPointer base;2173 if (codeOrigin.inlineCallFrame) {2174 if (codeOrigin.inlineCallFrame->arguments.size() <= 1) {2175 // We should have already exited due to the bounds check, above. Just tell the2176 // compiler that anything dominated by this instruction is not reachable, so2177 // that we don't waste time generating such code. This will also plant some2178 // kind of crashing instruction so that if by some fluke the bounds check didn't2179 // work, we'll crash in an easy-to-see way.2180 didAlreadyTerminate();2181 return;2182 }2183 base = addressFor(codeOrigin.inlineCallFrame->arguments[1].virtualRegister());2184 } else2185 base = addressFor(virtualRegisterForArgument(1));2186 2187 LValue pointer = m_out.baseIndex(2188 base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight);2189 setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)));2190 }2191 2192 2136 void compileGetArrayLength() 2193 2137 { … … 2203 2147 LValue string = lowCell(m_node->child1()); 2204 2148 setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length)); 2149 return; 2150 } 2151 2152 case Array::DirectArguments: { 2153 LValue arguments = lowCell(m_node->child1()); 2154 speculate( 2155 ExoticObjectMode, noValue(), nullptr, 2156 m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_overrides))); 2157 setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length)); 2158 return; 2159 } 2160 2161 case Array::ScopedArguments: { 2162 LValue arguments = lowCell(m_node->child1()); 2163 speculate( 2164 ExoticObjectMode, noValue(), nullptr, 2165 m_out.notZero8(m_out.loadPtr(arguments, m_heaps.ScopedArguments_overrodeThings))); 2166 setInt32(m_out.load32NonNegative(arguments, m_heaps.ScopedArguments_totalLength)); 2205 2167 return; 2206 2168 } … … 2323 2285 } 2324 2286 2287 case Array::DirectArguments: { 2288 LValue base = lowCell(m_node->child1()); 2289 LValue index = lowInt32(m_node->child2()); 2290 2291 speculate( 2292 ExoticObjectMode, noValue(), nullptr, 2293 m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_overrides))); 2294 speculate( 2295 ExoticObjectMode, noValue(), nullptr, 2296 m_out.aboveOrEqual( 2297 index, 2298 m_out.load32NonNegative(base, m_heaps.DirectArguments_length))); 2299 2300 TypedPointer address = m_out.baseIndex( 2301 m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index)); 2302 setJSValue(m_out.load64(address)); 2303 return; 2304 } 2305 2306 case Array::ScopedArguments: { 2307 LValue base = lowCell(m_node->child1()); 2308 LValue index = lowInt32(m_node->child2()); 2309 2310 speculate( 2311 ExoticObjectMode, noValue(), nullptr, 2312 m_out.aboveOrEqual( 2313 index, 2314 m_out.load32NonNegative(base, m_heaps.ScopedArguments_totalLength))); 2315 2316 LValue table = m_out.loadPtr(base, m_heaps.ScopedArguments_table); 2317 LValue namedLength = m_out.load32(table, m_heaps.ScopedArgumentsTable_length); 2318 2319 LBasicBlock namedCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments named case")); 2320 LBasicBlock overflowCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments overflow case")); 2321 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments continuation")); 2322 2323 m_out.branch( 2324 m_out.aboveOrEqual(index, namedLength), unsure(overflowCase), unsure(namedCase)); 2325 2326 LBasicBlock lastNext = m_out.appendTo(namedCase, overflowCase); 2327 2328 LValue scope = m_out.loadPtr(base, m_heaps.ScopedArguments_scope); 2329 LValue arguments = m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments); 2330 2331 TypedPointer address = m_out.baseIndex( 2332 m_heaps.scopedArgumentsTableArguments, arguments, m_out.zeroExtPtr(index)); 2333 LValue scopeOffset = m_out.load32(address); 2334 2335 speculate( 2336 ExoticObjectMode, noValue(), nullptr, 2337 m_out.equal(scopeOffset, m_out.constInt32(ScopeOffset::invalidOffset))); 2338 2339 address = m_out.baseIndex( 2340 m_heaps.JSEnvironmentRecord_variables, scope, m_out.zeroExtPtr(scopeOffset)); 2341 ValueFromBlock namedResult = m_out.anchor(m_out.load64(address)); 2342 m_out.jump(continuation); 2343 2344 m_out.appendTo(overflowCase, continuation); 2345 2346 address = m_out.baseIndex( 2347 m_heaps.ScopedArguments_overflowStorage, base, 2348 m_out.zeroExtPtr(m_out.sub(index, namedLength))); 2349 LValue overflowValue = m_out.load64(address); 2350 speculate(ExoticObjectMode, noValue(), nullptr, m_out.isZero64(overflowValue)); 2351 ValueFromBlock overflowResult = m_out.anchor(overflowValue); 2352 m_out.jump(continuation); 2353 2354 m_out.appendTo(continuation, lastNext); 2355 setJSValue(m_out.phi(m_out.int64, namedResult, overflowResult)); 2356 return; 2357 } 2358 2325 2359 case Array::Generic: { 2326 2360 setJSValue(vmCall( … … 2347 2381 storage, 2348 2382 m_out.shl( 2349 m_out.zeroExt (index, m_out.intPtr),2383 m_out.zeroExtPtr(index), 2350 2384 m_out.constIntPtr(logElementSize(type))))); 2351 2385 … … 2419 2453 } 2420 2454 2455 void compileGetMyArgumentByVal() 2456 { 2457 InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame; 2458 2459 LValue index = lowInt32(m_node->child2()); 2460 2461 LValue limit; 2462 if (inlineCallFrame && !inlineCallFrame->isVarargs()) 2463 limit = m_out.constInt32(inlineCallFrame->arguments.size() - 1); 2464 else { 2465 VirtualRegister argumentCountRegister; 2466 if (!inlineCallFrame) 2467 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 2468 else 2469 argumentCountRegister = inlineCallFrame->argumentCountRegister; 2470 limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One); 2471 } 2472 2473 speculate(ExoticObjectMode, noValue(), 0, m_out.aboveOrEqual(index, limit)); 2474 2475 TypedPointer base; 2476 if (inlineCallFrame) { 2477 if (inlineCallFrame->arguments.size() <= 1) { 2478 // We should have already exited due to the bounds check, above. Just tell the 2479 // compiler that anything dominated by this instruction is not reachable, so 2480 // that we don't waste time generating such code. This will also plant some 2481 // kind of crashing instruction so that if by some fluke the bounds check didn't 2482 // work, we'll crash in an easy-to-see way. 2483 didAlreadyTerminate(); 2484 return; 2485 } 2486 base = addressFor(inlineCallFrame->arguments[1].virtualRegister()); 2487 } else 2488 base = addressFor(virtualRegisterForArgument(1)); 2489 2490 LValue pointer = m_out.baseIndex( 2491 base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight); 2492 setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer))); 2493 } 2494 2421 2495 void compilePutByVal() 2422 2496 { … … 2474 2548 m_node->arrayMode().type() == Array::Int32 ? 2475 2549 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties, 2476 storage, m_out.zeroExt(index, m_out.intPtr), 2477 m_state.forNode(child2).m_value); 2550 storage, m_out.zeroExtPtr(index), m_state.forNode(child2).m_value); 2478 2551 2479 2552 if (m_node->op() == PutByValAlias) { … … 2500 2573 2501 2574 TypedPointer elementPointer = m_out.baseIndex( 2502 m_heaps.indexedDoubleProperties, 2503 storage, m_out.zeroExt(index, m_out.intPtr), 2575 m_heaps.indexedDoubleProperties, storage, m_out.zeroExtPtr(index), 2504 2576 m_state.forNode(child2).m_value); 2505 2577 … … 2715 2787 LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath); 2716 2788 m_out.store( 2717 value, 2718 m_out.baseIndex(heap, storage, m_out.zeroExt(prevLength, m_out.intPtr)), 2719 refType); 2789 value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), refType); 2720 2790 LValue newLength = m_out.add(prevLength, m_out.int32One); 2721 2791 m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength); … … 2770 2840 LValue newLength = m_out.sub(prevLength, m_out.int32One); 2771 2841 m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength); 2772 TypedPointer pointer = m_out.baseIndex( 2773 heap, storage, m_out.zeroExt(newLength, m_out.intPtr)); 2842 TypedPointer pointer = m_out.baseIndex(heap, storage, m_out.zeroExtPtr(newLength)); 2774 2843 if (m_node->arrayMode().type() != Array::Double) { 2775 2844 LValue result = m_out.load64(pointer); … … 2801 2870 return; 2802 2871 } 2872 } 2873 2874 void compileCreateActivation() 2875 { 2876 LValue scope = lowCell(m_node->child1()); 2877 SymbolTable* table = m_graph.symbolTableFor(m_node->origin.semantic); 2878 Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure(); 2879 2880 LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateActivation slow path")); 2881 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateActivation continuation")); 2882 2883 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); 2884 2885 LValue fastObject = allocateObject<JSLexicalEnvironment>( 2886 JSLexicalEnvironment::allocationSize(table), structure, m_out.intPtrZero, slowPath); 2887 2888 // We don't need memory barriers since we just fast-created the activation, so the 2889 // activation must be young. 2890 m_out.storePtr(scope, fastObject, m_heaps.JSScope_next); 2891 m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable); 2892 2893 for (unsigned i = 0; i < table->scopeSize(); ++i) { 2894 m_out.store64( 2895 m_out.constInt64(JSValue::encode(jsUndefined())), 2896 fastObject, m_heaps.JSEnvironmentRecord_variables[i]); 2897 } 2898 2899 ValueFromBlock fastResult = m_out.anchor(fastObject); 2900 m_out.jump(continuation); 2901 2902 m_out.appendTo(slowPath, continuation); 2903 LValue callResult = vmCall( 2904 m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure), 2905 scope, weakPointer(table)); 2906 ValueFromBlock slowResult = m_out.anchor(callResult); 2907 m_out.jump(continuation); 2908 2909 m_out.appendTo(continuation, lastNext); 2910 setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult)); 2911 } 2912 2913 void compileNewFunction() 2914 { 2915 LValue result = vmCall( 2916 m_out.operation(operationNewFunction), m_callFrame, 2917 lowCell(m_node->child1()), weakPointer(m_node->castOperand<FunctionExecutable*>())); 2918 setJSValue(result); 2919 } 2920 2921 void compileCreateDirectArguments() 2922 { 2923 // FIXME: A more effective way of dealing with the argument count and callee is to have 2924 // them be explicit arguments to this node. 2925 // https://bugs.webkit.org/show_bug.cgi?id=142207 2926 2927 Structure* structure = 2928 m_graph.globalObjectFor(m_node->origin.semantic)->directArgumentsStructure(); 2929 2930 unsigned minCapacity = m_graph.baselineCodeBlockFor(m_node->origin.semantic)->numParameters() - 1; 2931 2932 LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments slow path")); 2933 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments continuation")); 2934 2935 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); 2936 2937 ArgumentsLength length = getArgumentsLength(); 2938 2939 LValue fastObject; 2940 if (length.isKnown) { 2941 fastObject = allocateObject<DirectArguments>( 2942 DirectArguments::allocationSize(std::max(length.known, minCapacity)), structure, 2943 m_out.intPtrZero, slowPath); 2944 } else { 2945 LValue size = m_out.add( 2946 m_out.shl(length.value, m_out.constInt32(3)), 2947 m_out.constInt32(DirectArguments::storageOffset())); 2948 2949 size = m_out.select( 2950 m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)), 2951 size, m_out.constInt32(DirectArguments::allocationSize(minCapacity))); 2952 2953 fastObject = allocateVariableSizedObject<DirectArguments>( 2954 size, structure, m_out.intPtrZero, slowPath); 2955 } 2956 2957 m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length); 2958 m_out.store32(m_out.constInt32(minCapacity), fastObject, m_heaps.DirectArguments_minCapacity); 2959 m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_overrides); 2960 m_out.storePtr(getCurrentCallee(), fastObject, m_heaps.DirectArguments_callee); 2961 2962 ValueFromBlock fastResult = m_out.anchor(fastObject); 2963 m_out.jump(continuation); 2964 2965 m_out.appendTo(slowPath, continuation); 2966 LValue callResult = vmCall( 2967 m_out.operation(operationCreateDirectArguments), m_callFrame, weakPointer(structure), 2968 length.value, m_out.constInt32(minCapacity)); 2969 ValueFromBlock slowResult = m_out.anchor(callResult); 2970 m_out.jump(continuation); 2971 2972 m_out.appendTo(continuation, lastNext); 2973 LValue result = m_out.phi(m_out.intPtr, fastResult, slowResult); 2974 2975 if (length.isKnown) { 2976 VirtualRegister start = AssemblyHelpers::argumentsStart(m_node->origin.semantic); 2977 for (unsigned i = 0; i < std::max(length.known, minCapacity); ++i) { 2978 m_out.store64( 2979 m_out.load64(addressFor(start + i)), 2980 result, m_heaps.DirectArguments_storage[i]); 2981 } 2982 } else { 2983 LValue stackBase = getArgumentsStart(); 2984 2985 LBasicBlock loop = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments loop body")); 2986 LBasicBlock end = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments loop end")); 2987 2988 ValueFromBlock originalLength; 2989 if (minCapacity) { 2990 LValue capacity = m_out.select( 2991 m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)), 2992 length.value, 2993 m_out.constInt32(minCapacity)); 2994 originalLength = m_out.anchor(m_out.zeroExtPtr(capacity)); 2995 m_out.jump(loop); 2996 } else { 2997 originalLength = m_out.anchor(m_out.zeroExtPtr(length.value)); 2998 m_out.branch(m_out.isNull(originalLength.value()), unsure(end), unsure(loop)); 2999 } 3000 3001 lastNext = m_out.appendTo(loop, end); 3002 LValue previousIndex = m_out.phi(m_out.intPtr, originalLength); 3003 LValue index = m_out.sub(previousIndex, m_out.intPtrOne); 3004 m_out.store64( 3005 m_out.load64(m_out.baseIndex(m_heaps.variables, stackBase, index)), 3006 m_out.baseIndex(m_heaps.DirectArguments_storage, result, index)); 3007 ValueFromBlock nextIndex = m_out.anchor(index); 3008 addIncoming(previousIndex, nextIndex); 3009 m_out.branch(m_out.isNull(index), unsure(end), unsure(loop)); 3010 3011 m_out.appendTo(end, lastNext); 3012 } 3013 3014 setJSValue(result); 3015 } 3016 3017 void compileCreateScopedArguments() 3018 { 3019 LValue scope = lowCell(m_node->child1()); 3020 3021 LValue result = vmCall( 3022 m_out.operation(operationCreateScopedArguments), m_callFrame, 3023 weakPointer( 3024 m_graph.globalObjectFor(m_node->origin.semantic)->scopedArgumentsStructure()), 3025 getArgumentsStart(), getArgumentsLength().value, getCurrentCallee(), scope); 3026 3027 setJSValue(result); 3028 } 3029 3030 void compileCreateClonedArguments() 3031 { 3032 LValue result = vmCall( 3033 m_out.operation(operationCreateClonedArguments), m_callFrame, 3034 weakPointer( 3035 m_graph.globalObjectFor(m_node->origin.semantic)->outOfBandArgumentsStructure()), 3036 getArgumentsStart(), getArgumentsLength().value, getCurrentCallee()); 3037 3038 setJSValue(result); 2803 3039 } 2804 3040 … … 3268 3504 ValueFromBlock char8Bit = m_out.anchor(m_out.zeroExt( 3269 3505 m_out.load8(m_out.baseIndex( 3270 m_heaps.characters8, 3271 storage, m_out.zeroExt(index, m_out.intPtr), 3506 m_heaps.characters8, storage, m_out.zeroExtPtr(index), 3272 3507 m_state.forNode(m_node->child2()).m_value)), 3273 3508 m_out.int32)); … … 3278 3513 ValueFromBlock char16Bit = m_out.anchor(m_out.zeroExt( 3279 3514 m_out.load16(m_out.baseIndex( 3280 m_heaps.characters16, 3281 storage, m_out.zeroExt(index, m_out.intPtr), 3515 m_heaps.characters16, storage, m_out.zeroExtPtr(index), 3282 3516 m_state.forNode(m_node->child2()).m_value)), 3283 3517 m_out.int32)); … … 3301 3535 3302 3536 results.append(m_out.anchor(m_out.loadPtr(m_out.baseIndex( 3303 m_heaps.singleCharacterStrings, smallStrings, 3304 m_out.zeroExt(character, m_out.intPtr))))); 3537 m_heaps.singleCharacterStrings, smallStrings, m_out.zeroExtPtr(character))))); 3305 3538 m_out.jump(continuation); 3306 3539 … … 3361 3594 ValueFromBlock char8Bit = m_out.anchor(m_out.zeroExt( 3362 3595 m_out.load8(m_out.baseIndex( 3363 m_heaps.characters8, 3364 storage, m_out.zeroExt(index, m_out.intPtr), 3596 m_heaps.characters8, storage, m_out.zeroExtPtr(index), 3365 3597 m_state.forNode(m_node->child2()).m_value)), 3366 3598 m_out.int32)); … … 3371 3603 ValueFromBlock char16Bit = m_out.anchor(m_out.zeroExt( 3372 3604 m_out.load16(m_out.baseIndex( 3373 m_heaps.characters16, 3374 storage, m_out.zeroExt(index, m_out.intPtr), 3605 m_heaps.characters16, storage, m_out.zeroExtPtr(index), 3375 3606 m_state.forNode(m_node->child2()).m_value)), 3376 3607 m_out.int32)); … … 3542 3773 void compileGetGlobalVar() 3543 3774 { 3544 setJSValue(m_out.load64(m_out.absolute(m_node-> registerPointer())));3775 setJSValue(m_out.load64(m_out.absolute(m_node->variablePointer()))); 3545 3776 } 3546 3777 … … 3548 3779 { 3549 3780 m_out.store64( 3550 lowJSValue(m_node->child1()), m_out.absolute(m_node-> registerPointer()));3781 lowJSValue(m_node->child1()), m_out.absolute(m_node->variablePointer())); 3551 3782 } 3552 3783 … … 3586 3817 } 3587 3818 3819 void compileGetArgumentCount() 3820 { 3821 setInt32(m_out.load32(payloadFor(JSStack::ArgumentCount))); 3822 } 3823 3588 3824 void compileGetScope() 3589 3825 { … … 3596 3832 } 3597 3833 3598 void compileGetClosureRegisters()3599 {3600 if (WriteBarrierBase<Unknown>* registers = m_graph.tryGetRegisters(m_node->child1().node())) {3601 setStorage(m_out.constIntPtr(registers));3602 return;3603 }3604 3605 setStorage(m_out.loadPtr(3606 lowCell(m_node->child1()), m_heaps.JSEnvironmentRecord_registers));3607 }3608 3609 3834 void compileGetClosureVar() 3610 3835 { 3611 setJSValue(m_out.load64( 3612 addressFor(lowStorage(m_node->child2()), m_node->varNumber()))); 3836 setJSValue( 3837 m_out.load64( 3838 lowCell(m_node->child1()), 3839 m_heaps.JSEnvironmentRecord_variables[m_node->scopeOffset().offset()])); 3613 3840 } 3614 3841 … … 3616 3843 { 3617 3844 m_out.store64( 3618 lowJSValue(m_node->child3()), 3619 addressFor(lowStorage(m_node->child2()), m_node->varNumber())); 3845 lowJSValue(m_node->child2()), 3846 lowCell(m_node->child1()), 3847 m_heaps.JSEnvironmentRecord_variables[m_node->scopeOffset().offset()]); 3848 } 3849 3850 void compileGetFromArguments() 3851 { 3852 setJSValue( 3853 m_out.load64( 3854 lowCell(m_node->child1()), 3855 m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()])); 3856 } 3857 3858 void compilePutToArguments() 3859 { 3860 m_out.store64( 3861 lowJSValue(m_node->child2()), 3862 lowCell(m_node->child1()), 3863 m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()]); 3620 3864 } 3621 3865 … … 3859 4103 { 3860 4104 LValue jsCallee = lowJSValue(m_node->child1()); 4105 LValue thisArg = lowJSValue(m_node->child3()); 3861 4106 3862 4107 LValue jsArguments = nullptr; 3863 LValue thisArg = nullptr;3864 4108 3865 4109 switch (m_node->op()) { 3866 4110 case CallVarargs: 3867 jsArguments = lowJSValue(m_node->child2());3868 thisArg = lowJSValue(m_node->child3());3869 break;3870 case CallForwardVarargs:3871 thisArg = lowJSValue(m_node->child2());3872 break;3873 4111 case ConstructVarargs: 3874 4112 jsArguments = lowJSValue(m_node->child2()); 3875 thisArg = lowJSValue(m_node->child3()); 4113 break; 4114 case CallForwardVarargs: 4115 case ConstructForwardVarargs: 3876 4116 break; 3877 4117 default: … … 3937 4177 length, m_out.constInt32(data->mandatoryMinimum)); 3938 4178 } 4179 4180 void compileForwardVarargs() 4181 { 4182 LoadVarargsData* data = m_node->loadVarargsData(); 4183 InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame; 4184 4185 LValue length = getArgumentsLength(inlineCallFrame).value; 4186 LValue lengthIncludingThis = m_out.add(length, m_out.constInt32(1 - data->offset)); 4187 4188 speculate( 4189 VarargsOverflow, noValue(), nullptr, 4190 m_out.above(lengthIncludingThis, m_out.constInt32(data->limit))); 4191 4192 m_out.store32(lengthIncludingThis, payloadFor(data->machineCount)); 4193 4194 LValue sourceStart = getArgumentsStart(inlineCallFrame); 4195 LValue targetStart = addressFor(data->machineStart).value(); 4196 4197 LBasicBlock undefinedLoop = FTL_NEW_BLOCK(m_out, ("ForwardVarargs undefined loop body")); 4198 LBasicBlock mainLoopEntry = FTL_NEW_BLOCK(m_out, ("ForwardVarargs main loop entry")); 4199 LBasicBlock mainLoop = FTL_NEW_BLOCK(m_out, ("ForwardVarargs main loop body")); 4200 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ForwardVarargs continuation")); 4201 4202 LValue lengthAsPtr = m_out.zeroExtPtr(length); 4203 ValueFromBlock loopBound = m_out.anchor(m_out.constIntPtr(data->mandatoryMinimum)); 4204 m_out.branch( 4205 m_out.above(loopBound.value(), lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry)); 4206 4207 LBasicBlock lastNext = m_out.appendTo(undefinedLoop, mainLoopEntry); 4208 LValue previousIndex = m_out.phi(m_out.intPtr, loopBound); 4209 LValue currentIndex = m_out.sub(previousIndex, m_out.intPtrOne); 4210 m_out.store64( 4211 m_out.constInt64(JSValue::encode(jsUndefined())), 4212 m_out.baseIndex(m_heaps.variables, targetStart, currentIndex)); 4213 ValueFromBlock nextIndex = m_out.anchor(currentIndex); 4214 addIncoming(previousIndex, nextIndex); 4215 m_out.branch( 4216 m_out.above(currentIndex, lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry)); 4217 4218 m_out.appendTo(mainLoopEntry, mainLoop); 4219 loopBound = m_out.anchor(lengthAsPtr); 4220 m_out.branch(m_out.notNull(loopBound.value()), unsure(mainLoop), unsure(continuation)); 4221 4222 m_out.appendTo(mainLoop, continuation); 4223 previousIndex = m_out.phi(m_out.intPtr, loopBound); 4224 currentIndex = m_out.sub(previousIndex, m_out.intPtrOne); 4225 LValue value = m_out.load64( 4226 m_out.baseIndex( 4227 m_heaps.variables, sourceStart, 4228 m_out.add(currentIndex, m_out.constIntPtr(data->offset)))); 4229 m_out.store64(value, m_out.baseIndex(m_heaps.variables, targetStart, currentIndex)); 4230 nextIndex = m_out.anchor(currentIndex); 4231 addIncoming(previousIndex, nextIndex); 4232 m_out.branch(m_out.isNull(currentIndex), unsure(continuation), unsure(mainLoop)); 4233 4234 m_out.appendTo(continuation, lastNext); 4235 } 3939 4236 3940 4237 void compileJump() … … 4172 4469 } 4173 4470 4174 void compileCheckArgumentsNotCreated()4175 {4176 ASSERT(!isEmptySpeculation(4177 m_state.variables().operand(4178 m_graph.argumentsRegisterFor(m_node->origin.semantic)).m_type));4179 4180 checkArgumentsNotCreated();4181 }4182 4183 4471 void compileIsUndefined() 4184 4472 { … … 4552 4840 LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector); 4553 4841 ValueFromBlock inBoundsResult = m_out.anchor( 4554 m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector, 4555 storage, m_out.signExt(index, m_out.int64), ScaleEight))); 4842 m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index)))); 4556 4843 m_out.jump(continuation); 4557 4844 … … 4579 4866 LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector); 4580 4867 ValueFromBlock inBoundsResult = m_out.anchor( 4581 m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector, 4582 storage, m_out.signExt(index, m_out.int64), ScaleEight))); 4868 m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index)))); 4583 4869 m_out.jump(continuation); 4584 4870 … … 4879 5165 } 4880 5166 5167 struct ArgumentsLength { 5168 ArgumentsLength() 5169 : isKnown(false) 5170 , known(UINT_MAX) 5171 , value(nullptr) 5172 { 5173 } 5174 5175 bool isKnown; 5176 unsigned known; 5177 LValue value; 5178 }; 5179 ArgumentsLength getArgumentsLength(InlineCallFrame* inlineCallFrame) 5180 { 5181 ArgumentsLength length; 5182 5183 if (inlineCallFrame && !inlineCallFrame->isVarargs()) { 5184 length.known = inlineCallFrame->arguments.size() - 1; 5185 length.isKnown = true; 5186 length.value = m_out.constInt32(length.known); 5187 } else { 5188 length.known = UINT_MAX; 5189 length.isKnown = false; 5190 5191 VirtualRegister argumentCountRegister; 5192 if (!inlineCallFrame) 5193 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); 5194 else 5195 argumentCountRegister = inlineCallFrame->argumentCountRegister; 5196 length.value = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One); 5197 } 5198 5199 return length; 5200 } 5201 5202 ArgumentsLength getArgumentsLength() 5203 { 5204 return getArgumentsLength(m_node->origin.semantic.inlineCallFrame); 5205 } 5206 5207 LValue getCurrentCallee() 5208 { 5209 if (InlineCallFrame* frame = m_node->origin.semantic.inlineCallFrame) { 5210 if (frame->isClosureCall) 5211 return m_out.loadPtr(addressFor(frame->calleeRecovery.virtualRegister())); 5212 return weakPointer(frame->calleeRecovery.constant().asCell()); 5213 } 5214 return m_out.loadPtr(addressFor(JSStack::Callee)); 5215 } 5216 5217 LValue getArgumentsStart(InlineCallFrame* inlineCallFrame) 5218 { 5219 VirtualRegister start = AssemblyHelpers::argumentsStart(inlineCallFrame); 5220 return addressFor(start).value(); 5221 } 5222 5223 LValue getArgumentsStart() 5224 { 5225 return getArgumentsStart(m_node->origin.semantic.inlineCallFrame); 5226 } 5227 4881 5228 void checkStructure( 4882 5229 LValue structureID, const FormattedValue& formattedValue, ExitKind exitKind, … … 5099 5446 } 5100 5447 5101 TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue storage, LValue index, Edge edge )5448 TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue storage, LValue index, Edge edge, ptrdiff_t offset = 0) 5102 5449 { 5103 5450 return m_out.baseIndex( 5104 heap, storage, m_out.zeroExt(index, m_out.intPtr), 5105 m_state.forNode(edge).m_value); 5451 heap, storage, m_out.zeroExtPtr(index), m_state.forNode(edge).m_value, offset); 5106 5452 } 5107 5453 … … 5254 5600 5255 5601 template<typename ClassType> 5256 LValue allocateObject( Structure* structure, LValue butterfly, LBasicBlock slowPath)5257 {5258 size_t size = ClassType::allocationSize(0);5602 LValue allocateObject( 5603 size_t size, Structure* structure, LValue butterfly, LBasicBlock slowPath) 5604 { 5259 5605 MarkedAllocator* allocator = &vm().heap.allocatorForObjectOfType<ClassType>(size); 5260 5606 return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, slowPath); 5607 } 5608 5609 template<typename ClassType> 5610 LValue allocateObject(Structure* structure, LValue butterfly, LBasicBlock slowPath) 5611 { 5612 return allocateObject<ClassType>( 5613 ClassType::allocationSize(0), structure, butterfly, slowPath); 5614 } 5615 5616 template<typename ClassType> 5617 LValue allocateVariableSizedObject( 5618 LValue size, Structure* structure, LValue butterfly, LBasicBlock slowPath) 5619 { 5620 static_assert(!(MarkedSpace::preciseStep & (MarkedSpace::preciseStep - 1)), "MarkedSpace::preciseStep must be a power of two."); 5621 static_assert(!(MarkedSpace::impreciseStep & (MarkedSpace::impreciseStep - 1)), "MarkedSpace::impreciseStep must be a power of two."); 5622 5623 LValue subspace = m_out.constIntPtr(&vm().heap.subspaceForObjectOfType<ClassType>()); 5624 5625 LBasicBlock smallCaseBlock = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject small case")); 5626 LBasicBlock largeOrOversizeCaseBlock = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject large or oversize case")); 5627 LBasicBlock largeCaseBlock = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject large case")); 5628 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject continuation")); 5629 5630 LValue uproundedSize = m_out.add(size, m_out.constInt32(MarkedSpace::preciseStep - 1)); 5631 LValue isSmall = m_out.below(uproundedSize, m_out.constInt32(MarkedSpace::preciseCutoff)); 5632 m_out.branch(isSmall, unsure(smallCaseBlock), unsure(largeOrOversizeCaseBlock)); 5633 5634 LBasicBlock lastNext = m_out.appendTo(smallCaseBlock, largeOrOversizeCaseBlock); 5635 TypedPointer address = m_out.baseIndex( 5636 m_heaps.MarkedSpace_Subspace_preciseAllocators, subspace, 5637 m_out.zeroExtPtr(m_out.lShr(uproundedSize, m_out.constInt32(getLSBSet(MarkedSpace::preciseStep))))); 5638 ValueFromBlock smallAllocator = m_out.anchor(address.value()); 5639 m_out.jump(continuation); 5640 5641 m_out.appendTo(largeOrOversizeCaseBlock, largeCaseBlock); 5642 m_out.branch( 5643 m_out.below(uproundedSize, m_out.constInt32(MarkedSpace::impreciseCutoff)), 5644 usually(largeCaseBlock), rarely(slowPath)); 5645 5646 m_out.appendTo(largeCaseBlock, continuation); 5647 address = m_out.baseIndex( 5648 m_heaps.MarkedSpace_Subspace_impreciseAllocators, subspace, 5649 m_out.zeroExtPtr(m_out.lShr(uproundedSize, m_out.constInt32(getLSBSet(MarkedSpace::impreciseStep))))); 5650 ValueFromBlock largeAllocator = m_out.anchor(address.value()); 5651 m_out.jump(continuation); 5652 5653 m_out.appendTo(continuation, lastNext); 5654 LValue allocator = m_out.phi(m_out.intPtr, smallAllocator, largeAllocator); 5655 5656 return allocateObject(allocator, structure, butterfly, slowPath); 5261 5657 } 5262 5658 … … 5664 6060 } 5665 6061 5666 void checkArgumentsNotCreated()5667 {5668 CodeOrigin codeOrigin = m_node->origin.semantic;5669 VirtualRegister argumentsRegister = m_graph.argumentsRegisterFor(codeOrigin);5670 if (isEmptySpeculation(m_state.variables().operand(argumentsRegister).m_type))5671 return;5672 5673 VirtualRegister argsReg = m_graph.machineArgumentsRegisterFor(codeOrigin);5674 speculate(5675 ArgumentsEscaped, noValue(), 0,5676 m_out.notZero64(m_out.load64(addressFor(argsReg))));5677 }5678 5679 6062 void speculate( 5680 6063 ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) … … 6364 6747 } 6365 6748 6749 case Array::DirectArguments: 6750 return m_out.equal( 6751 m_out.load8(cell, m_heaps.JSCell_typeInfoType), 6752 m_out.constInt8(DirectArgumentsType)); 6753 6754 case Array::ScopedArguments: 6755 return m_out.equal( 6756 m_out.load8(cell, m_heaps.JSCell_typeInfoType), 6757 m_out.constInt8(ScopedArgumentsType)); 6758 6366 6759 default: 6367 6760 return m_out.equal( … … 6652 7045 m_out.appendTo(bufferHasSpace, bufferIsFull); 6653 7046 LValue writeBarrierBufferBase = m_out.loadPtr(m_out.absolute(&vm().heap.writeBarrierBuffer().m_buffer)); 6654 m_out.storePtr(base, m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents, writeBarrierBufferBase, m_out.zeroExt (currentBufferIndex, m_out.intPtr), ScalePtr));7047 m_out.storePtr(base, m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents, writeBarrierBufferBase, m_out.zeroExtPtr(currentBufferIndex))); 6655 7048 m_out.store32(m_out.add(currentBufferIndex, m_out.constInt32(1)), m_out.absolute(&vm().heap.writeBarrierBuffer().m_currentIndex)); 6656 7049 m_out.jump(continuation); … … 6790 7183 6791 7184 Node* node = availability.node(); 6792 if (!node->isPhantom ObjectAllocation())7185 if (!node->isPhantomAllocation()) 6793 7186 return; 6794 7187 6795 7188 auto result = map.add(node, nullptr); 6796 if (result.isNewEntry) 6797 result.iterator->value = exit.m_materializations.add(node->op()); 7189 if (result.isNewEntry) { 7190 result.iterator->value = 7191 exit.m_materializations.add(node->op(), node->origin.semantic); 7192 } 6798 7193 }); 6799 7194 … … 6862 7257 case FlushedDouble: 6863 7258 return ExitValue::inJSStackAsDouble(flush.virtualRegister()); 6864 6865 case FlushedArguments:6866 return ExitValue::argumentsObjectThatWasNotCreated();6867 7259 } 6868 7260 … … 6890 7282 return ExitValue::constant(node->asJSValue()); 6891 7283 6892 case PhantomArguments:6893 return ExitValue::argumentsObjectThatWasNotCreated();6894 6895 case PhantomNewObject:6896 return ExitValue::materializeNewObject(map.get(node));6897 6898 7284 default: 7285 if (node->isPhantomAllocation()) 7286 return ExitValue::materializeNewObject(map.get(node)); 6899 7287 break; 6900 7288 } … … 7069 7457 LValue tableBase = m_out.loadPtr( 7070 7458 m_out.absolute(vm().heap.structureIDTable().base())); 7071 LValue pointerIntoTable= m_out.baseIndex(7072 tableBase, m_out.zeroExt(tableIndex, m_out.intPtr), ScaleEight);7073 return m_out.loadPtr( TypedPointer(m_heaps.structureTable, pointerIntoTable));7459 TypedPointer address = m_out.baseIndex( 7460 m_heaps.structureTable, tableBase, m_out.zeroExtPtr(tableIndex)); 7461 return m_out.loadPtr(address); 7074 7462 } 7075 7463 -
trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
r181348 r181993 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 74 74 break; 75 75 76 case ExitValueArgumentsObjectThatWasNotCreated:77 jit.move(MacroAssembler::TrustedImm64(JSValue::encode(JSValue())), GPRInfo::regT0);78 break;79 80 76 case ExitValueRecovery: 81 77 record->locations[value.rightRecoveryArgument()].restoreInto( … … 231 227 232 228 // Materialize all objects. Don't materialize an object until all of the objects it needs 233 // have been materialized. 229 // have been materialized. Curiously, this is the only place that we have an algorithm that prevents 230 // OSR exit from handling cyclic object materializations. Of course, object allocation sinking 231 // currently wouldn't recognize a cycle as being sinkable - but if it did then the only thing that 232 // would ahve to change is this fixpoint. Instead we would allocate the objects first and populate 233 // them with data later. 234 234 HashSet<ExitTimeObjectMaterialization*> toMaterialize; 235 235 for (ExitTimeObjectMaterialization* materialization : exit.m_materializations) … … 444 444 handleExitCounts(jit, exit); 445 445 reifyInlinedCallFrames(jit, exit); 446 447 ArgumentsRecoveryGenerator argumentsRecovery;448 for (unsigned index = exit.m_values.size(); index--;) {449 if (!exit.m_values[index].isArgumentsObjectThatWasNotCreated())450 continue;451 int operand = exit.m_values.operandForIndex(index);452 argumentsRecovery.generateFor(operand, exit.m_codeOrigin, jit);453 }454 455 446 adjustAndJumpToTarget(jit, exit); 456 447 -
trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp
r173993 r181993 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #if ENABLE(FTL_JIT) 30 30 31 #include "ClonedArguments.h" 32 #include "DirectArguments.h" 31 33 #include "JSCInlines.h" 32 34 … … 55 57 DeferGCForAWhile deferGC(vm.heap); 56 58 57 // In the future, we may have many different kinds of materializations. For now we just 58 // materialize NewObject. 59 RELEASE_ASSERT(materialization->type() == PhantomNewObject); 60 61 // First figure out what the structure is. 62 Structure* structure = nullptr; 63 for (unsigned i = materialization->properties().size(); i--;) { 64 const ExitPropertyValue& property = materialization->properties()[i]; 65 if (property.location() != PromotedLocationDescriptor(StructurePLoc)) 66 continue; 67 68 structure = jsCast<Structure*>(JSValue::decode(values[i])); 69 } 70 RELEASE_ASSERT(structure); 71 72 // Let's create that object! 73 JSFinalObject* result = JSFinalObject::create(vm, structure); 74 75 // Now figure out what the heck to populate the object with. Use getPropertiesConcurrently() 76 // because that happens to be lower-level and more convenient. It doesn't change the 77 // materialization of the property table. We want to have minimal visible effects on the 78 // system. Also, don't mind that this is O(n^2). It doesn't matter. We only get here from OSR 79 // exit. 80 for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) { 59 switch (materialization->type()) { 60 case PhantomNewObject: { 61 // First figure out what the structure is. 62 Structure* structure = nullptr; 81 63 for (unsigned i = materialization->properties().size(); i--;) { 82 64 const ExitPropertyValue& property = materialization->properties()[i]; 83 if (property.location() .kind() != NamedPropertyPLoc)65 if (property.location() != PromotedLocationDescriptor(StructurePLoc)) 84 66 continue; 85 if (codeBlock->identifier(property.location().info()).impl() != entry.key) 86 continue; 67 68 structure = jsCast<Structure*>(JSValue::decode(values[i])); 69 break; 70 } 71 RELEASE_ASSERT(structure); 72 73 // Let's create that object! 74 JSFinalObject* result = JSFinalObject::create(vm, structure); 75 76 // Now figure out what the heck to populate the object with. Use getPropertiesConcurrently() 77 // because that happens to be lower-level and more convenient. It doesn't change the 78 // materialization of the property table. We want to have minimal visible effects on the 79 // system. Also, don't mind that this is O(n^2). It doesn't matter. We only get here from OSR 80 // exit. 81 for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) { 82 for (unsigned i = materialization->properties().size(); i--;) { 83 const ExitPropertyValue& property = materialization->properties()[i]; 84 if (property.location().kind() != NamedPropertyPLoc) 85 continue; 86 if (codeBlock->identifier(property.location().info()).impl() != entry.key) 87 continue; 87 88 88 result->putDirect(vm, entry.offset, JSValue::decode(values[i])); 89 result->putDirect(vm, entry.offset, JSValue::decode(values[i])); 90 } 91 } 92 93 return result; 94 } 95 96 case PhantomDirectArguments: 97 case PhantomClonedArguments: { 98 if (!materialization->origin().inlineCallFrame) { 99 switch (materialization->type()) { 100 case PhantomDirectArguments: 101 return DirectArguments::createByCopying(exec); 102 case PhantomClonedArguments: 103 return ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned); 104 default: 105 RELEASE_ASSERT_NOT_REACHED(); 106 return nullptr; 107 } 108 } 109 110 // First figure out the argument count. If there isn't one then we represent the machine frame. 111 unsigned argumentCount = 0; 112 if (materialization->origin().inlineCallFrame->isVarargs()) { 113 for (unsigned i = materialization->properties().size(); i--;) { 114 const ExitPropertyValue& property = materialization->properties()[i]; 115 if (property.location() != PromotedLocationDescriptor(ArgumentCountPLoc)) 116 continue; 117 118 argumentCount = JSValue::decode(values[i]).asUInt32(); 119 RELEASE_ASSERT(argumentCount); 120 break; 121 } 122 RELEASE_ASSERT(argumentCount); 123 } else 124 argumentCount = materialization->origin().inlineCallFrame->arguments.size(); 125 126 JSFunction* callee = nullptr; 127 if (materialization->origin().inlineCallFrame->isClosureCall) { 128 for (unsigned i = materialization->properties().size(); i--;) { 129 const ExitPropertyValue& property = materialization->properties()[i]; 130 if (property.location() != PromotedLocationDescriptor(ArgumentsCalleePLoc)) 131 continue; 132 133 callee = jsCast<JSFunction*>(JSValue::decode(values[i])); 134 break; 135 } 136 } else 137 callee = materialization->origin().inlineCallFrame->calleeConstant(); 138 RELEASE_ASSERT(callee); 139 140 CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock( 141 materialization->origin(), exec->codeBlock()); 142 143 // We have an inline frame and we have all of the data we need to recreate it. 144 switch (materialization->type()) { 145 case PhantomDirectArguments: { 146 unsigned length = argumentCount - 1; 147 unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1)); 148 DirectArguments* result = DirectArguments::create( 149 vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity); 150 result->callee().set(vm, result, callee); 151 for (unsigned i = materialization->properties().size(); i--;) { 152 const ExitPropertyValue& property = materialization->properties()[i]; 153 if (property.location().kind() != ArgumentPLoc) 154 continue; 155 156 unsigned index = property.location().info(); 157 if (index >= capacity) 158 continue; 159 result->setIndexQuickly(vm, index, JSValue::decode(values[i])); 160 } 161 return result; 162 } 163 case PhantomClonedArguments: { 164 unsigned length = argumentCount - 1; 165 ClonedArguments* result = ClonedArguments::createEmpty( 166 vm, codeBlock->globalObject()->outOfBandArgumentsStructure(), callee); 167 168 for (unsigned i = materialization->properties().size(); i--;) { 169 const ExitPropertyValue& property = materialization->properties()[i]; 170 if (property.location().kind() != ArgumentPLoc) 171 continue; 172 173 unsigned index = property.location().info(); 174 if (index >= length) 175 continue; 176 result->putDirectIndex(exec, index, JSValue::decode(values[i])); 177 } 178 179 result->putDirect(vm, vm.propertyNames->length, jsNumber(length)); 180 return result; 181 } 182 default: 183 RELEASE_ASSERT_NOT_REACHED(); 184 return nullptr; 89 185 } 90 186 } 91 92 return result; 187 188 default: 189 RELEASE_ASSERT_NOT_REACHED(); 190 return nullptr; 191 } 93 192 } 94 193 -
trunk/Source/JavaScriptCore/ftl/FTLOutput.h
r181035 r181993 134 134 LValue bitXor(LValue left, LValue right) { return buildXor(m_builder, left, right); } 135 135 LValue shl(LValue left, LValue right) { return buildShl(m_builder, left, right); } 136 LValue aShr(LValue left, LValue right) { return buildAShr(m_builder, left, right); } 137 LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); } 136 LValue aShr(LValue left, LValue right) { return buildAShr(m_builder, left, right); } // arithmetic = signed 137 LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); } // logical = unsigned 138 138 LValue bitNot(LValue value) { return buildNot(m_builder, value); } 139 139 … … 203 203 LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); } 204 204 LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); } 205 LValue zeroExtPtr(LValue value) { return zeroExt(value, intPtr); } 205 206 LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); } 206 207 LValue fpToUInt(LValue value, LType type) { return buildFPToUI(m_builder, value, type); } … … 218 219 LValue bitCast(LValue value, LType type) { return buildBitCast(m_builder, value, type); } 219 220 221 // Hilariously, the #define machinery in the stdlib means that this method is actually called 222 // __builtin_alloca. So far this appears benign. :-| 220 223 LValue alloca(LType type) { return buildAlloca(m_builder, type); } 221 224 -
trunk/Source/JavaScriptCore/heap/CopyToken.h
r174795 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 TypedArrayVectorCopyToken, 34 34 MapBackingStoreCopyToken, 35 ArgumentsSlowArgumentDataCopyToken35 DirectArgumentsOverridesCopyToken 36 36 }; 37 37 -
trunk/Source/JavaScriptCore/interpreter/CallFrame.h
r179862 r181993 240 240 } 241 241 242 JSValue getArgumentUnsafe(size_t argIndex) 243 { 244 // User beware! This method does not verify that there is a valid 245 // argument at the specified argIndex. This is used for debugging 246 // and verification code only. The caller is expected to know what 247 // he/she is doing when calling this method. 248 return this[argumentOffset(argIndex)].jsValue(); 249 } 250 242 251 static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); } 243 252 JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); } … … 296 305 } 297 306 298 JSValue getArgumentUnsafe(size_t argIndex)299 {300 // User beware! This method does not verify that there is a valid301 // argument at the specified argIndex. This is used for debugging302 // and verification code only. The caller is expected to know what303 // he/she is doing when calling this method.304 return this[argumentOffset(argIndex)].jsValue();305 }306 307 307 void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; } 308 308 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r181889 r181993 31 31 #include "Interpreter.h" 32 32 33 #include "Arguments.h"34 33 #include "BatchedTransitionOptimizer.h" 35 34 #include "CallFrameClosure.h" 36 35 #include "CallFrameInlines.h" 36 #include "ClonedArguments.h" 37 37 #include "CodeBlock.h" 38 #include "DirectArguments.h" 38 39 #include "Heap.h" 39 40 #include "Debugger.h" … … 45 46 #include "JSArray.h" 46 47 #include "JSBoundFunction.h" 48 #include "JSCInlines.h" 47 49 #include "JSLexicalEnvironment.h" 48 50 #include "JSNameScope.h" … … 56 58 #include "LiteralParser.h" 57 59 #include "ObjectPrototype.h" 58 #include "JSCInlines.h"59 60 #include "Parser.h" 60 61 #include "ProtoCallFrame.h" … … 63 64 #include "Register.h" 64 65 #include "SamplingTool.h" 66 #include "ScopedArguments.h" 65 67 #include "StackAlignment.h" 66 68 #include "StackVisitor.h" … … 137 139 unsigned sizeOfVarargs(CallFrame* callFrame, JSValue arguments, uint32_t firstVarArgOffset) 138 140 { 141 if (UNLIKELY(!arguments.isCell())) { 142 if (arguments.isUndefinedOrNull()) 143 return 0; 144 145 callFrame->vm().throwException(callFrame, createInvalidFunctionApplyParameterError(callFrame, arguments)); 146 return 0; 147 } 148 149 JSCell* cell = arguments.asCell(); 139 150 unsigned length; 140 if (!arguments) 141 length = callFrame->argumentCount(); 142 else if (arguments.isUndefinedOrNull()) 143 length = 0; 144 else if (!arguments.isObject()) { 151 switch (cell->type()) { 152 case DirectArgumentsType: 153 length = jsCast<DirectArguments*>(cell)->length(callFrame); 154 break; 155 case ScopedArgumentsType: 156 length =jsCast<ScopedArguments*>(cell)->length(callFrame); 157 break; 158 case StringType: 145 159 callFrame->vm().throwException(callFrame, createInvalidFunctionApplyParameterError(callFrame, arguments)); 146 160 return 0; 147 } else if (asObject(arguments)->classInfo() == Arguments::info()) 148 length = asArguments(arguments)->length(callFrame); 149 else if (isJSArray(arguments)) 150 length = asArray(arguments)->length(); 151 else 152 length = asObject(arguments)->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); 161 default: 162 ASSERT(arguments.isObject()); 163 if (isJSArray(cell)) 164 length = jsCast<JSArray*>(cell)->length(); 165 else 166 length = jsCast<JSObject*>(cell)->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); 167 break; 168 } 153 169 154 170 if (length >= firstVarArgOffset) … … 165 181 166 182 CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1); 167 if (length > Arguments::MaxArguments || !stack->ensureCapacityFor(calleeFrame->registers())) {183 if (length > maxArguments || !stack->ensureCapacityFor(calleeFrame->registers())) { 168 184 throwStackOverflowError(callFrame); 169 185 return 0; … … 175 191 void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue arguments, uint32_t offset, uint32_t length) 176 192 { 177 if (!arguments) { // f.apply(x, arguments), with arguments unmodified. 178 for (size_t i = 0; i < length; ++i) 179 callFrame->r(firstElementDest + i) = callFrame->argumentAfterCapture(i + offset); 193 if (UNLIKELY(!arguments.isCell())) 180 194 return; 181 } 182 183 if (arguments.isUndefinedOrNull()) 195 196 JSCell* cell = arguments.asCell(); 197 switch (cell->type()) { 198 case DirectArgumentsType: 199 jsCast<DirectArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length); 184 200 return; 185 186 if (asObject(arguments)->classInfo() == Arguments::info()) { 187 asArguments(arguments)->copyToArguments(callFrame, firstElementDest, offset, length); 201 case ScopedArgumentsType: 202 jsCast<ScopedArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length); 188 203 return; 189 } 190 191 if (isJSArray(arguments)) { 192 asArray(arguments)->copyToArguments(callFrame, firstElementDest, offset, length); 204 default: { 205 ASSERT(arguments.isObject()); 206 JSObject* object = jsCast<JSObject*>(cell); 207 if (isJSArray(object)) { 208 jsCast<JSArray*>(object)->copyToArguments(callFrame, firstElementDest, offset, length); 209 return; 210 } 211 unsigned i; 212 for (i = 0; i < length && object->canGetIndexQuickly(i + offset); ++i) 213 callFrame->r(firstElementDest + i) = object->getIndexQuickly(i + offset); 214 for (; i < length; ++i) 215 callFrame->r(firstElementDest + i) = object->get(callFrame, i + offset); 193 216 return; 194 } 195 196 for (unsigned i = 0; i < length; ++i) { 197 callFrame->r(firstElementDest + i) = asObject(arguments)->get(callFrame, i + offset); 198 if (UNLIKELY(callFrame->vm().exception())) 199 return; 200 } 217 } } 201 218 } 202 219 … … 385 402 debugger->didExecuteProgram(callFrame); 386 403 ASSERT(!callFrame->hadException()); 387 }388 389 if (CodeBlock* codeBlock = visitor->codeBlock()) {390 if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) {391 #if ENABLE(DFG_JIT)392 RELEASE_ASSERT(!visitor->isInlinedFrame());393 #endif394 }395 396 if (codeBlock->codeType() == FunctionCode && codeBlock->usesArguments()) {397 if (Arguments* arguments = visitor->existingArguments()) {398 #if ENABLE(DFG_JIT)399 if (visitor->isInlinedFrame())400 arguments->tearOff(callFrame, visitor->inlineCallFrame());401 else402 #endif403 arguments->tearOff(callFrame);404 }405 }406 404 } 407 405 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.h
r180279 r181993 310 310 311 311 unsigned sizeOfVarargs(CallFrame* exec, JSValue arguments, uint32_t firstVarArgOffset); 312 static const unsigned maxArguments = 0x10000; 312 313 unsigned sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset); 313 314 void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length); -
trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp
r180279 r181993 27 27 #include "StackVisitor.h" 28 28 29 #include "Arguments.h"30 29 #include "CallFrameInlines.h" 30 #include "ClonedArguments.h" 31 31 #include "Executable.h" 32 32 #include "Interpreter.h" … … 256 256 } 257 257 258 Arguments* StackVisitor::Frame::createArguments()258 ClonedArguments* StackVisitor::Frame::createArguments() 259 259 { 260 260 ASSERT(m_callFrame); 261 261 CallFrame* physicalFrame = m_callFrame; 262 VM& vm = physicalFrame->vm(); 263 Arguments* arguments; 262 ClonedArguments* arguments; 264 263 ArgumentsMode mode; 265 264 if (Options::enableFunctionDotArguments()) 266 mode = ClonedArgumentsCreationMode;265 mode = ArgumentsMode::Cloned; 267 266 else 268 mode = FakeArgumentValuesCreationMode;267 mode = ArgumentsMode::FakeValues; 269 268 #if ENABLE(DFG_JIT) 270 269 if (isInlinedFrame()) { 271 270 ASSERT(m_inlineCallFrame); 272 arguments = Arguments::create(vm, physicalFrame, m_inlineCallFrame, mode); 273 arguments->tearOff(physicalFrame, m_inlineCallFrame); 274 jsCast<Arguments*>((JSCell*)arguments); 271 arguments = ClonedArguments::createWithInlineFrame(physicalFrame, physicalFrame, m_inlineCallFrame, mode); 275 272 } else 276 273 #endif 277 { 278 JSLexicalEnvironment* lexicalEnvironment = nullptr; 279 arguments = Arguments::create(vm, physicalFrame, lexicalEnvironment, mode); 280 arguments->tearOff(physicalFrame); 281 } 274 arguments = ClonedArguments::createWithMachineFrame(physicalFrame, physicalFrame, mode); 282 275 return arguments; 283 }284 285 Arguments* StackVisitor::Frame::existingArguments()286 {287 if (codeBlock()->codeType() != FunctionCode)288 return 0;289 if (!codeBlock()->usesArguments())290 return 0;291 292 VirtualRegister reg;293 294 #if ENABLE(DFG_JIT)295 if (isInlinedFrame())296 reg = inlineCallFrame()->argumentsRegister;297 else298 #endif // ENABLE(DFG_JIT)299 reg = codeBlock()->argumentsRegister();300 301 // Care should be taken here since exception fuzzing may raise exceptions in302 // places where they would be otherwise impossible. Therefore, callFrame may303 // lack activation even if the codeBlock signals need of activation. Also,304 // even if codeBlock signals the use of arguments, the305 // unmodifiedArgumentsRegister may not be initialized yet (neither locally306 // nor in lexicalEnvironment).307 JSValue result = jsUndefined();308 if (codeBlock()->needsActivation() && callFrame()->hasActivation())309 result = callFrame()->lexicalEnvironment()->registerAt(unmodifiedArgumentsRegister(reg).offset()).get();310 if (!result || !result.isCell()) // Try local unmodifiedArgumentsRegister if lexicalEnvironment is not present (generally possible) or has not set up registers yet (only possible if fuzzing exceptions).311 result = callFrame()->r(unmodifiedArgumentsRegister(reg).offset()).jsValue();312 if (!result || !result.isCell()) // Protect against the case when exception fuzzing throws when unmodifiedArgumentsRegister is not set up yet (e.g., in op_enter).313 return 0;314 return jsCast<Arguments*>(result);315 276 } 316 277 -
trunk/Source/JavaScriptCore/interpreter/StackVisitor.h
r176479 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 35 35 struct InlineCallFrame; 36 36 37 class Arguments;38 37 class CodeBlock; 39 38 class ExecState; … … 41 40 class JSObject; 42 41 class JSScope; 42 class ClonedArguments; 43 43 class Register; 44 44 … … 79 79 JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column); 80 80 81 Arguments* createArguments(); 82 Arguments* existingArguments(); 81 ClonedArguments* createArguments(); 83 82 VMEntryFrame* vmEntryFrame() const { return m_VMEntryFrame; } 84 83 CallFrame* callFrame() const { return m_callFrame; } -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r180279 r181993 89 89 } 90 90 91 void storeValue(JSValueRegs regs, BaseIndex address) 92 { 93 #if USE(JSVALUE64) 94 store64(regs.gpr(), address); 95 #else 96 store32(regs.payloadGPR(), address.withOffset(PayloadOffset)); 97 store32(regs.tagGPR(), address.withOffset(TagOffset)); 98 #endif 99 } 100 91 101 void storeValue(JSValueRegs regs, void* address) 92 102 { … … 114 124 } 115 125 126 void loadValue(BaseIndex address, JSValueRegs regs) 127 { 128 #if USE(JSVALUE64) 129 load64(address, regs.gpr()); 130 #else 131 if (address.base == regs.payloadGPR() || address.index == regs.payloadGPR()) { 132 // We actually could handle the case where the registers are aliased to both 133 // tag and payload, but we don't for now. 134 RELEASE_ASSERT(address.base != regs.tagGPR()); 135 RELEASE_ASSERT(address.index != regs.tagGPR()); 136 137 load32(address.withOffset(TagOffset), regs.tagGPR()); 138 load32(address.withOffset(PayloadOffset), regs.payloadGPR()); 139 } else { 140 load32(address.withOffset(PayloadOffset), regs.payloadGPR()); 141 load32(address.withOffset(TagOffset), regs.tagGPR()); 142 } 143 #endif 144 } 145 116 146 void moveTrustedValue(JSValue value, JSValueRegs regs) 117 147 { … … 121 151 move(TrustedImm32(value.tag()), regs.tagGPR()); 122 152 move(TrustedImm32(value.payload()), regs.payloadGPR()); 153 #endif 154 } 155 156 void storeTrustedValue(JSValue value, Address address) 157 { 158 #if USE(JSVALUE64) 159 store64(TrustedImm64(JSValue::encode(value)), address); 160 #else 161 store32(TrustedImm32(value.tag()), address.withOffset(TagOffset)); 162 store32(TrustedImm32(value.payload()), address.withOffset(PayloadOffset)); 163 #endif 164 } 165 166 void storeTrustedValue(JSValue value, BaseIndex address) 167 { 168 #if USE(JSVALUE64) 169 store64(TrustedImm64(JSValue::encode(value)), address); 170 #else 171 store32(TrustedImm32(value.tag()), address.withOffset(TagOffset)); 172 store32(TrustedImm32(value.payload()), address.withOffset(PayloadOffset)); 123 173 #endif 124 174 } … … 325 375 #else 326 376 return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag)); 377 #endif 378 } 379 Jump branchIfNotCell(JSValueRegs regs) 380 { 381 #if USE(JSVALUE64) 382 return branchIfNotCell(regs.gpr()); 383 #else 384 return branchIfNotCell(regs.tagGPR()); 385 #endif 386 } 387 388 Jump branchIsEmpty(JSValueRegs regs) 389 { 390 #if USE(JSVALUE64) 391 return branchTest64(Zero, regs.gpr()); 392 #else 393 return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::EmptyValueTag)); 327 394 #endif 328 395 } … … 635 702 } 636 703 637 VirtualRegister baselineArgumentsRegisterFor(InlineCallFrame* inlineCallFrame) 704 SymbolTable* symbolTableFor(const CodeOrigin& codeOrigin) 705 { 706 return baselineCodeBlockFor(codeOrigin)->symbolTable(); 707 } 708 709 static VirtualRegister argumentsStart(InlineCallFrame* inlineCallFrame) 638 710 { 639 711 if (!inlineCallFrame) 640 return baselineCodeBlock()->argumentsRegister(); 641 642 return VirtualRegister(baselineCodeBlockForInlineCallFrame( 643 inlineCallFrame)->argumentsRegister().offset() + inlineCallFrame->stackOffset); 644 } 645 646 VirtualRegister baselineArgumentsRegisterFor(const CodeOrigin& codeOrigin) 647 { 648 return baselineArgumentsRegisterFor(codeOrigin.inlineCallFrame); 649 } 650 651 SymbolTable* symbolTableFor(const CodeOrigin& codeOrigin) 652 { 653 return baselineCodeBlockFor(codeOrigin)->symbolTable(); 654 } 655 656 int offsetOfLocals(const CodeOrigin& codeOrigin) 657 { 658 if (!codeOrigin.inlineCallFrame) 659 return 0; 660 return codeOrigin.inlineCallFrame->stackOffset * sizeof(Register); 661 } 662 663 int offsetOfArguments(InlineCallFrame* inlineCallFrame) 664 { 665 if (!inlineCallFrame) 666 return CallFrame::argumentOffset(0) * sizeof(Register); 712 return VirtualRegister(CallFrame::argumentOffset(0)); 667 713 if (inlineCallFrame->arguments.size() <= 1) 668 return 0;714 return virtualRegisterForLocal(0); 669 715 ValueRecovery recovery = inlineCallFrame->arguments[1]; 670 716 RELEASE_ASSERT(recovery.technique() == DisplacedInJSStack); 671 return recovery.virtualRegister() .offset() * sizeof(Register);672 } 673 674 int offsetOfArguments(const CodeOrigin& codeOrigin)675 { 676 return offsetOfArguments(codeOrigin.inlineCallFrame);717 return recovery.virtualRegister(); 718 } 719 720 static VirtualRegister argumentsStart(const CodeOrigin& codeOrigin) 721 { 722 return argumentsStart(codeOrigin.inlineCallFrame); 677 723 } 678 724 -
trunk/Source/JavaScriptCore/jit/CCallHelpers.h
r180938 r181993 34 34 namespace JSC { 35 35 36 #if CPU(MIPS) || (OS(WINDOWS) && CPU(X86_64)) 37 #define POKE_ARGUMENT_OFFSET 4 38 #else 39 #define POKE_ARGUMENT_OFFSET 0 40 #endif 41 36 42 class CCallHelpers : public AssemblyHelpers { 37 43 public: … … 39 45 : AssemblyHelpers(vm, codeBlock) 40 46 { 47 } 48 49 // The most general helper for setting arguments that fit in a GPR, if you can compute each 50 // argument without using any argument registers. You usually want one of the setupArguments*() 51 // methods below instead of this. This thing is most useful if you have *a lot* of arguments. 52 template<typename Functor> 53 void setupArgument(unsigned argumentIndex, const Functor& functor) 54 { 55 unsigned numberOfRegs = GPRInfo::numberOfArgumentRegisters; // Disguise the constant from clang's tautological compare warning. 56 if (argumentIndex < numberOfRegs) { 57 functor(GPRInfo::toArgumentRegister(argumentIndex)); 58 return; 59 } 60 61 functor(GPRInfo::nonArgGPR0); 62 poke(GPRInfo::nonArgGPR0, POKE_ARGUMENT_OFFSET + argumentIndex - GPRInfo::numberOfArgumentRegisters); 41 63 } 42 64 … … 864 886 } 865 887 866 #if CPU(MIPS) || (OS(WINDOWS) && CPU(X86_64))867 #define POKE_ARGUMENT_OFFSET 4868 #else869 #define POKE_ARGUMENT_OFFSET 0870 #endif871 872 888 #if CPU(X86_64) || CPU(ARM64) 873 889 ALWAYS_INLINE void setupArguments(FPRReg arg1) -
trunk/Source/JavaScriptCore/jit/GPRInfo.h
r180279 r181993 1 1 /* 2 * Copyright (C) 2011, 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 55 55 } 56 56 57 static JSValueRegs withTwoAvailableRegs(GPRReg gpr, GPRReg) 58 { 59 return JSValueRegs(gpr); 60 } 61 57 62 bool operator!() const { return m_gpr == InvalidGPRReg; } 58 63 … … 145 150 , m_payloadGPR(payloadGPR) 146 151 { 152 } 153 154 static JSValueRegs withTwoAvailableRegs(GPRReg gpr1, GPRReg gpr2) 155 { 156 return JSValueRegs(gpr1, gpr2); 147 157 } 148 158 … … 324 334 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 }; 325 335 return registerForIndex[index]; 336 } 337 338 static GPRReg toArgumentRegister(unsigned) 339 { 340 UNREACHABLE_FOR_PLATFORM(); 341 return InvalidGPRReg; 326 342 } 327 343 … … 495 511 ASSERT(index < numberOfRegisters); 496 512 static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 }; 513 return registerForIndex[index]; 514 } 515 516 static GPRReg toArgumentRegister(unsigned index) 517 { 518 ASSERT(index < numberOfArgumentRegisters); 519 static const GPRReg registerForIndex[numberOfArgumentRegisters] = { argumentGPR0, argumentGPR1, argumentGPR2, argumentGPR3 }; 497 520 return registerForIndex[index]; 498 521 } -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r181990 r181993 203 203 DEFINE_OP(op_create_this) 204 204 DEFINE_OP(op_to_this) 205 DEFINE_OP(op_create_direct_arguments) 206 DEFINE_OP(op_create_scoped_arguments) 207 DEFINE_OP(op_create_out_of_band_arguments) 205 208 DEFINE_OP(op_check_tdz) 206 DEFINE_OP(op_init_lazy_reg)207 DEFINE_OP(op_create_arguments)208 209 DEFINE_OP(op_debug) 209 210 DEFINE_OP(op_del_by_id) … … 218 219 case op_get_array_length: 219 220 DEFINE_OP(op_get_by_id) 220 DEFINE_OP(op_get_arguments_length)221 221 DEFINE_OP(op_get_by_val) 222 DEFINE_OP(op_get_argument_by_val)223 222 DEFINE_OP(op_check_has_instance) 224 223 DEFINE_OP(op_instanceof) … … 292 291 DEFINE_OP(op_switch_imm) 293 292 DEFINE_OP(op_switch_string) 294 DEFINE_OP(op_tear_off_arguments)295 293 DEFINE_OP(op_throw) 296 294 DEFINE_OP(op_throw_static_error) … … 301 299 DEFINE_OP(op_get_from_scope) 302 300 DEFINE_OP(op_put_to_scope) 301 DEFINE_OP(op_get_from_arguments) 302 DEFINE_OP(op_put_to_arguments) 303 303 304 304 DEFINE_OP(op_get_enumerable_length) … … 385 385 case op_get_array_length: 386 386 DEFINE_SLOWCASE_OP(op_get_by_id) 387 DEFINE_SLOWCASE_OP(op_get_arguments_length)388 387 DEFINE_SLOWCASE_OP(op_get_by_val) 389 DEFINE_SLOWCASE_OP(op_get_argument_by_val)390 388 DEFINE_SLOWCASE_OP(op_check_has_instance) 391 389 DEFINE_SLOWCASE_OP(op_instanceof) -
trunk/Source/JavaScriptCore/jit/JIT.h
r181891 r181993 347 347 JumpList emitContiguousGetByVal(Instruction*, PatchableJump& badType, IndexingType expectedShape = ContiguousShape); 348 348 JumpList emitArrayStorageGetByVal(Instruction*, PatchableJump& badType); 349 JumpList emitDirectArgumentsGetByVal(Instruction*, PatchableJump& badType); 350 JumpList emitScopedArgumentsGetByVal(Instruction*, PatchableJump& badType); 349 351 JumpList emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType); 350 352 JumpList emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType); … … 469 471 void emit_op_create_this(Instruction*); 470 472 void emit_op_to_this(Instruction*); 473 void emit_op_create_direct_arguments(Instruction*); 474 void emit_op_create_scoped_arguments(Instruction*); 475 void emit_op_create_out_of_band_arguments(Instruction*); 471 476 void emit_op_check_tdz(Instruction*); 472 void emit_op_create_arguments(Instruction*);473 477 void emit_op_debug(Instruction*); 474 478 void emit_op_del_by_id(Instruction*); … … 621 625 void emit_op_get_from_scope(Instruction*); 622 626 void emit_op_put_to_scope(Instruction*); 627 void emit_op_get_from_arguments(Instruction*); 628 void emit_op_put_to_arguments(Instruction*); 623 629 void emitSlow_op_resolve_scope(Instruction*, Vector<SlowCaseEntry>::iterator&); 624 630 void emitSlow_op_get_from_scope(Instruction*, Vector<SlowCaseEntry>::iterator&); … … 698 704 MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, const Identifier*); 699 705 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg); 706 MacroAssembler::Call callOperation(C_JITOperation_EJsc, GPRReg); 700 707 MacroAssembler::Call callOperation(J_JITOperation_EJscC, int, GPRReg, JSCell*); 701 708 MacroAssembler::Call callOperation(C_JITOperation_EJscZ, GPRReg, int32_t); -
trunk/Source/JavaScriptCore/jit/JITCall.cpp
r180279 r181993 30 30 #include "JIT.h" 31 31 32 #include "Arguments.h"33 32 #include "CodeBlock.h" 34 33 #include "JITInlines.h" … … 63 62 int firstVarArgOffset = instruction[6].u.operand; 64 63 65 JumpList slowCase;66 JumpList end;67 bool canOptimize = m_codeBlock->usesArguments()68 && arguments == m_codeBlock->argumentsRegister().offset()69 && !m_codeBlock->symbolTable()->slowArguments();70 71 if (canOptimize) {72 emitGetVirtualRegister(arguments, regT0);73 slowCase.append(branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(JSValue()))));74 75 move(TrustedImm32(-firstFreeRegister), regT1);76 emitSetupVarargsFrameFastCase(*this, regT1, regT0, regT1, regT2, firstVarArgOffset, slowCase);77 end.append(jump());78 slowCase.link(this);79 }80 81 64 emitGetVirtualRegister(arguments, regT1); 82 65 callOperation(operationSizeFrameForVarargs, regT1, -firstFreeRegister, firstVarArgOffset); … … 88 71 move(returnValueGPR, regT1); 89 72 90 if (canOptimize)91 end.link(this);92 93 73 // Profile the argument count. 94 74 load32(Address(regT1, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset), regT2); -
trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp
r180279 r181993 30 30 #include "JIT.h" 31 31 32 #include "Arguments.h"33 32 #include "CodeBlock.h" 34 33 #include "Interpreter.h" … … 123 122 int firstVarArgOffset = instruction[6].u.operand; 124 123 125 JumpList slowCase;126 JumpList end;127 bool canOptimize = m_codeBlock->usesArguments()128 && VirtualRegister(arguments) == m_codeBlock->argumentsRegister()129 && !m_codeBlock->symbolTable()->slowArguments();130 131 if (canOptimize) {132 emitLoadTag(arguments, regT1);133 slowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)));134 135 move(TrustedImm32(-firstFreeRegister), regT1);136 emitSetupVarargsFrameFastCase(*this, regT1, regT0, regT1, regT2, firstVarArgOffset, slowCase);137 end.append(jump());138 slowCase.link(this);139 }140 141 124 emitLoad(arguments, regT1, regT0); 142 125 callOperation(operationSizeFrameForVarargs, regT1, regT0, -firstFreeRegister, firstVarArgOffset); … … 147 130 callOperation(operationSetupVarargsFrame, regT1, regT2, regT4, firstVarArgOffset, regT0); 148 131 move(returnValueGPR, regT1); 149 150 if (canOptimize)151 end.link(this);152 132 153 133 // Profile the argument count. -
trunk/Source/JavaScriptCore/jit/JITInlines.h
r181343 r181993 194 194 } 195 195 196 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EJsc operation, GPRReg arg1) 197 { 198 setupArgumentsWithExecState(arg1); 199 return appendCallWithExceptionCheck(operation); 200 } 201 196 202 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EJscZ operation, GPRReg arg1, int32_t arg2) 197 203 { -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r181891 r181993 29 29 #include "JIT.h" 30 30 31 #include "Arguments.h"32 31 #include "BasicBlockLocation.h" 33 32 #include "CopiedSpaceInlines.h" … … 246 245 } 247 246 248 void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)249 {250 int arguments = currentInstruction[1].u.operand;251 int lexicalEnvironment = currentInstruction[2].u.operand;252 253 Jump argsNotCreated = branchTest64(Zero, Address(callFrameRegister, sizeof(Register) * (VirtualRegister(arguments).offset())));254 emitGetVirtualRegister(VirtualRegister(arguments).offset(), regT0);255 emitGetVirtualRegister(lexicalEnvironment, regT1);256 callOperation(operationTearOffArguments, regT0, regT1);257 argsNotCreated.link(this);258 }259 260 247 void JIT::emit_op_ret(Instruction* currentInstruction) 261 248 { … … 678 665 679 666 emitGetVirtualRegister(scope, regT0); 680 callOperation(operationCreateActivation, regT0 , 0);667 callOperation(operationCreateActivation, regT0); 681 668 emitStoreCell(dst, returnValueGPR); 682 669 emitStoreCell(scope, returnValueGPR); … … 689 676 loadPtr(Address(regT0, JSFunction::offsetOfScopeChain()), regT0); 690 677 emitStoreCell(dst, regT0); 691 }692 693 void JIT::emit_op_create_arguments(Instruction* currentInstruction)694 {695 int dst = currentInstruction[1].u.operand;696 int lexicalEnvironment = currentInstruction[2].u.operand;697 698 Jump argsCreated = branchTest64(NonZero, Address(callFrameRegister, sizeof(Register) * dst));699 700 if (VirtualRegister(lexicalEnvironment).isValid()) {701 emitGetVirtualRegister(lexicalEnvironment, regT0);702 callOperation(operationCreateArguments, regT0);703 } else704 callOperation(operationCreateArguments, TrustedImmPtr(nullptr));705 emitStoreCell(dst, returnValueGPR);706 emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(dst)), returnValueGPR);707 708 argsCreated.link(this);709 }710 711 void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction)712 {713 int dst = currentInstruction[1].u.operand;714 715 store64(TrustedImm64((int64_t)0), Address(callFrameRegister, sizeof(Register) * dst));716 678 } 717 679 … … 914 876 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_number); 915 877 slowPathCall.call(); 916 }917 918 void JIT::emit_op_get_arguments_length(Instruction* currentInstruction)919 {920 int dst = currentInstruction[1].u.operand;921 int argumentsRegister = currentInstruction[2].u.operand;922 addSlowCase(branchTest64(NonZero, addressFor(argumentsRegister)));923 emitGetFromCallFrameHeader32(JSStack::ArgumentCount, regT0);924 sub32(TrustedImm32(1), regT0);925 emitFastArithReTagImmediate(regT0, regT0);926 emitPutVirtualRegister(dst, regT0);927 }928 929 void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)930 {931 linkSlowCase(iter);932 int dst = currentInstruction[1].u.operand;933 int base = currentInstruction[2].u.operand;934 callOperation(operationGetArgumentsLength, dst, base);935 }936 937 void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)938 {939 int dst = currentInstruction[1].u.operand;940 int argumentsRegister = currentInstruction[2].u.operand;941 int property = currentInstruction[3].u.operand;942 addSlowCase(branchTest64(NonZero, addressFor(argumentsRegister)));943 emitGetVirtualRegister(property, regT1);944 addSlowCase(emitJumpIfNotImmediateInteger(regT1));945 emitGetFromCallFrameHeader32(JSStack::ArgumentCount, regT2);946 sub32(TrustedImm32(1), regT2);947 addSlowCase(branch32(AboveOrEqual, regT1, regT2));948 949 signExtend32ToPtr(regT1, regT1);950 load64(BaseIndex(callFrameRegister, regT1, TimesEight, CallFrame::argumentOffset(0) * static_cast<int>(sizeof(Register))), regT0);951 emitValueProfilingSite();952 emitPutVirtualRegister(dst, regT0);953 }954 955 void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)956 {957 int dst = currentInstruction[1].u.operand;958 int arguments = currentInstruction[2].u.operand;959 int property = currentInstruction[3].u.operand;960 int lexicalEnvironment = currentInstruction[4].u.operand;961 962 linkSlowCase(iter);963 Jump skipArgumentsCreation = jump();964 965 linkSlowCase(iter);966 linkSlowCase(iter);967 if (VirtualRegister(lexicalEnvironment).isValid()) {968 emitGetVirtualRegister(lexicalEnvironment, regT0);969 callOperation(operationCreateArguments, regT0);970 } else971 callOperation(operationCreateArguments, TrustedImmPtr(nullptr));972 emitStoreCell(arguments, returnValueGPR);973 emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(arguments)), returnValueGPR);974 975 skipArgumentsCreation.link(this);976 emitGetVirtualRegister(arguments, regT0);977 emitGetVirtualRegister(property, regT1);978 callOperation(WithProfile, operationGetByValGeneric, dst, regT0, regT1);979 878 } 980 879 … … 1043 942 Jump lazyJump; 1044 943 int dst = currentInstruction[1].u.operand; 1045 if (currentInstruction[4].u.operand) {1046 #if USE(JSVALUE32_64)1047 lazyJump = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));1048 #else1049 lazyJump = branchTest64(NonZero, addressFor(dst));1050 #endif1051 }1052 944 1053 945 #if USE(JSVALUE64) … … 1058 950 FunctionExecutable* funcExec = m_codeBlock->functionDecl(currentInstruction[3].u.operand); 1059 951 callOperation(operationNewFunction, dst, regT0, funcExec); 1060 1061 if (currentInstruction[4].u.operand)1062 lazyJump.link(this);1063 952 } 1064 953 … … 1435 1324 } 1436 1325 1326 void JIT::emit_op_create_direct_arguments(Instruction* currentInstruction) 1327 { 1328 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_direct_arguments); 1329 slowPathCall.call(); 1330 } 1331 1332 void JIT::emit_op_create_scoped_arguments(Instruction* currentInstruction) 1333 { 1334 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_scoped_arguments); 1335 slowPathCall.call(); 1336 } 1337 1338 void JIT::emit_op_create_out_of_band_arguments(Instruction* currentInstruction) 1339 { 1340 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_out_of_band_arguments); 1341 slowPathCall.call(); 1342 } 1343 1437 1344 } // namespace JSC 1438 1345 -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r181891 r181993 350 350 } 351 351 352 void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)353 {354 VirtualRegister arguments = VirtualRegister(currentInstruction[1].u.operand);355 int lexicalEnvironment = currentInstruction[2].u.operand;356 357 Jump argsNotCreated = branch32(Equal, tagFor(arguments.offset()), TrustedImm32(JSValue::EmptyValueTag));358 emitLoadPayload(arguments.offset(), regT0);359 emitLoadPayload(lexicalEnvironment, regT1);360 callOperation(operationTearOffArguments, regT0, regT1);361 argsNotCreated.link(this);362 }363 364 352 void JIT::emit_op_to_primitive(Instruction* currentInstruction) 365 353 { … … 910 898 911 899 emitLoadPayload(currentInstruction[2].u.operand, regT0); 912 callOperation(operationCreateActivation, regT0 , 0);900 callOperation(operationCreateActivation, regT0); 913 901 emitStoreCell(lexicalEnvironment, returnValueGPR); 914 902 emitStoreCell(scope, returnValueGPR); … … 921 909 loadPtr(Address(regT0, JSFunction::offsetOfScopeChain()), regT0); 922 910 emitStoreCell(dst, regT0); 923 }924 925 void JIT::emit_op_create_arguments(Instruction* currentInstruction)926 {927 int dst = currentInstruction[1].u.operand;928 int lexicalEnvironment = currentInstruction[2].u.operand;929 930 Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));931 932 if (VirtualRegister(lexicalEnvironment).isValid()) {933 emitLoadPayload(lexicalEnvironment, regT0);934 callOperation(operationCreateArguments, regT0);935 } else936 callOperation(operationCreateArguments, TrustedImmPtr(nullptr));937 emitStoreCell(dst, returnValueGPR);938 emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(dst)).offset(), returnValueGPR);939 940 argsCreated.link(this);941 }942 943 void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction)944 {945 int dst = currentInstruction[1].u.operand;946 947 emitStore(dst, JSValue());948 911 } 949 912 … … 1027 990 callOperation(operationProfileDidCall, regT1, regT0); 1028 991 profilerDone.link(this); 1029 }1030 1031 void JIT::emit_op_get_arguments_length(Instruction* currentInstruction)1032 {1033 int dst = currentInstruction[1].u.operand;1034 int argumentsRegister = currentInstruction[2].u.operand;1035 addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag)));1036 load32(payloadFor(JSStack::ArgumentCount), regT0);1037 sub32(TrustedImm32(1), regT0);1038 emitStoreInt32(dst, regT0);1039 }1040 1041 void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)1042 {1043 linkSlowCase(iter);1044 int dst = currentInstruction[1].u.operand;1045 int base = currentInstruction[2].u.operand;1046 callOperation(operationGetArgumentsLength, dst, base);1047 }1048 1049 void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)1050 {1051 int dst = currentInstruction[1].u.operand;1052 int argumentsRegister = currentInstruction[2].u.operand;1053 int property = currentInstruction[3].u.operand;1054 addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag)));1055 emitLoad(property, regT1, regT2);1056 addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));1057 // regT2 now contains the integer index of the argument we want, including this1058 load32(payloadFor(JSStack::ArgumentCount), regT3);1059 sub32(TrustedImm32(1), regT3);1060 addSlowCase(branch32(AboveOrEqual, regT2, regT3));1061 1062 loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + CallFrame::argumentOffset(0) * static_cast<int>(sizeof(Register))), regT0);1063 loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + CallFrame::argumentOffset(0) * static_cast<int>(sizeof(Register))), regT1);1064 emitValueProfilingSite();1065 emitStore(dst, regT1, regT0);1066 }1067 1068 void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)1069 {1070 int dst = currentInstruction[1].u.operand;1071 int arguments = currentInstruction[2].u.operand;1072 int property = currentInstruction[3].u.operand;1073 int lexicalEnvironment = currentInstruction[4].u.operand;1074 1075 linkSlowCase(iter);1076 Jump skipArgumentsCreation = jump();1077 1078 linkSlowCase(iter);1079 linkSlowCase(iter);1080 1081 if (VirtualRegister(lexicalEnvironment).isValid()) {1082 emitLoadPayload(lexicalEnvironment, regT0);1083 callOperation(operationCreateArguments, regT0);1084 } else1085 callOperation(operationCreateArguments, TrustedImmPtr(nullptr));1086 emitStoreCell(arguments, returnValueGPR);1087 emitStoreCell(unmodifiedArgumentsRegister(VirtualRegister(arguments)).offset(), returnValueGPR);1088 1089 skipArgumentsCreation.link(this);1090 emitLoad(arguments, regT1, regT0);1091 emitLoad(property, regT3, regT2);1092 callOperation(WithProfile, operationGetByValGeneric, dst, regT1, regT0, regT3, regT2);1093 992 } 1094 993 -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r181891 r181993 29 29 #if ENABLE(JIT) 30 30 31 #include "Arguments.h"32 31 #include "ArrayConstructor.h" 33 32 #include "DFGCompilationMode.h" … … 48 47 #include "JSFunctionNameScope.h" 49 48 #include "JSGlobalObjectFunctions.h" 49 #include "JSLexicalEnvironment.h" 50 50 #include "JSNameScope.h" 51 51 #include "JSPropertyNameEnumerator.h" … … 531 531 // Attempt to optimize. 532 532 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm)); 533 if ( arrayMode != byValInfo.arrayMode) {533 if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) { 534 534 JIT::compilePutByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode); 535 535 didOptimize = true; … … 576 576 // Attempt to optimize. 577 577 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm)); 578 if ( arrayMode != byValInfo.arrayMode) {578 if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) { 579 579 JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode); 580 580 didOptimize = true; … … 733 733 else 734 734 linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers); 735 735 736 return reinterpret_cast<char*>(codePtr.executableAddress()); 736 737 } … … 1354 1355 } 1355 1356 1356 JSCell* JIT_OPERATION operationCreateActivation(ExecState* exec, JSScope* currentScope , int32_t offset)1357 { 1358 VM& vm = exec->vm(); 1359 NativeCallFrameTracer tracer(&vm, exec); 1360 JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, exec->registers() + offset,currentScope, exec->codeBlock());1357 JSCell* JIT_OPERATION operationCreateActivation(ExecState* exec, JSScope* currentScope) 1358 { 1359 VM& vm = exec->vm(); 1360 NativeCallFrameTracer tracer(&vm, exec); 1361 JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, currentScope, exec->codeBlock()); 1361 1362 return lexicalEnvironment; 1362 }1363 1364 // FIXME: This is a temporary thunk for the DFG until we add the lexicalEnvironment operand to the DFG CreateArguments node.1365 JSCell* JIT_OPERATION operationCreateArgumentsForDFG(ExecState* exec)1366 {1367 JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr();1368 return operationCreateArguments(exec, lexicalEnvironment);1369 }1370 1371 JSCell* JIT_OPERATION operationCreateArguments(ExecState* exec, JSLexicalEnvironment* lexicalEnvironment)1372 {1373 VM& vm = exec->vm();1374 NativeCallFrameTracer tracer(&vm, exec);1375 // NB: This needs to be exceedingly careful with top call frame tracking, since it1376 // may be called from OSR exit, while the state of the call stack is bizarre.1377 Arguments* result = Arguments::create(vm, exec, lexicalEnvironment);1378 ASSERT(!vm.exception());1379 return result;1380 }1381 1382 JSCell* JIT_OPERATION operationCreateArgumentsDuringOSRExit(ExecState* exec)1383 {1384 DeferGCForAWhile(exec->vm().heap);1385 JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr();1386 return operationCreateArguments(exec, lexicalEnvironment);1387 }1388 1389 EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)1390 {1391 VM& vm = exec->vm();1392 NativeCallFrameTracer tracer(&vm, exec);1393 // Here we can assume that the argumernts were created. Because otherwise the JIT code would1394 // have not made this call.1395 Identifier ident(&vm, "length");1396 JSValue baseValue = exec->uncheckedR(argumentsRegister).jsValue();1397 PropertySlot slot(baseValue);1398 return JSValue::encode(baseValue.get(exec, ident, slot));1399 1363 } 1400 1364 … … 1566 1530 } 1567 1531 1568 void JIT_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell*)1569 {1570 ASSERT(exec->codeBlock()->usesArguments());1571 jsCast<Arguments*>(argumentsCell)->tearOff(exec);1572 }1573 1574 1532 EncodedJSValue JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encodedBase, const Identifier* identifier) 1575 1533 { … … 1735 1693 if (modeAndType.type() == LocalClosureVar) { 1736 1694 JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope); 1737 environment-> registerAt(pc[6].u.operand).set(vm, environment, value);1695 environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value); 1738 1696 if (VariableWatchpointSet* set = pc[5].u.watchpointSet) 1739 1697 set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>"); … … 1796 1754 1797 1755 JSValue value = exec->r(pc[2].u.operand).jsValue(); 1798 pc[1].u. registerPointer->set(*vm, exec->codeBlock()->globalObject(), value);1756 pc[1].u.variablePointer->set(*vm, exec->codeBlock()->globalObject(), value); 1799 1757 } 1800 1758 -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r181891 r181993 66 66 F: CallFrame* 67 67 I: StringImpl* 68 Icf: InlineCal LFrame*68 Icf: InlineCallFrame* 69 69 Idc: const Identifier* 70 70 J: EncodedJSValue 71 71 Jcp: const JSValue* 72 72 Jsc: JSScope* 73 Jsf: JSFunction* 73 74 Jss: JSString* 74 75 L: JSLexicalEnvironment* … … 130 131 typedef JSCell* JIT_OPERATION (*C_JITOperation_EIcf)(ExecState*, InlineCallFrame*); 131 132 typedef JSCell* JIT_OPERATION (*C_JITOperation_EJ)(ExecState*, EncodedJSValue); 133 typedef JSCell* JIT_OPERATION (*C_JITOperation_EJsc)(ExecState*, JSScope*); 132 134 typedef JSCell* JIT_OPERATION (*C_JITOperation_EJscC)(ExecState*, JSScope*, JSCell*); 133 135 typedef JSCell* JIT_OPERATION (*C_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t); … … 142 144 typedef JSCell* JIT_OPERATION (*C_JITOperation_EOZ)(ExecState*, JSObject*, int32_t); 143 145 typedef JSCell* JIT_OPERATION (*C_JITOperation_ESt)(ExecState*, Structure*); 146 typedef JSCell* JIT_OPERATION (*C_JITOperation_EStJscSymtab)(ExecState*, Structure*, JSScope*, SymbolTable*); 147 typedef JSCell* JIT_OPERATION (*C_JITOperation_EStRZJsfL)(ExecState*, Structure*, Register*, int32_t, JSFunction*, JSLexicalEnvironment*); 148 typedef JSCell* JIT_OPERATION (*C_JITOperation_EStRZJsf)(ExecState*, Structure*, Register*, int32_t, JSFunction*); 149 typedef JSCell* JIT_OPERATION (*C_JITOperation_EStZ)(ExecState*, Structure*, int32_t); 150 typedef JSCell* JIT_OPERATION (*C_JITOperation_EStZZ)(ExecState*, Structure*, int32_t, int32_t); 144 151 typedef JSCell* JIT_OPERATION (*C_JITOperation_EZ)(ExecState*, int32_t); 145 152 typedef double JIT_OPERATION (*D_JITOperation_D)(double); … … 294 301 void JIT_OPERATION operationProfileWillCall(ExecState*, EncodedJSValue) WTF_INTERNAL; 295 302 EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState*, EncodedJSValue, EncodedJSValue baseVal) WTF_INTERNAL; 296 JSCell* JIT_OPERATION operationCreateActivation(ExecState*, JSScope* currentScope, int32_t offset) WTF_INTERNAL; 297 JSCell* JIT_OPERATION operationCreateArgumentsForDFG(ExecState*) WTF_INTERNAL; // FIXME: This is a temporary thunk for the DFG until we add the lexicalEnvironment operand to the DFG CreateArguments node. 298 JSCell* JIT_OPERATION operationCreateArguments(ExecState*, JSLexicalEnvironment*) WTF_INTERNAL; 299 JSCell* JIT_OPERATION operationCreateArgumentsDuringOSRExit(ExecState*) WTF_INTERNAL; 300 EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL; 303 JSCell* JIT_OPERATION operationCreateActivation(ExecState*, JSScope* currentScope) WTF_INTERNAL; 301 304 EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL; 302 305 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL; … … 304 307 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL; 305 308 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL; 306 void JIT_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;307 309 EncodedJSValue JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, const Identifier*) WTF_INTERNAL; 308 310 JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r181831 r181993 1 1 /* 2 * Copyright (C) 2008, 2009, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 31 31 #include "CodeBlock.h" 32 #include "DirectArguments.h" 32 33 #include "GCAwareJITStubRoutine.h" 33 34 #include "GetterSetter.h" … … 41 42 #include "ResultType.h" 42 43 #include "SamplingTool.h" 44 #include "ScopedArguments.h" 45 #include "ScopedArgumentsTable.h" 43 46 #include <wtf/StringPrintStream.h> 44 47 … … 665 668 { 666 669 emitGetVirtualRegister(scope, regT0); 667 loadPtr(Address(regT0, JSEnvironmentRecord::offsetOfRegisters()), regT0); 668 loadPtr(Address(regT0, operand * sizeof(Register)), regT0); 670 loadPtr(Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register)), regT0); 669 671 } 670 672 … … 749 751 emitGetVirtualRegister(value, regT1); 750 752 emitGetVirtualRegister(scope, regT0); 751 loadPtr(Address(regT0, JSEnvironmentRecord::offsetOfRegisters()), regT0);752 753 emitNotifyWrite(regT1, regT2, set); 753 storePtr(regT1, Address(regT0, operand * sizeof(Register)));754 storePtr(regT1, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register))); 754 755 } 755 756 … … 806 807 } 807 808 809 void JIT::emit_op_get_from_arguments(Instruction* currentInstruction) 810 { 811 int dst = currentInstruction[1].u.operand; 812 int arguments = currentInstruction[2].u.operand; 813 int index = currentInstruction[3].u.operand; 814 815 emitGetVirtualRegister(arguments, regT0); 816 load64(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>)), regT0); 817 emitValueProfilingSite(); 818 emitPutVirtualRegister(dst); 819 } 820 821 void JIT::emit_op_put_to_arguments(Instruction* currentInstruction) 822 { 823 int arguments = currentInstruction[1].u.operand; 824 int index = currentInstruction[2].u.operand; 825 int value = currentInstruction[3].u.operand; 826 827 emitWriteBarrier(arguments, value, ShouldFilterValue); 828 829 emitGetVirtualRegister(arguments, regT0); 830 emitGetVirtualRegister(value, regT1); 831 store64(regT1, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>))); 832 } 833 808 834 void JIT::emit_op_init_global_const(Instruction* currentInstruction) 809 835 { … … 811 837 emitWriteBarrier(globalObject, currentInstruction[2].u.operand, ShouldFilterValue); 812 838 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); 813 store64(regT0, currentInstruction[1].u. registerPointer);839 store64(regT0, currentInstruction[1].u.variablePointer); 814 840 } 815 841 … … 951 977 case JITArrayStorage: 952 978 slowCases = emitArrayStorageGetByVal(currentInstruction, badType); 979 break; 980 case JITDirectArguments: 981 slowCases = emitDirectArgumentsGetByVal(currentInstruction, badType); 982 break; 983 case JITScopedArguments: 984 slowCases = emitScopedArgumentsGetByVal(currentInstruction, badType); 953 985 break; 954 986 default: … … 1045 1077 repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code())); 1046 1078 repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(isDirect ? operationDirectPutByValGeneric : operationPutByValGeneric)); 1079 } 1080 1081 JIT::JumpList JIT::emitDirectArgumentsGetByVal(Instruction*, PatchableJump& badType) 1082 { 1083 JumpList slowCases; 1084 1085 #if USE(JSVALUE64) 1086 RegisterID base = regT0; 1087 RegisterID property = regT1; 1088 JSValueRegs result = JSValueRegs(regT0); 1089 RegisterID scratch = regT3; 1090 #else 1091 RegisterID base = regT0; 1092 RegisterID property = regT2; 1093 JSValueRegs result = JSValueRegs(regT1, regT0); 1094 RegisterID scratch = regT3; 1095 #endif 1096 1097 load8(Address(base, JSCell::typeInfoTypeOffset()), scratch); 1098 badType = patchableBranch32(NotEqual, scratch, TrustedImm32(DirectArgumentsType)); 1099 1100 slowCases.append(branch32(AboveOrEqual, property, Address(base, DirectArguments::offsetOfLength()))); 1101 slowCases.append(branchTestPtr(NonZero, Address(base, DirectArguments::offsetOfOverrides()))); 1102 1103 zeroExtend32ToPtr(property, scratch); 1104 loadValue(BaseIndex(base, scratch, TimesEight, DirectArguments::storageOffset()), result); 1105 1106 return slowCases; 1107 } 1108 1109 JIT::JumpList JIT::emitScopedArgumentsGetByVal(Instruction*, PatchableJump& badType) 1110 { 1111 JumpList slowCases; 1112 1113 #if USE(JSVALUE64) 1114 RegisterID base = regT0; 1115 RegisterID property = regT1; 1116 JSValueRegs result = JSValueRegs(regT0); 1117 RegisterID scratch = regT3; 1118 RegisterID scratch2 = regT4; 1119 #else 1120 RegisterID base = regT0; 1121 RegisterID property = regT2; 1122 JSValueRegs result = JSValueRegs(regT1, regT0); 1123 RegisterID scratch = regT3; 1124 RegisterID scratch2 = regT4; 1125 #endif 1126 1127 load8(Address(base, JSCell::typeInfoTypeOffset()), scratch); 1128 badType = patchableBranch32(NotEqual, scratch, TrustedImm32(DirectArgumentsType)); 1129 slowCases.append(branch32(AboveOrEqual, property, Address(base, ScopedArguments::offsetOfTotalLength()))); 1130 1131 loadPtr(Address(base, ScopedArguments::offsetOfTable()), scratch); 1132 load32(Address(scratch, ScopedArgumentsTable::offsetOfLength()), scratch2); 1133 Jump overflowCase = branch32(AboveOrEqual, property, scratch2); 1134 loadPtr(Address(base, ScopedArguments::offsetOfScope()), scratch2); 1135 loadPtr(Address(scratch, ScopedArgumentsTable::offsetOfArguments()), scratch); 1136 load32(BaseIndex(scratch, property, TimesFour), scratch); 1137 slowCases.append(branch32(Equal, scratch, TrustedImm32(ScopeOffset::invalidOffset))); 1138 loadValue(BaseIndex(scratch2, scratch, TimesEight, JSEnvironmentRecord::offsetOfVariables()), result); 1139 Jump done = jump(); 1140 overflowCase.link(this); 1141 sub32(property, scratch2); 1142 neg32(scratch2); 1143 loadValue(BaseIndex(base, scratch2, TimesEight, ScopedArguments::overflowStorageOffset()), result); 1144 slowCases.append(branchIsEmpty(result)); 1145 done.link(this); 1146 1147 return slowCases; 1047 1148 } 1048 1149 -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r181831 r181993 1 1 /* 2 * Copyright (C) 2008, 2009, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 31 31 32 32 #include "CodeBlock.h" 33 #include "DirectArguments.h" 33 34 #include "GCAwareJITStubRoutine.h" 34 35 #include "Interpreter.h" … … 689 690 { 690 691 emitLoad(scope, regT1, regT0); 691 loadPtr(Address(regT0, JSEnvironmentRecord::offsetOfRegisters()), regT0); 692 load32(Address(regT0, operand * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), regT1); 693 load32(Address(regT0, operand * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), regT0); 692 load32(Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + TagOffset), regT1); 693 load32(Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + PayloadOffset), regT0); 694 694 } 695 695 … … 781 781 emitLoad(scope, regT1, regT0); 782 782 emitNotifyWrite(regT3, regT2, regT4, set); 783 loadPtr(Address(regT0, JSEnvironmentRecord::offsetOfRegisters()), regT0); 784 store32(regT3, Address(regT0, operand * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 785 store32(regT2, Address(regT0, operand * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); 783 store32(regT3, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + TagOffset)); 784 store32(regT2, Address(regT0, JSEnvironmentRecord::offsetOfVariables() + operand * sizeof(Register) + PayloadOffset)); 786 785 } 787 786 … … 836 835 } 837 836 837 void JIT::emit_op_get_from_arguments(Instruction* currentInstruction) 838 { 839 int dst = currentInstruction[1].u.operand; 840 int arguments = currentInstruction[2].u.operand; 841 int index = currentInstruction[3].u.operand; 842 843 emitLoadPayload(arguments, regT0); 844 load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset), regT1); 845 load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset), regT0); 846 emitValueProfilingSite(); 847 emitStore(dst, regT1, regT0); 848 } 849 850 void JIT::emit_op_put_to_arguments(Instruction* currentInstruction) 851 { 852 int arguments = currentInstruction[1].u.operand; 853 int index = currentInstruction[2].u.operand; 854 int value = currentInstruction[3].u.operand; 855 856 emitWriteBarrier(arguments, value, ShouldFilterValue); 857 858 emitLoadPayload(arguments, regT0); 859 emitLoad(value, regT1, regT2); 860 store32(regT1, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset)); 861 store32(regT2, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset)); 862 } 863 838 864 void JIT::emit_op_init_global_const(Instruction* currentInstruction) 839 865 { 840 WriteBarrier<Unknown>* registerPointer = currentInstruction[1].u.registerPointer;866 WriteBarrier<Unknown>* variablePointer = currentInstruction[1].u.variablePointer; 841 867 int value = currentInstruction[2].u.operand; 842 868 … … 847 873 emitLoad(value, regT1, regT0); 848 874 849 store32(regT1, registerPointer->tagPointer());850 store32(regT0, registerPointer->payloadPointer());875 store32(regT1, variablePointer->tagPointer()); 876 store32(regT0, variablePointer->payloadPointer()); 851 877 } 852 878 -
trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp
r180279 r181993 29 29 #if ENABLE(JIT) 30 30 31 #include " Arguments.h"31 #include "Interpreter.h" 32 32 #include "JSCInlines.h" 33 33 #include "StackAlignment.h" … … 70 70 endVarArgs.link(&jit); 71 71 } 72 slowCase.append(jit.branch32(CCallHelpers::Above, scratchGPR1, CCallHelpers::TrustedImm32( Arguments::MaxArguments + 1)));72 slowCase.append(jit.branch32(CCallHelpers::Above, scratchGPR1, CCallHelpers::TrustedImm32(maxArguments + 1))); 73 73 74 74 emitSetVarargsFrame(jit, scratchGPR1, true, numUsedSlotsGPR, scratchGPR2); -
trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
r178073 r181993 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 #include "CommonSlowPaths.h" 31 31 #include "Debugger.h" 32 #include "DirectArguments.h" 32 33 #include "Executable.h" 33 34 #include "Heap.h" -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r181889 r181993 27 27 #include "LLIntSlowPaths.h" 28 28 29 #include "Arguments.h"30 29 #include "ArrayConstructor.h" 31 30 #include "CallFrame.h" 32 31 #include "CommonSlowPaths.h" 33 32 #include "CommonSlowPathsExceptions.h" 33 #include "Error.h" 34 34 #include "ErrorHandlingScope.h" 35 35 #include "ExceptionFuzz.h" … … 255 255 LLINT_SLOW_PATH_DECL(trace) 256 256 { 257 dataLogF("%p / %p: executing bc#%zu, %s, scope %p,pc = %p\n",257 dataLogF("%p / %p: executing bc#%zu, %s, pc = %p\n", 258 258 exec->codeBlock(), 259 259 exec, 260 260 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), 261 opcodeNames[exec->vm().interpreter->getOpcodeID(pc[0].u.opcode)], 262 exec->uncheckedR(exec->codeBlock()->scopeRegister().offset()).Register::scope(), pc); 261 opcodeNames[exec->vm().interpreter->getOpcodeID(pc[0].u.opcode)], pc); 263 262 if (exec->vm().interpreter->getOpcodeID(pc[0].u.opcode) == op_enter) { 264 263 dataLogF("Frame will eventually return to %p\n", exec->returnPC().value()); … … 508 507 JSScope* scope = exec->uncheckedR(scopeReg).Register::scope(); 509 508 JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, scope, exec->codeBlock()); 510 exec->uncheckedR(pc[2].u.operand) = lexicalEnvironment;511 509 LLINT_RETURN(JSValue(lexicalEnvironment)); 512 510 } … … 756 754 } 757 755 758 LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)759 {760 LLINT_BEGIN();761 JSValue arguments = LLINT_OP(2).jsValue();762 if (!arguments) {763 int lexicalEnvironmentReg = pc[4].u.operand;764 JSLexicalEnvironment* lexicalEnvironment = VirtualRegister(lexicalEnvironmentReg).isValid() ?765 exec->uncheckedR(lexicalEnvironmentReg).lexicalEnvironment() : nullptr;766 arguments = JSValue(Arguments::create(vm, exec, lexicalEnvironment));767 768 LLINT_CHECK_EXCEPTION();769 LLINT_OP(2) = arguments;770 exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[2].u.operand)).offset()) = arguments;771 }772 773 LLINT_RETURN_PROFILED(op_get_argument_by_val, getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));774 }775 776 756 LLINT_SLOW_PATH_DECL(slow_path_put_by_val) 777 757 { … … 1240 1220 } 1241 1221 1242 LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)1243 {1244 LLINT_BEGIN();1245 ASSERT(exec->codeBlock()->usesArguments());1246 Arguments* arguments = jsCast<Arguments*>(exec->uncheckedR(VirtualRegister(pc[1].u.operand).offset()).jsValue());1247 arguments->tearOff(exec);1248 LLINT_END();1249 }1250 1251 1222 LLINT_SLOW_PATH_DECL(slow_path_strcat) 1252 1223 { … … 1408 1379 if (modeAndType.type() == LocalClosureVar) { 1409 1380 JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope); 1410 environment-> registerAt(pc[6].u.operand).set(vm, environment, value);1381 environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value); 1411 1382 if (VariableWatchpointSet* set = pc[5].u.watchpointSet) 1412 1383 set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>"); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r181981 r181993 42 42 end 43 43 const SlotSize = 8 44 45 const JSEnvironmentRecord_variables = (sizeof JSEnvironmentRecord + SlotSize - 1) & ~(SlotSize - 1) 46 const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(SlotSize - 1) 44 47 45 48 const StackAlignment = 16 … … 924 927 925 928 929 _llint_op_create_direct_arguments: 930 traceExecution() 931 callSlowPath(_slow_path_create_direct_arguments) 932 dispatch(2) 933 934 935 _llint_op_create_scoped_arguments: 936 traceExecution() 937 callSlowPath(_slow_path_create_scoped_arguments) 938 dispatch(3) 939 940 941 _llint_op_create_out_of_band_arguments: 942 traceExecution() 943 callSlowPath(_slow_path_create_out_of_band_arguments) 944 dispatch(2) 945 946 947 _llint_op_new_func: 948 traceExecution() 949 callSlowPath(_llint_slow_path_new_func) 950 dispatch(4) 951 952 926 953 _llint_op_new_array: 927 954 traceExecution() -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r181466 r181993 723 723 _llint_op_create_lexical_environment: 724 724 traceExecution() 725 loadi 4[PC], t0726 725 callSlowPath(_llint_slow_path_create_lexical_environment) 727 726 dispatch(3) … … 736 735 storei t0, PayloadOffset[cfr, t1, 8] 737 736 dispatch(2) 738 739 740 _llint_op_init_lazy_reg:741 traceExecution()742 loadi 4[PC], t0743 storei EmptyValueTag, TagOffset[cfr, t0, 8]744 storei 0, PayloadOffset[cfr, t0, 8]745 dispatch(2)746 747 748 _llint_op_create_arguments:749 traceExecution()750 loadi 4[PC], t0751 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateArgumentsDone752 callSlowPath(_slow_path_create_arguments)753 .opCreateArgumentsDone:754 dispatch(3)755 737 756 738 … … 1451 1433 1452 1434 1453 _llint_op_get_arguments_length:1454 traceExecution()1455 loadi 8[PC], t01456 loadi 4[PC], t11457 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentsLengthSlow1458 loadi ArgumentCount + PayloadOffset[cfr], t21459 subi 1, t21460 storei Int32Tag, TagOffset[cfr, t1, 8]1461 storei t2, PayloadOffset[cfr, t1, 8]1462 dispatch(4)1463 1464 .opGetArgumentsLengthSlow:1465 callSlowPath(_llint_slow_path_get_arguments_length)1466 dispatch(4)1467 1468 1469 1435 macro putById(getPropertyStorage) 1470 1436 traceExecution() … … 1615 1581 callSlowPath(_llint_slow_path_get_by_val) 1616 1582 dispatch(6) 1617 1618 1619 _llint_op_get_argument_by_val:1620 # FIXME: At some point we should array profile this. Right now it isn't necessary1621 # since the DFG will never turn a get_argument_by_val into a GetByVal.1622 traceExecution()1623 loadi 8[PC], t01624 loadi 12[PC], t11625 bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentByValSlow1626 loadConstantOrVariablePayload(t1, Int32Tag, t2, .opGetArgumentByValSlow)1627 loadi ArgumentCount + PayloadOffset[cfr], t11628 subi 1, t11629 biaeq t2, t1, .opGetArgumentByValSlow1630 loadi 4[PC], t31631 loadi FirstArgumentOffset + TagOffset[cfr, t2, 8], t01632 loadi FirstArgumentOffset + PayloadOffset[cfr, t2, 8], t11633 storei t0, TagOffset[cfr, t3, 8]1634 storei t1, PayloadOffset[cfr, t3, 8]1635 valueProfile(t0, t1, 24, t2)1636 dispatch(7)1637 1638 .opGetArgumentByValSlow:1639 callSlowPath(_llint_slow_path_get_argument_by_val)1640 dispatch(7)1641 1583 1642 1584 … … 1922 1864 1923 1865 1924 _llint_op_new_func:1925 traceExecution()1926 btiz 16[PC], .opNewFuncUnchecked1927 loadi 4[PC], t11928 bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewFuncDone1929 .opNewFuncUnchecked:1930 callSlowPath(_llint_slow_path_new_func)1931 .opNewFuncDone:1932 dispatch(5)1933 1934 1866 macro arrayProfileForCall() 1935 1867 loadi 16[PC], t3 … … 1964 1896 slowPathForCall(slowPath) 1965 1897 end 1966 1967 _llint_op_tear_off_arguments:1968 traceExecution()1969 loadi 4[PC], t01970 bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffArgumentsNotCreated1971 callSlowPath(_llint_slow_path_tear_off_arguments)1972 .opTearOffArgumentsNotCreated:1973 dispatch(3)1974 1898 1975 1899 … … 2214 2138 2215 2139 macro getClosureVar() 2216 loadp JSEnvironmentRecord::m_registers[t0], t02217 2140 loadisFromInstruction(6, t3) 2218 loadp TagOffset[t0, t3, 8], t12219 loadp PayloadOffset[t0, t3, 8], t22141 loadp JSEnvironmentRecord_variables + TagOffset[t0, t3, 8], t1 2142 loadp JSEnvironmentRecord_variables + PayloadOffset[t0, t3, 8], t2 2220 2143 valueProfile(t1, t2, 28, t0) 2221 2144 loadisFromInstruction(1, t0) … … 2291 2214 loadisFromInstruction(3, t1) 2292 2215 loadConstantOrVariable(t1, t2, t3) 2293 loadp JSEnvironmentRecord::m_registers[t0], t02294 2216 loadisFromInstruction(6, t1) 2295 storei t2, TagOffset[t0, t1, 8]2296 storei t3, PayloadOffset[t0, t1, 8]2217 storei t2, JSEnvironmentRecord_variables + TagOffset[t0, t1, 8] 2218 storei t3, JSEnvironmentRecord_variables + PayloadOffset[t0, t1, 8] 2297 2219 end 2298 2220 … … 2304 2226 notifyWrite(t4, t2, t3, t1, .pDynamic) 2305 2227 .noVariableWatchpointSet: 2306 loadp JSEnvironmentRecord::m_registers[t0], t02307 2228 loadisFromInstruction(6, t1) 2308 storei t2, TagOffset[t0, t1, 8]2309 storei t3, PayloadOffset[t0, t1, 8]2229 storei t2, JSEnvironmentRecord_variables + TagOffset[t0, t1, 8] 2230 storei t3, JSEnvironmentRecord_variables + PayloadOffset[t0, t1, 8] 2310 2231 end 2311 2232 … … 2368 2289 callSlowPath(_llint_slow_path_put_to_scope) 2369 2290 dispatch(7) 2291 2292 2293 _llint_op_get_from_arguments: 2294 traceExecution() 2295 loadisFromInstruction(2, t0) 2296 loadi PayloadOffset[cfr, t0, 8], t0 2297 loadi 12[PC], t1 2298 loadi DirectArguments_storage + TagOffset[t0, t1, 8], t2 2299 loadi DirectArguments_storage + PayloadOffset[t0, t1, 8], t3 2300 loadisFromInstruction(1, t1) 2301 valueProfile(t2, t3, 16, t0) 2302 storei t2, TagOffset[cfr, t1, 8] 2303 storei t3, PayloadOffset[cfr, t1, 8] 2304 dispatch(5) 2305 2306 2307 _llint_op_put_to_arguments: 2308 traceExecution() 2309 writeBarrierOnOperands(1, 3) 2310 loadisFromInstruction(1, t0) 2311 loadi PayloadOffset[cfr, t0, 8], t0 2312 loadisFromInstruction(3, t1) 2313 loadConstantOrVariable(t1, t2, t3) 2314 loadi 8[PC], t1 2315 storei t2, DirectArguments_storage + TagOffset[t0, t1, 8] 2316 storei t3, DirectArguments_storage + PayloadOffset[t0, t1, 8] 2317 dispatch(4) 2318 2370 2319 2371 2320 _llint_op_profile_type: -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r181466 r181993 610 610 _llint_op_create_lexical_environment: 611 611 traceExecution() 612 loadisFromInstruction(1, t0)613 612 callSlowPath(_llint_slow_path_create_lexical_environment) 614 613 dispatch(3) … … 622 621 storeq t0, [cfr, t1, 8] 623 622 dispatch(2) 624 625 626 _llint_op_init_lazy_reg:627 traceExecution()628 loadisFromInstruction(1, t0)629 storeq ValueEmpty, [cfr, t0, 8]630 dispatch(2)631 632 633 _llint_op_create_arguments:634 traceExecution()635 loadisFromInstruction(1, t0)636 bqneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone637 callSlowPath(_slow_path_create_arguments)638 .opCreateArgumentsDone:639 dispatch(3)640 623 641 624 … … 1315 1298 1316 1299 1317 _llint_op_get_arguments_length:1318 traceExecution()1319 loadisFromInstruction(2, t0)1320 loadisFromInstruction(1, t1)1321 btqnz [cfr, t0, 8], .opGetArgumentsLengthSlow1322 loadi ArgumentCount + PayloadOffset[cfr], t21323 subi 1, t21324 orq tagTypeNumber, t21325 storeq t2, [cfr, t1, 8]1326 dispatch(4)1327 1328 .opGetArgumentsLengthSlow:1329 callSlowPath(_llint_slow_path_get_arguments_length)1330 dispatch(4)1331 1332 1333 1300 macro putById(getPropertyStorage) 1334 1301 traceExecution() … … 1475 1442 callSlowPath(_llint_slow_path_get_by_val) 1476 1443 dispatch(6) 1477 1478 1479 _llint_op_get_argument_by_val:1480 # FIXME: At some point we should array profile this. Right now it isn't necessary1481 # since the DFG will never turn a get_argument_by_val into a GetByVal.1482 traceExecution()1483 loadisFromInstruction(2, t0)1484 loadisFromInstruction(3, t1)1485 btqnz [cfr, t0, 8], .opGetArgumentByValSlow1486 loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)1487 loadi ArgumentCount + PayloadOffset[cfr], t11488 sxi2q t2, t21489 subi 1, t11490 biaeq t2, t1, .opGetArgumentByValSlow1491 loadisFromInstruction(1, t3)1492 loadpFromInstruction(6, t1)1493 loadq FirstArgumentOffset[cfr, t2, 8], t01494 storeq t0, [cfr, t3, 8]1495 valueProfile(t0, 6, t1)1496 dispatch(7)1497 1498 .opGetArgumentByValSlow:1499 callSlowPath(_llint_slow_path_get_argument_by_val)1500 dispatch(7)1501 1444 1502 1445 … … 1782 1725 1783 1726 1784 _llint_op_new_func:1785 traceExecution()1786 loadisFromInstruction(4, t2)1787 btiz t2, .opNewFuncUnchecked1788 loadisFromInstruction(1, t1)1789 btqnz [cfr, t1, 8], .opNewFuncDone1790 .opNewFuncUnchecked:1791 callSlowPath(_llint_slow_path_new_func)1792 .opNewFuncDone:1793 dispatch(5)1794 1795 1727 macro arrayProfileForCall() 1796 1728 loadisFromInstruction(4, t3) … … 1824 1756 slowPathForCall(slowPath) 1825 1757 end 1826 1827 _llint_op_tear_off_arguments:1828 traceExecution()1829 loadisFromInstruction(1, t0)1830 btqz [cfr, t0, 8], .opTearOffArgumentsNotCreated1831 callSlowPath(_llint_slow_path_tear_off_arguments)1832 .opTearOffArgumentsNotCreated:1833 dispatch(3)1834 1758 1835 1759 … … 2081 2005 2082 2006 macro getClosureVar() 2083 loadp JSEnvironmentRecord::m_registers[t0], t02084 2007 loadisFromInstruction(6, t1) 2085 loadq [t0, t1, 8], t02008 loadq JSEnvironmentRecord_variables[t0, t1, 8], t0 2086 2009 valueProfile(t0, 7, t1) 2087 2010 loadisFromInstruction(1, t1) … … 2155 2078 loadisFromInstruction(3, t1) 2156 2079 loadConstantOrVariable(t1, t2) 2157 loadp JSEnvironmentRecord::m_registers[t0], t02158 2080 loadisFromInstruction(6, t1) 2159 storeq t2, [t0, t1, 8]2081 storeq t2, JSEnvironmentRecord_variables[t0, t1, 8] 2160 2082 end 2161 2083 … … 2167 2089 notifyWrite(t3, t2, t1, .pDynamic) 2168 2090 .noVariableWatchpointSet: 2169 loadp JSEnvironmentRecord::m_registers[t0], t02170 2091 loadisFromInstruction(6, t1) 2171 storeq t2, [t0, t1, 8]2092 storeq t2, JSEnvironmentRecord_variables[t0, t1, 8] 2172 2093 end 2173 2094 … … 2230 2151 callSlowPath(_llint_slow_path_put_to_scope) 2231 2152 dispatch(7) 2153 2154 2155 _llint_op_get_from_arguments: 2156 traceExecution() 2157 loadVariable(2, t0) 2158 loadi 24[PB, PC, 8], t1 2159 loadq DirectArguments_storage[t0, t1, 8], t0 2160 valueProfile(t0, 4, t1) 2161 loadisFromInstruction(1, t1) 2162 storeq t0, [cfr, t1, 8] 2163 dispatch(5) 2164 2165 2166 _llint_op_put_to_arguments: 2167 traceExecution() 2168 writeBarrierOnOperands(1, 3) 2169 loadVariable(1, t0) 2170 loadi 16[PB, PC, 8], t1 2171 loadisFromInstruction(3, t3) 2172 loadConstantOrVariable(t3, t2) 2173 storeq t2, DirectArguments_storage[t0, t1, 8] 2174 dispatch(4) 2175 2232 2176 2233 2177 _llint_op_profile_type: -
trunk/Source/JavaScriptCore/parser/Nodes.h
r181901 r181993 2 2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013, 2015 Apple Inc. All rights reserved. 5 5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) 6 6 * Copyright (C) 2007 Maks Orlovich … … 1471 1471 size_t capturedVariableCount() const { return m_capturedVariables.size(); } 1472 1472 const IdentifierSet& capturedVariables() const { return m_capturedVariables; } 1473 bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); } 1473 bool captures(StringImpl* uid) { return m_capturedVariables.contains(uid); } 1474 bool captures(const Identifier& ident) { return captures(ident.impl()); } 1474 1475 1475 1476 VarStack& varStack() { return m_varStack; } -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r181891 r181993 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013, 2014Apple Inc. All rights reserved.2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 26 26 #include "config.h" 27 27 #include "CommonSlowPaths.h" 28 #include "Arguments.h"29 28 #include "ArityCheckFailReturnThunks.h" 30 29 #include "ArrayConstructor.h" 31 30 #include "CallFrame.h" 31 #include "ClonedArguments.h" 32 32 #include "CodeProfiling.h" 33 33 #include "CommonSlowPathsExceptions.h" 34 #include "DirectArguments.h" 35 #include "Error.h" 34 36 #include "ErrorHandlingScope.h" 35 37 #include "ExceptionFuzz.h" … … 39 41 #include "JIT.h" 40 42 #include "JITStubs.h" 43 #include "JSCInlines.h" 41 44 #include "JSCJSValue.h" 42 45 #include "JSGlobalObjectFunctions.h" … … 50 53 #include "LowLevelInterpreter.h" 51 54 #include "ObjectConstructor.h" 52 #include " JSCInlines.h"55 #include "ScopedArguments.h" 53 56 #include "StructureRareDataInlines.h" 54 57 #include "TypeProfilerLog.h" … … 211 214 } 212 215 213 SLOW_PATH_DECL(slow_path_create_arguments) 214 { 215 BEGIN(); 216 int lexicalEnvironmentReg = pc[2].u.operand; 217 JSLexicalEnvironment* lexicalEnvironment = VirtualRegister(lexicalEnvironmentReg).isValid() ? 218 exec->uncheckedR(lexicalEnvironmentReg).lexicalEnvironment() : nullptr; 219 JSValue arguments = JSValue(Arguments::create(vm, exec, lexicalEnvironment)); 220 CHECK_EXCEPTION(); 221 exec->uncheckedR(pc[1].u.operand) = arguments; 222 exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[1].u.operand)).offset()) = arguments; 223 END(); 216 SLOW_PATH_DECL(slow_path_create_direct_arguments) 217 { 218 BEGIN(); 219 RETURN(DirectArguments::createByCopying(exec)); 220 } 221 222 SLOW_PATH_DECL(slow_path_create_scoped_arguments) 223 { 224 BEGIN(); 225 JSLexicalEnvironment* scope = jsCast<JSLexicalEnvironment*>(OP(2).jsValue()); 226 ScopedArgumentsTable* table = exec->codeBlock()->symbolTable()->arguments(); 227 RETURN(ScopedArguments::createByCopying(exec, table, scope)); 228 } 229 230 SLOW_PATH_DECL(slow_path_create_out_of_band_arguments) 231 { 232 BEGIN(); 233 RETURN(ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned)); 224 234 } 225 235 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h
r181891 r181993 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013Apple Inc. All rights reserved.2 * Copyright (C) 2011-2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 183 183 SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck); 184 184 SLOW_PATH_HIDDEN_DECL(slow_path_touch_entry); 185 SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments); 185 SLOW_PATH_HIDDEN_DECL(slow_path_create_direct_arguments); 186 SLOW_PATH_HIDDEN_DECL(slow_path_create_scoped_arguments); 187 SLOW_PATH_HIDDEN_DECL(slow_path_create_out_of_band_arguments); 186 188 SLOW_PATH_HIDDEN_DECL(slow_path_create_this); 187 189 SLOW_PATH_HIDDEN_DECL(slow_path_enter); -
trunk/Source/JavaScriptCore/runtime/ConstantMode.h
r160109 r181993 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #define ConstantMode_h 28 28 29 #include <wtf/PrintStream.h> 30 29 31 namespace JSC { 30 32 31 33 enum ConstantMode { IsConstant, IsVariable }; 32 34 35 inline ConstantMode modeForIsConstant(bool isConstant) 36 { 37 return isConstant ? IsConstant : IsVariable; 38 } 39 33 40 } // namespace JSC 41 42 namespace WTF { 43 44 void printInternal(PrintStream&, JSC::ConstantMode); 45 46 } // namespace WTF 34 47 35 48 #endif // ConstantMode_h -
trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
r181901 r181993 1 1 /* 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved. 4 4 * 5 5 * This library is free software; you can redistribute it and/or … … 22 22 #include "FunctionPrototype.h" 23 23 24 #include "Arguments.h"25 24 #include "BuiltinExecutables.h" 26 25 #include "BuiltinNames.h" 26 #include "Error.h" 27 27 #include "JSArray.h" 28 28 #include "JSBoundFunction.h" -
trunk/Source/JavaScriptCore/runtime/JSArgumentsIterator.cpp
r181203 r181993 1 1 /* 2 * Copyright (C) 2013 Apple, Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple, Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #include "JSArgumentsIterator.h" 28 28 29 #include "Arguments.h" 29 #include "ClonedArguments.h" 30 #include "DirectArguments.h" 30 31 #include "JSCInlines.h" 32 #include "ScopedArguments.h" 31 33 32 34 namespace JSC { … … 34 36 const ClassInfo JSArgumentsIterator::s_info = { "ArgumentsIterator", &Base::s_info, 0, CREATE_METHOD_TABLE(JSArgumentsIterator) }; 35 37 36 void JSArgumentsIterator::finishCreation(VM& vm, Arguments* arguments)38 void JSArgumentsIterator::finishCreation(VM& vm, JSObject* arguments) 37 39 { 38 40 Base::finishCreation(vm); … … 47 49 } 48 50 51 EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState* exec) 52 { 53 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 54 if (!thisObj->inherits(DirectArguments::info()) && !thisObj->inherits(ScopedArguments::info()) && !thisObj->inherits(ClonedArguments::info())) 55 return JSValue::encode(throwTypeError(exec, ASCIILiteral("Attempted to use Arguments iterator on non-Arguments object"))); 56 return JSValue::encode(JSArgumentsIterator::create(exec->vm(), exec->callee()->globalObject()->argumentsIteratorStructure(), thisObj)); 49 57 } 58 59 } -
trunk/Source/JavaScriptCore/runtime/JSArgumentsIterator.h
r181203 r181993 1 1 /* 2 * Copyright (C) 2013 Apple, Inc. All rights reserved.2 * Copyright (C) 2013, 2015 Apple, Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #define JSArgumentsIterator_h 28 28 29 #include " Arguments.h"29 #include "JSObject.h" 30 30 31 31 namespace JSC { … … 42 42 } 43 43 44 static JSArgumentsIterator* create(VM& vm, Structure* structure, Arguments* arguments)44 static JSArgumentsIterator* create(VM& vm, Structure* structure, JSObject* arguments) 45 45 { 46 46 JSArgumentsIterator* instance = new (NotNull, allocateCell<JSArgumentsIterator>(vm.heap)) JSArgumentsIterator(vm, structure); … … 51 51 bool next(CallFrame* callFrame, JSValue& value) 52 52 { 53 if (m_nextIndex >= m_arguments->length(callFrame)) 53 unsigned length = 54 m_arguments->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); 55 if (m_nextIndex >= length) 54 56 return false; 55 value = m_arguments->tryGetArgument(m_nextIndex++); 56 if (!value) 57 value = jsUndefined(); 57 value = m_arguments->getIndex(callFrame, m_nextIndex++); 58 58 return true; 59 59 } … … 72 72 } 73 73 74 void finishCreation(VM&, Arguments*);74 void finishCreation(VM&, JSObject*); 75 75 76 WriteBarrier< Arguments> m_arguments;76 WriteBarrier<JSObject> m_arguments; 77 77 size_t m_nextIndex; 78 78 }; 79 80 EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*); 79 81 80 82 } -
trunk/Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp
r173490 r181993 1 1 /* 2 * Copyright (C) 2007, 2008, 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2007, 2008, 2012, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 36 36 const ClassInfo JSEnvironmentRecord::s_info = { "EnvironmentRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(JSEnvironmentRecord) }; 37 37 38 void JSEnvironmentRecord::visitChildren(JSCell* cell, SlotVisitor& visitor) 39 { 40 JSEnvironmentRecord* thisObject = jsCast<JSEnvironmentRecord*>(cell); 41 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 42 Base::visitChildren(thisObject, visitor); 43 visitor.appendValues(thisObject->variables(), thisObject->m_symbolTable->scopeSize()); 44 } 45 38 46 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSEnvironmentRecord.h
r180514 r181993 47 47 typedef JSSymbolTableObject Base; 48 48 49 WriteBarrierBase<Unknown>* registers() { return m_registers; } 50 WriteBarrierBase<Unknown>& registerAt(int index) const { return m_registers[index]; } 49 WriteBarrierBase<Unknown>* variables() 50 { 51 return bitwise_cast<WriteBarrierBase<Unknown>*>(bitwise_cast<char*>(this) + offsetOfVariables()); 52 } 53 54 bool isValid(ScopeOffset offset) 55 { 56 return !!offset && offset.offset() < m_symbolTable->scopeSize(); 57 } 58 59 WriteBarrierBase<Unknown>& variableAt(ScopeOffset offset) 60 { 61 ASSERT(isValid(offset)); 62 return variables()[offset.offset()]; 63 } 51 64 52 WriteBarrierBase<Unknown>* const * addressOfRegisters() const { return &m_registers; } 53 static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSEnvironmentRecord, m_registers); } 65 static size_t offsetOfVariables() 66 { 67 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSEnvironmentRecord)); 68 } 69 70 static ptrdiff_t offsetOfVariable(ScopeOffset offset) 71 { 72 return offsetOfVariables() + offset.offset() * sizeof(WriteBarrier<Unknown>); 73 } 54 74 55 75 DECLARE_INFO; 56 76 77 static size_t allocationSizeForScopeSize(unsigned scopeSize) 78 { 79 return offsetOfVariables() + scopeSize * sizeof(WriteBarrier<Unknown>); 80 } 81 82 static size_t allocationSize(SymbolTable* symbolTable) 83 { 84 return allocationSizeForScopeSize(symbolTable->scopeSize()); 85 } 86 57 87 protected: 58 88 static const unsigned StructureFlags = Base::StructureFlags; … … 61 91 VM& vm, 62 92 Structure* structure, 63 Register* registers,64 93 JSScope* scope, 65 94 SymbolTable* symbolTable) 66 95 : Base(vm, structure, scope, symbolTable) 67 , m_registers(reinterpret_cast<WriteBarrierBase<Unknown>*>(registers))68 96 { 69 97 } 98 99 void finishCreationUninitialized(VM& vm) 100 { 101 Base::finishCreation(vm); 102 } 103 104 void finishCreation(VM& vm) 105 { 106 finishCreationUninitialized(vm); 107 for (unsigned i = m_symbolTable->scopeSize(); i--;) { 108 // Filling this with undefined is useful because that's what variables start out as. 109 variableAt(ScopeOffset(i)).setUndefined(); 110 } 111 } 70 112 71 WriteBarrierBase<Unknown>* m_registers; // "r" in the stack.113 static void visitChildren(JSCell*, SlotVisitor&); 72 114 }; 73 115 -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r180506 r181993 26 26 #include "JSFunction.h" 27 27 28 #include " Arguments.h"28 #include "ClonedArguments.h" 29 29 #include "CodeBlock.h" 30 30 #include "CommonIdentifiers.h" … … 35 35 #include "JSArray.h" 36 36 #include "JSBoundFunction.h" 37 #include "JSCInlines.h" 37 38 #include "JSFunctionInlines.h" 38 39 #include "JSGlobalObject.h" … … 41 42 #include "ObjectConstructor.h" 42 43 #include "ObjectPrototype.h" 43 #include "JSCInlines.h"44 44 #include "Parser.h" 45 45 #include "PropertyNameArray.h" -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r181664 r181993 1 1 /* 2 * Copyright (C) 2007, 2008, 2009, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2007, 2008, 2009, 2014, 2015 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca) 4 4 * … … 31 31 #include "JSGlobalObject.h" 32 32 33 #include "Arguments.h"34 33 #include "ArgumentsIteratorConstructor.h" 35 34 #include "ArgumentsIteratorPrototype.h" … … 40 39 #include "BooleanConstructor.h" 41 40 #include "BooleanPrototype.h" 41 #include "ClonedArguments.h" 42 42 #include "CodeBlock.h" 43 43 #include "CodeCache.h" … … 47 47 #include "Debugger.h" 48 48 #include "DebuggerScope.h" 49 #include "DirectArguments.h" 49 50 #include "Error.h" 50 51 #include "ErrorConstructor.h" … … 111 112 #include "RegExpObject.h" 112 113 #include "RegExpPrototype.h" 114 #include "ScopedArguments.h" 113 115 #include "SetConstructor.h" 114 116 #include "SetIteratorConstructor.h" … … 281 283 282 284 m_callbackFunctionStructure.set(vm, this, JSCallbackFunction::createStructure(vm, this, m_functionPrototype.get())); 283 m_argumentsStructure.set(vm, this, Arguments::createStructure(vm, this, m_objectPrototype.get())); 285 m_directArgumentsStructure.set(vm, this, DirectArguments::createStructure(vm, this, m_objectPrototype.get())); 286 m_scopedArgumentsStructure.set(vm, this, ScopedArguments::createStructure(vm, this, m_objectPrototype.get())); 287 m_outOfBandArgumentsStructure.set(vm, this, ClonedArguments::createStructure(vm, this, m_objectPrototype.get())); 284 288 m_callbackConstructorStructure.set(vm, this, JSCallbackConstructor::createStructure(vm, this, m_objectPrototype.get())); 285 289 m_callbackObjectStructure.set(vm, this, JSCallbackObject<JSDestructibleObject>::createStructure(vm, this, m_objectPrototype.get())); … … 475 479 { 476 480 ConcurrentJITLocker locker(symbolTable()->m_lock); 477 int index = symbolTable()->size(locker); 478 SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0); 481 SymbolTableEntry entry = symbolTable()->get(locker, ident.impl()); 482 if (!entry.isNull()) { 483 NewGlobalVar result; 484 result.offset = entry.scopeOffset(); 485 result.set = entry.watchpointSet(); 486 return result; 487 } 488 489 ScopeOffset offset = symbolTable()->takeNextScopeOffset(locker); 490 SymbolTableEntry newEntry(VarOffset(offset), (constantMode == IsConstant) ? ReadOnly : 0); 479 491 if (constantMode == IsVariable) 480 492 newEntry.prepareToWatch(symbolTable()); 481 SymbolTable::Map::AddResult result = symbolTable()->add(locker, ident.impl(), newEntry);482 if (result.isNewEntry)483 addRegisters(1);484 493 else 485 index = result.iterator->value.getIndex(); 494 newEntry.disableWatching(); 495 symbolTable()->add(locker, ident.impl(), newEntry); 496 497 ScopeOffset offsetForAssert = addVariables(1); 498 RELEASE_ASSERT(offsetForAssert == offset); 499 486 500 NewGlobalVar var; 487 var. registerNumber = index;488 var.set = result.iterator->value.watchpointSet();501 var.offset = offset; 502 var.set = newEntry.watchpointSet(); 489 503 return var; 490 504 } … … 495 509 removeDirect(vm, propertyName); // Newly declared functions overwrite existing properties. 496 510 NewGlobalVar var = addGlobalVar(propertyName, IsVariable); 497 registerAt(var.registerNumber).set(exec->vm(), this, value);511 variableAt(var.offset).set(exec->vm(), this, value); 498 512 if (var.set) 499 513 var.set->notifyWrite(vm, value, VariableWriteFireDetail(this, propertyName)); … … 692 706 visitor.append(&thisObject->m_catchScopeStructure); 693 707 visitor.append(&thisObject->m_functionNameScopeStructure); 694 visitor.append(&thisObject->m_argumentsStructure); 708 visitor.append(&thisObject->m_directArgumentsStructure); 709 visitor.append(&thisObject->m_scopedArgumentsStructure); 710 visitor.append(&thisObject->m_outOfBandArgumentsStructure); 695 711 for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) 696 712 visitor.append(&thisObject->m_originalArrayStructureForIndexingShape[i]); … … 749 765 void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count) 750 766 { 751 addRegisters(count);767 ScopeOffset startOffset = addVariables(count); 752 768 753 769 for (int i = 0; i < count; ++i) { … … 755 771 ASSERT(global.attributes & DontDelete); 756 772 757 int index = symbolTable()->size(); 758 SymbolTableEntry newEntry(index, global.attributes); 759 symbolTable()->add(global.identifier.impl(), newEntry); 760 registerAt(index).set(vm(), this, global.value); 773 ScopeOffset offset; 774 { 775 ConcurrentJITLocker locker(symbolTable()->m_lock); 776 offset = symbolTable()->takeNextScopeOffset(locker); 777 RELEASE_ASSERT(offset = startOffset + i); 778 SymbolTableEntry newEntry(VarOffset(offset), global.attributes); 779 symbolTable()->add(locker, global.identifier.impl(), newEntry); 780 } 781 variableAt(offset).set(vm(), this, global.value); 761 782 } 762 783 } -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r181084 r181993 1 1 /* 2 2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> 3 * Copyright (C) 2007, 2008, 2009, 2014 Apple Inc. All rights reserved.3 * Copyright (C) 2007, 2008, 2009, 2014, 2015 Apple Inc. All rights reserved. 4 4 * 5 5 * This library is free software; you can redistribute it and/or … … 205 205 WriteBarrier<Structure> m_catchScopeStructure; 206 206 WriteBarrier<Structure> m_functionNameScopeStructure; 207 WriteBarrier<Structure> m_argumentsStructure; 207 WriteBarrier<Structure> m_directArgumentsStructure; 208 WriteBarrier<Structure> m_scopedArgumentsStructure; 209 WriteBarrier<Structure> m_outOfBandArgumentsStructure; 208 210 209 211 // Lists the actual structures used for having these particular indexing shapes. … … 330 332 331 333 struct NewGlobalVar { 332 int registerNumber;334 ScopeOffset offset; 333 335 VariableWatchpointSet* set; 334 336 }; … … 417 419 Structure* catchScopeStructure() const { return m_catchScopeStructure.get(); } 418 420 Structure* functionNameScopeStructure() const { return m_functionNameScopeStructure.get(); } 419 Structure* argumentsStructure() const { return m_argumentsStructure.get(); } 421 Structure* directArgumentsStructure() const { return m_directArgumentsStructure.get(); } 422 Structure* scopedArgumentsStructure() const { return m_scopedArgumentsStructure.get(); } 423 Structure* outOfBandArgumentsStructure() const { return m_outOfBandArgumentsStructure.get(); } 420 424 Structure* originalArrayStructureForIndexingType(IndexingType indexingType) const 421 425 { -
trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp
r180529 r181993 1 1 /* 2 * Copyright (C) 2008, 2009, 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2014, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 #include "JSLexicalEnvironment.h" 31 31 32 #include "Arguments.h"33 32 #include "Interpreter.h" 34 33 #include "JSFunction.h" … … 41 40 const ClassInfo JSLexicalEnvironment::s_info = { "JSLexicalEnvironment", &Base::s_info, 0, CREATE_METHOD_TABLE(JSLexicalEnvironment) }; 42 41 43 void JSLexicalEnvironment::visitChildren(JSCell* cell, SlotVisitor& visitor)44 {45 JSLexicalEnvironment* thisObject = jsCast<JSLexicalEnvironment*>(cell);46 ASSERT_GC_OBJECT_INHERITS(thisObject, info());47 Base::visitChildren(thisObject, visitor);48 49 for (int i = 0; i < thisObject->symbolTable()->captureCount(); ++i)50 visitor.append(&thisObject->storage()[i]);51 }52 53 42 inline bool JSLexicalEnvironment::symbolTableGet(PropertyName propertyName, PropertySlot& slot) 54 43 { … … 57 46 return false; 58 47 48 ScopeOffset offset = entry.scopeOffset(); 49 59 50 // Defend against the inspector asking for a var after it has been optimized out. 60 if (!isValid( entry))51 if (!isValid(offset)) 61 52 return false; 62 53 63 slot.setValue(this, DontEnum, registerAt(entry.getIndex()).get());54 slot.setValue(this, DontEnum, variableAt(offset).get()); 64 55 return true; 65 56 } … … 71 62 return false; 72 63 64 ScopeOffset offset = entry.scopeOffset(); 65 73 66 // Defend against the inspector asking for a var after it has been optimized out. 74 if (!isValid( entry))67 if (!isValid(offset)) 75 68 return false; 76 69 77 descriptor.setDescriptor( registerAt(entry.getIndex()).get(), entry.getAttributes());70 descriptor.setDescriptor(variableAt(offset).get(), entry.getAttributes()); 78 71 return true; 79 72 } … … 96 89 return true; 97 90 } 91 ScopeOffset offset = iter->value.scopeOffset(); 98 92 // Defend against the inspector asking for a var after it has been optimized out. 99 if (!isValid( iter->value))93 if (!isValid(offset)) 100 94 return false; 101 95 if (VariableWatchpointSet* set = iter->value.watchpointSet()) 102 set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have inv calidated it.103 reg = & registerAt(iter->value.getIndex());96 set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it. 97 reg = &variableAt(offset); 104 98 } 105 99 reg->set(vm, this, value); … … 117 111 if (it->value.getAttributes() & DontEnum && !shouldIncludeDontEnumProperties(mode)) 118 112 continue; 119 if (!thisObject->isValid(it->value ))113 if (!thisObject->isValid(it->value.scopeOffset())) 120 114 continue; 121 115 propertyNames.add(Identifier(exec, it->key.get())); … … 138 132 SymbolTableEntry& entry = iter->value; 139 133 ASSERT(!entry.isNull()); 140 if (!isValid(entry)) 134 135 ScopeOffset offset = entry.scopeOffset(); 136 if (!isValid(offset)) 141 137 return false; 142 138 143 139 entry.setAttributes(attributes); 144 reg = & registerAt(entry.getIndex());140 reg = &variableAt(offset); 145 141 } 146 142 reg->set(vm, this, value); -
trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h
r180529 r181993 1 1 /* 2 * Copyright (C) 2008, 2009, 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 #include "CopiedSpaceInlines.h" 34 34 #include "JSEnvironmentRecord.h" 35 #include "Nodes.h"36 35 #include "SymbolTable.h" 37 36 … … 42 41 class JSLexicalEnvironment : public JSEnvironmentRecord { 43 42 private: 44 JSLexicalEnvironment(VM&, CallFrame*, Register*, JSScope*, CodeBlock*);43 JSLexicalEnvironment(VM&, Structure*, JSScope*, SymbolTable*); 45 44 46 45 public: 47 46 typedef JSEnvironmentRecord Base; 48 47 49 static JSLexicalEnvironment* create(VM& vm, CallFrame* callFrame, Register* registers, JSScope* currentScope, CodeBlock* codeBlock) 48 static JSLexicalEnvironment* create( 49 VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable) 50 50 { 51 JSLexicalEnvironment* result = 52 new ( 53 NotNull, 54 allocateCell<JSLexicalEnvironment>(vm.heap, allocationSize(symbolTable))) 55 JSLexicalEnvironment(vm, structure, currentScope, symbolTable); 56 result->finishCreation(vm); 57 return result; 58 } 59 60 static JSLexicalEnvironment* create(VM& vm, CallFrame* callFrame, JSScope* currentScope, CodeBlock* codeBlock) 61 { 62 JSGlobalObject* globalObject = callFrame->lexicalGlobalObject(); 63 Structure* structure = globalObject->activationStructure(); 51 64 SymbolTable* symbolTable = codeBlock->symbolTable(); 52 ASSERT(codeBlock->codeType() == FunctionCode); 53 JSLexicalEnvironment* lexicalEnvironment = new ( 54 NotNull, 55 allocateCell<JSLexicalEnvironment>( 56 vm.heap, 57 allocationSize(symbolTable) 58 ) 59 ) JSLexicalEnvironment(vm, callFrame, registers, currentScope, codeBlock); 60 lexicalEnvironment->finishCreation(vm); 61 return lexicalEnvironment; 65 return create(vm, structure, currentScope, symbolTable); 62 66 } 63 67 64 static JSLexicalEnvironment* create(VM& vm, CallFrame* callFrame, JSScope* currentScope, CodeBlock* codeBlock)65 {66 return create(vm, callFrame, callFrame->registers() + codeBlock->framePointerOffsetToGetActivationRegisters(), currentScope, codeBlock);67 }68 69 static void visitChildren(JSCell*, SlotVisitor&);70 71 68 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); 72 69 static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); … … 82 79 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject) { return Structure::create(vm, globalObject, jsNull(), TypeInfo(ActivationObjectType, StructureFlags), info()); } 83 80 84 WriteBarrierBase<Unknown>& registerAt(int) const;85 bool isValidIndex(int) const;86 bool isValid(const SymbolTableEntry&) const;87 int registersOffset();88 static int registersOffset(SymbolTable*);89 90 81 protected: 91 82 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | Base::StructureFlags; … … 97 88 bool symbolTablePut(ExecState*, PropertyName, JSValue, bool shouldThrow); 98 89 bool symbolTablePutWithAttributes(VM&, PropertyName, JSValue, unsigned attributes); 99 100 static size_t allocationSize(SymbolTable*);101 static size_t storageOffset();102 103 WriteBarrier<Unknown>* storage(); // captureCount() number of registers.104 90 }; 105 91 106 inline JSLexicalEnvironment::JSLexicalEnvironment(VM& vm, CallFrame* callFrame, Register* registers, JSScope* currentScope, CodeBlock* codeBlock) 107 : Base( 108 vm, 109 callFrame->lexicalGlobalObject()->activationStructure(), 110 registers, 111 currentScope, 112 codeBlock->symbolTable()) 92 inline JSLexicalEnvironment::JSLexicalEnvironment(VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable) 93 : Base(vm, structure, currentScope, symbolTable) 113 94 { 114 SymbolTable* symbolTable = codeBlock->symbolTable();115 WriteBarrier<Unknown>* storage = this->storage();116 size_t captureCount = symbolTable->captureCount();117 for (size_t i = 0; i < captureCount; ++i)118 new (NotNull, &storage[i]) WriteBarrier<Unknown>(UndefinedWriteBarrierTag);119 m_registers = reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(120 reinterpret_cast<char*>(this) + registersOffset(symbolTable));121 95 } 122 123 JSLexicalEnvironment* asActivation(JSValue);124 96 125 97 inline JSLexicalEnvironment* asActivation(JSValue value) … … 134 106 } 135 107 136 inline int JSLexicalEnvironment::registersOffset(SymbolTable* symbolTable)137 {138 return storageOffset() + ((symbolTable->captureCount() - symbolTable->captureStart() - 1) * sizeof(WriteBarrier<Unknown>));139 }140 141 inline size_t JSLexicalEnvironment::storageOffset()142 {143 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSLexicalEnvironment));144 }145 146 inline WriteBarrier<Unknown>* JSLexicalEnvironment::storage()147 {148 return reinterpret_cast_ptr<WriteBarrier<Unknown>*>(149 reinterpret_cast<char*>(this) + storageOffset());150 }151 152 inline size_t JSLexicalEnvironment::allocationSize(SymbolTable* symbolTable)153 {154 size_t objectSizeInBytes = WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSLexicalEnvironment));155 size_t storageSizeInBytes = symbolTable->captureCount() * sizeof(WriteBarrier<Unknown>);156 return objectSizeInBytes + storageSizeInBytes;157 }158 159 inline bool JSLexicalEnvironment::isValidIndex(int index) const160 {161 if (index > symbolTable()->captureStart())162 return false;163 if (index <= symbolTable()->captureEnd())164 return false;165 return true;166 }167 168 inline bool JSLexicalEnvironment::isValid(const SymbolTableEntry& entry) const169 {170 return isValidIndex(entry.getIndex());171 }172 173 inline WriteBarrierBase<Unknown>& JSLexicalEnvironment::registerAt(int index) const174 {175 ASSERT(isValidIndex(index));176 return Base::registerAt(index);177 }178 179 108 } // namespace JSC 180 109 -
trunk/Source/JavaScriptCore/runtime/JSNameScope.cpp
r180514 r181993 48 48 } 49 49 50 void JSNameScope::visitChildren(JSCell* cell, SlotVisitor& visitor)51 {52 JSNameScope* thisObject = jsCast<JSNameScope*>(cell);53 ASSERT_GC_OBJECT_INHERITS(thisObject, info());54 Base::visitChildren(thisObject, visitor);55 visitor.append(&thisObject->m_registerStore);56 }57 58 50 JSValue JSNameScope::toThis(JSCell*, ExecState* exec, ECMAMode ecmaMode) 59 51 { -
trunk/Source/JavaScriptCore/runtime/JSNameScope.h
r180514 r181993 45 45 static T* create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue value) 46 46 { 47 T* scopeObject = new (NotNull, allocateCell<T>(vm.heap)) T(vm, globalObject, currentScope, symbolTable); 47 T* scopeObject = new ( 48 NotNull, allocateCell<T>(vm.heap, allocationSizeForScopeSize(1))) 49 T(vm, globalObject, currentScope, symbolTable); 48 50 scopeObject->finishCreation(vm, value); 49 51 return scopeObject; … … 52 54 static JSNameScope* create(VM&, JSGlobalObject*, JSScope* currentScope, SymbolTable*, JSValue, Type); 53 55 54 static void visitChildren(JSCell*, SlotVisitor&);55 56 static JSValue toThis(JSCell*, ExecState*, ECMAMode); 56 57 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); … … 59 60 DECLARE_INFO; 60 61 61 JSValue value() const { return m_registerStore.get(); }62 JSValue value() { return variableAt(ScopeOffset(0)).get(); } 62 63 63 64 protected: 64 65 void finishCreation(VM& vm, JSValue value) 65 66 { 66 Base::finishCreation (vm);67 m_registerStore.set(vm, this, value);67 Base::finishCreationUninitialized(vm); 68 variableAt(ScopeOffset(0)).set(vm, this, value); 68 69 } 69 70 … … 71 72 72 73 JSNameScope(VM& vm, Structure* structure, JSScope* next, SymbolTable* symbolTable) 73 : Base(vm, structure, reinterpret_cast<Register*>(&m_registerStore + 1),next, symbolTable)74 : Base(vm, structure, next, symbolTable) 74 75 { 76 ASSERT(symbolTable->scopeSize() == 1); 75 77 } 76 77 private:78 WriteBarrier<Unknown> m_registerStore;79 78 }; 80 79 -
trunk/Source/JavaScriptCore/runtime/JSScope.cpp
r174226 r181993 1 1 /* 2 * Copyright (C) 2012 , 2013, 2014Apple Inc. All Rights Reserved.2 * Copyright (C) 2012-2015 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 63 63 64 64 if (!entry.isNull()) { 65 op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, 0, lexicalEnvironment, entry.watchpointSet(), entry. getIndex());65 op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, 0, lexicalEnvironment, entry.watchpointSet(), entry.scopeOffset().offset()); 66 66 return true; 67 67 } … … 83 83 op = ResolveOp( 84 84 makeType(GlobalVar, needsVarInjectionChecks), depth, 0, 0, entry.watchpointSet(), 85 reinterpret_cast<uintptr_t>(globalObject-> registerAt(entry.getIndex()).slot()));85 reinterpret_cast<uintptr_t>(globalObject->variableAt(entry.scopeOffset()).slot())); 86 86 return true; 87 87 } -
trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp
r171939 r181993 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 34 34 namespace JSC { 35 35 36 int JSSegmentedVariableObject::findRegisterIndex(void* registerAddress)36 ScopeOffset JSSegmentedVariableObject::findVariableIndex(void* variableAddress) 37 37 { 38 38 ConcurrentJITLocker locker(m_lock); 39 39 40 for ( int i = m_registers.size(); i--;) {41 if (&m_ registers[i] != registerAddress)40 for (unsigned i = m_variables.size(); i--;) { 41 if (&m_variables[i] != variableAddress) 42 42 continue; 43 return i;43 return ScopeOffset(i); 44 44 } 45 45 CRASH(); 46 return -1;46 return ScopeOffset(); 47 47 } 48 48 49 int JSSegmentedVariableObject::addRegisters(int numberOfRegistersToAdd)49 ScopeOffset JSSegmentedVariableObject::addVariables(unsigned numberOfVariablesToAdd) 50 50 { 51 51 ConcurrentJITLocker locker(m_lock); 52 52 53 ASSERT(numberOfRegistersToAdd >= 0); 53 size_t oldSize = m_variables.size(); 54 m_variables.grow(oldSize + numberOfVariablesToAdd); 54 55 55 size_t oldSize = m_registers.size();56 m_registers.grow(oldSize + numberOfRegistersToAdd);56 for (size_t i = numberOfVariablesToAdd; i--;) 57 m_variables[oldSize + i].setWithoutWriteBarrier(jsUndefined()); 57 58 58 for (size_t i = numberOfRegistersToAdd; i--;) 59 m_registers[oldSize + i].setWithoutWriteBarrier(jsUndefined()); 60 61 return static_cast<int>(oldSize); 59 return ScopeOffset(oldSize); 62 60 } 63 61 … … 68 66 JSSymbolTableObject::visitChildren(thisObject, slotVisitor); 69 67 70 for (unsigned i = thisObject->m_ registers.size(); i--;)71 slotVisitor.append(&thisObject->m_ registers[i]);68 for (unsigned i = thisObject->m_variables.size(); i--;) 69 slotVisitor.append(&thisObject->m_variables[i]); 72 70 } 73 71 -
trunk/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h
r180514 r181993 58 58 typedef JSSymbolTableObject Base; 59 59 60 WriteBarrier<Unknown>& registerAt(int index) { return m_registers[index]; }60 WriteBarrier<Unknown>& variableAt(ScopeOffset offset) { return m_variables[offset.offset()]; } 61 61 62 62 // This is a slow method call, which searches the register bank to find the index 63 63 // given a pointer. It will CRASH() if it does not find the register. Only use this 64 64 // in debug code (like bytecode dumping). 65 JS_EXPORT_PRIVATE int findRegisterIndex(void*);65 JS_EXPORT_PRIVATE ScopeOffset findVariableIndex(void*); 66 66 67 WriteBarrier<Unknown>* assert RegisterIsInThisObject(WriteBarrier<Unknown>* registerPointer)67 WriteBarrier<Unknown>* assertVariableIsInThisObject(WriteBarrier<Unknown>* variablePointer) 68 68 { 69 #if !ASSERT_DISABLED 70 findRegisterIndex(registerPointer); 71 #endif 72 return registerPointer; 69 if (!ASSERT_DISABLED) 70 findVariableIndex(variablePointer); 71 return variablePointer; 73 72 } 74 73 75 74 // Adds numberOfRegistersToAdd registers, initializes them to Undefined, and returns 76 75 // the index of the first one added. 77 JS_EXPORT_PRIVATE int addRegisters(int numberOfRegistersToAdd);76 JS_EXPORT_PRIVATE ScopeOffset addVariables(unsigned numberOfVariablesToAdd); 78 77 79 78 JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); … … 91 90 } 92 91 93 SegmentedVector<WriteBarrier<Unknown>, 16> m_ registers;92 SegmentedVector<WriteBarrier<Unknown>, 16> m_variables; 94 93 ConcurrentJITLock m_lock; 95 94 }; -
trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
r180514 r181993 48 48 JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 49 49 50 static ptrdiff_t offsetOfSymbolTable() { return OBJECT_OFFSETOF(JSSymbolTableObject, m_symbolTable); } 51 50 52 protected: 51 53 static const unsigned StructureFlags = IsEnvironmentRecord | OverridesGetPropertyNames | Base::StructureFlags; … … 79 81 SymbolTableEntry::Fast entry = iter->value; 80 82 ASSERT(!entry.isNull()); 81 slot.setValue(object, entry.getAttributes() | DontDelete, object-> registerAt(entry.getIndex()).get());83 slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(entry.scopeOffset()).get()); 82 84 return true; 83 85 } … … 95 97 ASSERT(!entry.isNull()); 96 98 descriptor.setDescriptor( 97 object-> registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete);99 object->variableAt(entry.scopeOffset()).get(), entry.getAttributes() | DontDelete); 98 100 return true; 99 101 } … … 111 113 SymbolTableEntry::Fast entry = iter->value; 112 114 ASSERT(!entry.isNull()); 113 slot.setValue(object, entry.getAttributes() | DontDelete, object-> registerAt(entry.getIndex()).get());115 slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(entry.scopeOffset()).get()); 114 116 slotIsWriteable = !entry.isReadOnly(); 115 117 return true; … … 146 148 set->notifyWrite(vm, value, object, propertyName); 147 149 } 148 reg = &object-> registerAt(fastEntry.getIndex());150 reg = &object->variableAt(fastEntry.scopeOffset()); 149 151 } 150 152 // I'd prefer we not hold lock while executing barriers, since I prefer to reserve … … 174 176 set->notifyWrite(vm, value, object, propertyName); 175 177 entry.setAttributes(attributes); 176 reg = &object-> registerAt(entry.getIndex());178 reg = &object->variableAt(entry.scopeOffset()); 177 179 } 178 180 reg->set(vm, object, value); -
trunk/Source/JavaScriptCore/runtime/JSType.h
r179429 r181993 1 1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 59 59 ImpureProxyType, 60 60 WithScopeType, 61 ArgumentsType, 61 DirectArgumentsType, 62 ScopedArgumentsType, 62 63 63 64 Int8ArrayType, -
trunk/Source/JavaScriptCore/runtime/Options.h
r181990 r181993 126 126 v(optionString, dfgFunctionWhitelistFile, nullptr) \ 127 127 v(bool, dumpBytecodeAtDFGTime, false) \ 128 v(bool, dumpGraphAfterParsing, false) \ 128 129 v(bool, dumpGraphAtEachPhase, false) \ 129 130 v(bool, verboseDFGByteCodeParsing, false) \ -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r180989 r181993 70 70 void SymbolTableEntry::prepareToWatch(SymbolTable* symbolTable) 71 71 { 72 if (!isWatchable()) 73 return; 72 74 FatEntry* entry = inflate(); 73 75 if (entry->m_watchpoints) … … 99 101 SymbolTable::SymbolTable(VM& vm) 100 102 : JSCell(vm, vm.symbolTableStructure.get()) 101 , m_parameterCountIncludingThis(0)102 103 , m_usesNonStrictEval(false) 103 , m_captureStart(0)104 , m_captureEnd(0)105 104 , m_functionEnteredOnce(ClearWatchpoint) 106 105 { … … 112 111 { 113 112 SymbolTable* thisSymbolTable = jsCast<SymbolTable*>(thisCell); 113 114 visitor.append(&thisSymbolTable->m_arguments); 115 114 116 if (!thisSymbolTable->m_watchpointCleanup) { 115 117 thisSymbolTable->m_watchpointCleanup = … … 147 149 unsigned size = 0; 148 150 for (auto& entry : m_map) { 149 V irtualRegister reg(entry.value.getIndex());150 if ( reg.isLocal())151 size = std::max(size, static_cast<unsigned>(reg.toLocal()) + 1);151 VarOffset offset = entry.value.varOffset(); 152 if (offset.isScope()) 153 size = std::max(size, offset.scopeOffset().offset() + 1); 152 154 } 153 155 154 156 m_localToEntry = std::make_unique<LocalToEntryVec>(size, nullptr); 155 157 for (auto& entry : m_map) { 156 V irtualRegister reg(entry.value.getIndex());157 if ( reg.isLocal())158 m_localToEntry->at( reg.toLocal()) = &entry.value;158 VarOffset offset = entry.value.varOffset(); 159 if (offset.isScope()) 160 m_localToEntry->at(offset.scopeOffset().offset()) = &entry.value; 159 161 } 160 162 } … … 163 165 } 164 166 165 SymbolTableEntry* SymbolTable::entryFor(const ConcurrentJITLocker& locker, VirtualRegister reg) 166 { 167 if (!reg.isLocal()) 168 return nullptr; 169 return localToEntry(locker)[reg.toLocal()]; 170 } 171 172 SymbolTable* SymbolTable::cloneCapturedNames(VM& vm) 167 SymbolTableEntry* SymbolTable::entryFor(const ConcurrentJITLocker& locker, ScopeOffset offset) 168 { 169 return localToEntry(locker)[offset.offset()]; 170 } 171 172 SymbolTable* SymbolTable::cloneScopePart(VM& vm) 173 173 { 174 174 SymbolTable* result = SymbolTable::create(vm); 175 175 176 result->m_parameterCountIncludingThis = m_parameterCountIncludingThis;177 176 result->m_usesNonStrictEval = m_usesNonStrictEval; 178 result->m_captureStart = m_captureStart;179 result->m_captureEnd = m_captureEnd;180 177 181 178 for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { 182 if (!i sCaptured(iter->value.getIndex()))179 if (!iter->value.varOffset().isScope()) 183 180 continue; 184 181 result->m_map.add( 185 182 iter->key, 186 SymbolTableEntry(iter->value.getIndex(), iter->value.getAttributes())); 187 } 188 189 if (m_slowArguments) { 190 result->m_slowArguments = std::make_unique<SlowArgument[]>(parameterCount()); 191 for (unsigned i = parameterCount(); i--;) 192 result->m_slowArguments[i] = m_slowArguments[i]; 193 } 194 183 SymbolTableEntry(iter->value.varOffset(), iter->value.getAttributes())); 184 } 185 186 result->m_maxScopeOffset = m_maxScopeOffset; 187 188 if (ScopedArgumentsTable* arguments = this->arguments()) 189 result->m_arguments.set(vm, result, arguments); 190 195 191 if (m_typeProfilingRareData) { 196 192 result->m_typeProfilingRareData = std::make_unique<TypeProfilingRareData>(); … … 204 200 205 201 { 206 auto iter = m_typeProfilingRareData->m_ registerToVariableMap.begin();207 auto end = m_typeProfilingRareData->m_ registerToVariableMap.end();202 auto iter = m_typeProfilingRareData->m_offsetToVariableMap.begin(); 203 auto end = m_typeProfilingRareData->m_offsetToVariableMap.end(); 208 204 for (; iter != end; ++iter) 209 result->m_typeProfilingRareData->m_ registerToVariableMap.set(iter->key, iter->value);205 result->m_typeProfilingRareData->m_offsetToVariableMap.set(iter->key, iter->value); 210 206 } 211 207 … … 230 226 for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { 231 227 m_typeProfilingRareData->m_uniqueIDMap.set(iter->key, TypeProfilerNeedsUniqueIDGeneration); 232 m_typeProfilingRareData->m_ registerToVariableMap.set(iter->value.getIndex(), iter->key);228 m_typeProfilingRareData->m_offsetToVariableMap.set(iter->value.varOffset(), iter->key); 233 229 } 234 230 } … … 253 249 } 254 250 255 GlobalVariableID SymbolTable::uniqueIDFor Register(const ConcurrentJITLocker& locker, int registerIndex, VM& vm)256 { 257 RELEASE_ASSERT(m_typeProfilingRareData); 258 259 auto iter = m_typeProfilingRareData->m_ registerToVariableMap.find(registerIndex);260 auto end = m_typeProfilingRareData->m_ registerToVariableMap.end();251 GlobalVariableID SymbolTable::uniqueIDForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm) 252 { 253 RELEASE_ASSERT(m_typeProfilingRareData); 254 255 auto iter = m_typeProfilingRareData->m_offsetToVariableMap.find(offset); 256 auto end = m_typeProfilingRareData->m_offsetToVariableMap.end(); 261 257 if (iter == end) 262 258 return TypeProfilerNoGlobalIDExists; … … 265 261 } 266 262 267 RefPtr<TypeSet> SymbolTable::globalTypeSetFor Register(const ConcurrentJITLocker& locker, int registerIndex, VM& vm)268 { 269 RELEASE_ASSERT(m_typeProfilingRareData); 270 271 uniqueIDFor Register(locker, registerIndex, vm); // Lazily create the TypeSet if necessary.272 273 auto iter = m_typeProfilingRareData->m_ registerToVariableMap.find(registerIndex);274 auto end = m_typeProfilingRareData->m_ registerToVariableMap.end();263 RefPtr<TypeSet> SymbolTable::globalTypeSetForOffset(const ConcurrentJITLocker& locker, VarOffset offset, VM& vm) 264 { 265 RELEASE_ASSERT(m_typeProfilingRareData); 266 267 uniqueIDForOffset(locker, offset, vm); // Lazily create the TypeSet if necessary. 268 269 auto iter = m_typeProfilingRareData->m_offsetToVariableMap.find(offset); 270 auto end = m_typeProfilingRareData->m_offsetToVariableMap.end(); 275 271 if (iter == end) 276 272 return nullptr; -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r180989 r181993 31 31 32 32 #include "ConcurrentJITLock.h" 33 #include "ConstantMode.h" 33 34 #include "JSObject.h" 35 #include "ScopedArgumentsTable.h" 34 36 #include "TypeLocation.h" 37 #include "VarOffset.h" 35 38 #include "VariableWatchpointSet.h" 36 39 #include <memory> … … 39 42 40 43 namespace JSC { 41 42 struct SlowArgument {43 public:44 enum Status {45 Normal = 0,46 Captured = 1,47 Deleted = 248 };49 50 SlowArgument()51 : status(Normal)52 , index(0)53 {54 }55 56 Status status;57 int index; // If status is 'Deleted', index is bogus.58 };59 44 60 45 static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); } … … 87 72 88 73 struct SymbolTableEntry { 74 private: 75 static VarOffset varOffsetFromBits(intptr_t bits) 76 { 77 VarKind kind; 78 intptr_t kindBits = bits & KindBitsMask; 79 if (kindBits <= UnwatchableScopeKindBits) 80 kind = VarKind::Scope; 81 else if (kindBits == StackKindBits) 82 kind = VarKind::Stack; 83 else 84 kind = VarKind::DirectArgument; 85 return VarOffset::assemble(kind, static_cast<int>(bits >> FlagBits)); 86 } 87 88 static ScopeOffset scopeOffsetFromBits(intptr_t bits) 89 { 90 ASSERT((bits & KindBitsMask) <= UnwatchableScopeKindBits); 91 return ScopeOffset(static_cast<int>(bits >> FlagBits)); 92 } 93 94 public: 95 89 96 // Use the SymbolTableEntry::Fast class, either via implicit cast or by calling 90 97 // getFast(), when you (1) only care about isNull(), getIndex(), and isReadOnly(), … … 108 115 } 109 116 110 int getIndex() const 111 { 112 return static_cast<int>(m_bits >> FlagBits); 113 } 114 117 VarOffset varOffset() const 118 { 119 return varOffsetFromBits(m_bits); 120 } 121 122 // Asserts if the offset is anything but a scope offset. This structures the assertions 123 // in a way that may result in better code, even in release, than doing 124 // varOffset().scopeOffset(). 125 ScopeOffset scopeOffset() const 126 { 127 return scopeOffsetFromBits(m_bits); 128 } 129 115 130 bool isReadOnly() const 116 131 { … … 118 133 } 119 134 135 bool isDontEnum() const 136 { 137 return m_bits & DontEnumFlag; 138 } 139 120 140 unsigned getAttributes() const 121 141 { 122 142 unsigned attributes = 0; 123 if ( m_bits & ReadOnlyFlag)143 if (isReadOnly()) 124 144 attributes |= ReadOnly; 125 if ( m_bits & DontEnumFlag)145 if (isDontEnum()) 126 146 attributes |= DontEnum; 127 147 return attributes; … … 143 163 } 144 164 145 SymbolTableEntry( int index)165 SymbolTableEntry(VarOffset offset) 146 166 : m_bits(SlimFlag) 147 167 { 148 ASSERT(isValid Index(index));149 pack( index, false, false);150 } 151 152 SymbolTableEntry( int index, unsigned attributes)168 ASSERT(isValidVarOffset(offset)); 169 pack(offset, true, false, false); 170 } 171 172 SymbolTableEntry(VarOffset offset, unsigned attributes) 153 173 : m_bits(SlimFlag) 154 174 { 155 ASSERT(isValid Index(index));156 pack( index, attributes & ReadOnly, attributes & DontEnum);175 ASSERT(isValidVarOffset(offset)); 176 pack(offset, true, attributes & ReadOnly, attributes & DontEnum); 157 177 } 158 178 … … 182 202 } 183 203 184 int getIndex() const 185 { 186 return static_cast<int>(bits() >> FlagBits); 204 VarOffset varOffset() const 205 { 206 return varOffsetFromBits(bits()); 207 } 208 209 bool isWatchable() const 210 { 211 return (m_bits & KindBitsMask) == ScopeKindBits; 212 } 213 214 // Asserts if the offset is anything but a scope offset. This structures the assertions 215 // in a way that may result in better code, even in release, than doing 216 // varOffset().scopeOffset(). 217 ScopeOffset scopeOffset() const 218 { 219 return scopeOffsetFromBits(bits()); 187 220 } 188 221 … … 207 240 return getFast().getAttributes(); 208 241 } 209 242 210 243 void setAttributes(unsigned attributes) 211 244 { 212 pack( getIndex(), attributes & ReadOnly, attributes & DontEnum);245 pack(varOffset(), isWatchable(), attributes & ReadOnly, attributes & DontEnum); 213 246 } 214 247 … … 218 251 } 219 252 253 ConstantMode constantMode() const 254 { 255 return modeForIsConstant(isReadOnly()); 256 } 257 258 bool isDontEnum() const 259 { 260 return bits() & DontEnumFlag; 261 } 262 220 263 JSValue inferredValue(); 264 265 void disableWatching() 266 { 267 if (varOffset().isScope()) 268 pack(varOffset(), false, isReadOnly(), isDontEnum()); 269 } 221 270 222 271 void prepareToWatch(SymbolTable*); … … 243 292 static const intptr_t DontEnumFlag = 0x4; 244 293 static const intptr_t NotNullFlag = 0x8; 245 static const intptr_t FlagBits = 4; 294 static const intptr_t KindBitsMask = 0x30; 295 static const intptr_t ScopeKindBits = 0x00; 296 static const intptr_t UnwatchableScopeKindBits = 0x10; 297 static const intptr_t StackKindBits = 0x20; 298 static const intptr_t DirectArgumentKindBits = 0x30; 299 static const intptr_t FlagBits = 6; 246 300 247 301 class FatEntry { … … 310 364 JS_EXPORT_PRIVATE void freeFatEntrySlow(); 311 365 312 void pack( int index, bool readOnly, bool dontEnum)366 void pack(VarOffset offset, bool isWatchable, bool readOnly, bool dontEnum) 313 367 { 314 368 ASSERT(!isFat()); 315 369 intptr_t& bitsRef = bits(); 316 bitsRef = (static_cast<intptr_t>(index) << FlagBits) | NotNullFlag | SlimFlag; 370 bitsRef = 371 (static_cast<intptr_t>(offset.rawOffset()) << FlagBits) | NotNullFlag | SlimFlag; 317 372 if (readOnly) 318 373 bitsRef |= ReadOnlyFlag; 319 374 if (dontEnum) 320 375 bitsRef |= DontEnumFlag; 321 } 322 323 bool isValidIndex(int index) 324 { 325 return ((static_cast<intptr_t>(index) << FlagBits) >> FlagBits) == static_cast<intptr_t>(index); 376 switch (offset.kind()) { 377 case VarKind::Scope: 378 if (isWatchable) 379 bitsRef |= ScopeKindBits; 380 else 381 bitsRef |= UnwatchableScopeKindBits; 382 break; 383 case VarKind::Stack: 384 bitsRef |= StackKindBits; 385 break; 386 case VarKind::DirectArgument: 387 bitsRef |= DirectArgumentKindBits; 388 break; 389 default: 390 RELEASE_ASSERT_NOT_REACHED(); 391 break; 392 } 393 } 394 395 static bool isValidVarOffset(VarOffset offset) 396 { 397 return ((static_cast<intptr_t>(offset.rawOffset()) << FlagBits) >> FlagBits) == static_cast<intptr_t>(offset.rawOffset()); 326 398 } 327 399 … … 340 412 typedef HashMap<RefPtr<StringImpl>, GlobalVariableID> UniqueIDMap; 341 413 typedef HashMap<RefPtr<StringImpl>, RefPtr<TypeSet>> UniqueTypeSetMap; 342 typedef HashMap< int, RefPtr<StringImpl>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> RegisterToVariableMap;414 typedef HashMap<VarOffset, RefPtr<StringImpl>> OffsetToVariableMap; 343 415 typedef Vector<SymbolTableEntry*> LocalToEntryVec; 344 416 … … 353 425 { 354 426 SymbolTable* result = create(vm); 355 result->add(ident.impl(), SymbolTableEntry( -1, attributes));427 result->add(ident.impl(), SymbolTableEntry(VarOffset(ScopeOffset(0)), attributes)); 356 428 return result; 357 429 } … … 425 497 } 426 498 427 Map::AddResult add(const ConcurrentJITLocker&, StringImpl* key, const SymbolTableEntry& entry) 499 ScopeOffset maxScopeOffset() const 500 { 501 return m_maxScopeOffset; 502 } 503 504 void didUseScopeOffset(ScopeOffset offset) 505 { 506 if (!m_maxScopeOffset || m_maxScopeOffset < offset) 507 m_maxScopeOffset = offset; 508 } 509 510 void didUseVarOffset(VarOffset offset) 511 { 512 if (offset.isScope()) 513 didUseScopeOffset(offset.scopeOffset()); 514 } 515 516 unsigned scopeSize() const 517 { 518 ScopeOffset maxScopeOffset = this->maxScopeOffset(); 519 520 // Do some calculation that relies on invalid scope offset plus one being zero. 521 unsigned fastResult = maxScopeOffset.offsetUnchecked() + 1; 522 523 // Assert that this works. 524 ASSERT(fastResult == (!maxScopeOffset ? 0 : maxScopeOffset.offset() + 1)); 525 526 return fastResult; 527 } 528 529 ScopeOffset nextScopeOffset() const 530 { 531 return ScopeOffset(scopeSize()); 532 } 533 534 ScopeOffset takeNextScopeOffset(const ConcurrentJITLocker&) 535 { 536 ScopeOffset result = nextScopeOffset(); 537 m_maxScopeOffset = result; 538 return result; 539 } 540 541 ScopeOffset takeNextScopeOffset() 542 { 543 ConcurrentJITLocker locker(m_lock); 544 return takeNextScopeOffset(locker); 545 } 546 547 void add(const ConcurrentJITLocker&, StringImpl* key, const SymbolTableEntry& entry) 428 548 { 429 549 RELEASE_ASSERT(!m_localToEntry); 430 return m_map.add(key, entry); 550 didUseVarOffset(entry.varOffset()); 551 Map::AddResult result = m_map.add(key, entry); 552 ASSERT_UNUSED(result, result.isNewEntry); 431 553 } 432 554 … … 437 559 } 438 560 439 Map::AddResultset(const ConcurrentJITLocker&, StringImpl* key, const SymbolTableEntry& entry)561 void set(const ConcurrentJITLocker&, StringImpl* key, const SymbolTableEntry& entry) 440 562 { 441 563 RELEASE_ASSERT(!m_localToEntry); 442 return m_map.set(key, entry); 564 didUseVarOffset(entry.varOffset()); 565 m_map.set(key, entry); 443 566 } 444 567 … … 460 583 } 461 584 585 // The principle behind ScopedArgumentsTable modifications is that we will create one and 586 // leave it unlocked - thereby allowing in-place changes - until someone asks for a pointer to 587 // the table. Then, we will lock it. Then both our future changes and their future changes 588 // will first have to make a copy. This discipline means that usually when we create a 589 // ScopedArguments object, we don't have to make a copy of the ScopedArgumentsTable - instead 590 // we just take a reference to one that we already have. 591 592 uint32_t argumentsLength() const 593 { 594 if (!m_arguments) 595 return 0; 596 return m_arguments->length(); 597 } 598 599 void setArgumentsLength(VM& vm, uint32_t length) 600 { 601 if (UNLIKELY(!m_arguments)) 602 m_arguments.set(vm, this, ScopedArgumentsTable::create(vm)); 603 m_arguments.set(vm, this, m_arguments->setLength(vm, length)); 604 } 605 606 ScopeOffset argumentOffset(uint32_t i) const 607 { 608 ASSERT_WITH_SECURITY_IMPLICATION(m_arguments); 609 return m_arguments->get(i); 610 } 611 612 void setArgumentOffset(VM& vm, uint32_t i, ScopeOffset offset) 613 { 614 ASSERT_WITH_SECURITY_IMPLICATION(m_arguments); 615 m_arguments.set(vm, this, m_arguments->set(vm, i, offset)); 616 } 617 618 ScopedArgumentsTable* arguments() const 619 { 620 if (!m_arguments) 621 return nullptr; 622 m_arguments->lock(); 623 return m_arguments.get(); 624 } 625 462 626 const LocalToEntryVec& localToEntry(const ConcurrentJITLocker&); 463 SymbolTableEntry* entryFor(const ConcurrentJITLocker&, VirtualRegister);464 465 GlobalVariableID uniqueIDForVariable(const ConcurrentJITLocker&, StringImpl* key, VM& vm);466 GlobalVariableID uniqueIDFor Register(const ConcurrentJITLocker& locker, int registerIndex, VM& vm);467 RefPtr<TypeSet> globalTypeSetFor Register(const ConcurrentJITLocker& locker, int registerIndex, VM& vm);468 RefPtr<TypeSet> globalTypeSetForVariable(const ConcurrentJITLocker& locker, StringImpl* key, VM& vm);627 SymbolTableEntry* entryFor(const ConcurrentJITLocker&, ScopeOffset); 628 629 GlobalVariableID uniqueIDForVariable(const ConcurrentJITLocker&, StringImpl* key, VM&); 630 GlobalVariableID uniqueIDForOffset(const ConcurrentJITLocker&, VarOffset, VM&); 631 RefPtr<TypeSet> globalTypeSetForOffset(const ConcurrentJITLocker&, VarOffset, VM&); 632 RefPtr<TypeSet> globalTypeSetForVariable(const ConcurrentJITLocker&, StringImpl* key, VM&); 469 633 470 634 bool usesNonStrictEval() { return m_usesNonStrictEval; } 471 635 void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; } 472 636 473 int captureStart() const { return m_captureStart; } 474 void setCaptureStart(int captureStart) { m_captureStart = captureStart; } 475 476 int captureEnd() const { return m_captureEnd; } 477 void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; } 478 479 int captureCount() const { return -(m_captureEnd - m_captureStart); } 480 481 bool isCaptured(int operand) 482 { 483 return operand <= captureStart() && operand > captureEnd(); 484 } 485 486 int parameterCount() { return m_parameterCountIncludingThis - 1; } 487 int parameterCountIncludingThis() { return m_parameterCountIncludingThis; } 488 void setParameterCountIncludingThis(int parameterCountIncludingThis) { m_parameterCountIncludingThis = parameterCountIncludingThis; } 489 490 // 0 if we don't capture any arguments; parameterCount() in length if we do. 491 const SlowArgument* slowArguments() { return m_slowArguments.get(); } 492 void setSlowArguments(std::unique_ptr<SlowArgument[]> slowArguments) { m_slowArguments = WTF::move(slowArguments); } 493 494 SymbolTable* cloneCapturedNames(VM&); 637 SymbolTable* cloneScopePart(VM&); 495 638 496 639 void prepareForTypeProfiling(const ConcurrentJITLocker&); … … 520 663 521 664 Map m_map; 665 ScopeOffset m_maxScopeOffset; 666 522 667 struct TypeProfilingRareData { 523 668 UniqueIDMap m_uniqueIDMap; 524 RegisterToVariableMap m_registerToVariableMap;669 OffsetToVariableMap m_offsetToVariableMap; 525 670 UniqueTypeSetMap m_uniqueTypeSetMap; 526 671 }; 527 672 std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData; 528 673 529 int m_parameterCountIncludingThis;530 674 bool m_usesNonStrictEval; 531 532 int m_captureStart; 533 int m_captureEnd; 534 535 std::unique_ptr<SlowArgument[]> m_slowArguments; 675 676 WriteBarrier<ScopedArgumentsTable> m_arguments; 536 677 537 678 std::unique_ptr<WatchpointCleanup> m_watchpointCleanup; -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r181990 r181993 218 218 getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); 219 219 customGetterSetterStructure.set(*this, CustomGetterSetter::createStructure(*this, 0, jsNull())); 220 scopedArgumentsTableStructure.set(*this, ScopedArgumentsTable::createStructure(*this, 0, jsNull())); 220 221 apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); 221 222 JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull())); -
trunk/Source/JavaScriptCore/runtime/VM.h
r181458 r181993 1 1 /* 2 * Copyright (C) 2008, 2009, 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 251 251 Strong<Structure> getterSetterStructure; 252 252 Strong<Structure> customGetterSetterStructure; 253 Strong<Structure> scopedArgumentsTableStructure; 253 254 Strong<Structure> apiWrapperStructure; 254 255 Strong<Structure> JSScopeStructure; -
trunk/Source/WTF/ChangeLog
r181979 r181993 1 2015-03-25 Filip Pizlo <fpizlo@apple.com> 2 3 Heap variables shouldn't end up in the stack frame 4 https://bugs.webkit.org/show_bug.cgi?id=141174 5 6 Reviewed by Geoffrey Garen. 7 8 * wtf/FastBitVector.h: 9 (WTF::FastBitVector::resize): Small change: don't resize if you don't have to resize. 10 1 11 2015-03-25 Filip Pizlo <fpizlo@apple.com> 2 12 -
trunk/Source/WTF/wtf/FastBitVector.h
r181467 r181993 72 72 void resize(size_t numBits) 73 73 { 74 if (numBits == m_numBits) 75 return; 76 74 77 // Use fastCalloc instead of fastRealloc because we expect the common 75 78 // use case for this method to be initializing the size of the bitvector.
Note:
See TracChangeset
for help on using the changeset viewer.