Heap variables shouldn't end up in the stack frame
https://bugs.webkit.org/show_bug.cgi?id=141174
Reviewed by Geoffrey Garen.
Source/JavaScriptCore:
This is a major change to how JavaScriptCore handles declared variables (i.e. "var"). It removes
any ambiguity about whether a variable should be in the heap or on the stack. A variable will no
longer move between heap and stack during its lifetime. This enables a bunch of optimizations and
simplifications:
- Accesses to variables no longer need checks or indirections to determine where the variable is
at that moment in time. For example, loading a closure variable now takes just one load instead
of two. Loading an argument by index now takes a bounds check and a load in the fastest case
(when no arguments object allocation is required) while previously that same operation required
a "did I allocate arguments yet" check, a bounds check, and then the load.
- Reasoning about the allocation of an activation or arguments object now follows the same simple
logic as the allocation of any other kind of object. Previously, those objects were lazily
allocated - so an allocation instruction wasn't the actual allocation site, since it might not
allocate anything at all. This made the implementation of traditional escape analyses really
awkward, and ultimately it meant that we missed important cases. Now, we can reason about the
arguments object using the usual SSA tricks which allows for more comprehensive removal.
- The allocations of arguments objects, functions, and activations are now much faster. While
this patch generally expands our ability to eliminate arguments object allocations, an earlier
version of the patch - which lacked that functionality - was a progression on some arguments-
and closure-happy benchmarks because although no allocations were eliminated, all allocations
were faster.
- There is no tear-off. The runtime no loner needs to know about where on the stack a frame keeps
its arguments objects or activations. The runtime doesn't have to do things to the arguments
objects and activations that a frame allocated, when the frame is unwound. We always had horrid
bugs in that code, so it's good to see it go. This removes *a ton* of machinery from the DFG,
FTL, CodeBlock, and other places. All of the things having to do with "captured variables" is
now gone. This also enables implementing block-scoping. Without this change, block-scope
support would require telling CodeBlock and all of the rest of the runtime about all of the
variables that store currently-live scopes. That would have been so disastrously hard that it
might as well be impossible. With this change, it's fair game for the bytecode generator to
simply allocate whatever activations it wants, wherever it wants, and to keep them live for
however long it wants. This all works, because after bytecode generation, an activation is just
an object and variables that refer to it are just normal variables.
- SymbolTable can now tell you explicitly where a variable lives. The answer is in the form of a
VarOffset object, which has methods like isStack(), isScope(), etc. VirtualRegister is never
used for offsets of non-stack variables anymore. We now have shiny new objects for other kinds
of offsets - ScopeOffset for offsets into scopes, and DirectArgumentsOffset for offsets into
an arguments object.
- Functions that create activations can now tier-up into the FTL. Previously they couldn't. Also,
using activations used to prevent inlining; now functions that use activations can be inlined
just fine.
This is a >1% speed-up on Octane. This is a >2% speed-up on CompressionBench. This is a tiny
speed-up on AsmBench (~0.4% or something). This looks like it might be a speed-up on SunSpider.
It's only a slow-down on very short-running microbenchmarks we had previously written for our old
style of tear-off-based arguments optimization. Those benchmarks are not part of any major suite.
The easiest way of understanding this change is to start by looking at the changes in runtime/,
and then the changes in bytecompiler/, and then sort of work your way up the compiler tiers.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbortReason.h:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::BaseIndex::withOffset):
* bytecode/ByValInfo.h:
(JSC::hasOptimizableIndexingForJSType):
(JSC::hasOptimizableIndexing):
(JSC::jitArrayModeForJSType):
(JSC::jitArrayModePermitsPut):
(JSC::jitArrayModeForStructure):
* bytecode/BytecodeKills.h: Added.
(JSC::BytecodeKills::BytecodeKills):
(JSC::BytecodeKills::operandIsKilled):
(JSC::BytecodeKills::forEachOperandKilledAt):
(JSC::BytecodeKills::KillSet::KillSet):
(JSC::BytecodeKills::KillSet::add):
(JSC::BytecodeKills::KillSet::forEachLocal):
(JSC::BytecodeKills::KillSet::contains):
* bytecode/BytecodeList.json:
* bytecode/BytecodeLivenessAnalysis.cpp:
(JSC::isValidRegisterForLiveness):
(JSC::stepOverInstruction):
(JSC::BytecodeLivenessAnalysis::runLivenessFixpoint):
(JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset):
(JSC::BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset):
(JSC::BytecodeLivenessAnalysis::computeFullLiveness):
(JSC::BytecodeLivenessAnalysis::computeKills):
(JSC::indexForOperand): Deleted.
(JSC::BytecodeLivenessAnalysis::getLivenessInfoForNonCapturedVarsAtBytecodeOffset): Deleted.
(JSC::getLivenessInfo): Deleted.
* bytecode/BytecodeLivenessAnalysis.h:
* bytecode/BytecodeLivenessAnalysisInlines.h:
(JSC::operandIsAlwaysLive):
(JSC::operandThatIsNotAlwaysLiveIsLive):
(JSC::operandIsLive):
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::nameForRegister):
(JSC::CodeBlock::validate):
(JSC::CodeBlock::isCaptured): Deleted.
(JSC::CodeBlock::framePointerOffsetToGetActivationRegisters): Deleted.
(JSC::CodeBlock::machineSlowArguments): Deleted.
* bytecode/CodeBlock.h:
(JSC::unmodifiedArgumentsRegister): Deleted.
(JSC::CodeBlock::setArgumentsRegister): Deleted.
(JSC::CodeBlock::argumentsRegister): Deleted.
(JSC::CodeBlock::uncheckedArgumentsRegister): Deleted.
(JSC::CodeBlock::usesArguments): Deleted.
(JSC::CodeBlock::captureCount): Deleted.
(JSC::CodeBlock::captureStart): Deleted.
(JSC::CodeBlock::captureEnd): Deleted.
(JSC::CodeBlock::argumentIndexAfterCapture): Deleted.
(JSC::CodeBlock::hasSlowArguments): Deleted.
(JSC::ExecState::argumentAfterCapture): Deleted.
* bytecode/CodeOrigin.h:
* bytecode/DataFormat.h:
(JSC::dataFormatToString):
* bytecode/FullBytecodeLiveness.h:
(JSC::FullBytecodeLiveness::getLiveness):
(JSC::FullBytecodeLiveness::operandIsLive):
(JSC::FullBytecodeLiveness::FullBytecodeLiveness): Deleted.
(JSC::FullBytecodeLiveness::getOut): Deleted.
* bytecode/Instruction.h:
(JSC::Instruction::Instruction):
* bytecode/Operands.h:
(JSC::Operands::virtualRegisterForIndex):
* bytecode/SpeculatedType.cpp:
(JSC::dumpSpeculation):
(JSC::speculationToAbbreviatedString):
(JSC::speculationFromClassInfo):
* bytecode/SpeculatedType.h:
(JSC::isDirectArgumentsSpeculation):
(JSC::isScopedArgumentsSpeculation):
(JSC::isActionableMutableArraySpeculation):
(JSC::isActionableArraySpeculation):
(JSC::isArgumentsSpeculation): Deleted.
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::setArgumentsRegister): Deleted.
(JSC::UnlinkedCodeBlock::usesArguments): Deleted.
(JSC::UnlinkedCodeBlock::argumentsRegister): Deleted.
* bytecode/ValueRecovery.cpp:
(JSC::ValueRecovery::dumpInContext):
* bytecode/ValueRecovery.h:
(JSC::ValueRecovery::directArgumentsThatWereNotCreated):
(JSC::ValueRecovery::outOfBandArgumentsThatWereNotCreated):
(JSC::ValueRecovery::nodeID):
(JSC::ValueRecovery::argumentsThatWereNotCreated): Deleted.
* bytecode/VirtualRegister.h:
(JSC::VirtualRegister::operator==):
(JSC::VirtualRegister::operator!=):
(JSC::VirtualRegister::operator<):
(JSC::VirtualRegister::operator>):
(JSC::VirtualRegister::operator<=):
(JSC::VirtualRegister::operator>=):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeNextParameter):
(JSC::BytecodeGenerator::visibleNameForParameter):
(JSC::BytecodeGenerator::emitMove):
(JSC::BytecodeGenerator::variable):
(JSC::BytecodeGenerator::createVariable):
(JSC::BytecodeGenerator::emitResolveScope):
(JSC::BytecodeGenerator::emitGetFromScope):
(JSC::BytecodeGenerator::emitPutToScope):
(JSC::BytecodeGenerator::initializeVariable):
(JSC::BytecodeGenerator::emitInstanceOf):
(JSC::BytecodeGenerator::emitNewFunction):
(JSC::BytecodeGenerator::emitNewFunctionInternal):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitReturn):
(JSC::BytecodeGenerator::emitConstruct):
(JSC::BytecodeGenerator::isArgumentNumber):
(JSC::BytecodeGenerator::emitEnumeration):
(JSC::BytecodeGenerator::addVar): Deleted.
(JSC::BytecodeGenerator::emitInitLazyRegister): Deleted.
(JSC::BytecodeGenerator::initializeCapturedVariable): Deleted.
(JSC::BytecodeGenerator::resolveCallee): Deleted.
(JSC::BytecodeGenerator::addCallee): Deleted.
(JSC::BytecodeGenerator::addParameter): Deleted.
(JSC::BytecodeGenerator::willResolveToArgumentsRegister): Deleted.
(JSC::BytecodeGenerator::uncheckedLocalArgumentsRegister): Deleted.
(JSC::BytecodeGenerator::createLazyRegisterIfNecessary): Deleted.
(JSC::BytecodeGenerator::isCaptured): Deleted.
(JSC::BytecodeGenerator::local): Deleted.
(JSC::BytecodeGenerator::constLocal): Deleted.
(JSC::BytecodeGenerator::emitResolveConstantLocal): Deleted.
(JSC::BytecodeGenerator::emitGetArgumentsLength): Deleted.
(JSC::BytecodeGenerator::emitGetArgumentByVal): Deleted.
(JSC::BytecodeGenerator::emitLazyNewFunction): Deleted.
(JSC::BytecodeGenerator::createArgumentsIfNecessary): Deleted.
* bytecompiler/BytecodeGenerator.h:
(JSC::Variable::Variable):
(JSC::Variable::isResolved):
(JSC::Variable::ident):
(JSC::Variable::offset):
(JSC::Variable::isLocal):
(JSC::Variable::local):
(JSC::Variable::isSpecial):
(JSC::BytecodeGenerator::argumentsRegister):
(JSC::BytecodeGenerator::emitNode):
(JSC::BytecodeGenerator::registerFor):
(JSC::Local::Local): Deleted.
(JSC::Local::operator bool): Deleted.
(JSC::Local::get): Deleted.
(JSC::Local::isSpecial): Deleted.
(JSC::ResolveScopeInfo::ResolveScopeInfo): Deleted.
(JSC::ResolveScopeInfo::isLocal): Deleted.
(JSC::ResolveScopeInfo::localIndex): Deleted.
(JSC::BytecodeGenerator::hasSafeLocalArgumentsRegister): Deleted.
(JSC::BytecodeGenerator::captureMode): Deleted.
(JSC::BytecodeGenerator::shouldTearOffArgumentsEagerly): Deleted.
(JSC::BytecodeGenerator::shouldCreateArgumentsEagerly): Deleted.
(JSC::BytecodeGenerator::hasWatchableVariable): Deleted.
(JSC::BytecodeGenerator::watchableVariableIdentifier): Deleted.
* bytecompiler/NodesCodegen.cpp:
(JSC::ResolveNode::isPure):
(JSC::ResolveNode::emitBytecode):
(JSC::BracketAccessorNode::emitBytecode):
(JSC::DotAccessorNode::emitBytecode):
(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
(JSC::PostfixNode::emitResolve):
(JSC::DeleteResolveNode::emitBytecode):
(JSC::TypeOfResolveNode::emitBytecode):
(JSC::PrefixNode::emitResolve):
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::ConstDeclNode::emitCodeSingle):
(JSC::EmptyVarExpression::emitBytecode):
(JSC::ForInNode::tryGetBoundLocal):
(JSC::ForInNode::emitLoopHeader):
(JSC::ForOfNode::emitBytecode):
(JSC::ArrayPatternNode::emitDirectBinding):
(JSC::BindingNode::bindValue):
(JSC::getArgumentByVal): Deleted.
* dfg/DFGAbstractHeap.h:
* dfg/DFGAbstractInterpreter.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberWorld):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberCapturedVars): Deleted.
* dfg/DFGAbstractValue.h:
* dfg/DFGArgumentPosition.h:
(JSC::DFG::ArgumentPosition::addVariable):
* dfg/DFGArgumentsEliminationPhase.cpp: Added.
(JSC::DFG::performArgumentsElimination):
* dfg/DFGArgumentsEliminationPhase.h: Added.
* dfg/DFGArgumentsSimplificationPhase.cpp: Removed.
* dfg/DFGArgumentsSimplificationPhase.h: Removed.
* dfg/DFGArgumentsUtilities.cpp: Added.
(JSC::DFG::argumentsInvolveStackSlot):
(JSC::DFG::emitCodeToGetArgumentsArrayLength):
* dfg/DFGArgumentsUtilities.h: Added.
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::refine):
(JSC::DFG::ArrayMode::alreadyChecked):
(JSC::DFG::arrayTypeToString):
* dfg/DFGArrayMode.h:
(JSC::DFG::ArrayMode::canCSEStorage):
(JSC::DFG::ArrayMode::modeForPut):
* dfg/DFGAvailabilityMap.cpp:
(JSC::DFG::AvailabilityMap::prune):
* dfg/DFGAvailabilityMap.h:
(JSC::DFG::AvailabilityMap::closeOverNodes):
(JSC::DFG::AvailabilityMap::closeStartingWithLocal):
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::newVariableAccessData):
(JSC::DFG::ByteCodeParser::getLocal):
(JSC::DFG::ByteCodeParser::setLocal):
(JSC::DFG::ByteCodeParser::getArgument):
(JSC::DFG::ByteCodeParser::setArgument):
(JSC::DFG::ByteCodeParser::flushDirect):
(JSC::DFG::ByteCodeParser::flush):
(JSC::DFG::ByteCodeParser::noticeArgumentsUse):
(JSC::DFG::ByteCodeParser::handleVarargsCall):
(JSC::DFG::ByteCodeParser::attemptToInlineCall):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* dfg/DFGCPSRethreadingPhase.cpp:
(JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
(JSC::DFG::CPSRethreadingPhase::canonicalizeLocalsInBlock):
* dfg/DFGCSEPhase.cpp:
* dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h: Added.
(JSC::DFG::CallCreateDirectArgumentsSlowPathGenerator::CallCreateDirectArgumentsSlowPathGenerator):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::isSupportedForInlining):
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGCommon.h:
* dfg/DFGCommonData.h:
(JSC::DFG::CommonData::CommonData):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::cleanVariables):
* dfg/DFGDisassembler.h:
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGFlushFormat.cpp:
(WTF::printInternal):
* dfg/DFGFlushFormat.h:
(JSC::DFG::resultFor):
(JSC::DFG::useKindFor):
(JSC::DFG::dataFormatFor):
* dfg/DFGForAllKills.h: Added.
(JSC::DFG::forAllLiveNodesAtTail):
(JSC::DFG::forAllDirectlyKilledOperands):
(JSC::DFG::forAllKilledOperands):
(JSC::DFG::forAllKilledNodesAtNodeIndex):
(JSC::DFG::forAllKillsInBlock):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::substituteGetLocal):
(JSC::DFG::Graph::livenessFor):
(JSC::DFG::Graph::killsFor):
(JSC::DFG::Graph::tryGetConstantClosureVar):
(JSC::DFG::Graph::tryGetRegisters): Deleted.
* dfg/DFGGraph.h:
(JSC::DFG::Graph::symbolTableFor):
(JSC::DFG::Graph::uses):
(JSC::DFG::Graph::bytecodeRegisterForArgument): Deleted.
(JSC::DFG::Graph::capturedVarsFor): Deleted.
(JSC::DFG::Graph::usesArguments): Deleted.
(JSC::DFG::Graph::argumentsRegisterFor): Deleted.
(JSC::DFG::Graph::machineArgumentsRegisterFor): Deleted.
(JSC::DFG::Graph::uncheckedArgumentsRegisterFor): Deleted.
* dfg/DFGHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGHeapLocation.h:
* dfg/DFGInPlaceAbstractState.cpp:
(JSC::DFG::InPlaceAbstractState::initialize):
(JSC::DFG::InPlaceAbstractState::mergeStateAtTail):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGMayExit.cpp:
(JSC::DFG::mayExit):
* dfg/DFGMinifiedID.h:
* dfg/DFGMinifiedNode.cpp:
(JSC::DFG::MinifiedNode::fromNode):
* dfg/DFGMinifiedNode.h:
(JSC::DFG::belongsInMinifiedGraph):
(JSC::DFG::MinifiedNode::hasInlineCallFrame):
(JSC::DFG::MinifiedNode::inlineCallFrame):
* dfg/DFGNode.cpp:
(JSC::DFG::Node::convertToIdentityOn):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasConstant):
(JSC::DFG::Node::constant):
(JSC::DFG::Node::hasScopeOffset):
(JSC::DFG::Node::scopeOffset):
(JSC::DFG::Node::hasDirectArgumentsOffset):
(JSC::DFG::Node::capturedArgumentsOffset):
(JSC::DFG::Node::variablePointer):
(JSC::DFG::Node::hasCallVarargsData):
(JSC::DFG::Node::hasLoadVarargsData):
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasCellOperand):
(JSC::DFG::Node::objectMaterializationData):
(JSC::DFG::Node::isPhantomAllocation):
(JSC::DFG::Node::willHaveCodeGenOrOSR):
(JSC::DFG::Node::shouldSpeculateDirectArguments):
(JSC::DFG::Node::shouldSpeculateScopedArguments):
(JSC::DFG::Node::isPhantomArguments): Deleted.
(JSC::DFG::Node::hasVarNumber): Deleted.
(JSC::DFG::Node::varNumber): Deleted.
(JSC::DFG::Node::registerPointer): Deleted.
(JSC::DFG::Node::shouldSpeculateArguments): Deleted.
* dfg/DFGNodeType.h:
* dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
(JSC::DFG::OSRAvailabilityAnalysisPhase::run):
(JSC::DFG::LocalOSRAvailabilityCalculator::executeNode):
* dfg/DFGOSRExitCompiler.cpp:
(JSC::DFG::OSRExitCompiler::emitRestoreArguments):
* dfg/DFGOSRExitCompiler.h:
(JSC::DFG::OSRExitCompiler::badIndex): Deleted.
(JSC::DFG::OSRExitCompiler::initializePoisoned): Deleted.
(JSC::DFG::OSRExitCompiler::poisonIndex): Deleted.
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompilerCommon.cpp:
(JSC::DFG::reifyInlinedCallFrames):
(JSC::DFG::ArgumentsRecoveryGenerator::ArgumentsRecoveryGenerator): Deleted.
(JSC::DFG::ArgumentsRecoveryGenerator::~ArgumentsRecoveryGenerator): Deleted.
(JSC::DFG::ArgumentsRecoveryGenerator::generateFor): Deleted.
* dfg/DFGOSRExitCompilerCommon.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h:
(JSC::DFG::PreciseLocalClobberizeAdaptor::read):
(JSC::DFG::PreciseLocalClobberizeAdaptor::write):
(JSC::DFG::PreciseLocalClobberizeAdaptor::def):
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
(JSC::DFG::preciseLocalClobberize):
(JSC::DFG::PreciseLocalClobberizeAdaptor::writeTop): Deleted.
(JSC::DFG::forEachLocalReadByUnwind): Deleted.
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::run):
(JSC::DFG::PredictionPropagationPhase::propagate):
(JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting):
(JSC::DFG::PredictionPropagationPhase::propagateThroughArgumentPositions):
* dfg/DFGPromoteHeapAccess.h:
(JSC::DFG::promoteHeapAccess):
* dfg/DFGPromotedHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGPromotedHeapLocation.h:
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitAllocateJSArray):
(JSC::DFG::SpeculativeJIT::emitGetLength):
(JSC::DFG::SpeculativeJIT::emitGetCallee):
(JSC::DFG::SpeculativeJIT::emitGetArgumentStart):
(JSC::DFG::SpeculativeJIT::checkArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments):
(JSC::DFG::SpeculativeJIT::compileGetByValOnScopedArguments):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
(JSC::DFG::SpeculativeJIT::compileNewFunction):
(JSC::DFG::SpeculativeJIT::compileForwardVarargs):
(JSC::DFG::SpeculativeJIT::compileCreateActivation):
(JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
(JSC::DFG::SpeculativeJIT::compileGetFromArguments):
(JSC::DFG::SpeculativeJIT::compilePutToArguments):
(JSC::DFG::SpeculativeJIT::compileCreateScopedArguments):
(JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
(JSC::DFG::SpeculativeJIT::emitAllocateArguments): Deleted.
(JSC::DFG::SpeculativeJIT::compileGetByValOnArguments): Deleted.
(JSC::DFG::SpeculativeJIT::compileGetArgumentsLength): Deleted.
(JSC::DFG::SpeculativeJIT::compileNewFunctionNoCheck): Deleted.
(JSC::DFG::SpeculativeJIT::compileNewFunctionExpression): Deleted.
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
(JSC::DFG::SpeculativeJIT::emitAllocateJSObjectWithKnownSize):
(JSC::DFG::SpeculativeJIT::emitAllocateJSObject):
(JSC::DFG::SpeculativeJIT::framePointerOffsetToGetActivationRegisters): Deleted.
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStackLayoutPhase.cpp:
(JSC::DFG::StackLayoutPhase::run):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* dfg/DFGStructureRegistrationPhase.cpp:
(JSC::DFG::StructureRegistrationPhase::run):
* dfg/DFGUnificationPhase.cpp:
(JSC::DFG::UnificationPhase::run):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validateCPS):
* dfg/DFGValueSource.cpp:
(JSC::DFG::ValueSource::dump):
* dfg/DFGValueSource.h:
(JSC::DFG::dataFormatToValueSourceKind):
(JSC::DFG::valueSourceKindToDataFormat):
(JSC::DFG::ValueSource::ValueSource):
(JSC::DFG::ValueSource::forFlushFormat):
(JSC::DFG::ValueSource::valueRecovery):
* dfg/DFGVarargsForwardingPhase.cpp: Added.
(JSC::DFG::performVarargsForwarding):
* dfg/DFGVarargsForwardingPhase.h: Added.
* dfg/DFGVariableAccessData.cpp:
(JSC::DFG::VariableAccessData::VariableAccessData):
(JSC::DFG::VariableAccessData::flushFormat):
(JSC::DFG::VariableAccessData::mergeIsCaptured): Deleted.
* dfg/DFGVariableAccessData.h:
(JSC::DFG::VariableAccessData::shouldNeverUnbox):
(JSC::DFG::VariableAccessData::shouldUseDoubleFormat):
(JSC::DFG::VariableAccessData::isCaptured): Deleted.
(JSC::DFG::VariableAccessData::mergeIsArgumentsAlias): Deleted.
(JSC::DFG::VariableAccessData::isArgumentsAlias): Deleted.
* dfg/DFGVariableAccessDataDump.cpp:
(JSC::DFG::VariableAccessDataDump::dump):
* dfg/DFGVariableAccessDataDump.h:
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::tryToSetConstantRecovery):
* dfg/DFGVariableEventStream.h:
* ftl/FTLAbstractHeap.cpp:
(JSC::FTL::AbstractHeap::dump):
(JSC::FTL::AbstractField::dump):
(JSC::FTL::IndexedAbstractHeap::dump):
(JSC::FTL::NumberedAbstractHeap::dump):
(JSC::FTL::AbsoluteAbstractHeap::dump):
* ftl/FTLAbstractHeap.h:
* ftl/FTLAbstractHeapRepository.cpp:
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLCompile.cpp:
(JSC::FTL::mmAllocateDataSection):
* ftl/FTLExitArgument.cpp:
(JSC::FTL::ExitArgument::dump):
* ftl/FTLExitPropertyValue.cpp:
(JSC::FTL::ExitPropertyValue::withLocalsOffset):
* ftl/FTLExitPropertyValue.h:
* ftl/FTLExitTimeObjectMaterialization.cpp:
(JSC::FTL::ExitTimeObjectMaterialization::ExitTimeObjectMaterialization):
(JSC::FTL::ExitTimeObjectMaterialization::accountForLocalsOffset):
* ftl/FTLExitTimeObjectMaterialization.h:
(JSC::FTL::ExitTimeObjectMaterialization::origin):
* ftl/FTLExitValue.cpp:
(JSC::FTL::ExitValue::withLocalsOffset):
(JSC::FTL::ExitValue::valueFormat):
(JSC::FTL::ExitValue::dumpInContext):
* ftl/FTLExitValue.h:
(JSC::FTL::ExitValue::isArgument):
(JSC::FTL::ExitValue::argumentsObjectThatWasNotCreated): Deleted.
(JSC::FTL::ExitValue::isArgumentsObjectThatWasNotCreated): Deleted.
(JSC::FTL::ExitValue::valueFormat): Deleted.
* ftl/FTLInlineCacheSize.cpp:
(JSC::FTL::sizeOfCallForwardVarargs):
(JSC::FTL::sizeOfConstructForwardVarargs):
(JSC::FTL::sizeOfICFor):
* ftl/FTLInlineCacheSize.h:
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLJSCallVarargs.cpp:
(JSC::FTL::JSCallVarargs::JSCallVarargs):
(JSC::FTL::JSCallVarargs::emit):
* ftl/FTLJSCallVarargs.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::lower):
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compilePutStack):
(JSC::FTL::LowerDFGToLLVM::compileGetArrayLength):
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::LowerDFGToLLVM::compileGetMyArgumentByVal):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::compileArrayPush):
(JSC::FTL::LowerDFGToLLVM::compileArrayPop):
(JSC::FTL::LowerDFGToLLVM::compileCreateActivation):
(JSC::FTL::LowerDFGToLLVM::compileNewFunction):
(JSC::FTL::LowerDFGToLLVM::compileCreateDirectArguments):
(JSC::FTL::LowerDFGToLLVM::compileCreateScopedArguments):
(JSC::FTL::LowerDFGToLLVM::compileCreateClonedArguments):
(JSC::FTL::LowerDFGToLLVM::compileStringCharAt):
(JSC::FTL::LowerDFGToLLVM::compileStringCharCodeAt):
(JSC::FTL::LowerDFGToLLVM::compileGetGlobalVar):
(JSC::FTL::LowerDFGToLLVM::compilePutGlobalVar):
(JSC::FTL::LowerDFGToLLVM::compileGetArgumentCount):
(JSC::FTL::LowerDFGToLLVM::compileGetClosureVar):
(JSC::FTL::LowerDFGToLLVM::compilePutClosureVar):
(JSC::FTL::LowerDFGToLLVM::compileGetFromArguments):
(JSC::FTL::LowerDFGToLLVM::compilePutToArguments):
(JSC::FTL::LowerDFGToLLVM::compileCallOrConstructVarargs):
(JSC::FTL::LowerDFGToLLVM::compileForwardVarargs):
(JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorPname):
(JSC::FTL::LowerDFGToLLVM::ArgumentsLength::ArgumentsLength):
(JSC::FTL::LowerDFGToLLVM::getArgumentsLength):
(JSC::FTL::LowerDFGToLLVM::getCurrentCallee):
(JSC::FTL::LowerDFGToLLVM::getArgumentsStart):
(JSC::FTL::LowerDFGToLLVM::baseIndex):
(JSC::FTL::LowerDFGToLLVM::allocateObject):
(JSC::FTL::LowerDFGToLLVM::allocateVariableSizedObject):
(JSC::FTL::LowerDFGToLLVM::isArrayType):
(JSC::FTL::LowerDFGToLLVM::emitStoreBarrier):
(JSC::FTL::LowerDFGToLLVM::buildExitArguments):
(JSC::FTL::LowerDFGToLLVM::exitValueForAvailability):
(JSC::FTL::LowerDFGToLLVM::exitValueForNode):
(JSC::FTL::LowerDFGToLLVM::loadStructure):
(JSC::FTL::LowerDFGToLLVM::compilePhantomArguments): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileGetMyArgumentsLength): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileGetClosureRegisters): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileCheckArgumentsNotCreated): Deleted.
(JSC::FTL::LowerDFGToLLVM::checkArgumentsNotCreated): Deleted.
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileRecovery):
(JSC::FTL::compileStub):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationMaterializeObjectInOSR):
* ftl/FTLOutput.h:
(JSC::FTL::Output::aShr):
(JSC::FTL::Output::lShr):
(JSC::FTL::Output::zeroExtPtr):
* heap/CopyToken.h:
* interpreter/CallFrame.h:
(JSC::ExecState::getArgumentUnsafe):
* interpreter/Interpreter.cpp:
(JSC::sizeOfVarargs):
(JSC::sizeFrameForVarargs):
(JSC::loadVarargs):
(JSC::unwindCallFrame):
* interpreter/Interpreter.h:
* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::Frame::createArguments):
(JSC::StackVisitor::Frame::existingArguments): Deleted.
* interpreter/StackVisitor.h:
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::storeValue):
(JSC::AssemblyHelpers::loadValue):
(JSC::AssemblyHelpers::storeTrustedValue):
(JSC::AssemblyHelpers::branchIfNotCell):
(JSC::AssemblyHelpers::branchIsEmpty):
(JSC::AssemblyHelpers::argumentsStart):
(JSC::AssemblyHelpers::baselineArgumentsRegisterFor): Deleted.
(JSC::AssemblyHelpers::offsetOfLocals): Deleted.
(JSC::AssemblyHelpers::offsetOfArguments): Deleted.
* jit/CCallHelpers.h:
(JSC::CCallHelpers::setupArgument):
* jit/GPRInfo.h:
(JSC::JSValueRegs::withTwoAvailableRegs):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITCall.cpp:
(JSC::JIT::compileSetupVarargsFrame):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileSetupVarargsFrame):
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_create_lexical_environment):
(JSC::JIT::emit_op_new_func):
(JSC::JIT::emit_op_create_direct_arguments):
(JSC::JIT::emit_op_create_scoped_arguments):
(JSC::JIT::emit_op_create_out_of_band_arguments):
(JSC::JIT::emit_op_tear_off_arguments): Deleted.
(JSC::JIT::emit_op_create_arguments): Deleted.
(JSC::JIT::emit_op_init_lazy_reg): Deleted.
(JSC::JIT::emit_op_get_arguments_length): Deleted.
(JSC::JIT::emitSlow_op_get_arguments_length): Deleted.
(JSC::JIT::emit_op_get_argument_by_val): Deleted.
(JSC::JIT::emitSlow_op_get_argument_by_val): Deleted.
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_create_lexical_environment):
(JSC::JIT::emit_op_tear_off_arguments): Deleted.
(JSC::JIT::emit_op_create_arguments): Deleted.
(JSC::JIT::emit_op_init_lazy_reg): Deleted.
(JSC::JIT::emit_op_get_arguments_length): Deleted.
(JSC::JIT::emitSlow_op_get_arguments_length): Deleted.
(JSC::JIT::emit_op_get_argument_by_val): Deleted.
(JSC::JIT::emitSlow_op_get_argument_by_val): Deleted.
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitGetClosureVar):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_get_from_arguments):
(JSC::JIT::emit_op_put_to_arguments):
(JSC::JIT::emit_op_init_global_const):
(JSC::JIT::privateCompileGetByVal):
(JSC::JIT::emitDirectArgumentsGetByVal):
(JSC::JIT::emitScopedArgumentsGetByVal):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emitGetClosureVar):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_get_from_arguments):
(JSC::JIT::emit_op_put_to_arguments):
(JSC::JIT::emit_op_init_global_const):
* jit/SetupVarargsFrame.cpp:
(JSC::emitSetupVarargsFrameFastCase):
* llint/LLIntOffsetsExtractor.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* parser/Nodes.h:
(JSC::ScopeNode::captures):
* runtime/Arguments.cpp: Removed.
* runtime/Arguments.h: Removed.
* runtime/ArgumentsMode.h: Added.
* runtime/DirectArgumentsOffset.cpp: Added.
(JSC::DirectArgumentsOffset::dump):
* runtime/DirectArgumentsOffset.h: Added.
(JSC::DirectArgumentsOffset::DirectArgumentsOffset):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* runtime/ConstantMode.cpp: Added.
(WTF::printInternal):
* runtime/ConstantMode.h:
(JSC::modeForIsConstant):
* runtime/DirectArguments.cpp: Added.
(JSC::DirectArguments::DirectArguments):
(JSC::DirectArguments::createUninitialized):
(JSC::DirectArguments::create):
(JSC::DirectArguments::createByCopying):
(JSC::DirectArguments::visitChildren):
(JSC::DirectArguments::copyBackingStore):
(JSC::DirectArguments::createStructure):
(JSC::DirectArguments::overrideThings):
(JSC::DirectArguments::overrideThingsIfNecessary):
(JSC::DirectArguments::overrideArgument):
(JSC::DirectArguments::copyToArguments):
(JSC::DirectArguments::overridesSize):
* runtime/DirectArguments.h: Added.
(JSC::DirectArguments::internalLength):
(JSC::DirectArguments::length):
(JSC::DirectArguments::canAccessIndexQuickly):
(JSC::DirectArguments::getIndexQuickly):
(JSC::DirectArguments::setIndexQuickly):
(JSC::DirectArguments::callee):
(JSC::DirectArguments::argument):
(JSC::DirectArguments::overrodeThings):
(JSC::DirectArguments::offsetOfCallee):
(JSC::DirectArguments::offsetOfLength):
(JSC::DirectArguments::offsetOfMinCapacity):
(JSC::DirectArguments::offsetOfOverrides):
(JSC::DirectArguments::storageOffset):
(JSC::DirectArguments::offsetOfSlot):
(JSC::DirectArguments::allocationSize):
(JSC::DirectArguments::storage):
* runtime/FunctionPrototype.cpp:
* runtime/GenericArguments.h: Added.
(JSC::GenericArguments::GenericArguments):
* runtime/GenericArgumentsInlines.h: Added.
(JSC::GenericArguments<Type>::getOwnPropertySlot):
(JSC::GenericArguments<Type>::getOwnPropertySlotByIndex):
(JSC::GenericArguments<Type>::getOwnPropertyNames):
(JSC::GenericArguments<Type>::put):
(JSC::GenericArguments<Type>::putByIndex):
(JSC::GenericArguments<Type>::deleteProperty):
(JSC::GenericArguments<Type>::deletePropertyByIndex):
(JSC::GenericArguments<Type>::defineOwnProperty):
(JSC::GenericArguments<Type>::copyToArguments):
* runtime/GenericOffset.h: Added.
(JSC::GenericOffset::GenericOffset):
(JSC::GenericOffset::operator!):
(JSC::GenericOffset::offsetUnchecked):
(JSC::GenericOffset::offset):
(JSC::GenericOffset::operator==):
(JSC::GenericOffset::operator!=):
(JSC::GenericOffset::operator<):
(JSC::GenericOffset::operator>):
(JSC::GenericOffset::operator<=):
(JSC::GenericOffset::operator>=):
(JSC::GenericOffset::operator+):
(JSC::GenericOffset::operator-):
(JSC::GenericOffset::operator+=):
(JSC::GenericOffset::operator-=):
* runtime/JSArgumentsIterator.cpp:
(JSC::JSArgumentsIterator::finishCreation):
(JSC::argumentsFuncIterator):
* runtime/JSArgumentsIterator.h:
(JSC::JSArgumentsIterator::create):
(JSC::JSArgumentsIterator::next):
* runtime/JSEnvironmentRecord.cpp:
(JSC::JSEnvironmentRecord::visitChildren):
* runtime/JSEnvironmentRecord.h:
(JSC::JSEnvironmentRecord::variables):
(JSC::JSEnvironmentRecord::isValid):
(JSC::JSEnvironmentRecord::variableAt):
(JSC::JSEnvironmentRecord::offsetOfVariables):
(JSC::JSEnvironmentRecord::offsetOfVariable):
(JSC::JSEnvironmentRecord::allocationSizeForScopeSize):
(JSC::JSEnvironmentRecord::allocationSize):
(JSC::JSEnvironmentRecord::JSEnvironmentRecord):
(JSC::JSEnvironmentRecord::finishCreationUninitialized):
(JSC::JSEnvironmentRecord::finishCreation):
(JSC::JSEnvironmentRecord::registers): Deleted.
(JSC::JSEnvironmentRecord::registerAt): Deleted.
(JSC::JSEnvironmentRecord::addressOfRegisters): Deleted.
(JSC::JSEnvironmentRecord::offsetOfRegisters): Deleted.
* runtime/JSFunction.cpp:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::addGlobalVar):
(JSC::JSGlobalObject::addFunction):
(JSC::JSGlobalObject::visitChildren):
(JSC::JSGlobalObject::addStaticGlobals):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::directArgumentsStructure):
(JSC::JSGlobalObject::scopedArgumentsStructure):
(JSC::JSGlobalObject::outOfBandArgumentsStructure):
(JSC::JSGlobalObject::argumentsStructure): Deleted.
* runtime/JSLexicalEnvironment.cpp:
(JSC::JSLexicalEnvironment::symbolTableGet):
(JSC::JSLexicalEnvironment::symbolTablePut):
(JSC::JSLexicalEnvironment::getOwnNonIndexPropertyNames):
(JSC::JSLexicalEnvironment::symbolTablePutWithAttributes):
(JSC::JSLexicalEnvironment::visitChildren): Deleted.
* runtime/JSLexicalEnvironment.h:
(JSC::JSLexicalEnvironment::create):
(JSC::JSLexicalEnvironment::JSLexicalEnvironment):
(JSC::JSLexicalEnvironment::registersOffset): Deleted.
(JSC::JSLexicalEnvironment::storageOffset): Deleted.
(JSC::JSLexicalEnvironment::storage): Deleted.
(JSC::JSLexicalEnvironment::allocationSize): Deleted.
(JSC::JSLexicalEnvironment::isValidIndex): Deleted.
(JSC::JSLexicalEnvironment::isValid): Deleted.
(JSC::JSLexicalEnvironment::registerAt): Deleted.
* runtime/JSNameScope.cpp:
(JSC::JSNameScope::visitChildren): Deleted.
* runtime/JSNameScope.h:
(JSC::JSNameScope::create):
(JSC::JSNameScope::value):
(JSC::JSNameScope::finishCreation):
(JSC::JSNameScope::JSNameScope):
* runtime/JSScope.cpp:
(JSC::abstractAccess):
* runtime/JSSegmentedVariableObject.cpp:
(JSC::JSSegmentedVariableObject::findVariableIndex):
(JSC::JSSegmentedVariableObject::addVariables):
(JSC::JSSegmentedVariableObject::visitChildren):
(JSC::JSSegmentedVariableObject::findRegisterIndex): Deleted.
(JSC::JSSegmentedVariableObject::addRegisters): Deleted.
* runtime/JSSegmentedVariableObject.h:
(JSC::JSSegmentedVariableObject::variableAt):
(JSC::JSSegmentedVariableObject::assertVariableIsInThisObject):
(JSC::JSSegmentedVariableObject::registerAt): Deleted.
(JSC::JSSegmentedVariableObject::assertRegisterIsInThisObject): Deleted.
* runtime/JSSymbolTableObject.h:
(JSC::JSSymbolTableObject::offsetOfSymbolTable):
(JSC::symbolTableGet):
(JSC::symbolTablePut):
(JSC::symbolTablePutWithAttributes):
* runtime/JSType.h:
* runtime/Options.h:
* runtime/ClonedArguments.cpp: Added.
(JSC::ClonedArguments::ClonedArguments):
(JSC::ClonedArguments::createEmpty):
(JSC::ClonedArguments::createWithInlineFrame):
(JSC::ClonedArguments::createWithMachineFrame):
(JSC::ClonedArguments::createByCopyingFrom):
(JSC::ClonedArguments::createStructure):
(JSC::ClonedArguments::getOwnPropertySlot):
(JSC::ClonedArguments::getOwnPropertyNames):
(JSC::ClonedArguments::put):
(JSC::ClonedArguments::deleteProperty):
(JSC::ClonedArguments::defineOwnProperty):
(JSC::ClonedArguments::materializeSpecials):
(JSC::ClonedArguments::materializeSpecialsIfNecessary):
* runtime/ClonedArguments.h: Added.
(JSC::ClonedArguments::specialsMaterialized):
* runtime/ScopeOffset.cpp: Added.
(JSC::ScopeOffset::dump):
* runtime/ScopeOffset.h: Added.
(JSC::ScopeOffset::ScopeOffset):
* runtime/ScopedArguments.cpp: Added.
(JSC::ScopedArguments::ScopedArguments):
(JSC::ScopedArguments::finishCreation):
(JSC::ScopedArguments::createUninitialized):
(JSC::ScopedArguments::create):
(JSC::ScopedArguments::createByCopying):
(JSC::ScopedArguments::createByCopyingFrom):
(JSC::ScopedArguments::visitChildren):
(JSC::ScopedArguments::createStructure):
(JSC::ScopedArguments::overrideThings):
(JSC::ScopedArguments::overrideThingsIfNecessary):
(JSC::ScopedArguments::overrideArgument):
(JSC::ScopedArguments::copyToArguments):
* runtime/ScopedArguments.h: Added.
(JSC::ScopedArguments::internalLength):
(JSC::ScopedArguments::length):
(JSC::ScopedArguments::canAccessIndexQuickly):
(JSC::ScopedArguments::getIndexQuickly):
(JSC::ScopedArguments::setIndexQuickly):
(JSC::ScopedArguments::callee):
(JSC::ScopedArguments::overrodeThings):
(JSC::ScopedArguments::offsetOfOverrodeThings):
(JSC::ScopedArguments::offsetOfTotalLength):
(JSC::ScopedArguments::offsetOfTable):
(JSC::ScopedArguments::offsetOfScope):
(JSC::ScopedArguments::overflowStorageOffset):
(JSC::ScopedArguments::allocationSize):
(JSC::ScopedArguments::overflowStorage):
* runtime/ScopedArgumentsTable.cpp: Added.
(JSC::ScopedArgumentsTable::ScopedArgumentsTable):
(JSC::ScopedArgumentsTable::~ScopedArgumentsTable):
(JSC::ScopedArgumentsTable::destroy):
(JSC::ScopedArgumentsTable::create):
(JSC::ScopedArgumentsTable::clone):
(JSC::ScopedArgumentsTable::setLength):
(JSC::ScopedArgumentsTable::set):
(JSC::ScopedArgumentsTable::createStructure):
* runtime/ScopedArgumentsTable.h: Added.
(JSC::ScopedArgumentsTable::length):
(JSC::ScopedArgumentsTable::get):
(JSC::ScopedArgumentsTable::lock):
(JSC::ScopedArgumentsTable::offsetOfLength):
(JSC::ScopedArgumentsTable::offsetOfArguments):
(JSC::ScopedArgumentsTable::at):
* runtime/SymbolTable.cpp:
(JSC::SymbolTableEntry::prepareToWatch):
(JSC::SymbolTable::SymbolTable):
(JSC::SymbolTable::visitChildren):
(JSC::SymbolTable::localToEntry):
(JSC::SymbolTable::entryFor):
(JSC::SymbolTable::cloneScopePart):
(JSC::SymbolTable::prepareForTypeProfiling):
(JSC::SymbolTable::uniqueIDForOffset):
(JSC::SymbolTable::globalTypeSetForOffset):
(JSC::SymbolTable::cloneCapturedNames): Deleted.
(JSC::SymbolTable::uniqueIDForRegister): Deleted.
(JSC::SymbolTable::globalTypeSetForRegister): Deleted.
* runtime/SymbolTable.h:
(JSC::SymbolTableEntry::varOffsetFromBits):
(JSC::SymbolTableEntry::scopeOffsetFromBits):
(JSC::SymbolTableEntry::Fast::varOffset):
(JSC::SymbolTableEntry::Fast::scopeOffset):
(JSC::SymbolTableEntry::Fast::isDontEnum):
(JSC::SymbolTableEntry::Fast::getAttributes):
(JSC::SymbolTableEntry::SymbolTableEntry):
(JSC::SymbolTableEntry::varOffset):
(JSC::SymbolTableEntry::isWatchable):
(JSC::SymbolTableEntry::scopeOffset):
(JSC::SymbolTableEntry::setAttributes):
(JSC::SymbolTableEntry::constantMode):
(JSC::SymbolTableEntry::isDontEnum):
(JSC::SymbolTableEntry::disableWatching):
(JSC::SymbolTableEntry::pack):
(JSC::SymbolTableEntry::isValidVarOffset):
(JSC::SymbolTable::createNameScopeTable):
(JSC::SymbolTable::maxScopeOffset):
(JSC::SymbolTable::didUseScopeOffset):
(JSC::SymbolTable::didUseVarOffset):
(JSC::SymbolTable::scopeSize):
(JSC::SymbolTable::nextScopeOffset):
(JSC::SymbolTable::takeNextScopeOffset):
(JSC::SymbolTable::add):
(JSC::SymbolTable::set):
(JSC::SymbolTable::argumentsLength):
(JSC::SymbolTable::setArgumentsLength):
(JSC::SymbolTable::argumentOffset):
(JSC::SymbolTable::setArgumentOffset):
(JSC::SymbolTable::arguments):
(JSC::SlowArgument::SlowArgument): Deleted.
(JSC::SymbolTableEntry::Fast::getIndex): Deleted.
(JSC::SymbolTableEntry::getIndex): Deleted.
(JSC::SymbolTableEntry::isValidIndex): Deleted.
(JSC::SymbolTable::captureStart): Deleted.
(JSC::SymbolTable::setCaptureStart): Deleted.
(JSC::SymbolTable::captureEnd): Deleted.
(JSC::SymbolTable::setCaptureEnd): Deleted.
(JSC::SymbolTable::captureCount): Deleted.
(JSC::SymbolTable::isCaptured): Deleted.
(JSC::SymbolTable::parameterCount): Deleted.
(JSC::SymbolTable::parameterCountIncludingThis): Deleted.
(JSC::SymbolTable::setParameterCountIncludingThis): Deleted.
(JSC::SymbolTable::slowArguments): Deleted.
(JSC::SymbolTable::setSlowArguments): Deleted.
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* runtime/VarOffset.cpp: Added.
(JSC::VarOffset::dump):
(WTF::printInternal):
* runtime/VarOffset.h: Added.
(JSC::VarOffset::VarOffset):
(JSC::VarOffset::assemble):
(JSC::VarOffset::isValid):
(JSC::VarOffset::operator!):
(JSC::VarOffset::kind):
(JSC::VarOffset::isStack):
(JSC::VarOffset::isScope):
(JSC::VarOffset::isDirectArgument):
(JSC::VarOffset::stackOffsetUnchecked):
(JSC::VarOffset::scopeOffsetUnchecked):
(JSC::VarOffset::capturedArgumentsOffsetUnchecked):
(JSC::VarOffset::stackOffset):
(JSC::VarOffset::scopeOffset):
(JSC::VarOffset::capturedArgumentsOffset):
(JSC::VarOffset::rawOffset):
(JSC::VarOffset::checkSanity):
(JSC::VarOffset::operator==):
(JSC::VarOffset::operator!=):
(JSC::VarOffset::hash):
(JSC::VarOffset::isHashTableDeletedValue):
(JSC::VarOffsetHash::hash):
(JSC::VarOffsetHash::equal):
* tests/stress/arguments-exit-strict-mode.js: Added.
* tests/stress/arguments-exit.js: Added.
* tests/stress/arguments-inlined-exit-strict-mode-fixed.js: Added.
* tests/stress/arguments-inlined-exit-strict-mode.js: Added.
* tests/stress/arguments-inlined-exit.js: Added.
* tests/stress/arguments-interference.js: Added.
* tests/stress/arguments-interference-cfg.js: Added.
* tests/stress/dead-get-closure-var.js: Added.
* tests/stress/get-declared-unpassed-argument-in-direct-arguments.js: Added.
* tests/stress/get-declared-unpassed-argument-in-scoped-arguments.js: Added.
* tests/stress/varargs-closure-inlined-exit-strict-mode.js: Added.
* tests/stress/varargs-closure-inlined-exit.js: Added.
* tests/stress/varargs-exit.js: Added.
* tests/stress/varargs-inlined-exit.js: Added.
* tests/stress/varargs-inlined-simple-exit-aliasing-weird-reversed-args.js: Added.
* tests/stress/varargs-inlined-simple-exit-aliasing-weird.js: Added.
* tests/stress/varargs-inlined-simple-exit-aliasing.js: Added.
* tests/stress/varargs-inlined-simple-exit.js: Added.
* tests/stress/varargs-too-few-arguments.js: Added.
* tests/stress/varargs-varargs-closure-inlined-exit.js: Added.
* tests/stress/varargs-varargs-inlined-exit-strict-mode.js: Added.
* tests/stress/varargs-varargs-inlined-exit.js: Added.
Source/WTF:
* wtf/FastBitVector.h:
(WTF::FastBitVector::resize): Small change: don't resize if you don't have to resize.
LayoutTests:
* js/function-apply-aliased-expected.txt:
* js/function-dot-arguments-expected.txt:
* js/regress/arguments-expected.txt: Added.
* js/regress/arguments-named-and-reflective-expected.txt: Added.
* js/regress/arguments-named-and-reflective.html: Added.
* js/regress/arguments-strict-mode-expected.txt: Added.
* js/regress/arguments-strict-mode.html: Added.
* js/regress/arguments.html: Added.
* js/regress/script-tests/arguments-named-and-reflective.js: Added.
* js/regress/script-tests/arguments-strict-mode.js: Added.
* js/regress/script-tests/arguments.js: Added.
* js/regress/script-tests/try-catch-get-by-val-cloned-arguments.js: Added.
* js/regress/script-tests/try-catch-get-by-val-direct-arguments.js: Added.
* js/regress/script-tests/try-catch-get-by-val-scoped-arguments.js: Added.
* js/regress/script-tests/varargs-call.js: Added.
* js/regress/script-tests/varargs-construct-inline.js: Added.
* js/regress/script-tests/varargs-construct.js: Added.
* js/regress/script-tests/varargs-inline.js: Added.
* js/regress/script-tests/varargs-strict-mode.js: Added.
* js/regress/script-tests/varargs.js: Added.
* js/regress/try-catch-get-by-val-cloned-arguments-expected.txt: Added.
* js/regress/try-catch-get-by-val-cloned-arguments.html: Added.
* js/regress/try-catch-get-by-val-direct-arguments-expected.txt: Added.
* js/regress/try-catch-get-by-val-direct-arguments.html: Added.
* js/regress/try-catch-get-by-val-scoped-arguments-expected.txt: Added.
* js/regress/try-catch-get-by-val-scoped-arguments.html: Added.
* js/regress/varargs-call-expected.txt: Added.
* js/regress/varargs-call.html: Added.
* js/regress/varargs-construct-expected.txt: Added.
* js/regress/varargs-construct-inline-expected.txt: Added.
* js/regress/varargs-construct-inline.html: Added.
* js/regress/varargs-construct.html: Added.
* js/regress/varargs-expected.txt: Added.
* js/regress/varargs-inline-expected.txt: Added.
* js/regress/varargs-inline.html: Added.
* js/regress/varargs-strict-mode-expected.txt: Added.
* js/regress/varargs-strict-mode.html: Added.
* js/regress/varargs.html: Added.
* js/script-tests/function-apply-aliased.js:
* js/script-tests/function-dot-arguments.js:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@181993 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ftl/FTLAbstractHeap.cpp b/Source/JavaScriptCore/ftl/FTLAbstractHeap.cpp
index 0037a7a..ce9fa0f 100644
--- a/Source/JavaScriptCore/ftl/FTLAbstractHeap.cpp
+++ b/Source/JavaScriptCore/ftl/FTLAbstractHeap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -53,6 +53,20 @@
setMetadata(instruction, repository.m_tbaaKind, tbaaMetadata(repository));
}
+void AbstractHeap::dump(PrintStream& out) const
+{
+ out.print(heapName());
+ if (m_parent)
+ out.print("->", *m_parent);
+}
+
+void AbstractField::dump(PrintStream& out) const
+{
+ out.print(heapName(), "(", m_offset, ")");
+ if (parent())
+ out.print("->", *parent());
+}
+
IndexedAbstractHeap::IndexedAbstractHeap(LContext context, AbstractHeap* parent, const char* heapName, ptrdiff_t offset, size_t elementSize)
: m_heapForAnyIndex(parent, heapName)
, m_heapNameLength(strlen(heapName))
@@ -176,6 +190,11 @@
RELEASE_ASSERT_NOT_REACHED();
}
+void IndexedAbstractHeap::dump(PrintStream& out) const
+{
+ out.print("Indexed:", atAnyIndex());
+}
+
NumberedAbstractHeap::NumberedAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName)
: m_indexedHeap(context, heap, heapName, 0, 1)
{
@@ -185,6 +204,11 @@
{
}
+void NumberedAbstractHeap::dump(PrintStream& out) const
+{
+ out.print("Numbered: ", atAnyNumber());
+}
+
AbsoluteAbstractHeap::AbsoluteAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName)
: m_indexedHeap(context, heap, heapName, 0, 1)
{
@@ -194,6 +218,11 @@
{
}
+void AbsoluteAbstractHeap::dump(PrintStream& out) const
+{
+ out.print("Absolute:", atAnyAddress());
+}
+
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
diff --git a/Source/JavaScriptCore/ftl/FTLAbstractHeap.h b/Source/JavaScriptCore/ftl/FTLAbstractHeap.h
index eb163c1..a19ce38 100644
--- a/Source/JavaScriptCore/ftl/FTLAbstractHeap.h
+++ b/Source/JavaScriptCore/ftl/FTLAbstractHeap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -99,6 +99,8 @@
void decorateInstruction(LValue instruction, const AbstractHeapRepository&) const;
+ void dump(PrintStream&) const;
+
private:
friend class AbstractHeapRepository;
@@ -135,6 +137,8 @@
return m_offset;
}
+ void dump(PrintStream&) const;
+
private:
ptrdiff_t m_offset;
};
@@ -157,6 +161,8 @@
TypedPointer baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0);
+ void dump(PrintStream&) const;
+
private:
const AbstractField& returnInitialized(AbstractField& field, ptrdiff_t index)
{
@@ -201,6 +207,8 @@
const AbstractHeap& at(unsigned number) { return m_indexedHeap.at(number); }
const AbstractHeap& operator[](unsigned number) { return at(number); }
+ void dump(PrintStream&) const;
+
private:
// We use the fact that the indexed heap already has a superset of the
@@ -222,6 +230,8 @@
const AbstractHeap& operator[](void* address) { return at(address); }
+ void dump(PrintStream&) const;
+
private:
// The trick here is that the indexed heap is "indexed" by a pointer-width
// integer. Pointers are themselves pointer-width integers. So we can reuse
diff --git a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp
index a5fba3a..e416fda 100644
--- a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp
+++ b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,11 +28,14 @@
#if ENABLE(FTL_JIT)
+#include "DirectArguments.h"
#include "GetterSetter.h"
#include "JSEnvironmentRecord.h"
#include "JSPropertyNameEnumerator.h"
#include "JSScope.h"
#include "JSCInlines.h"
+#include "ScopedArguments.h"
+#include "ScopedArgumentsTable.h"
namespace JSC { namespace FTL {
diff --git a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
index 19c1ff0f..97cc8f3 100644
--- a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
+++ b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,10 +35,7 @@
namespace JSC { namespace FTL {
#define FOR_EACH_ABSTRACT_HEAP(macro) \
- macro(length) \
- macro(structureTable) \
- macro(typedArrayProperties) \
- macro(WriteBarrierBuffer_bufferContents)
+ macro(typedArrayProperties)
#define FOR_EACH_ABSTRACT_FIELD(macro) \
macro(ArrayBuffer_data, ArrayBuffer::offsetOfData()) \
@@ -46,6 +43,10 @@
macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
macro(Butterfly_vectorLength, Butterfly::offsetOfVectorLength()) \
macro(CallFrame_callerFrame, CallFrame::callerFrameOffset()) \
+ macro(DirectArguments_callee, DirectArguments::offsetOfCallee()) \
+ macro(DirectArguments_length, DirectArguments::offsetOfLength()) \
+ macro(DirectArguments_minCapacity, DirectArguments::offsetOfMinCapacity()) \
+ macro(DirectArguments_overrides, DirectArguments::offsetOfOverrides()) \
macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \
macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
@@ -70,10 +71,16 @@
macro(JSString_flags, JSString::offsetOfFlags()) \
macro(JSString_length, JSString::offsetOfLength()) \
macro(JSString_value, JSString::offsetOfValue()) \
- macro(JSEnvironmentRecord_registers, JSEnvironmentRecord::offsetOfRegisters()) \
+ macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \
macro(JSWrapperObject_internalValue, JSWrapperObject::internalValueOffset()) \
macro(MarkedAllocator_freeListHead, MarkedAllocator::offsetOfFreeListHead()) \
macro(MarkedBlock_markBits, MarkedBlock::offsetOfMarks()) \
+ macro(ScopedArguments_overrodeThings, ScopedArguments::offsetOfOverrodeThings()) \
+ macro(ScopedArguments_scope, ScopedArguments::offsetOfScope()) \
+ macro(ScopedArguments_table, ScopedArguments::offsetOfTable()) \
+ macro(ScopedArguments_totalLength, ScopedArguments::offsetOfTotalLength()) \
+ macro(ScopedArgumentsTable_arguments, ScopedArgumentsTable::offsetOfArguments()) \
+ macro(ScopedArgumentsTable_length, ScopedArgumentsTable::offsetOfLength()) \
macro(StringImpl_data, StringImpl::dataOffset()) \
macro(StringImpl_hashAndFlags, StringImpl::flagsOffset()) \
macro(Structure_classInfo, Structure::classInfoOffset()) \
@@ -82,14 +89,23 @@
macro(Structure_structureID, Structure::structureIDOffset())
#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
+ macro(DirectArguments_storage, DirectArguments::storageOffset(), sizeof(EncodedJSValue)) \
+ macro(JSEnvironmentRecord_variables, JSEnvironmentRecord::offsetOfVariables(), sizeof(EncodedJSValue)) \
+ macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier<JSString>)) \
macro(JSRopeString_fibers, JSRopeString::offsetOfFibers(), sizeof(WriteBarrier<JSString>)) \
+ macro(MarkedSpace_Subspace_impreciseAllocators, OBJECT_OFFSETOF(MarkedSpace::Subspace, impreciseAllocators), sizeof(MarkedAllocator)) \
+ macro(MarkedSpace_Subspace_preciseAllocators, OBJECT_OFFSETOF(MarkedSpace::Subspace, preciseAllocators), sizeof(MarkedAllocator)) \
+ macro(ScopedArguments_overflowStorage, ScopedArguments::overflowStorageOffset(), sizeof(EncodedJSValue)) \
+ macro(WriteBarrierBuffer_bufferContents, 0, sizeof(JSCell*)) \
macro(characters8, 0, sizeof(LChar)) \
macro(characters16, 0, sizeof(UChar)) \
macro(indexedInt32Properties, 0, sizeof(EncodedJSValue)) \
macro(indexedDoubleProperties, 0, sizeof(double)) \
macro(indexedContiguousProperties, 0, sizeof(EncodedJSValue)) \
macro(indexedArrayStorageProperties, 0, sizeof(EncodedJSValue)) \
+ macro(scopedArgumentsTableArguments, 0, sizeof(int32_t)) \
macro(singleCharacterStrings, 0, sizeof(JSString*)) \
+ macro(structureTable, 0, sizeof(Structure*)) \
macro(variables, 0, sizeof(Register))
#define FOR_EACH_NUMBERED_ABSTRACT_HEAP(macro) \
diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
index e0a21db..85de49b 100644
--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
@@ -44,7 +44,6 @@
switch (node->op()) {
case JSConstant:
- case GetMyArgumentsLength:
case GetLocal:
case SetLocal:
case PutStack:
@@ -103,9 +102,15 @@
case ExtractOSREntryLocal:
case LoopHint:
case SkipScope:
- case GetClosureRegisters:
+ case CreateActivation:
+ case NewFunction:
case GetClosureVar:
case PutClosureVar:
+ case CreateDirectArguments:
+ case CreateScopedArguments:
+ case CreateClonedArguments:
+ case GetFromArguments:
+ case PutToArguments:
case InvalidationPoint:
case StringCharAt:
case CheckCell:
@@ -124,6 +129,7 @@
case CallVarargs:
case CallForwardVarargs:
case ConstructVarargs:
+ case ConstructForwardVarargs:
case LoadVarargs:
case NativeCall:
case NativeConstruct:
@@ -137,8 +143,8 @@
case GetExecutable:
case GetScope:
case AllocationProfileWatchpoint:
- case CheckArgumentsNotCreated:
case GetCallee:
+ case GetArgumentCount:
case ToString:
case MakeRope:
case NewArrayWithSize:
@@ -147,11 +153,9 @@
case MultiGetByOffset:
case MultiPutByOffset:
case ToPrimitive:
- case PhantomArguments:
case Throw:
case ThrowReferenceError:
case Unreachable:
- case GetMyArgumentByVal:
case IsUndefined:
case IsBoolean:
case IsNumber:
@@ -180,6 +184,10 @@
case PutHint:
case CheckStructureImmediate:
case MaterializeNewObject:
+ case PhantomDirectArguments:
+ case PhantomClonedArguments:
+ case GetMyArgumentByVal:
+ case ForwardVarargs:
// These are OK.
break;
case Identity:
@@ -208,6 +216,8 @@
case Array::Int32:
case Array::Double:
case Array::Contiguous:
+ case Array::DirectArguments:
+ case Array::ScopedArguments:
break;
default:
if (isTypedView(node->arrayMode().typedArrayType()))
@@ -221,6 +231,8 @@
case Array::Double:
case Array::Contiguous:
case Array::String:
+ case Array::DirectArguments:
+ case Array::ScopedArguments:
break;
default:
if (isTypedView(node->arrayMode().typedArrayType()))
@@ -247,6 +259,8 @@
case Array::Int32:
case Array::Double:
case Array::Contiguous:
+ case Array::DirectArguments:
+ case Array::ScopedArguments:
break;
default:
if (isTypedView(node->arrayMode().typedArrayType()))
@@ -367,17 +381,6 @@
return CannotCompile;
}
- if (graph.m_codeBlock->needsActivation()) {
- // Need this because although we also don't support
- // CreateActivation, we might not see those nodes in case of
- // OSR entry.
- // FIXME: Support activations.
- // https://bugs.webkit.org/show_bug.cgi?id=129576
- if (verboseCapabilities())
- dataLog("FTL rejecting ", *graph.m_codeBlock, " because it uses activations.\n");
- return CannotCompile;
- }
-
CapabilityLevel result = CanCompileAndOSREnter;
for (BlockIndex blockIndex = graph.numBlocks(); blockIndex--;) {
diff --git a/Source/JavaScriptCore/ftl/FTLCompile.cpp b/Source/JavaScriptCore/ftl/FTLCompile.cpp
index 4b41b89..a83e891 100644
--- a/Source/JavaScriptCore/ftl/FTLCompile.cpp
+++ b/Source/JavaScriptCore/ftl/FTLCompile.cpp
@@ -140,6 +140,9 @@
static int offsetOfStackRegion(StackMaps::RecordMap& recordMap, uint32_t stackmapID)
{
+ if (stackmapID == UINT_MAX)
+ return 0;
+
StackMaps::RecordMap::iterator iter = recordMap.find(stackmapID);
RELEASE_ASSERT(iter != recordMap.end());
RELEASE_ASSERT(iter->value.size() == 1);
@@ -301,21 +304,12 @@
VM& vm = graph.m_vm;
StackMaps stackmaps = jitCode->stackmaps;
- int localsOffset =
- offsetOfStackRegion(recordMap, state.capturedStackmapID) + graph.m_nextMachineLocal;
-
- int varargsSpillSlotsOffset;
- if (state.varargsSpillSlotsStackmapID != UINT_MAX)
- varargsSpillSlotsOffset = offsetOfStackRegion(recordMap, state.varargsSpillSlotsStackmapID);
- else
- varargsSpillSlotsOffset = 0;
+ int localsOffset = offsetOfStackRegion(recordMap, state.capturedStackmapID) + graph.m_nextMachineLocal;
+ int varargsSpillSlotsOffset = offsetOfStackRegion(recordMap, state.varargsSpillSlotsStackmapID);
for (unsigned i = graph.m_inlineVariableData.size(); i--;) {
InlineCallFrame* inlineCallFrame = graph.m_inlineVariableData[i].inlineCallFrame;
- if (inlineCallFrame->argumentsRegister.isValid())
- inlineCallFrame->argumentsRegister += localsOffset;
-
if (inlineCallFrame->argumentCountRegister.isValid())
inlineCallFrame->argumentCountRegister += localsOffset;
@@ -330,11 +324,6 @@
}
}
- if (codeBlock->usesArguments()) {
- codeBlock->setArgumentsRegister(
- VirtualRegister(codeBlock->argumentsRegister().offset() + localsOffset));
- }
-
MacroAssembler::Label stackOverflowException;
{
@@ -396,15 +385,10 @@
info.m_thunkAddress = linkBuffer->locationOf(info.m_thunkLabel);
exit.m_patchableCodeOffset = linkBuffer->offsetOf(info.m_thunkJump);
- for (unsigned j = exit.m_values.size(); j--;) {
- ExitValue value = exit.m_values[j];
- if (!value.isInJSStackSomehow())
- continue;
- if (!value.virtualRegister().isLocal())
- continue;
- exit.m_values[j] = value.withVirtualRegister(
- VirtualRegister(value.virtualRegister().offset() + localsOffset));
- }
+ for (unsigned j = exit.m_values.size(); j--;)
+ exit.m_values[j] = exit.m_values[j].withLocalsOffset(localsOffset);
+ for (ExitTimeObjectMaterialization* materialization : exit.m_materializations)
+ materialization->accountForLocalsOffset(localsOffset);
if (verboseCompilationEnabled()) {
DumpContext context;
@@ -588,7 +572,7 @@
JSCallVarargs& call = state.jsCallVarargses[i];
CCallHelpers fastPathJIT(&vm, codeBlock);
- call.emit(fastPathJIT, graph, varargsSpillSlotsOffset);
+ call.emit(fastPathJIT, varargsSpillSlotsOffset);
char* startOfIC = bitwise_cast<char*>(generatedFunction) + call.m_instructionOffset;
size_t sizeOfIC = sizeOfICFor(call.node());
diff --git a/Source/JavaScriptCore/ftl/FTLExitArgument.cpp b/Source/JavaScriptCore/ftl/FTLExitArgument.cpp
index cbe0de7..381b3d3 100644
--- a/Source/JavaScriptCore/ftl/FTLExitArgument.cpp
+++ b/Source/JavaScriptCore/ftl/FTLExitArgument.cpp
@@ -32,7 +32,7 @@
void ExitArgument::dump(PrintStream& out) const
{
- out.print("arg", argument(), " as ", format());
+ out.print("#", argument(), " as ", format());
}
} } // namespace JSC::FTL
diff --git a/Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp b/Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp
index 2b72b69..698874a 100644
--- a/Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp
+++ b/Source/JavaScriptCore/ftl/FTLExitPropertyValue.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +30,11 @@
namespace JSC { namespace FTL {
+ExitPropertyValue ExitPropertyValue::withLocalsOffset(int offset) const
+{
+ return ExitPropertyValue(m_location, m_value.withLocalsOffset(offset));
+}
+
void ExitPropertyValue::dump(PrintStream& out) const
{
out.print(m_location, " => ", m_value);
diff --git a/Source/JavaScriptCore/ftl/FTLExitPropertyValue.h b/Source/JavaScriptCore/ftl/FTLExitPropertyValue.h
index bdb47b9..00ef77c 100644
--- a/Source/JavaScriptCore/ftl/FTLExitPropertyValue.h
+++ b/Source/JavaScriptCore/ftl/FTLExitPropertyValue.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,6 +51,8 @@
DFG::PromotedLocationDescriptor location() const { return m_location; }
const ExitValue& value() const { return m_value; }
+ ExitPropertyValue withLocalsOffset(int offset) const;
+
void dump(PrintStream& out) const;
private:
diff --git a/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp b/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp
index d57cdac..1fd86a0 100644
--- a/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp
+++ b/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,8 +34,9 @@
using namespace JSC::DFG;
-ExitTimeObjectMaterialization::ExitTimeObjectMaterialization(NodeType type)
+ExitTimeObjectMaterialization::ExitTimeObjectMaterialization(NodeType type, CodeOrigin codeOrigin)
: m_type(type)
+ , m_origin(codeOrigin)
{
}
@@ -58,6 +59,12 @@
return ExitValue();
}
+void ExitTimeObjectMaterialization::accountForLocalsOffset(int offset)
+{
+ for (ExitPropertyValue& property : m_properties)
+ property = property.withLocalsOffset(offset);
+}
+
void ExitTimeObjectMaterialization::dump(PrintStream& out) const
{
out.print(RawPointer(this), ":", Graph::opName(m_type), "(", listDump(m_properties), ")");
diff --git a/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h b/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h
index d55affc..b6ac38b 100644
--- a/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h
+++ b/Source/JavaScriptCore/ftl/FTLExitTimeObjectMaterialization.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -38,20 +38,24 @@
class ExitTimeObjectMaterialization {
WTF_MAKE_NONCOPYABLE(ExitTimeObjectMaterialization)
public:
- ExitTimeObjectMaterialization(DFG::NodeType);
+ ExitTimeObjectMaterialization(DFG::NodeType, CodeOrigin);
~ExitTimeObjectMaterialization();
void add(DFG::PromotedLocationDescriptor, const ExitValue&);
DFG::NodeType type() const { return m_type; }
+ CodeOrigin origin() const { return m_origin; }
ExitValue get(DFG::PromotedLocationDescriptor) const;
const Vector<ExitPropertyValue>& properties() const { return m_properties; }
+ void accountForLocalsOffset(int offset);
+
void dump(PrintStream& out) const;
private:
DFG::NodeType m_type;
+ CodeOrigin m_origin;
Vector<ExitPropertyValue> m_properties;
};
diff --git a/Source/JavaScriptCore/ftl/FTLExitValue.cpp b/Source/JavaScriptCore/ftl/FTLExitValue.cpp
index 275b30a..2bcce6c 100644
--- a/Source/JavaScriptCore/ftl/FTLExitValue.cpp
+++ b/Source/JavaScriptCore/ftl/FTLExitValue.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -41,6 +41,48 @@
return result;
}
+ExitValue ExitValue::withLocalsOffset(int offset) const
+{
+ if (!isInJSStackSomehow())
+ return *this;
+ if (!virtualRegister().isLocal())
+ return *this;
+ return withVirtualRegister(virtualRegister() + offset);
+}
+
+ValueFormat ExitValue::valueFormat() const
+{
+ switch (kind()) {
+ case InvalidExitValue:
+ RELEASE_ASSERT_NOT_REACHED();
+ return InvalidValueFormat;
+
+ case ExitValueDead:
+ case ExitValueConstant:
+ case ExitValueInJSStack:
+ case ExitValueMaterializeNewObject:
+ return ValueFormatJSValue;
+
+ case ExitValueArgument:
+ return exitArgument().format();
+
+ case ExitValueInJSStackAsInt32:
+ return ValueFormatInt32;
+
+ case ExitValueInJSStackAsInt52:
+ return ValueFormatInt52;
+
+ case ExitValueInJSStackAsDouble:
+ return ValueFormatDouble;
+
+ case ExitValueRecovery:
+ return recoveryFormat();
+ }
+
+ RELEASE_ASSERT_NOT_REACHED();
+ return InvalidValueFormat;
+}
+
void ExitValue::dumpInContext(PrintStream& out, DumpContext* context) const
{
switch (kind()) {
@@ -68,9 +110,6 @@
case ExitValueInJSStackAsDouble:
out.print("InJSStackAsDouble:", virtualRegister());
return;
- case ExitValueArgumentsObjectThatWasNotCreated:
- out.print("ArgumentsObjectThatWasNotCreated");
- return;
case ExitValueRecovery:
out.print("Recovery(", recoveryOpcode(), ", arg", leftRecoveryArgument(), ", arg", rightRecoveryArgument(), ", ", recoveryFormat(), ")");
return;
diff --git a/Source/JavaScriptCore/ftl/FTLExitValue.h b/Source/JavaScriptCore/ftl/FTLExitValue.h
index b19c350..b34f23a 100644
--- a/Source/JavaScriptCore/ftl/FTLExitValue.h
+++ b/Source/JavaScriptCore/ftl/FTLExitValue.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,7 +51,6 @@
ExitValueInJSStackAsInt32,
ExitValueInJSStackAsInt52,
ExitValueInJSStackAsDouble,
- ExitValueArgumentsObjectThatWasNotCreated,
ExitValueRecovery,
ExitValueMaterializeNewObject
};
@@ -122,13 +121,6 @@
return result;
}
- static ExitValue argumentsObjectThatWasNotCreated()
- {
- ExitValue result;
- result.m_kind = ExitValueArgumentsObjectThatWasNotCreated;
- return result;
- }
-
static ExitValue recovery(RecoveryOpcode opcode, unsigned leftArgument, unsigned rightArgument, ValueFormat format)
{
ExitValue result;
@@ -159,7 +151,6 @@
}
bool isConstant() const { return kind() == ExitValueConstant; }
bool isArgument() const { return kind() == ExitValueArgument; }
- bool isArgumentsObjectThatWasNotCreated() const { return kind() == ExitValueArgumentsObjectThatWasNotCreated; }
bool isRecovery() const { return kind() == ExitValueRecovery; }
bool isObjectMaterialization() const { return kind() == ExitValueMaterializeNewObject; }
@@ -220,43 +211,13 @@
return result;
}
+ ExitValue withLocalsOffset(int offset) const;
+
// If it's in the JSStack somehow, this will tell you what format it's in, in a manner
// that is compatible with exitArgument().format(). If it's a constant or it's dead, it
// will claim to be a JSValue. If it's an argument then it will tell you the argument's
// format.
- ValueFormat valueFormat() const
- {
- switch (kind()) {
- case InvalidExitValue:
- RELEASE_ASSERT_NOT_REACHED();
- return InvalidValueFormat;
-
- case ExitValueDead:
- case ExitValueConstant:
- case ExitValueInJSStack:
- case ExitValueArgumentsObjectThatWasNotCreated:
- case ExitValueMaterializeNewObject:
- return ValueFormatJSValue;
-
- case ExitValueArgument:
- return exitArgument().format();
-
- case ExitValueInJSStackAsInt32:
- return ValueFormatInt32;
-
- case ExitValueInJSStackAsInt52:
- return ValueFormatInt52;
-
- case ExitValueInJSStackAsDouble:
- return ValueFormatDouble;
-
- case ExitValueRecovery:
- return recoveryFormat();
- }
-
- RELEASE_ASSERT_NOT_REACHED();
- return InvalidValueFormat;
- }
+ ValueFormat valueFormat() const;
void dump(PrintStream&) const;
void dumpInContext(PrintStream&, DumpContext*) const;
diff --git a/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp b/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp
index 230a264..dcd5d65 100644
--- a/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp
+++ b/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp
@@ -85,21 +85,30 @@
size_t sizeOfCallForwardVarargs()
{
#if CPU(ARM64)
- return 460;
+ return 312;
#else
- return 372;
+ return 250;
#endif
}
size_t sizeOfConstructVarargs()
{
#if CPU(ARM64)
- return 300;
+ return 332;
#else
return 275;
#endif
}
+size_t sizeOfConstructForwardVarargs()
+{
+#if CPU(ARM64)
+ return 312;
+#else
+ return 250;
+#endif
+}
+
size_t sizeOfIn()
{
#if CPU(ARM64)
@@ -125,6 +134,8 @@
return sizeOfCallForwardVarargs();
case ConstructVarargs:
return sizeOfConstructVarargs();
+ case ConstructForwardVarargs:
+ return sizeOfConstructForwardVarargs();
case In:
return sizeOfIn();
default:
diff --git a/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h b/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h
index 6fe9116..82f3bbc 100644
--- a/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h
+++ b/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h
@@ -42,6 +42,7 @@
size_t sizeOfCallVarargs();
size_t sizeOfCallForwardVarargs();
size_t sizeOfConstructVarargs();
+size_t sizeOfConstructForwardVarargs();
size_t sizeOfIn();
size_t sizeOfICFor(DFG::Node*);
diff --git a/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h b/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
index 8f0b274..7a413fc 100644
--- a/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
+++ b/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
@@ -63,6 +63,11 @@
macro(C_JITOperation_EJssJss, functionType(intPtr, intPtr, intPtr, intPtr)) \
macro(C_JITOperation_EJssJssJss, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
macro(C_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \
+ macro(C_JITOperation_EStJscSymtab, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
+ macro(C_JITOperation_EStRZJsf, functionType(intPtr, intPtr, intPtr, intPtr, int32, intPtr)) \
+ macro(C_JITOperation_EStRZJsfL, functionType(intPtr, intPtr, intPtr, intPtr, int32, intPtr, intPtr)) \
+ macro(C_JITOperation_EStZ, functionType(intPtr, intPtr, intPtr, int32)) \
+ macro(C_JITOperation_EStZZ, functionType(intPtr, intPtr, intPtr, int32, int32)) \
macro(C_JITOperation_EZ, functionType(intPtr, intPtr, int32)) \
macro(D_JITOperation_D, functionType(doubleType, doubleType)) \
macro(I_JITOperation_EJss, functionType(intPtr, intPtr, intPtr)) \
@@ -76,6 +81,7 @@
macro(J_JITOperation_EJA, functionType(int64, intPtr, int64, intPtr)) \
macro(J_JITOperation_EJC, functionType(int64, intPtr, int64, intPtr)) \
macro(J_JITOperation_EJJ, functionType(int64, intPtr, int64, int64)) \
+ macro(J_JITOperation_EJscC, functionType(intPtr, intPtr, intPtr, intPtr)) \
macro(J_JITOperation_EJssZ, functionType(int64, intPtr, intPtr, int32)) \
macro(J_JITOperation_ESsiJI, functionType(int64, intPtr, intPtr, int64, intPtr)) \
macro(Jss_JITOperation_EZ, functionType(intPtr, intPtr, int32)) \
diff --git a/Source/JavaScriptCore/ftl/FTLJSCallVarargs.cpp b/Source/JavaScriptCore/ftl/FTLJSCallVarargs.cpp
index e9b41c7..ac87a3c 100644
--- a/Source/JavaScriptCore/ftl/FTLJSCallVarargs.cpp
+++ b/Source/JavaScriptCore/ftl/FTLJSCallVarargs.cpp
@@ -28,7 +28,6 @@
#if ENABLE(FTL_JIT)
-#include "DFGGraph.h"
#include "DFGNode.h"
#include "DFGOperations.h"
#include "JSCInlines.h"
@@ -51,11 +50,14 @@
: m_stackmapID(stackmapID)
, m_node(node)
, m_callBase(
- node->op() == ConstructVarargs ? CallLinkInfo::ConstructVarargs : CallLinkInfo::CallVarargs,
+ (node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs)
+ ? CallLinkInfo::ConstructVarargs : CallLinkInfo::CallVarargs,
node->origin.semantic)
, m_instructionOffset(0)
{
- ASSERT(node->op() == CallVarargs || node->op() == CallForwardVarargs || node->op() == ConstructVarargs);
+ ASSERT(
+ node->op() == CallVarargs || node->op() == CallForwardVarargs
+ || node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs);
}
unsigned JSCallVarargs::numSpillSlotsNeeded()
@@ -63,11 +65,11 @@
return 4;
}
-void JSCallVarargs::emit(CCallHelpers& jit, Graph& graph, int32_t spillSlotsOffset)
+void JSCallVarargs::emit(CCallHelpers& jit, int32_t spillSlotsOffset)
{
// We are passed three pieces of information:
// - The callee.
- // - The arguments object.
+ // - The arguments object, if it's not a forwarding call.
// - The "this" value, if it's a constructor call.
CallVarargsData* data = m_node->callVarargsData();
@@ -76,20 +78,19 @@
GPRReg argumentsGPR = InvalidGPRReg;
GPRReg thisGPR = InvalidGPRReg;
- bool argumentsOnStack = false;
+
+ bool forwarding = false;
switch (m_node->op()) {
case CallVarargs:
+ case ConstructVarargs:
argumentsGPR = GPRInfo::argumentGPR1;
thisGPR = GPRInfo::argumentGPR2;
break;
case CallForwardVarargs:
+ case ConstructForwardVarargs:
thisGPR = GPRInfo::argumentGPR1;
- argumentsOnStack = true;
- break;
- case ConstructVarargs:
- argumentsGPR = GPRInfo::argumentGPR1;
- thisGPR = GPRInfo::argumentGPR2;
+ forwarding = true;
break;
default:
RELEASE_ASSERT_NOT_REACHED();
@@ -115,21 +116,9 @@
GPRReg scratchGPR1 = allocator.allocateScratchGPR();
GPRReg scratchGPR2 = allocator.allocateScratchGPR();
GPRReg scratchGPR3 = allocator.allocateScratchGPR();
- if (argumentsOnStack)
- argumentsGPR = allocator.allocateScratchGPR();
+
RELEASE_ASSERT(!allocator.numberOfReusedRegisters());
- auto loadArguments = [&] (bool clobbered) {
- if (argumentsOnStack) {
- jit.load64(
- CCallHelpers::addressFor(graph.machineArgumentsRegisterFor(m_node->origin.semantic)),
- argumentsGPR);
- } else if (clobbered) {
- jit.load64(
- CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot), argumentsGPR);
- }
- };
-
auto computeUsedStack = [&] (GPRReg targetGPR, unsigned extra) {
if (isARM64()) {
// Have to do this the weird way because $sp on ARM64 means zero when used in a subtraction.
@@ -151,60 +140,54 @@
m_exceptions.append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth));
};
- loadArguments(false);
-
if (isARM64()) {
jit.move(CCallHelpers::stackPointerRegister, scratchGPR1);
jit.storePtr(scratchGPR1, CCallHelpers::addressFor(spillSlotsOffset + stackPointerSpillSlot));
} else
jit.storePtr(CCallHelpers::stackPointerRegister, CCallHelpers::addressFor(spillSlotsOffset + stackPointerSpillSlot));
-
- // Attempt the forwarding fast path, if it's been requested.
- CCallHelpers::Jump haveArguments;
- if (m_node->op() == CallForwardVarargs) {
- // Do the horrific foo.apply(this, arguments) optimization.
- // FIXME: do this optimization at the IR level.
-
- CCallHelpers::JumpList slowCase;
- slowCase.append(jit.branchTest64(CCallHelpers::NonZero, argumentsGPR));
-
- computeUsedStack(scratchGPR2, 0);
- emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, m_node->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase);
-
- jit.move(calleeGPR, GPRInfo::regT0);
- haveArguments = jit.jump();
- slowCase.link(&jit);
- }
-
- // Gotta spill the callee, arguments, and this because we will need them later and we will have some
- // calls that clobber them.
- jit.store64(calleeGPR, CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot));
- if (!argumentsOnStack)
- jit.store64(argumentsGPR, CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot));
- jit.store64(thisGPR, CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot));
-
+
unsigned extraStack = sizeof(CallerFrameAndPC) +
WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*));
- computeUsedStack(scratchGPR1, 0);
- jit.subPtr(CCallHelpers::TrustedImm32(extraStack), CCallHelpers::stackPointerRegister);
- jit.setupArgumentsWithExecState(argumentsGPR, scratchGPR1, CCallHelpers::TrustedImm32(data->firstVarArgOffset));
- callWithExceptionCheck(bitwise_cast<void*>(operationSizeFrameForVarargs));
-
- jit.move(GPRInfo::returnValueGPR, scratchGPR1);
- computeUsedStack(scratchGPR2, extraStack);
- loadArguments(true);
- emitSetVarargsFrame(jit, scratchGPR1, false, scratchGPR2, scratchGPR2);
- jit.addPtr(CCallHelpers::TrustedImm32(-extraStack), scratchGPR2, CCallHelpers::stackPointerRegister);
- jit.setupArgumentsWithExecState(scratchGPR2, argumentsGPR, CCallHelpers::TrustedImm32(data->firstVarArgOffset), scratchGPR1);
- callWithExceptionCheck(bitwise_cast<void*>(operationSetupVarargsFrame));
-
- jit.move(GPRInfo::returnValueGPR, scratchGPR2);
- jit.load64(CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot), thisGPR);
- jit.load64(CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot), GPRInfo::regT0);
+ if (forwarding) {
+ CCallHelpers::JumpList slowCase;
+ computeUsedStack(scratchGPR2, 0);
+ emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, m_node->child2()->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase);
+
+ CCallHelpers::Jump done = jit.jump();
+ slowCase.link(&jit);
+ jit.subPtr(CCallHelpers::TrustedImm32(extraStack), CCallHelpers::stackPointerRegister);
+ jit.setupArgumentsExecState();
+ callWithExceptionCheck(bitwise_cast<void*>(operationThrowStackOverflowForVarargs));
+ jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
+
+ done.link(&jit);
+ jit.move(calleeGPR, GPRInfo::regT0);
+ } else {
+ // Gotta spill the callee, arguments, and this because we will need them later and we will have some
+ // calls that clobber them.
+ jit.store64(calleeGPR, CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot));
+ jit.store64(argumentsGPR, CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot));
+ jit.store64(thisGPR, CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot));
- if (m_node->op() == CallForwardVarargs)
- haveArguments.link(&jit);
+ computeUsedStack(scratchGPR1, 0);
+ jit.subPtr(CCallHelpers::TrustedImm32(extraStack), CCallHelpers::stackPointerRegister);
+ jit.setupArgumentsWithExecState(argumentsGPR, scratchGPR1, CCallHelpers::TrustedImm32(data->firstVarArgOffset));
+ callWithExceptionCheck(bitwise_cast<void*>(operationSizeFrameForVarargs));
+
+ jit.move(GPRInfo::returnValueGPR, scratchGPR1);
+ computeUsedStack(scratchGPR2, extraStack);
+ jit.load64(CCallHelpers::addressFor(spillSlotsOffset + argumentsSpillSlot), argumentsGPR);
+ emitSetVarargsFrame(jit, scratchGPR1, false, scratchGPR2, scratchGPR2);
+ jit.addPtr(CCallHelpers::TrustedImm32(-extraStack), scratchGPR2, CCallHelpers::stackPointerRegister);
+ jit.setupArgumentsWithExecState(scratchGPR2, argumentsGPR, CCallHelpers::TrustedImm32(data->firstVarArgOffset), scratchGPR1);
+ callWithExceptionCheck(bitwise_cast<void*>(operationSetupVarargsFrame));
+
+ jit.move(GPRInfo::returnValueGPR, scratchGPR2);
+
+ jit.load64(CCallHelpers::addressFor(spillSlotsOffset + thisSpillSlot), thisGPR);
+ jit.load64(CCallHelpers::addressFor(spillSlotsOffset + calleeSpillSlot), GPRInfo::regT0);
+ }
jit.addPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), scratchGPR2, CCallHelpers::stackPointerRegister);
diff --git a/Source/JavaScriptCore/ftl/FTLJSCallVarargs.h b/Source/JavaScriptCore/ftl/FTLJSCallVarargs.h
index cdaefb9..5128ff8 100644
--- a/Source/JavaScriptCore/ftl/FTLJSCallVarargs.h
+++ b/Source/JavaScriptCore/ftl/FTLJSCallVarargs.h
@@ -35,7 +35,6 @@
class LinkBuffer;
namespace DFG {
-class Graph;
struct Node;
}
@@ -50,7 +49,7 @@
static unsigned numSpillSlotsNeeded();
- void emit(CCallHelpers&, DFG::Graph&, int32_t spillSlotsOffset);
+ void emit(CCallHelpers&, int32_t spillSlotsOffset);
void link(VM&, LinkBuffer&, CodeLocationLabel exceptionHandler);
unsigned stackmapID() const { return m_stackmapID; }
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
index 252c31d..a040d67 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
@@ -32,6 +32,7 @@
#include "DFGAbstractInterpreterInlines.h"
#include "DFGInPlaceAbstractState.h"
#include "DFGOSRAvailabilityAnalysisPhase.h"
+#include "DirectArguments.h"
#include "FTLAbstractHeapRepository.h"
#include "FTLAvailableRecovery.h"
#include "FTLForOSREntryJITCode.h"
@@ -43,7 +44,10 @@
#include "FTLThunks.h"
#include "FTLWeightedTarget.h"
#include "JSCInlines.h"
+#include "JSLexicalEnvironment.h"
#include "OperandsInlines.h"
+#include "ScopedArguments.h"
+#include "ScopedArgumentsTable.h"
#include "VirtualRegister.h"
#include <atomic>
#include <dlfcn.h>
@@ -167,21 +171,18 @@
}
}
}
-
- LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
-
+
if (maxNumberOfArguments >= 0) {
m_execState = m_out.alloca(arrayType(m_out.int64, JSStack::CallFrameHeaderSize + maxNumberOfArguments));
m_execStorage = m_out.ptrToInt(m_execState, m_out.intPtr);
}
+ LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
+
m_captured = m_out.add(
m_out.ptrToInt(capturedAlloca, m_out.intPtr),
m_out.constIntPtr(m_graph.m_nextMachineLocal * sizeof(Register)));
- // We should not create any alloca's after this point, since they will cease to
- // be mem2reg candidates.
-
m_ftlState.capturedStackmapID = m_stackmapIDs++;
m_out.call(
m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.capturedStackmapID),
@@ -195,6 +196,7 @@
case CallVarargs:
case CallForwardVarargs:
case ConstructVarargs:
+ case ConstructForwardVarargs:
hasVarargs = true;
break;
default:
@@ -211,6 +213,9 @@
m_out.int32Zero, varargsSpillSlots);
}
+ // We should not create any alloca's after this point, since they will cease to
+ // be mem2reg candidates.
+
m_callFrame = m_out.ptrToInt(
m_out.call(m_out.frameAddressIntrinsic(), m_out.int32Zero), m_out.intPtr);
m_tagTypeNumber = m_out.constInt64(TagTypeNumber);
@@ -434,9 +439,6 @@
case Int52Constant:
compileInt52Constant();
break;
- case PhantomArguments:
- compilePhantomArguments();
- break;
case DoubleRep:
compileDoubleRep();
break;
@@ -461,12 +463,6 @@
case PutStack:
compilePutStack();
break;
- case GetMyArgumentsLength:
- compileGetMyArgumentsLength();
- break;
- case GetMyArgumentByVal:
- compileGetMyArgumentByVal();
- break;
case Phantom:
case HardPhantom:
case Check:
@@ -592,6 +588,9 @@
case GetByVal:
compileGetByVal();
break;
+ case GetMyArgumentByVal:
+ compileGetMyArgumentByVal();
+ break;
case PutByVal:
case PutByValAlias:
case PutByValDirect:
@@ -603,6 +602,21 @@
case ArrayPop:
compileArrayPop();
break;
+ case CreateActivation:
+ compileCreateActivation();
+ break;
+ case NewFunction:
+ compileNewFunction();
+ break;
+ case CreateDirectArguments:
+ compileCreateDirectArguments();
+ break;
+ case CreateScopedArguments:
+ compileCreateScopedArguments();
+ break;
+ case CreateClonedArguments:
+ compileCreateClonedArguments();
+ break;
case NewObject:
compileNewObject();
break;
@@ -670,21 +684,27 @@
case GetCallee:
compileGetCallee();
break;
+ case GetArgumentCount:
+ compileGetArgumentCount();
+ break;
case GetScope:
compileGetScope();
break;
case SkipScope:
compileSkipScope();
break;
- case GetClosureRegisters:
- compileGetClosureRegisters();
- break;
case GetClosureVar:
compileGetClosureVar();
break;
case PutClosureVar:
compilePutClosureVar();
break;
+ case GetFromArguments:
+ compileGetFromArguments();
+ break;
+ case PutToArguments:
+ compilePutToArguments();
+ break;
case CompareEq:
compileCompareEq();
break;
@@ -716,11 +736,15 @@
case CallVarargs:
case CallForwardVarargs:
case ConstructVarargs:
+ case ConstructForwardVarargs:
compileCallOrConstructVarargs();
break;
case LoadVarargs:
compileLoadVarargs();
break;
+ case ForwardVarargs:
+ compileForwardVarargs();
+ break;
#if ENABLE(FTL_NATIVE_CALL_INLINING)
case NativeCall:
case NativeConstruct:
@@ -749,9 +773,6 @@
case InvalidationPoint:
compileInvalidationPoint();
break;
- case CheckArgumentsNotCreated:
- compileCheckArgumentsNotCreated();
- break;
case IsUndefined:
compileIsUndefined();
break;
@@ -829,6 +850,8 @@
case MovHint:
case ZombieHint:
case PhantomNewObject:
+ case PhantomDirectArguments:
+ case PhantomClonedArguments:
case PutHint:
case BottomValue:
case KillStack:
@@ -838,7 +861,7 @@
break;
}
- if (!m_state.isValid()) {
+ if (!m_state.isValid() && !m_node->isTerminal()) {
safelyInvalidateAfterTermination();
return false;
}
@@ -917,11 +940,6 @@
setStrictInt52(m_out.constInt64(value));
}
- void compilePhantomArguments()
- {
- setJSValue(m_out.constInt64(JSValue::encode(JSValue())));
- }
-
void compileDoubleRep()
{
switch (m_node->child1().useKind()) {
@@ -1095,8 +1113,7 @@
{
StackAccessData* data = m_node->stackAccessData();
switch (data->format) {
- case FlushedJSValue:
- case FlushedArguments: {
+ case FlushedJSValue: {
LValue value = lowJSValue(m_node->child1());
m_out.store64(value, addressFor(data->machineLocal));
break;
@@ -2116,79 +2133,6 @@
setInt32(m_out.castToInt32(m_out.phi(m_out.intPtr, simpleOut, wastefulOut)));
}
- void compileGetMyArgumentsLength()
- {
- checkArgumentsNotCreated();
-
- if (m_node->origin.semantic.inlineCallFrame
- && !m_node->origin.semantic.inlineCallFrame->isVarargs()) {
- setInt32(
- m_out.constInt32(
- m_node->origin.semantic.inlineCallFrame->arguments.size() - 1));
- } else {
- VirtualRegister argumentCountRegister;
- if (!m_node->origin.semantic.inlineCallFrame)
- argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);
- else
- argumentCountRegister = m_node->origin.semantic.inlineCallFrame->argumentCountRegister;
- setInt32(
- m_out.add(
- m_out.load32NonNegative(payloadFor(argumentCountRegister)),
- m_out.constInt32(-1)));
- }
- }
-
- void compileGetMyArgumentByVal()
- {
- checkArgumentsNotCreated();
-
- CodeOrigin codeOrigin = m_node->origin.semantic;
-
- LValue index = lowInt32(m_node->child1());
-
- LValue limit;
- if (codeOrigin.inlineCallFrame
- && !codeOrigin.inlineCallFrame->isVarargs())
- limit = m_out.constInt32(codeOrigin.inlineCallFrame->arguments.size() - 1);
- else {
- VirtualRegister argumentCountRegister;
- if (!codeOrigin.inlineCallFrame)
- argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);
- else
- argumentCountRegister = codeOrigin.inlineCallFrame->argumentCountRegister;
- limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);
- }
-
- speculate(Uncountable, noValue(), 0, m_out.aboveOrEqual(index, limit));
-
- SymbolTable* symbolTable = m_graph.baselineCodeBlockFor(codeOrigin)->symbolTable();
- if (symbolTable->slowArguments()) {
- // FIXME: FTL should support activations.
- // https://bugs.webkit.org/show_bug.cgi?id=129576
-
- DFG_CRASH(m_graph, m_node, "Unimplemented");
- }
-
- TypedPointer base;
- if (codeOrigin.inlineCallFrame) {
- if (codeOrigin.inlineCallFrame->arguments.size() <= 1) {
- // We should have already exited due to the bounds check, above. Just tell the
- // compiler that anything dominated by this instruction is not reachable, so
- // that we don't waste time generating such code. This will also plant some
- // kind of crashing instruction so that if by some fluke the bounds check didn't
- // work, we'll crash in an easy-to-see way.
- didAlreadyTerminate();
- return;
- }
- base = addressFor(codeOrigin.inlineCallFrame->arguments[1].virtualRegister());
- } else
- base = addressFor(virtualRegisterForArgument(1));
-
- LValue pointer = m_out.baseIndex(
- base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight);
- setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)));
- }
-
void compileGetArrayLength()
{
switch (m_node->arrayMode().type()) {
@@ -2205,6 +2149,24 @@
return;
}
+ case Array::DirectArguments: {
+ LValue arguments = lowCell(m_node->child1());
+ speculate(
+ ExoticObjectMode, noValue(), nullptr,
+ m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_overrides)));
+ setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length));
+ return;
+ }
+
+ case Array::ScopedArguments: {
+ LValue arguments = lowCell(m_node->child1());
+ speculate(
+ ExoticObjectMode, noValue(), nullptr,
+ m_out.notZero8(m_out.loadPtr(arguments, m_heaps.ScopedArguments_overrodeThings)));
+ setInt32(m_out.load32NonNegative(arguments, m_heaps.ScopedArguments_totalLength));
+ return;
+ }
+
default:
if (isTypedView(m_node->arrayMode().typedArrayType())) {
setInt32(
@@ -2322,6 +2284,78 @@
return;
}
+ case Array::DirectArguments: {
+ LValue base = lowCell(m_node->child1());
+ LValue index = lowInt32(m_node->child2());
+
+ speculate(
+ ExoticObjectMode, noValue(), nullptr,
+ m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_overrides)));
+ speculate(
+ ExoticObjectMode, noValue(), nullptr,
+ m_out.aboveOrEqual(
+ index,
+ m_out.load32NonNegative(base, m_heaps.DirectArguments_length)));
+
+ TypedPointer address = m_out.baseIndex(
+ m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index));
+ setJSValue(m_out.load64(address));
+ return;
+ }
+
+ case Array::ScopedArguments: {
+ LValue base = lowCell(m_node->child1());
+ LValue index = lowInt32(m_node->child2());
+
+ speculate(
+ ExoticObjectMode, noValue(), nullptr,
+ m_out.aboveOrEqual(
+ index,
+ m_out.load32NonNegative(base, m_heaps.ScopedArguments_totalLength)));
+
+ LValue table = m_out.loadPtr(base, m_heaps.ScopedArguments_table);
+ LValue namedLength = m_out.load32(table, m_heaps.ScopedArgumentsTable_length);
+
+ LBasicBlock namedCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments named case"));
+ LBasicBlock overflowCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments overflow case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments continuation"));
+
+ m_out.branch(
+ m_out.aboveOrEqual(index, namedLength), unsure(overflowCase), unsure(namedCase));
+
+ LBasicBlock lastNext = m_out.appendTo(namedCase, overflowCase);
+
+ LValue scope = m_out.loadPtr(base, m_heaps.ScopedArguments_scope);
+ LValue arguments = m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments);
+
+ TypedPointer address = m_out.baseIndex(
+ m_heaps.scopedArgumentsTableArguments, arguments, m_out.zeroExtPtr(index));
+ LValue scopeOffset = m_out.load32(address);
+
+ speculate(
+ ExoticObjectMode, noValue(), nullptr,
+ m_out.equal(scopeOffset, m_out.constInt32(ScopeOffset::invalidOffset)));
+
+ address = m_out.baseIndex(
+ m_heaps.JSEnvironmentRecord_variables, scope, m_out.zeroExtPtr(scopeOffset));
+ ValueFromBlock namedResult = m_out.anchor(m_out.load64(address));
+ m_out.jump(continuation);
+
+ m_out.appendTo(overflowCase, continuation);
+
+ address = m_out.baseIndex(
+ m_heaps.ScopedArguments_overflowStorage, base,
+ m_out.zeroExtPtr(m_out.sub(index, namedLength)));
+ LValue overflowValue = m_out.load64(address);
+ speculate(ExoticObjectMode, noValue(), nullptr, m_out.isZero64(overflowValue));
+ ValueFromBlock overflowResult = m_out.anchor(overflowValue);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.int64, namedResult, overflowResult));
+ return;
+ }
+
case Array::Generic: {
setJSValue(vmCall(
m_out.operation(operationGetByVal), m_callFrame,
@@ -2346,7 +2380,7 @@
m_out.add(
storage,
m_out.shl(
- m_out.zeroExt(index, m_out.intPtr),
+ m_out.zeroExtPtr(index),
m_out.constIntPtr(logElementSize(type)))));
if (isInt(type)) {
@@ -2418,6 +2452,46 @@
} }
}
+ void compileGetMyArgumentByVal()
+ {
+ InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
+
+ LValue index = lowInt32(m_node->child2());
+
+ LValue limit;
+ if (inlineCallFrame && !inlineCallFrame->isVarargs())
+ limit = m_out.constInt32(inlineCallFrame->arguments.size() - 1);
+ else {
+ VirtualRegister argumentCountRegister;
+ if (!inlineCallFrame)
+ argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);
+ else
+ argumentCountRegister = inlineCallFrame->argumentCountRegister;
+ limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);
+ }
+
+ speculate(ExoticObjectMode, noValue(), 0, m_out.aboveOrEqual(index, limit));
+
+ TypedPointer base;
+ if (inlineCallFrame) {
+ if (inlineCallFrame->arguments.size() <= 1) {
+ // We should have already exited due to the bounds check, above. Just tell the
+ // compiler that anything dominated by this instruction is not reachable, so
+ // that we don't waste time generating such code. This will also plant some
+ // kind of crashing instruction so that if by some fluke the bounds check didn't
+ // work, we'll crash in an easy-to-see way.
+ didAlreadyTerminate();
+ return;
+ }
+ base = addressFor(inlineCallFrame->arguments[1].virtualRegister());
+ } else
+ base = addressFor(virtualRegisterForArgument(1));
+
+ LValue pointer = m_out.baseIndex(
+ base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight);
+ setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)));
+ }
+
void compilePutByVal()
{
Edge child1 = m_graph.varArgChild(m_node, 0);
@@ -2473,8 +2547,7 @@
TypedPointer elementPointer = m_out.baseIndex(
m_node->arrayMode().type() == Array::Int32 ?
m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
- storage, m_out.zeroExt(index, m_out.intPtr),
- m_state.forNode(child2).m_value);
+ storage, m_out.zeroExtPtr(index), m_state.forNode(child2).m_value);
if (m_node->op() == PutByValAlias) {
m_out.store64(value, elementPointer);
@@ -2499,8 +2572,7 @@
m_out.doubleNotEqualOrUnordered(value, value));
TypedPointer elementPointer = m_out.baseIndex(
- m_heaps.indexedDoubleProperties,
- storage, m_out.zeroExt(index, m_out.intPtr),
+ m_heaps.indexedDoubleProperties, storage, m_out.zeroExtPtr(index),
m_state.forNode(child2).m_value);
if (m_node->op() == PutByValAlias) {
@@ -2714,9 +2786,7 @@
LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
m_out.store(
- value,
- m_out.baseIndex(heap, storage, m_out.zeroExt(prevLength, m_out.intPtr)),
- refType);
+ value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), refType);
LValue newLength = m_out.add(prevLength, m_out.int32One);
m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
@@ -2769,8 +2839,7 @@
LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
LValue newLength = m_out.sub(prevLength, m_out.int32One);
m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
- TypedPointer pointer = m_out.baseIndex(
- heap, storage, m_out.zeroExt(newLength, m_out.intPtr));
+ TypedPointer pointer = m_out.baseIndex(heap, storage, m_out.zeroExtPtr(newLength));
if (m_node->arrayMode().type() != Array::Double) {
LValue result = m_out.load64(pointer);
m_out.store64(m_out.int64Zero, pointer);
@@ -2802,6 +2871,173 @@
}
}
+ void compileCreateActivation()
+ {
+ LValue scope = lowCell(m_node->child1());
+ SymbolTable* table = m_graph.symbolTableFor(m_node->origin.semantic);
+ Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
+
+ LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateActivation slow path"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateActivation continuation"));
+
+ LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
+
+ LValue fastObject = allocateObject<JSLexicalEnvironment>(
+ JSLexicalEnvironment::allocationSize(table), structure, m_out.intPtrZero, slowPath);
+
+ // We don't need memory barriers since we just fast-created the activation, so the
+ // activation must be young.
+ m_out.storePtr(scope, fastObject, m_heaps.JSScope_next);
+ m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
+
+ for (unsigned i = 0; i < table->scopeSize(); ++i) {
+ m_out.store64(
+ m_out.constInt64(JSValue::encode(jsUndefined())),
+ fastObject, m_heaps.JSEnvironmentRecord_variables[i]);
+ }
+
+ ValueFromBlock fastResult = m_out.anchor(fastObject);
+ m_out.jump(continuation);
+
+ m_out.appendTo(slowPath, continuation);
+ LValue callResult = vmCall(
+ m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure),
+ scope, weakPointer(table));
+ ValueFromBlock slowResult = m_out.anchor(callResult);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
+ }
+
+ void compileNewFunction()
+ {
+ LValue result = vmCall(
+ m_out.operation(operationNewFunction), m_callFrame,
+ lowCell(m_node->child1()), weakPointer(m_node->castOperand<FunctionExecutable*>()));
+ setJSValue(result);
+ }
+
+ void compileCreateDirectArguments()
+ {
+ // FIXME: A more effective way of dealing with the argument count and callee is to have
+ // them be explicit arguments to this node.
+ // https://bugs.webkit.org/show_bug.cgi?id=142207
+
+ Structure* structure =
+ m_graph.globalObjectFor(m_node->origin.semantic)->directArgumentsStructure();
+
+ unsigned minCapacity = m_graph.baselineCodeBlockFor(m_node->origin.semantic)->numParameters() - 1;
+
+ LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments slow path"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments continuation"));
+
+ LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
+
+ ArgumentsLength length = getArgumentsLength();
+
+ LValue fastObject;
+ if (length.isKnown) {
+ fastObject = allocateObject<DirectArguments>(
+ DirectArguments::allocationSize(std::max(length.known, minCapacity)), structure,
+ m_out.intPtrZero, slowPath);
+ } else {
+ LValue size = m_out.add(
+ m_out.shl(length.value, m_out.constInt32(3)),
+ m_out.constInt32(DirectArguments::storageOffset()));
+
+ size = m_out.select(
+ m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
+ size, m_out.constInt32(DirectArguments::allocationSize(minCapacity)));
+
+ fastObject = allocateVariableSizedObject<DirectArguments>(
+ size, structure, m_out.intPtrZero, slowPath);
+ }
+
+ m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length);
+ m_out.store32(m_out.constInt32(minCapacity), fastObject, m_heaps.DirectArguments_minCapacity);
+ m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_overrides);
+ m_out.storePtr(getCurrentCallee(), fastObject, m_heaps.DirectArguments_callee);
+
+ ValueFromBlock fastResult = m_out.anchor(fastObject);
+ m_out.jump(continuation);
+
+ m_out.appendTo(slowPath, continuation);
+ LValue callResult = vmCall(
+ m_out.operation(operationCreateDirectArguments), m_callFrame, weakPointer(structure),
+ length.value, m_out.constInt32(minCapacity));
+ ValueFromBlock slowResult = m_out.anchor(callResult);
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ LValue result = m_out.phi(m_out.intPtr, fastResult, slowResult);
+
+ if (length.isKnown) {
+ VirtualRegister start = AssemblyHelpers::argumentsStart(m_node->origin.semantic);
+ for (unsigned i = 0; i < std::max(length.known, minCapacity); ++i) {
+ m_out.store64(
+ m_out.load64(addressFor(start + i)),
+ result, m_heaps.DirectArguments_storage[i]);
+ }
+ } else {
+ LValue stackBase = getArgumentsStart();
+
+ LBasicBlock loop = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments loop body"));
+ LBasicBlock end = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments loop end"));
+
+ ValueFromBlock originalLength;
+ if (minCapacity) {
+ LValue capacity = m_out.select(
+ m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
+ length.value,
+ m_out.constInt32(minCapacity));
+ originalLength = m_out.anchor(m_out.zeroExtPtr(capacity));
+ m_out.jump(loop);
+ } else {
+ originalLength = m_out.anchor(m_out.zeroExtPtr(length.value));
+ m_out.branch(m_out.isNull(originalLength.value()), unsure(end), unsure(loop));
+ }
+
+ lastNext = m_out.appendTo(loop, end);
+ LValue previousIndex = m_out.phi(m_out.intPtr, originalLength);
+ LValue index = m_out.sub(previousIndex, m_out.intPtrOne);
+ m_out.store64(
+ m_out.load64(m_out.baseIndex(m_heaps.variables, stackBase, index)),
+ m_out.baseIndex(m_heaps.DirectArguments_storage, result, index));
+ ValueFromBlock nextIndex = m_out.anchor(index);
+ addIncoming(previousIndex, nextIndex);
+ m_out.branch(m_out.isNull(index), unsure(end), unsure(loop));
+
+ m_out.appendTo(end, lastNext);
+ }
+
+ setJSValue(result);
+ }
+
+ void compileCreateScopedArguments()
+ {
+ LValue scope = lowCell(m_node->child1());
+
+ LValue result = vmCall(
+ m_out.operation(operationCreateScopedArguments), m_callFrame,
+ weakPointer(
+ m_graph.globalObjectFor(m_node->origin.semantic)->scopedArgumentsStructure()),
+ getArgumentsStart(), getArgumentsLength().value, getCurrentCallee(), scope);
+
+ setJSValue(result);
+ }
+
+ void compileCreateClonedArguments()
+ {
+ LValue result = vmCall(
+ m_out.operation(operationCreateClonedArguments), m_callFrame,
+ weakPointer(
+ m_graph.globalObjectFor(m_node->origin.semantic)->outOfBandArgumentsStructure()),
+ getArgumentsStart(), getArgumentsLength().value, getCurrentCallee());
+
+ setJSValue(result);
+ }
+
void compileNewObject()
{
setJSValue(allocateObject(m_node->structure()));
@@ -3267,8 +3503,7 @@
ValueFromBlock char8Bit = m_out.anchor(m_out.zeroExt(
m_out.load8(m_out.baseIndex(
- m_heaps.characters8,
- storage, m_out.zeroExt(index, m_out.intPtr),
+ m_heaps.characters8, storage, m_out.zeroExtPtr(index),
m_state.forNode(m_node->child2()).m_value)),
m_out.int32));
m_out.jump(bitsContinuation);
@@ -3277,8 +3512,7 @@
ValueFromBlock char16Bit = m_out.anchor(m_out.zeroExt(
m_out.load16(m_out.baseIndex(
- m_heaps.characters16,
- storage, m_out.zeroExt(index, m_out.intPtr),
+ m_heaps.characters16, storage, m_out.zeroExtPtr(index),
m_state.forNode(m_node->child2()).m_value)),
m_out.int32));
m_out.branch(
@@ -3300,8 +3534,7 @@
LValue smallStrings = m_out.constIntPtr(vm().smallStrings.singleCharacterStrings());
results.append(m_out.anchor(m_out.loadPtr(m_out.baseIndex(
- m_heaps.singleCharacterStrings, smallStrings,
- m_out.zeroExt(character, m_out.intPtr)))));
+ m_heaps.singleCharacterStrings, smallStrings, m_out.zeroExtPtr(character)))));
m_out.jump(continuation);
m_out.appendTo(slowPath, continuation);
@@ -3360,8 +3593,7 @@
ValueFromBlock char8Bit = m_out.anchor(m_out.zeroExt(
m_out.load8(m_out.baseIndex(
- m_heaps.characters8,
- storage, m_out.zeroExt(index, m_out.intPtr),
+ m_heaps.characters8, storage, m_out.zeroExtPtr(index),
m_state.forNode(m_node->child2()).m_value)),
m_out.int32));
m_out.jump(continuation);
@@ -3370,8 +3602,7 @@
ValueFromBlock char16Bit = m_out.anchor(m_out.zeroExt(
m_out.load16(m_out.baseIndex(
- m_heaps.characters16,
- storage, m_out.zeroExt(index, m_out.intPtr),
+ m_heaps.characters16, storage, m_out.zeroExtPtr(index),
m_state.forNode(m_node->child2()).m_value)),
m_out.int32));
m_out.jump(continuation);
@@ -3541,13 +3772,13 @@
void compileGetGlobalVar()
{
- setJSValue(m_out.load64(m_out.absolute(m_node->registerPointer())));
+ setJSValue(m_out.load64(m_out.absolute(m_node->variablePointer())));
}
void compilePutGlobalVar()
{
m_out.store64(
- lowJSValue(m_node->child1()), m_out.absolute(m_node->registerPointer()));
+ lowJSValue(m_node->child1()), m_out.absolute(m_node->variablePointer()));
}
void compileNotifyWrite()
@@ -3585,6 +3816,11 @@
setJSValue(m_out.loadPtr(addressFor(JSStack::Callee)));
}
+ void compileGetArgumentCount()
+ {
+ setInt32(m_out.load32(payloadFor(JSStack::ArgumentCount)));
+ }
+
void compileGetScope()
{
setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSFunction_scope));
@@ -3595,28 +3831,36 @@
setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSScope_next));
}
- void compileGetClosureRegisters()
- {
- if (WriteBarrierBase<Unknown>* registers = m_graph.tryGetRegisters(m_node->child1().node())) {
- setStorage(m_out.constIntPtr(registers));
- return;
- }
-
- setStorage(m_out.loadPtr(
- lowCell(m_node->child1()), m_heaps.JSEnvironmentRecord_registers));
- }
-
void compileGetClosureVar()
{
- setJSValue(m_out.load64(
- addressFor(lowStorage(m_node->child2()), m_node->varNumber())));
+ setJSValue(
+ m_out.load64(
+ lowCell(m_node->child1()),
+ m_heaps.JSEnvironmentRecord_variables[m_node->scopeOffset().offset()]));
}
void compilePutClosureVar()
{
m_out.store64(
- lowJSValue(m_node->child3()),
- addressFor(lowStorage(m_node->child2()), m_node->varNumber()));
+ lowJSValue(m_node->child2()),
+ lowCell(m_node->child1()),
+ m_heaps.JSEnvironmentRecord_variables[m_node->scopeOffset().offset()]);
+ }
+
+ void compileGetFromArguments()
+ {
+ setJSValue(
+ m_out.load64(
+ lowCell(m_node->child1()),
+ m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()]));
+ }
+
+ void compilePutToArguments()
+ {
+ m_out.store64(
+ lowJSValue(m_node->child2()),
+ lowCell(m_node->child1()),
+ m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()]);
}
void compileCompareEq()
@@ -3858,21 +4102,17 @@
void compileCallOrConstructVarargs()
{
LValue jsCallee = lowJSValue(m_node->child1());
+ LValue thisArg = lowJSValue(m_node->child3());
LValue jsArguments = nullptr;
- LValue thisArg = nullptr;
switch (m_node->op()) {
case CallVarargs:
- jsArguments = lowJSValue(m_node->child2());
- thisArg = lowJSValue(m_node->child3());
- break;
- case CallForwardVarargs:
- thisArg = lowJSValue(m_node->child2());
- break;
case ConstructVarargs:
jsArguments = lowJSValue(m_node->child2());
- thisArg = lowJSValue(m_node->child3());
+ break;
+ case CallForwardVarargs:
+ case ConstructForwardVarargs:
break;
default:
DFG_CRASH(m_graph, m_node, "bad node type");
@@ -3936,6 +4176,63 @@
m_out.castToInt32(machineStart), jsArguments, m_out.constInt32(data->offset),
length, m_out.constInt32(data->mandatoryMinimum));
}
+
+ void compileForwardVarargs()
+ {
+ LoadVarargsData* data = m_node->loadVarargsData();
+ InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
+
+ LValue length = getArgumentsLength(inlineCallFrame).value;
+ LValue lengthIncludingThis = m_out.add(length, m_out.constInt32(1 - data->offset));
+
+ speculate(
+ VarargsOverflow, noValue(), nullptr,
+ m_out.above(lengthIncludingThis, m_out.constInt32(data->limit)));
+
+ m_out.store32(lengthIncludingThis, payloadFor(data->machineCount));
+
+ LValue sourceStart = getArgumentsStart(inlineCallFrame);
+ LValue targetStart = addressFor(data->machineStart).value();
+
+ LBasicBlock undefinedLoop = FTL_NEW_BLOCK(m_out, ("ForwardVarargs undefined loop body"));
+ LBasicBlock mainLoopEntry = FTL_NEW_BLOCK(m_out, ("ForwardVarargs main loop entry"));
+ LBasicBlock mainLoop = FTL_NEW_BLOCK(m_out, ("ForwardVarargs main loop body"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ForwardVarargs continuation"));
+
+ LValue lengthAsPtr = m_out.zeroExtPtr(length);
+ ValueFromBlock loopBound = m_out.anchor(m_out.constIntPtr(data->mandatoryMinimum));
+ m_out.branch(
+ m_out.above(loopBound.value(), lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry));
+
+ LBasicBlock lastNext = m_out.appendTo(undefinedLoop, mainLoopEntry);
+ LValue previousIndex = m_out.phi(m_out.intPtr, loopBound);
+ LValue currentIndex = m_out.sub(previousIndex, m_out.intPtrOne);
+ m_out.store64(
+ m_out.constInt64(JSValue::encode(jsUndefined())),
+ m_out.baseIndex(m_heaps.variables, targetStart, currentIndex));
+ ValueFromBlock nextIndex = m_out.anchor(currentIndex);
+ addIncoming(previousIndex, nextIndex);
+ m_out.branch(
+ m_out.above(currentIndex, lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry));
+
+ m_out.appendTo(mainLoopEntry, mainLoop);
+ loopBound = m_out.anchor(lengthAsPtr);
+ m_out.branch(m_out.notNull(loopBound.value()), unsure(mainLoop), unsure(continuation));
+
+ m_out.appendTo(mainLoop, continuation);
+ previousIndex = m_out.phi(m_out.intPtr, loopBound);
+ currentIndex = m_out.sub(previousIndex, m_out.intPtrOne);
+ LValue value = m_out.load64(
+ m_out.baseIndex(
+ m_heaps.variables, sourceStart,
+ m_out.add(currentIndex, m_out.constIntPtr(data->offset))));
+ m_out.store64(value, m_out.baseIndex(m_heaps.variables, targetStart, currentIndex));
+ nextIndex = m_out.anchor(currentIndex);
+ addIncoming(previousIndex, nextIndex);
+ m_out.branch(m_out.isNull(currentIndex), unsure(continuation), unsure(mainLoop));
+
+ m_out.appendTo(continuation, lastNext);
+ }
void compileJump()
{
@@ -4171,15 +4468,6 @@
info.m_isInvalidationPoint = true;
}
- void compileCheckArgumentsNotCreated()
- {
- ASSERT(!isEmptySpeculation(
- m_state.variables().operand(
- m_graph.argumentsRegisterFor(m_node->origin.semantic)).m_type));
-
- checkArgumentsNotCreated();
- }
-
void compileIsUndefined()
{
setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined));
@@ -4551,8 +4839,7 @@
LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
ValueFromBlock inBoundsResult = m_out.anchor(
- m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
- storage, m_out.signExt(index, m_out.int64), ScaleEight)));
+ m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index))));
m_out.jump(continuation);
m_out.appendTo(outOfBounds, continuation);
@@ -4578,8 +4865,7 @@
LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
ValueFromBlock inBoundsResult = m_out.anchor(
- m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
- storage, m_out.signExt(index, m_out.int64), ScaleEight)));
+ m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index))));
m_out.jump(continuation);
m_out.appendTo(outOfBounds, continuation);
@@ -4878,6 +5164,67 @@
return m_out.booleanFalse;
}
+ struct ArgumentsLength {
+ ArgumentsLength()
+ : isKnown(false)
+ , known(UINT_MAX)
+ , value(nullptr)
+ {
+ }
+
+ bool isKnown;
+ unsigned known;
+ LValue value;
+ };
+ ArgumentsLength getArgumentsLength(InlineCallFrame* inlineCallFrame)
+ {
+ ArgumentsLength length;
+
+ if (inlineCallFrame && !inlineCallFrame->isVarargs()) {
+ length.known = inlineCallFrame->arguments.size() - 1;
+ length.isKnown = true;
+ length.value = m_out.constInt32(length.known);
+ } else {
+ length.known = UINT_MAX;
+ length.isKnown = false;
+
+ VirtualRegister argumentCountRegister;
+ if (!inlineCallFrame)
+ argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);
+ else
+ argumentCountRegister = inlineCallFrame->argumentCountRegister;
+ length.value = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);
+ }
+
+ return length;
+ }
+
+ ArgumentsLength getArgumentsLength()
+ {
+ return getArgumentsLength(m_node->origin.semantic.inlineCallFrame);
+ }
+
+ LValue getCurrentCallee()
+ {
+ if (InlineCallFrame* frame = m_node->origin.semantic.inlineCallFrame) {
+ if (frame->isClosureCall)
+ return m_out.loadPtr(addressFor(frame->calleeRecovery.virtualRegister()));
+ return weakPointer(frame->calleeRecovery.constant().asCell());
+ }
+ return m_out.loadPtr(addressFor(JSStack::Callee));
+ }
+
+ LValue getArgumentsStart(InlineCallFrame* inlineCallFrame)
+ {
+ VirtualRegister start = AssemblyHelpers::argumentsStart(inlineCallFrame);
+ return addressFor(start).value();
+ }
+
+ LValue getArgumentsStart()
+ {
+ return getArgumentsStart(m_node->origin.semantic.inlineCallFrame);
+ }
+
void checkStructure(
LValue structureID, const FormattedValue& formattedValue, ExitKind exitKind,
const StructureSet& set)
@@ -5098,11 +5445,10 @@
return call;
}
- TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue storage, LValue index, Edge edge)
+ TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue storage, LValue index, Edge edge, ptrdiff_t offset = 0)
{
return m_out.baseIndex(
- heap, storage, m_out.zeroExt(index, m_out.intPtr),
- m_state.forNode(edge).m_value);
+ heap, storage, m_out.zeroExtPtr(index), m_state.forNode(edge).m_value, offset);
}
void compare(
@@ -5253,13 +5599,63 @@
}
template<typename ClassType>
- LValue allocateObject(Structure* structure, LValue butterfly, LBasicBlock slowPath)
+ LValue allocateObject(
+ size_t size, Structure* structure, LValue butterfly, LBasicBlock slowPath)
{
- size_t size = ClassType::allocationSize(0);
MarkedAllocator* allocator = &vm().heap.allocatorForObjectOfType<ClassType>(size);
return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, slowPath);
}
+ template<typename ClassType>
+ LValue allocateObject(Structure* structure, LValue butterfly, LBasicBlock slowPath)
+ {
+ return allocateObject<ClassType>(
+ ClassType::allocationSize(0), structure, butterfly, slowPath);
+ }
+
+ template<typename ClassType>
+ LValue allocateVariableSizedObject(
+ LValue size, Structure* structure, LValue butterfly, LBasicBlock slowPath)
+ {
+ static_assert(!(MarkedSpace::preciseStep & (MarkedSpace::preciseStep - 1)), "MarkedSpace::preciseStep must be a power of two.");
+ static_assert(!(MarkedSpace::impreciseStep & (MarkedSpace::impreciseStep - 1)), "MarkedSpace::impreciseStep must be a power of two.");
+
+ LValue subspace = m_out.constIntPtr(&vm().heap.subspaceForObjectOfType<ClassType>());
+
+ LBasicBlock smallCaseBlock = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject small case"));
+ LBasicBlock largeOrOversizeCaseBlock = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject large or oversize case"));
+ LBasicBlock largeCaseBlock = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject large case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocateVariableSizedObject continuation"));
+
+ LValue uproundedSize = m_out.add(size, m_out.constInt32(MarkedSpace::preciseStep - 1));
+ LValue isSmall = m_out.below(uproundedSize, m_out.constInt32(MarkedSpace::preciseCutoff));
+ m_out.branch(isSmall, unsure(smallCaseBlock), unsure(largeOrOversizeCaseBlock));
+
+ LBasicBlock lastNext = m_out.appendTo(smallCaseBlock, largeOrOversizeCaseBlock);
+ TypedPointer address = m_out.baseIndex(
+ m_heaps.MarkedSpace_Subspace_preciseAllocators, subspace,
+ m_out.zeroExtPtr(m_out.lShr(uproundedSize, m_out.constInt32(getLSBSet(MarkedSpace::preciseStep)))));
+ ValueFromBlock smallAllocator = m_out.anchor(address.value());
+ m_out.jump(continuation);
+
+ m_out.appendTo(largeOrOversizeCaseBlock, largeCaseBlock);
+ m_out.branch(
+ m_out.below(uproundedSize, m_out.constInt32(MarkedSpace::impreciseCutoff)),
+ usually(largeCaseBlock), rarely(slowPath));
+
+ m_out.appendTo(largeCaseBlock, continuation);
+ address = m_out.baseIndex(
+ m_heaps.MarkedSpace_Subspace_impreciseAllocators, subspace,
+ m_out.zeroExtPtr(m_out.lShr(uproundedSize, m_out.constInt32(getLSBSet(MarkedSpace::impreciseStep)))));
+ ValueFromBlock largeAllocator = m_out.anchor(address.value());
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ LValue allocator = m_out.phi(m_out.intPtr, smallAllocator, largeAllocator);
+
+ return allocateObject(allocator, structure, butterfly, slowPath);
+ }
+
// Returns a pointer to the end of the allocation.
LValue allocateBasicStorageAndGetEnd(LValue size, LBasicBlock slowPath)
{
@@ -5663,19 +6059,6 @@
return m_out.phi(m_out.int32, fastResult, slowResult);
}
- void checkArgumentsNotCreated()
- {
- CodeOrigin codeOrigin = m_node->origin.semantic;
- VirtualRegister argumentsRegister = m_graph.argumentsRegisterFor(codeOrigin);
- if (isEmptySpeculation(m_state.variables().operand(argumentsRegister).m_type))
- return;
-
- VirtualRegister argsReg = m_graph.machineArgumentsRegisterFor(codeOrigin);
- speculate(
- ArgumentsEscaped, noValue(), 0,
- m_out.notZero64(m_out.load64(addressFor(argsReg))));
- }
-
void speculate(
ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
{
@@ -6363,6 +6746,16 @@
DFG_CRASH(m_graph, m_node, "Corrupt array class");
}
+ case Array::DirectArguments:
+ return m_out.equal(
+ m_out.load8(cell, m_heaps.JSCell_typeInfoType),
+ m_out.constInt8(DirectArgumentsType));
+
+ case Array::ScopedArguments:
+ return m_out.equal(
+ m_out.load8(cell, m_heaps.JSCell_typeInfoType),
+ m_out.constInt8(ScopedArgumentsType));
+
default:
return m_out.equal(
m_out.load8(cell, m_heaps.JSCell_typeInfoType),
@@ -6651,7 +7044,7 @@
// Buffer has space, store to it.
m_out.appendTo(bufferHasSpace, bufferIsFull);
LValue writeBarrierBufferBase = m_out.loadPtr(m_out.absolute(&vm().heap.writeBarrierBuffer().m_buffer));
- m_out.storePtr(base, m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents, writeBarrierBufferBase, m_out.zeroExt(currentBufferIndex, m_out.intPtr), ScalePtr));
+ m_out.storePtr(base, m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents, writeBarrierBufferBase, m_out.zeroExtPtr(currentBufferIndex)));
m_out.store32(m_out.add(currentBufferIndex, m_out.constInt32(1)), m_out.absolute(&vm().heap.writeBarrierBuffer().m_currentIndex));
m_out.jump(continuation);
@@ -6789,12 +7182,14 @@
return;
Node* node = availability.node();
- if (!node->isPhantomObjectAllocation())
+ if (!node->isPhantomAllocation())
return;
auto result = map.add(node, nullptr);
- if (result.isNewEntry)
- result.iterator->value = exit.m_materializations.add(node->op());
+ if (result.isNewEntry) {
+ result.iterator->value =
+ exit.m_materializations.add(node->op(), node->origin.semantic);
+ }
});
for (unsigned i = 0; i < exit.m_values.size(); ++i) {
@@ -6861,9 +7256,6 @@
case FlushedDouble:
return ExitValue::inJSStackAsDouble(flush.virtualRegister());
-
- case FlushedArguments:
- return ExitValue::argumentsObjectThatWasNotCreated();
}
DFG_CRASH(m_graph, m_node, "Invalid flush format");
@@ -6889,13 +7281,9 @@
case DoubleConstant:
return ExitValue::constant(node->asJSValue());
- case PhantomArguments:
- return ExitValue::argumentsObjectThatWasNotCreated();
-
- case PhantomNewObject:
- return ExitValue::materializeNewObject(map.get(node));
-
default:
+ if (node->isPhantomAllocation())
+ return ExitValue::materializeNewObject(map.get(node));
break;
}
}
@@ -7068,9 +7456,9 @@
LValue tableIndex = m_out.load32(value, m_heaps.JSCell_structureID);
LValue tableBase = m_out.loadPtr(
m_out.absolute(vm().heap.structureIDTable().base()));
- LValue pointerIntoTable = m_out.baseIndex(
- tableBase, m_out.zeroExt(tableIndex, m_out.intPtr), ScaleEight);
- return m_out.loadPtr(TypedPointer(m_heaps.structureTable, pointerIntoTable));
+ TypedPointer address = m_out.baseIndex(
+ m_heaps.structureTable, tableBase, m_out.zeroExtPtr(tableIndex));
+ return m_out.loadPtr(address);
}
LValue weakPointer(JSCell* pointer)
diff --git a/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp b/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
index 597ab97..8fddc39a 100644
--- a/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -73,10 +73,6 @@
jit.load64(AssemblyHelpers::addressFor(value.virtualRegister()), GPRInfo::regT0);
break;
- case ExitValueArgumentsObjectThatWasNotCreated:
- jit.move(MacroAssembler::TrustedImm64(JSValue::encode(JSValue())), GPRInfo::regT0);
- break;
-
case ExitValueRecovery:
record->locations[value.rightRecoveryArgument()].restoreInto(
jit, stackmaps, registerScratch, GPRInfo::regT1);
@@ -230,7 +226,11 @@
}
// Materialize all objects. Don't materialize an object until all of the objects it needs
- // have been materialized.
+ // have been materialized. Curiously, this is the only place that we have an algorithm that prevents
+ // OSR exit from handling cyclic object materializations. Of course, object allocation sinking
+ // currently wouldn't recognize a cycle as being sinkable - but if it did then the only thing that
+ // would ahve to change is this fixpoint. Instead we would allocate the objects first and populate
+ // them with data later.
HashSet<ExitTimeObjectMaterialization*> toMaterialize;
for (ExitTimeObjectMaterialization* materialization : exit.m_materializations)
toMaterialize.add(materialization);
@@ -443,15 +443,6 @@
handleExitCounts(jit, exit);
reifyInlinedCallFrames(jit, exit);
-
- ArgumentsRecoveryGenerator argumentsRecovery;
- for (unsigned index = exit.m_values.size(); index--;) {
- if (!exit.m_values[index].isArgumentsObjectThatWasNotCreated())
- continue;
- int operand = exit.m_values.operandForIndex(index);
- argumentsRecovery.generateFor(operand, exit.m_codeOrigin, jit);
- }
-
adjustAndJumpToTarget(jit, exit);
LinkBuffer patchBuffer(*vm, jit, codeBlock);
diff --git a/Source/JavaScriptCore/ftl/FTLOperations.cpp b/Source/JavaScriptCore/ftl/FTLOperations.cpp
index 045e678..0d9be3e 100644
--- a/Source/JavaScriptCore/ftl/FTLOperations.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOperations.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,6 +28,8 @@
#if ENABLE(FTL_JIT)
+#include "ClonedArguments.h"
+#include "DirectArguments.h"
#include "JSCInlines.h"
namespace JSC { namespace FTL {
@@ -54,42 +56,139 @@
// We cannot GC. We've got pointers in evil places.
DeferGCForAWhile deferGC(vm.heap);
- // In the future, we may have many different kinds of materializations. For now we just
- // materialize NewObject.
- RELEASE_ASSERT(materialization->type() == PhantomNewObject);
-
- // First figure out what the structure is.
- Structure* structure = nullptr;
- for (unsigned i = materialization->properties().size(); i--;) {
- const ExitPropertyValue& property = materialization->properties()[i];
- if (property.location() != PromotedLocationDescriptor(StructurePLoc))
- continue;
-
- structure = jsCast<Structure*>(JSValue::decode(values[i]));
- }
- RELEASE_ASSERT(structure);
-
- // Let's create that object!
- JSFinalObject* result = JSFinalObject::create(vm, structure);
-
- // Now figure out what the heck to populate the object with. Use getPropertiesConcurrently()
- // because that happens to be lower-level and more convenient. It doesn't change the
- // materialization of the property table. We want to have minimal visible effects on the
- // system. Also, don't mind that this is O(n^2). It doesn't matter. We only get here from OSR
- // exit.
- for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) {
+ switch (materialization->type()) {
+ case PhantomNewObject: {
+ // First figure out what the structure is.
+ Structure* structure = nullptr;
for (unsigned i = materialization->properties().size(); i--;) {
const ExitPropertyValue& property = materialization->properties()[i];
- if (property.location().kind() != NamedPropertyPLoc)
+ if (property.location() != PromotedLocationDescriptor(StructurePLoc))
continue;
- if (codeBlock->identifier(property.location().info()).impl() != entry.key)
- continue;
+
+ structure = jsCast<Structure*>(JSValue::decode(values[i]));
+ break;
+ }
+ RELEASE_ASSERT(structure);
+
+ // Let's create that object!
+ JSFinalObject* result = JSFinalObject::create(vm, structure);
+
+ // Now figure out what the heck to populate the object with. Use getPropertiesConcurrently()
+ // because that happens to be lower-level and more convenient. It doesn't change the
+ // materialization of the property table. We want to have minimal visible effects on the
+ // system. Also, don't mind that this is O(n^2). It doesn't matter. We only get here from OSR
+ // exit.
+ for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) {
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location().kind() != NamedPropertyPLoc)
+ continue;
+ if (codeBlock->identifier(property.location().info()).impl() != entry.key)
+ continue;
- result->putDirect(vm, entry.offset, JSValue::decode(values[i]));
+ result->putDirect(vm, entry.offset, JSValue::decode(values[i]));
+ }
+ }
+
+ return result;
+ }
+
+ case PhantomDirectArguments:
+ case PhantomClonedArguments: {
+ if (!materialization->origin().inlineCallFrame) {
+ switch (materialization->type()) {
+ case PhantomDirectArguments:
+ return DirectArguments::createByCopying(exec);
+ case PhantomClonedArguments:
+ return ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned);
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+ }
+ }
+
+ // First figure out the argument count. If there isn't one then we represent the machine frame.
+ unsigned argumentCount = 0;
+ if (materialization->origin().inlineCallFrame->isVarargs()) {
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location() != PromotedLocationDescriptor(ArgumentCountPLoc))
+ continue;
+
+ argumentCount = JSValue::decode(values[i]).asUInt32();
+ RELEASE_ASSERT(argumentCount);
+ break;
+ }
+ RELEASE_ASSERT(argumentCount);
+ } else
+ argumentCount = materialization->origin().inlineCallFrame->arguments.size();
+
+ JSFunction* callee = nullptr;
+ if (materialization->origin().inlineCallFrame->isClosureCall) {
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location() != PromotedLocationDescriptor(ArgumentsCalleePLoc))
+ continue;
+
+ callee = jsCast<JSFunction*>(JSValue::decode(values[i]));
+ break;
+ }
+ } else
+ callee = materialization->origin().inlineCallFrame->calleeConstant();
+ RELEASE_ASSERT(callee);
+
+ CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock(
+ materialization->origin(), exec->codeBlock());
+
+ // We have an inline frame and we have all of the data we need to recreate it.
+ switch (materialization->type()) {
+ case PhantomDirectArguments: {
+ unsigned length = argumentCount - 1;
+ unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
+ DirectArguments* result = DirectArguments::create(
+ vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
+ result->callee().set(vm, result, callee);
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location().kind() != ArgumentPLoc)
+ continue;
+
+ unsigned index = property.location().info();
+ if (index >= capacity)
+ continue;
+ result->setIndexQuickly(vm, index, JSValue::decode(values[i]));
+ }
+ return result;
+ }
+ case PhantomClonedArguments: {
+ unsigned length = argumentCount - 1;
+ ClonedArguments* result = ClonedArguments::createEmpty(
+ vm, codeBlock->globalObject()->outOfBandArgumentsStructure(), callee);
+
+ for (unsigned i = materialization->properties().size(); i--;) {
+ const ExitPropertyValue& property = materialization->properties()[i];
+ if (property.location().kind() != ArgumentPLoc)
+ continue;
+
+ unsigned index = property.location().info();
+ if (index >= length)
+ continue;
+ result->putDirectIndex(exec, index, JSValue::decode(values[i]));
+ }
+
+ result->putDirect(vm, vm.propertyNames->length, jsNumber(length));
+ return result;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
}
}
-
- return result;
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+ }
}
} } // namespace JSC::FTL
diff --git a/Source/JavaScriptCore/ftl/FTLOutput.h b/Source/JavaScriptCore/ftl/FTLOutput.h
index cd3751e..65a6746 100644
--- a/Source/JavaScriptCore/ftl/FTLOutput.h
+++ b/Source/JavaScriptCore/ftl/FTLOutput.h
@@ -133,8 +133,8 @@
LValue bitOr(LValue left, LValue right) { return buildOr(m_builder, left, right); }
LValue bitXor(LValue left, LValue right) { return buildXor(m_builder, left, right); }
LValue shl(LValue left, LValue right) { return buildShl(m_builder, left, right); }
- LValue aShr(LValue left, LValue right) { return buildAShr(m_builder, left, right); }
- LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); }
+ LValue aShr(LValue left, LValue right) { return buildAShr(m_builder, left, right); } // arithmetic = signed
+ LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); } // logical = unsigned
LValue bitNot(LValue value) { return buildNot(m_builder, value); }
LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); }
@@ -202,6 +202,7 @@
LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); }
LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
+ LValue zeroExtPtr(LValue value) { return zeroExt(value, intPtr); }
LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); }
LValue fpToUInt(LValue value, LType type) { return buildFPToUI(m_builder, value, type); }
LValue fpToInt32(LValue value) { return fpToInt(value, int32); }
@@ -217,6 +218,8 @@
LValue ptrToInt(LValue value, LType type) { return buildPtrToInt(m_builder, value, type); }
LValue bitCast(LValue value, LType type) { return buildBitCast(m_builder, value, type); }
+ // Hilariously, the #define machinery in the stdlib means that this method is actually called
+ // __builtin_alloca. So far this appears benign. :-|
LValue alloca(LType type) { return buildAlloca(m_builder, type); }
// Access the value of an alloca. Also used as a low-level implementation primitive for