source: webkit/trunk/Source/JavaScriptCore/jsc.cpp@ 171641

Last change on this file since 171641 was 171641, checked in by [email protected], 11 years ago

Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376, r170382, r170383, r170399, r170436, r170489, r170490, r170556 from ftlopt.

Source/JavaScriptCore:

2014-06-27 Michael Saboff <[email protected]>


Unreviewed build fix after r169795.


Fixed ASSERT for 32 bit build.


  • dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):


2014-06-24 Saam Barati <[email protected]>


Web Inspector: debugger should be able to show variable types
https://bugs.webkit.org/show_bug.cgi?id=133395


Reviewed by Filip Pizlo.


Increase the amount of type information the VM gathers when directed
to do so. This initial commit is working towards the goal of
capturing, and then showing (via the Web Inspector) type information for all
assignment and load operations. This patch doesn't have the feature fully
implemented, but it ensures the VM has no performance regressions
unless the feature is specifically turned on.


  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h: (JSC::computeUsesForBytecodeOffset): (JSC::computeDefsForBytecodeOffset):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dumpBytecode): (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::finalizeUnconditionally):
  • bytecode/CodeBlock.h:
  • bytecode/Instruction.h:
  • bytecode/TypeLocation.h: Added. (JSC::TypeLocation::TypeLocation):
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitMove): (JSC::BytecodeGenerator::emitProfileTypesWithHighFidelity): (JSC::BytecodeGenerator::emitPutToScope): (JSC::BytecodeGenerator::emitPutById): (JSC::BytecodeGenerator::emitPutByVal):
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::isProfilingTypesWithHighFidelity):
  • bytecompiler/NodesCodegen.cpp: (JSC::PostfixNode::emitResolve): (JSC::PrefixNode::emitResolve): (JSC::ReadModifyResolveNode::emitBytecode): (JSC::AssignResolveNode::emitBytecode): (JSC::ConstDeclNode::emitCodeSingle): (JSC::ForInNode::emitBytecode):
  • heap/Heap.cpp: (JSC::Heap::collect):
  • inspector/agents/InspectorRuntimeAgent.cpp: (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange):
  • inspector/agents/InspectorRuntimeAgent.h:
  • inspector/protocol/Runtime.json:
  • jsc.cpp: (GlobalObject::finishCreation): (functionDumpTypesForAllVariables):
  • llint/LLIntSlowPaths.cpp: (JSC::LLInt::LLINT_SLOW_PATH_DECL): (JSC::LLInt::putToScopeCommon):
  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter.asm:
  • runtime/HighFidelityLog.cpp: Added. (JSC::HighFidelityLog::initializeHighFidelityLog): (JSC::HighFidelityLog::~HighFidelityLog): (JSC::HighFidelityLog::recordTypeInformationForLocation): (JSC::HighFidelityLog::processHighFidelityLog): (JSC::HighFidelityLog::actuallyProcessLogThreadFunction):
  • runtime/HighFidelityLog.h: Added. (JSC::HighFidelityLog::HighFidelityLog):
  • runtime/HighFidelityTypeProfiler.cpp: Added. (JSC::HighFidelityTypeProfiler::getTypesForVariableInRange): (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableInRange): (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableInRange): (JSC::HighFidelityTypeProfiler::insertNewLocation): (JSC::HighFidelityTypeProfiler::getLocationBasedHash):
  • runtime/HighFidelityTypeProfiler.h: Added.
  • runtime/Options.h:
  • runtime/Structure.cpp: (JSC::Structure::toStructureShape):
  • runtime/Structure.h:
  • runtime/SymbolTable.cpp: (JSC::SymbolTable::SymbolTable): (JSC::SymbolTable::cloneCapturedNames): (JSC::SymbolTable::uniqueIDForVariable): (JSC::SymbolTable::uniqueIDForRegister): (JSC::SymbolTable::globalTypeSetForRegister): (JSC::SymbolTable::globalTypeSetForVariable):
  • runtime/SymbolTable.h: (JSC::SymbolTable::add): (JSC::SymbolTable::set):
  • runtime/TypeSet.cpp: Added. (JSC::TypeSet::TypeSet): (JSC::TypeSet::getRuntimeTypeForValue): (JSC::TypeSet::addTypeForValue): (JSC::TypeSet::removeDuplicatesInStructureHistory): (JSC::TypeSet::seenTypes): (JSC::TypeSet::dumpSeenTypes): (JSC::StructureShape::StructureShape): (JSC::StructureShape::markAsFinal): (JSC::StructureShape::addProperty): (JSC::StructureShape::propertyHash): (JSC::StructureShape::leastUpperBound): (JSC::StructureShape::stringRepresentation):
  • runtime/TypeSet.h: Added. (JSC::StructureShape::create): (JSC::TypeSet::create):
  • runtime/VM.cpp: (JSC::VM::VM): (JSC::VM::getTypesForVariableInRange): (JSC::VM::updateHighFidelityTypeProfileState): (JSC::VM::dumpHighFidelityProfilingTypes):
  • runtime/VM.h: (JSC::VM::isProfilingTypesWithHighFidelity): (JSC::VM::highFidelityLog): (JSC::VM::highFidelityTypeProfiler): (JSC::VM::nextLocation): (JSC::VM::getNextUniqueVariableID):


2014-06-26 Mark Lam <[email protected]>


Remove unused instantiation of the WithScope structure.
<https://webkit.org/b/134331>


Reviewed by Oliver Hunt.


The WithScope structure instance is the VM is unused, and is now removed.


  • runtime/VM.cpp: (JSC::VM::VM):
  • runtime/VM.h:


2014-06-25 Mark Hahnenberg <[email protected]>


Structure bit fields should have a consistent format
https://bugs.webkit.org/show_bug.cgi?id=134307


Reviewed by Filip Pizlo.


Currently we use C-style bit fields for a number of member variables in Structure to save space.
This makes it difficult to load these fields in the JIT. We should instead use our own bitfield
format to make it easy to load and test these variables in JIT code.


  • runtime/JSObject.cpp: (JSC::JSObject::putDirectNonIndexAccessor): (JSC::JSObject::reifyStaticFunctionsForDelete):
  • runtime/Structure.cpp: (JSC::StructureTransitionTable::contains): (JSC::StructureTransitionTable::get): (JSC::StructureTransitionTable::add): (JSC::Structure::Structure): (JSC::Structure::materializePropertyMap): (JSC::Structure::addPropertyTransition): (JSC::Structure::despecifyFunctionTransition): (JSC::Structure::toDictionaryTransition): (JSC::Structure::freezeTransition): (JSC::Structure::preventExtensionsTransition): (JSC::Structure::takePropertyTableOrCloneIfPinned): (JSC::Structure::nonPropertyTransition): (JSC::Structure::flattenDictionaryStructure): (JSC::Structure::addPropertyWithoutTransition): (JSC::Structure::pin): (JSC::Structure::allocateRareData): (JSC::Structure::cloneRareDataFrom): (JSC::Structure::getConcurrently): (JSC::Structure::putSpecificValue): (JSC::Structure::getPropertyNamesFromStructure): (JSC::Structure::visitChildren): (JSC::Structure::checkConsistency):
  • runtime/Structure.h: (JSC::Structure::isExtensible): (JSC::Structure::isDictionary): (JSC::Structure::isUncacheableDictionary): (JSC::Structure::propertyAccessesAreCacheable): (JSC::Structure::previousID): (JSC::Structure::setHasGetterSetterPropertiesWithProtoCheck): (JSC::Structure::setContainsReadOnlyProperties): (JSC::Structure::disableSpecificFunctionTracking): (JSC::Structure::objectToStringValue): (JSC::Structure::setObjectToStringValue): (JSC::Structure::setPreviousID): (JSC::Structure::clearPreviousID): (JSC::Structure::previous): (JSC::Structure::rareData): (JSC::Structure::didTransition): Deleted. (JSC::Structure::hasGetterSetterProperties): Deleted. (JSC::Structure::hasReadOnlyOrGetterSetterPropertiesExcludingProto): Deleted. (JSC::Structure::setHasGetterSetterProperties): Deleted. (JSC::Structure::hasNonEnumerableProperties): Deleted. (JSC::Structure::staticFunctionsReified): Deleted. (JSC::Structure::setStaticFunctionsReified): Deleted.
  • runtime/StructureInlines.h: (JSC::Structure::setEnumerationCache): (JSC::Structure::enumerationCache): (JSC::Structure::checkOffsetConsistency):


2014-06-24 Mark Lam <[email protected]>


[ftlopt] Renamed DebuggerActivation to DebuggerScope.
<https://webkit.org/b/134273>


Reviewed by Michael Saboff.


  • CMakeLists.txt:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • debugger/DebuggerActivation.cpp: Removed.
  • debugger/DebuggerActivation.h: Removed.
  • debugger/DebuggerScope.cpp: Copied from ../../trunk/Source/JavaScriptCore/debugger/DebuggerActivation.cpp. (JSC::DebuggerScope::DebuggerScope): (JSC::DebuggerScope::finishCreation): (JSC::DebuggerScope::visitChildren): (JSC::DebuggerScope::className): (JSC::DebuggerScope::getOwnPropertySlot): (JSC::DebuggerScope::put): (JSC::DebuggerScope::deleteProperty): (JSC::DebuggerScope::getOwnPropertyNames): (JSC::DebuggerScope::defineOwnProperty): (JSC::DebuggerActivation::DebuggerActivation): Deleted. (JSC::DebuggerActivation::finishCreation): Deleted. (JSC::DebuggerActivation::visitChildren): Deleted. (JSC::DebuggerActivation::className): Deleted. (JSC::DebuggerActivation::getOwnPropertySlot): Deleted. (JSC::DebuggerActivation::put): Deleted. (JSC::DebuggerActivation::deleteProperty): Deleted. (JSC::DebuggerActivation::getOwnPropertyNames): Deleted. (JSC::DebuggerActivation::defineOwnProperty): Deleted.
  • debugger/DebuggerScope.h: Copied from ../../trunk/Source/JavaScriptCore/debugger/DebuggerActivation.h. (JSC::DebuggerScope::create): (JSC::DebuggerActivation::create): Deleted.
  • runtime/VM.cpp: (JSC::VM::VM):
  • runtime/VM.h:


2014-06-24 Filip Pizlo <[email protected]>


[ftlopt] PutByIdFlush can also be converted to a PutByOffset so don't assert otherwise
https://bugs.webkit.org/show_bug.cgi?id=134265


Reviewed by Geoffrey Garen.


More assertion fallout from the PutById folding work.


  • dfg/DFGNode.h: (JSC::DFG::Node::convertToPutByOffset):


2014-06-24 Filip Pizlo <[email protected]>


[ftlopt] GC should notify us if it resets to_this
https://bugs.webkit.org/show_bug.cgi?id=128231


Reviewed by Geoffrey Garen.


  • CMakeLists.txt:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/BytecodeList.json:
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dumpBytecode): (JSC::CodeBlock::finalizeUnconditionally):
  • bytecode/Instruction.h:
  • bytecode/ToThisStatus.cpp: Added. (JSC::merge): (WTF::printInternal):
  • bytecode/ToThisStatus.h: Added.
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator):
  • dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::parseBlock):
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/CommonSlowPaths.cpp: (JSC::SLOW_PATH_DECL):


2014-06-24 Filip Pizlo <[email protected]>


[ftlopt] StructureAbstractValue::onlyStructure() should return nullptr if isClobbered()
https://bugs.webkit.org/show_bug.cgi?id=134256


Reviewed by Michael Saboff.


This isn't testable right now (i.e. it's benign) but we should get it right anyway. The
point is to be able to precisely model what goes on in the snippets of code between a
side-effect and an InvalidationPoint.


This patch also cleans up onlyStructure() by delegating more work to
StructureSet::onlyStructure().


  • dfg/DFGStructureAbstractValue.h: (JSC::DFG::StructureAbstractValue::onlyStructure):


2014-06-24 Filip Pizlo <[email protected]>


[ftlopt][REGRESSION] PutById AI is introducing watchable structures without watching them
https://bugs.webkit.org/show_bug.cgi?id=134260


Reviewed by Geoffrey Garen.


This was causing loads of assertion failures in debug builds.


  • dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):


2014-06-21 Filip Pizlo <[email protected]>


[ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
https://bugs.webkit.org/show_bug.cgi?id=134090


Reviewed by Oliver Hunt.


This pretty much finishes off the work to eliminate the special-casing of singleton
structure sets by making it possible to fold GetById and PutById to various polymorphic
forms of the ByOffset nodes.


  • bytecode/GetByIdStatus.cpp: (JSC::GetByIdStatus::computeForStubInfo): (JSC::GetByIdStatus::computeFor):
  • bytecode/GetByIdStatus.h:
  • bytecode/PutByIdStatus.cpp: (JSC::PutByIdStatus::computeFor):
  • bytecode/PutByIdStatus.h:
  • bytecode/PutByIdVariant.h: (JSC::PutByIdVariant::constantChecks):
  • dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
  • dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::parseBlock):
  • dfg/DFGConstantFoldingPhase.cpp: (JSC::DFG::ConstantFoldingPhase::foldConstants): (JSC::DFG::ConstantFoldingPhase::emitPutByOffset): (JSC::DFG::ConstantFoldingPhase::addChecks):
  • dfg/DFGNode.h: (JSC::DFG::Node::convertToMultiGetByOffset): (JSC::DFG::Node::convertToMultiPutByOffset):
  • dfg/DFGSpeculativeJIT64.cpp: Also convert all release assertions to DFG assertions in this file, because I was hitting some of them while debugging. (JSC::DFG::SpeculativeJIT::fillJSValue): (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull): (JSC::DFG::SpeculativeJIT::emitCall): (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal): (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Strict): (JSC::DFG::SpeculativeJIT::fillSpeculateInt52): (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): (JSC::DFG::SpeculativeJIT::fillSpeculateCell): (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): (JSC::DFG::SpeculativeJIT::compileLogicalNot): (JSC::DFG::SpeculativeJIT::emitBranch): (JSC::DFG::SpeculativeJIT::compile):
  • dfg/DFGStructureAbstractValue.h: (JSC::DFG::StructureAbstractValue::set):


2014-06-19 Filip Pizlo <[email protected]>


[ftlopt] StructureSet::onlyStructure() should return nullptr if it's not a singleton (instead of asserting)
https://bugs.webkit.org/show_bug.cgi?id=134077


Reviewed by Sam Weinig.


This makes StructureSet and StructureAbstractValue more consistent and fixes a debug assert
in the abstract interpreter.


  • bytecode/StructureSet.h: (JSC::StructureSet::onlyStructure):


2014-06-18 Filip Pizlo <[email protected]>


DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
https://bugs.webkit.org/show_bug.cgi?id=133918


Reviewed by Mark Hahnenberg.


This also adds pruning of PutStructure, since I basically had no choice but
to implement such logic within MultiPutByOffset.


Also adds a bunch of PutById cache status dumping to bytecode dumping.


  • bytecode/GetByIdVariant.cpp: (JSC::GetByIdVariant::dumpInContext):
  • bytecode/GetByIdVariant.h: (JSC::GetByIdVariant::structureSet):
  • bytecode/PutByIdVariant.h: (JSC::PutByIdVariant::oldStructure):
  • bytecode/StructureSet.cpp: (JSC::StructureSet::filter): (JSC::StructureSet::filterArrayModes):
  • bytecode/StructureSet.h:
  • dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
  • dfg/DFGAbstractValue.cpp: (JSC::DFG::AbstractValue::changeStructure): (JSC::DFG::AbstractValue::contains):
  • dfg/DFGAbstractValue.h: (JSC::DFG::AbstractValue::couldBeType): (JSC::DFG::AbstractValue::isType):
  • dfg/DFGConstantFoldingPhase.cpp: (JSC::DFG::ConstantFoldingPhase::foldConstants): (JSC::DFG::ConstantFoldingPhase::emitGetByOffset): (JSC::DFG::ConstantFoldingPhase::emitPutByOffset): (JSC::DFG::ConstantFoldingPhase::addBaseCheck):
  • dfg/DFGGraph.cpp: (JSC::DFG::Graph::freezeStrong):
  • dfg/DFGGraph.h:
  • dfg/DFGStructureAbstractValue.h: (JSC::DFG::StructureAbstractValue::operator=):
  • ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
  • tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js: Added. (foo): (fu): (bar): (baz): (.bar): (.baz):
  • tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js: Added. (foo): (fu): (bar): (baz): (.bar): (.baz):
  • tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js: Added. (foo): (fu): (bar): (baz): (.bar): (.baz):


2014-06-18 Mark Hahnenberg <[email protected]>


Remove CompoundType and LeafType
https://bugs.webkit.org/show_bug.cgi?id=134037


Reviewed by Filip Pizlo.


We don't use them for anything. We'll replace them with a generic CellType type for all
the objects that are JSCells, aren't JSObjects, and for which we generally don't care about
their JSType at runtime.


  • llint/LLIntData.cpp: (JSC::LLInt::Data::performAssertions):
  • runtime/ArrayBufferNeuteringWatchpoint.cpp: (JSC::ArrayBufferNeuteringWatchpoint::createStructure):
  • runtime/Executable.h: (JSC::ExecutableBase::createStructure): (JSC::NativeExecutable::createStructure):
  • runtime/JSPromiseDeferred.h: (JSC::JSPromiseDeferred::createStructure):
  • runtime/JSPromiseReaction.h: (JSC::JSPromiseReaction::createStructure):
  • runtime/JSPropertyNameIterator.h: (JSC::JSPropertyNameIterator::createStructure):
  • runtime/JSType.h:
  • runtime/JSTypeInfo.h: (JSC::TypeInfo::TypeInfo):
  • runtime/MapData.h: (JSC::MapData::createStructure):
  • runtime/PropertyMapHashTable.h: (JSC::PropertyTable::createStructure):
  • runtime/RegExp.h: (JSC::RegExp::createStructure):
  • runtime/SparseArrayValueMap.cpp: (JSC::SparseArrayValueMap::createStructure):
  • runtime/Structure.cpp: (JSC::Structure::Structure):
  • runtime/StructureChain.h: (JSC::StructureChain::createStructure):
  • runtime/StructureRareData.cpp: (JSC::StructureRareData::createStructure):
  • runtime/SymbolTable.h: (JSC::SymbolTable::createStructure):
  • runtime/WeakMapData.h: (JSC::WeakMapData::createStructure):


2014-06-17 Filip Pizlo <[email protected]>


[ftlopt] PutStructure and PhantomPutStructure shouldn't leave the world in a clobbered state
https://bugs.webkit.org/show_bug.cgi?id=134002


Reviewed by Mark Hahnenberg.


The effect of this bug was that if we had a PutStructure or PhantomPutStructure then any
JSConstants would be in a Clobbered state, so we wouldn't take advantage of our knowledge
of the structure if that structure was watchable.


Also kill PhantomPutStructure.


  • dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition): (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransitions):
  • dfg/DFGClobberize.h: (JSC::DFG::clobberize):
  • dfg/DFGDoesGC.cpp: (JSC::DFG::doesGC):
  • dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode):
  • dfg/DFGGraph.cpp: (JSC::DFG::Graph::visitChildren):
  • dfg/DFGNode.h: (JSC::DFG::Node::hasTransition):
  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp: (JSC::DFG::PredictionPropagationPhase::propagate):
  • dfg/DFGSafeToExecute.h: (JSC::DFG::safeToExecute):
  • dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::compile):
  • dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compile):
  • dfg/DFGStructureAbstractValue.cpp: (JSC::DFG::StructureAbstractValue::observeTransition): (JSC::DFG::StructureAbstractValue::observeTransitions):
  • dfg/DFGValidate.cpp: (JSC::DFG::Validate::validate):
  • dfg/DFGWatchableStructureWatchingPhase.cpp: (JSC::DFG::WatchableStructureWatchingPhase::run):
  • ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile):
  • ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileNode): (JSC::FTL::LowerDFGToLLVM::compilePhantomPutStructure): Deleted.


2014-06-17 Filip Pizlo <[email protected]>


[ftlopt] DFG put_by_id should inline accesses with a slightly polymorphic base
https://bugs.webkit.org/show_bug.cgi?id=133964


Reviewed by Mark Hahnenberg.


  • bytecode/PutByIdStatus.cpp: (JSC::PutByIdStatus::appendVariant): (JSC::PutByIdStatus::computeForStubInfo):
  • bytecode/PutByIdVariant.cpp: (JSC::PutByIdVariant::oldStructureForTransition): (JSC::PutByIdVariant::writesStructures): (JSC::PutByIdVariant::reallocatesStorage): (JSC::PutByIdVariant::attemptToMerge): (JSC::PutByIdVariant::attemptToMergeTransitionWithReplace): (JSC::PutByIdVariant::dumpInContext):
  • bytecode/PutByIdVariant.h: (JSC::PutByIdVariant::PutByIdVariant): (JSC::PutByIdVariant::replace): (JSC::PutByIdVariant::transition): (JSC::PutByIdVariant::structure): (JSC::PutByIdVariant::oldStructure):
  • dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
  • dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handlePutById): (JSC::DFG::ByteCodeParser::parseBlock):
  • dfg/DFGConstantFoldingPhase.cpp: (JSC::DFG::ConstantFoldingPhase::foldConstants): (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
  • dfg/DFGGraph.cpp: (JSC::DFG::Graph::visitChildren):
  • dfg/DFGNode.cpp: (JSC::DFG::MultiPutByOffsetData::writesStructures): (JSC::DFG::MultiPutByOffsetData::reallocatesStorage):
  • ftl/FTLAbbreviations.h: (JSC::FTL::getLinkage):
  • ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileMultiPutByOffset): (JSC::FTL::LowerDFGToLLVM::getModuleByPathForSymbol):

Source/WebCore:

2014-07-25 Mark Lam <[email protected]>


[ftlopt] Renamed DebuggerActivation to DebuggerScope.
<https://webkit.org/b/134273>


Reviewed by Michael Saboff.


No new tests.


  • ForwardingHeaders/debugger/DebuggerActivation.h: Removed.
  • Removed because this is not used.

Source/WebKit/mac:

2014-07-25 Mark Lam <[email protected]>


[ftlopt] Renamed DebuggerActivation to DebuggerScope.
<https://webkit.org/b/134273>


Reviewed by Michael Saboff.


  • WebView/WebScriptDebugDelegate.mm:
  • Removed unneeded #include.

LayoutTests:

2014-07-25 Filip Pizlo <[email protected]>


[ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
https://bugs.webkit.org/show_bug.cgi?id=134090


Reviewed by Oliver Hunt.


  • js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt: Added.
  • js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt: Added.
  • js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html: Added.
  • js/regress/fold-get-by-id-to-multi-get-by-offset.html: Added.
  • js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt: Added.
  • js/regress/fold-put-by-id-to-multi-put-by-offset.html: Added.
  • js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js: Added. (foo): (fu): (bar): (.bar): (Number):
  • js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js: Added. (foo): (fu): (bar): (.bar): (Number):
  • js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js: Added. (foo): (fu): (bar): (.bar):


2014-06-19 Filip Pizlo <[email protected]>


[ftlopt] LICM should be able to hoist CheckStructure even if the loop clobbers structures so long as the structures being checked are watchable
https://bugs.webkit.org/show_bug.cgi?id=134056


Unreviewed, just landing the test cases for this attempted optimization. The test cases
will still be valid once we find a smart way of doing this optimization.


  • js/regress/hoist-poly-check-structure-effectful-loop-expected.txt: Added.
  • js/regress/hoist-poly-check-structure-effectful-loop.html: Added.
  • js/regress/hoist-poly-check-structure-expected.txt: Added.
  • js/regress/hoist-poly-check-structure.html: Added.
  • js/regress/script-tests/hoist-poly-check-structure-effectful-loop.js: Added. (foo): (test):
  • js/regress/script-tests/hoist-poly-check-structure.js: Added. (foo): (test):


2014-06-18 Filip Pizlo <[email protected]>


DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
https://bugs.webkit.org/show_bug.cgi?id=133918


Reviewed by Mark Hahnenberg.


  • js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt: Added.
  • js/regress/fold-multi-get-by-offset-to-get-by-offset.html: Added.
  • js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt: Added.
  • js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html: Added.
  • js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt: Added.
  • js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html: Added.
  • js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt: Added.
  • js/regress/fold-multi-put-by-offset-to-put-by-offset.html: Added.
  • js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt: Added.
  • js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html: Added.
  • js/regress/fold-put-structure-expected.txt: Added.
  • js/regress/fold-put-structure.html: Added.
  • js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js: Added. (foo): (fu): (bar): (.bar):
  • js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js: Added. (foo): (fu): (bar): (.bar):
  • js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js: Added. (foo): (fu): (bar): (.bar):
  • js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js: Added. (foo): (fu): (bar): (.bar):
  • js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js: Added. (foo): (fu): (bar): (.bar):
  • js/regress/script-tests/fold-put-structure.js: Added. (foo): (fu): (bar): (.bar):


2014-06-17 Filip Pizlo <[email protected]>


[ftlopt] DFG put_by_id should inline accesses with a slightly polymorphic base
https://bugs.webkit.org/show_bug.cgi?id=133964


Reviewed by Mark Hahnenberg.


  • js/regress/put-by-id-replace-and-transition-expected.txt: Added.
  • js/regress/put-by-id-replace-and-transition.html: Added.
  • js/regress/put-by-id-slightly-polymorphic-expected.txt: Added.
  • js/regress/put-by-id-slightly-polymorphic.html: Added.
  • js/regress/script-tests/put-by-id-replace-and-transition.js: Added.
  • js/regress/script-tests/put-by-id-slightly-polymorphic.js: Added.
  • Property svn:eol-style set to native
File size: 48.1 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012, 2013 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include "ArrayPrototype.h"
26#include "ButterflyInlines.h"
27#include "BytecodeGenerator.h"
28#include "CodeBlock.h"
29#include "Completion.h"
30#include "CopiedSpaceInlines.h"
31#include "ExceptionHelpers.h"
32#include "HeapStatistics.h"
33#include "InitializeThreading.h"
34#include "Interpreter.h"
35#include "JSArray.h"
36#include "JSArrayBuffer.h"
37#include "JSCInlines.h"
38#include "JSFunction.h"
39#include "JSLock.h"
40#include "JSProxy.h"
41#include "JSString.h"
42#include "ProfilerDatabase.h"
43#include "SamplingTool.h"
44#include "StackVisitor.h"
45#include "StructureInlines.h"
46#include "StructureRareDataInlines.h"
47#include "TestRunnerUtils.h"
48#include <math.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <thread>
53#include <wtf/CurrentTime.h>
54#include <wtf/MainThread.h>
55#include <wtf/StringPrintStream.h>
56#include <wtf/text/StringBuilder.h>
57
58#if !OS(WINDOWS)
59#include <unistd.h>
60#endif
61
62#if HAVE(READLINE)
63// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
64// We #define it to something else to avoid this conflict.
65#define Function ReadlineFunction
66#include <readline/history.h>
67#include <readline/readline.h>
68#undef Function
69#endif
70
71#if HAVE(SYS_TIME_H)
72#include <sys/time.h>
73#endif
74
75#if HAVE(SIGNAL_H)
76#include <signal.h>
77#endif
78
79#if COMPILER(MSVC) && !OS(WINCE)
80#include <crtdbg.h>
81#include <mmsystem.h>
82#include <windows.h>
83#endif
84
85#if PLATFORM(IOS) && CPU(ARM_THUMB2)
86#include <fenv.h>
87#include <arm/arch.h>
88#endif
89
90#if PLATFORM(EFL)
91#include <Ecore.h>
92#endif
93
94using namespace JSC;
95using namespace WTF;
96
97namespace {
98
99NO_RETURN_WITH_VALUE static void jscExit(int status)
100{
101#if ENABLE(DFG_JIT)
102 if (DFG::isCrashing()) {
103 for (;;) {
104#if OS(WINDOWS)
105 Sleep(1000);
106#else
107 pause();
108#endif
109 }
110 }
111#endif // ENABLE(DFG_JIT)
112 exit(status);
113}
114
115class Element;
116class ElementHandleOwner;
117class Masuqerader;
118class Root;
119class RuntimeArray;
120
121class Element : public JSNonFinalObject {
122public:
123 Element(VM& vm, Structure* structure, Root* root)
124 : Base(vm, structure)
125 , m_root(root)
126 {
127 }
128
129 typedef JSNonFinalObject Base;
130 static const bool needsDestruction = false;
131
132 Root* root() const { return m_root; }
133 void setRoot(Root* root) { m_root = root; }
134
135 static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
136 {
137 Structure* structure = createStructure(vm, globalObject, jsNull());
138 Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure, root);
139 element->finishCreation(vm);
140 return element;
141 }
142
143 void finishCreation(VM&);
144
145 static ElementHandleOwner* handleOwner();
146
147 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
148 {
149 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
150 }
151
152 DECLARE_INFO;
153
154private:
155 Root* m_root;
156};
157
158class ElementHandleOwner : public WeakHandleOwner {
159public:
160 virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
161 {
162 Element* element = jsCast<Element*>(handle.slot()->asCell());
163 return visitor.containsOpaqueRoot(element->root());
164 }
165};
166
167class Masquerader : public JSNonFinalObject {
168public:
169 Masquerader(VM& vm, Structure* structure)
170 : Base(vm, structure)
171 {
172 }
173
174 typedef JSNonFinalObject Base;
175
176 static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
177 {
178 globalObject->masqueradesAsUndefinedWatchpoint()->fireAll();
179 Structure* structure = createStructure(vm, globalObject, jsNull());
180 Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
181 result->finishCreation(vm);
182 return result;
183 }
184
185 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
186 {
187 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
188 }
189
190 DECLARE_INFO;
191
192protected:
193 static const unsigned StructureFlags = JSC::MasqueradesAsUndefined | Base::StructureFlags;
194};
195
196class Root : public JSDestructibleObject {
197public:
198 Root(VM& vm, Structure* structure)
199 : Base(vm, structure)
200 {
201 }
202
203 Element* element()
204 {
205 return m_element.get();
206 }
207
208 void setElement(Element* element)
209 {
210 Weak<Element> newElement(element, Element::handleOwner());
211 m_element.swap(newElement);
212 }
213
214 static Root* create(VM& vm, JSGlobalObject* globalObject)
215 {
216 Structure* structure = createStructure(vm, globalObject, jsNull());
217 Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
218 root->finishCreation(vm);
219 return root;
220 }
221
222 typedef JSDestructibleObject Base;
223
224 DECLARE_INFO;
225 static const bool needsDestruction = true;
226
227 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
228 {
229 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
230 }
231
232 static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
233 {
234 Base::visitChildren(thisObject, visitor);
235 visitor.addOpaqueRoot(thisObject);
236 }
237
238private:
239 Weak<Element> m_element;
240};
241
242class ImpureGetter : public JSNonFinalObject {
243public:
244 ImpureGetter(VM& vm, Structure* structure)
245 : Base(vm, structure)
246 {
247 }
248
249 DECLARE_INFO;
250 typedef JSNonFinalObject Base;
251
252 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
253 {
254 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
255 }
256
257 static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
258 {
259 ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
260 getter->finishCreation(vm, delegate);
261 return getter;
262 }
263
264 void finishCreation(VM& vm, JSObject* delegate)
265 {
266 Base::finishCreation(vm);
267 if (delegate)
268 m_delegate.set(vm, this, delegate);
269 }
270
271 static const unsigned StructureFlags = JSC::HasImpureGetOwnPropertySlot | JSC::OverridesGetOwnPropertySlot | JSC::OverridesVisitChildren | Base::StructureFlags;
272
273 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
274 {
275 ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
276
277 if (thisObject->m_delegate && thisObject->m_delegate->getPropertySlot(exec, name, slot))
278 return true;
279
280 return Base::getOwnPropertySlot(object, exec, name, slot);
281 }
282
283 static void visitChildren(JSCell* cell, SlotVisitor& visitor)
284 {
285 Base::visitChildren(cell, visitor);
286 ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
287 visitor.append(&thisObject->m_delegate);
288 }
289
290 void setDelegate(VM& vm, JSObject* delegate)
291 {
292 m_delegate.set(vm, this, delegate);
293 }
294
295private:
296 WriteBarrier<JSObject> m_delegate;
297};
298
299class RuntimeArray : public JSArray {
300public:
301 typedef JSArray Base;
302
303 static RuntimeArray* create(ExecState* exec)
304 {
305 VM& vm = exec->vm();
306 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
307 Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
308 RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
309 runtimeArray->finishCreation(exec);
310 vm.heap.addFinalizer(runtimeArray, destroy);
311 return runtimeArray;
312 }
313
314 ~RuntimeArray() { }
315
316 static void destroy(JSCell* cell)
317 {
318 static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
319 }
320
321 static const bool needsDestruction = false;
322
323 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
324 {
325 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
326 if (propertyName == exec->propertyNames().length) {
327 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
328 return true;
329 }
330
331 unsigned index = propertyName.asIndex();
332 if (index < thisObject->getLength()) {
333 ASSERT(index != PropertyName::NotAnIndex);
334 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
335 return true;
336 }
337
338 return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
339 }
340
341 static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
342 {
343 RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
344 if (index < thisObject->getLength()) {
345 slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
346 return true;
347 }
348
349 return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
350 }
351
352 static NO_RETURN_DUE_TO_CRASH void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
353 {
354 RELEASE_ASSERT_NOT_REACHED();
355 }
356
357 static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
358 {
359 RELEASE_ASSERT_NOT_REACHED();
360#if !COMPILER(CLANG) && !COMPILER(MSVC)
361 return true;
362#endif
363 }
364
365 unsigned getLength() const { return m_vector.size(); }
366
367 DECLARE_INFO;
368
369 static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
370 {
371 return globalObject->arrayPrototype();
372 }
373
374 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
375 {
376 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
377 }
378
379protected:
380 void finishCreation(ExecState* exec)
381 {
382 Base::finishCreation(exec->vm());
383 ASSERT(inherits(info()));
384
385 for (size_t i = 0; i < exec->argumentCount(); i++)
386 m_vector.append(exec->argument(i).toInt32(exec));
387 }
388
389 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSArray::StructureFlags;
390
391private:
392 RuntimeArray(ExecState* exec, Structure* structure)
393 : JSArray(exec->vm(), structure, 0)
394 {
395 }
396
397 static EncodedJSValue lengthGetter(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName)
398 {
399 RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
400 if (!thisObject)
401 return throwVMTypeError(exec);
402 return JSValue::encode(jsNumber(thisObject->getLength()));
403 }
404
405 Vector<int> m_vector;
406};
407
408const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Element) };
409const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Masquerader) };
410const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Root) };
411const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ImpureGetter) };
412const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(RuntimeArray) };
413
414ElementHandleOwner* Element::handleOwner()
415{
416 static ElementHandleOwner* owner = 0;
417 if (!owner)
418 owner = new ElementHandleOwner();
419 return owner;
420}
421
422void Element::finishCreation(VM& vm)
423{
424 Base::finishCreation(vm);
425 m_root->setElement(this);
426}
427
428}
429
430static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
431
432static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
433static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
434static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
435static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
436
437static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
438static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
439static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
440static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
441static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
442static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
443static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
444static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
445static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
446static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
447static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
448static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
449static EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState*);
450#ifndef NDEBUG
451static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
452static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
453#endif
454static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
455static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
456static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
457static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
458static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
459static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
460static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
461static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
462static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
463static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
464static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
465static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
466static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
467static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
468static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
469static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
470static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
471static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
472static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
473static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
474static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables (ExecState*);
475
476#if ENABLE(SAMPLING_FLAGS)
477static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
478static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
479#endif
480
481struct Script {
482 bool isFile;
483 char* argument;
484
485 Script(bool isFile, char *argument)
486 : isFile(isFile)
487 , argument(argument)
488 {
489 }
490};
491
492class CommandLine {
493public:
494 CommandLine(int argc, char** argv)
495 : m_interactive(false)
496 , m_dump(false)
497 , m_exitCode(false)
498 , m_profile(false)
499 {
500 parseArguments(argc, argv);
501 }
502
503 bool m_interactive;
504 bool m_dump;
505 bool m_exitCode;
506 Vector<Script> m_scripts;
507 Vector<String> m_arguments;
508 bool m_profile;
509 String m_profilerOutput;
510
511 void parseArguments(int, char**);
512};
513
514static const char interactivePrompt[] = ">>> ";
515
516class StopWatch {
517public:
518 void start();
519 void stop();
520 long getElapsedMS(); // call stop() first
521
522private:
523 double m_startTime;
524 double m_stopTime;
525};
526
527void StopWatch::start()
528{
529 m_startTime = monotonicallyIncreasingTime();
530}
531
532void StopWatch::stop()
533{
534 m_stopTime = monotonicallyIncreasingTime();
535}
536
537long StopWatch::getElapsedMS()
538{
539 return static_cast<long>((m_stopTime - m_startTime) * 1000);
540}
541
542class GlobalObject : public JSGlobalObject {
543private:
544 GlobalObject(VM&, Structure*);
545
546public:
547 typedef JSGlobalObject Base;
548
549 static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
550 {
551 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
552 object->finishCreation(vm, arguments);
553 vm.heap.addFinalizer(object, destroy);
554 return object;
555 }
556
557 static const bool needsDestruction = false;
558
559 DECLARE_INFO;
560 static const GlobalObjectMethodTable s_globalObjectMethodTable;
561
562 static Structure* createStructure(VM& vm, JSValue prototype)
563 {
564 return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
565 }
566
567 static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return true; }
568
569protected:
570 void finishCreation(VM& vm, const Vector<String>& arguments)
571 {
572 Base::finishCreation(vm);
573
574 addFunction(vm, "debug", functionDebug, 1);
575 addFunction(vm, "describe", functionDescribe, 1);
576 addFunction(vm, "describeArray", functionDescribeArray, 1);
577 addFunction(vm, "print", functionPrint, 1);
578 addFunction(vm, "quit", functionQuit, 0);
579 addFunction(vm, "gc", functionGCAndSweep, 0);
580 addFunction(vm, "fullGC", functionFullGC, 0);
581 addFunction(vm, "edenGC", functionEdenGC, 0);
582 addFunction(vm, "deleteAllCompiledCode", functionDeleteAllCompiledCode, 0);
583#ifndef NDEBUG
584 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
585 addFunction(vm, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
586#endif
587 addFunction(vm, "version", functionVersion, 1);
588 addFunction(vm, "run", functionRun, 1);
589 addFunction(vm, "load", functionLoad, 1);
590 addFunction(vm, "readFile", functionReadFile, 1);
591 addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
592 addFunction(vm, "jscStack", functionJSCStack, 1);
593 addFunction(vm, "readline", functionReadline, 0);
594 addFunction(vm, "preciseTime", functionPreciseTime, 0);
595 addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
596 addFunction(vm, "noInline", functionNeverInlineFunction, 1);
597 addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
598 addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
599 addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
600 addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
601#if ENABLE(SAMPLING_FLAGS)
602 addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
603 addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
604#endif
605 addConstructableFunction(vm, "Root", functionCreateRoot, 0);
606 addConstructableFunction(vm, "Element", functionCreateElement, 1);
607 addFunction(vm, "getElement", functionGetElement, 1);
608 addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
609
610 putDirectNativeFunction(vm, this, Identifier(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum | JSC::Function);
611 putDirectNativeFunction(vm, this, Identifier(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum | JSC::Function);
612 putDirectNativeFunction(vm, this, Identifier(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum | JSC::Function);
613 putDirectNativeFunction(vm, this, Identifier(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum | JSC::Function);
614 putDirectNativeFunction(vm, this, Identifier(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum | JSC::Function);
615
616 addFunction(vm, "effectful42", functionEffectful42, 0);
617 addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
618
619 addFunction(vm, "createProxy", functionCreateProxy, 1);
620 addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
621
622 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
623 addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
624 addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 4);
625
626 JSArray* array = constructEmptyArray(globalExec(), 0);
627 for (size_t i = 0; i < arguments.size(); ++i)
628 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
629 putDirect(vm, Identifier(globalExec(), "arguments"), array);
630
631 putDirect(vm, Identifier(globalExec(), "console"), jsUndefined());
632 }
633
634 void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
635 {
636 Identifier identifier(&vm, name);
637 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
638 }
639
640 void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
641 {
642 Identifier identifier(&vm, name);
643 putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
644 }
645};
646
647const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
648const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, 0, &shouldInterruptScriptBeforeTimeout };
649
650
651GlobalObject::GlobalObject(VM& vm, Structure* structure)
652 : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
653{
654}
655
656static inline String stringFromUTF(const char* utf8)
657{
658 // Find the the first non-ascii character, or nul.
659 const char* pos = utf8;
660 while (*pos > 0)
661 pos++;
662 size_t asciiLength = pos - utf8;
663
664 // Fast case - string is all ascii.
665 if (!*pos)
666 return String(utf8, asciiLength);
667
668 // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
669 ASSERT(*pos < 0);
670 ASSERT(strlen(utf8) == asciiLength + strlen(pos));
671 return String::fromUTF8WithLatin1Fallback(utf8, asciiLength + strlen(pos));
672}
673
674static inline SourceCode jscSource(const char* utf8, const String& filename)
675{
676 String str = stringFromUTF(utf8);
677 return makeSource(str, filename);
678}
679
680EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
681{
682 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
683 if (i)
684 putchar(' ');
685
686 printf("%s", exec->uncheckedArgument(i).toString(exec)->value(exec).utf8().data());
687 }
688
689 putchar('\n');
690 fflush(stdout);
691 return JSValue::encode(jsUndefined());
692}
693
694#ifndef NDEBUG
695EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
696{
697 if (!exec->callerFrame()->isVMEntrySentinel())
698 exec->vm().interpreter->dumpCallFrame(exec->callerFrame());
699 return JSValue::encode(jsUndefined());
700}
701#endif
702
703EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
704{
705 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
706 return JSValue::encode(jsUndefined());
707}
708
709EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
710{
711 if (exec->argumentCount() < 1)
712 return JSValue::encode(jsUndefined());
713 return JSValue::encode(jsString(exec, toString(exec->argument(0))));
714}
715
716EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
717{
718 if (exec->argumentCount() < 1)
719 return JSValue::encode(jsUndefined());
720 JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
721 if (!object)
722 return JSValue::encode(jsString(exec, "<not object>"));
723 return JSValue::encode(jsString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
724}
725
726class FunctionJSCStackFunctor {
727public:
728 FunctionJSCStackFunctor(StringBuilder& trace)
729 : m_trace(trace)
730 {
731 }
732
733 StackVisitor::Status operator()(StackVisitor& visitor)
734 {
735 m_trace.append(String::format(" %zu %s\n", visitor->index(), visitor->toString().utf8().data()));
736 return StackVisitor::Continue;
737 }
738
739private:
740 StringBuilder& m_trace;
741};
742
743EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
744{
745 StringBuilder trace;
746 trace.appendLiteral("--> Stack trace:\n");
747
748 FunctionJSCStackFunctor functor(trace);
749 exec->iterate(functor);
750 fprintf(stderr, "%s", trace.toString().utf8().data());
751 return JSValue::encode(jsUndefined());
752}
753
754EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
755{
756 JSLockHolder lock(exec);
757 return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
758}
759
760EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
761{
762 JSLockHolder lock(exec);
763 JSValue arg = exec->argument(0);
764 return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), arg.isNull() ? nullptr : jsCast<Root*>(exec->argument(0))));
765}
766
767EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
768{
769 JSLockHolder lock(exec);
770 Element* result = jsCast<Root*>(exec->argument(0).asCell())->element();
771 return JSValue::encode(result ? result : jsUndefined());
772}
773
774EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
775{
776 JSLockHolder lock(exec);
777 Element* element = jsCast<Element*>(exec->argument(0));
778 Root* root = jsCast<Root*>(exec->argument(1));
779 element->setRoot(root);
780 return JSValue::encode(jsUndefined());
781}
782
783EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
784{
785 JSLockHolder lock(exec);
786 JSValue target = exec->argument(0);
787 if (!target.isObject())
788 return JSValue::encode(jsUndefined());
789 JSObject* jsTarget = asObject(target.asCell());
790 Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->prototype());
791 JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
792 return JSValue::encode(proxy);
793}
794
795EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
796{
797 JSLockHolder lock(exec);
798 RuntimeArray* array = RuntimeArray::create(exec);
799 return JSValue::encode(array);
800}
801
802EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
803{
804 JSLockHolder lock(exec);
805 JSValue target = exec->argument(0);
806 JSObject* delegate = nullptr;
807 if (target.isObject())
808 delegate = asObject(target.asCell());
809 Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
810 ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
811 return JSValue::encode(result);
812}
813
814EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
815{
816 JSLockHolder lock(exec);
817 JSValue base = exec->argument(0);
818 if (!base.isObject())
819 return JSValue::encode(jsUndefined());
820 JSValue delegate = exec->argument(1);
821 if (!delegate.isObject())
822 return JSValue::encode(jsUndefined());
823 ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
824 impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
825 return JSValue::encode(jsUndefined());
826}
827
828EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
829{
830 JSLockHolder lock(exec);
831 exec->heap()->collectAllGarbage();
832 return JSValue::encode(jsUndefined());
833}
834
835EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
836{
837 JSLockHolder lock(exec);
838 exec->heap()->collect(FullCollection);
839 return JSValue::encode(jsUndefined());
840}
841
842EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
843{
844 JSLockHolder lock(exec);
845 exec->heap()->collect(EdenCollection);
846 return JSValue::encode(jsUndefined());
847}
848
849EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState* exec)
850{
851 JSLockHolder lock(exec);
852 exec->heap()->deleteAllCompiledCode();
853 return JSValue::encode(jsUndefined());
854}
855
856#ifndef NDEBUG
857EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
858{
859 JSLockHolder lock(exec);
860 exec->vm().releaseExecutableMemory();
861 return JSValue::encode(jsUndefined());
862}
863#endif
864
865EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
866{
867 // We need this function for compatibility with the Mozilla JS tests but for now
868 // we don't actually do any version-specific handling
869 return JSValue::encode(jsUndefined());
870}
871
872EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
873{
874 String fileName = exec->argument(0).toString(exec)->value(exec);
875 Vector<char> script;
876 if (!fillBufferWithContentsOfFile(fileName, script))
877 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
878
879 GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
880
881 JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
882 for (unsigned i = 1; i < exec->argumentCount(); ++i)
883 array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
884 globalObject->putDirect(
885 exec->vm(), Identifier(globalObject->globalExec(), "arguments"), array);
886
887 JSValue exception;
888 StopWatch stopWatch;
889 stopWatch.start();
890 evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &exception);
891 stopWatch.stop();
892
893 if (!!exception) {
894 exec->vm().throwException(globalObject->globalExec(), exception);
895 return JSValue::encode(jsUndefined());
896 }
897
898 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
899}
900
901EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
902{
903 String fileName = exec->argument(0).toString(exec)->value(exec);
904 Vector<char> script;
905 if (!fillBufferWithContentsOfFile(fileName, script))
906 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
907
908 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
909
910 JSValue evaluationException;
911 JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &evaluationException);
912 if (evaluationException)
913 exec->vm().throwException(exec, evaluationException);
914 return JSValue::encode(result);
915}
916
917EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
918{
919 String fileName = exec->argument(0).toString(exec)->value(exec);
920 Vector<char> script;
921 if (!fillBufferWithContentsOfFile(fileName, script))
922 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
923
924 return JSValue::encode(jsString(exec, stringFromUTF(script.data())));
925}
926
927EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
928{
929 String fileName = exec->argument(0).toString(exec)->value(exec);
930 Vector<char> script;
931 if (!fillBufferWithContentsOfFile(fileName, script))
932 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
933
934 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
935
936 StopWatch stopWatch;
937 stopWatch.start();
938
939 JSValue syntaxException;
940 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
941 stopWatch.stop();
942
943 if (!validSyntax)
944 exec->vm().throwException(exec, syntaxException);
945 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
946}
947
948#if ENABLE(SAMPLING_FLAGS)
949EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
950{
951 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
952 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
953 if ((flag >= 1) && (flag <= 32))
954 SamplingFlags::setFlag(flag);
955 }
956 return JSValue::encode(jsNull());
957}
958
959EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
960{
961 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
962 unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
963 if ((flag >= 1) && (flag <= 32))
964 SamplingFlags::clearFlag(flag);
965 }
966 return JSValue::encode(jsNull());
967}
968#endif
969
970EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
971{
972 Vector<char, 256> line;
973 int c;
974 while ((c = getchar()) != EOF) {
975 // FIXME: Should we also break on \r?
976 if (c == '\n')
977 break;
978 line.append(c);
979 }
980 line.append('\0');
981 return JSValue::encode(jsString(exec, line.data()));
982}
983
984EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
985{
986 return JSValue::encode(jsNumber(currentTime()));
987}
988
989EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
990{
991 return JSValue::encode(setNeverInline(exec));
992}
993
994EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
995{
996 return JSValue::encode(optimizeNextInvocation(exec));
997}
998
999EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1000{
1001 return JSValue::encode(numberOfDFGCompiles(exec));
1002}
1003
1004EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1005{
1006 if (exec->argumentCount() < 1)
1007 return JSValue::encode(jsUndefined());
1008
1009 CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1010 if (!block)
1011 return JSValue::encode(jsNumber(0));
1012
1013 return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1014}
1015
1016EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1017{
1018 if (exec->argumentCount() < 1)
1019 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Not enough arguments")));
1020
1021 JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
1022 if (!buffer)
1023 return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Expected an array buffer")));
1024
1025 ArrayBufferContents dummyContents;
1026 buffer->impl()->transfer(dummyContents);
1027
1028 return JSValue::encode(jsUndefined());
1029}
1030
1031EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1032{
1033 jscExit(EXIT_SUCCESS);
1034
1035#if COMPILER(MSVC)
1036 // Without this, Visual Studio will complain that this method does not return a value.
1037 return JSValue::encode(jsUndefined());
1038#endif
1039}
1040
1041EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1042EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1043
1044EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1045EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1046
1047EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
1048
1049EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
1050{
1051 return JSValue::encode(jsNumber(42));
1052}
1053
1054EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
1055{
1056 return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
1057}
1058
1059EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
1060{
1061 exec->vm().dumpHighFidelityProfilingTypes();
1062 return JSValue::encode(jsUndefined());
1063}
1064
1065// Use SEH for Release builds only to get rid of the crash report dialog
1066// (luckily the same tests fail in Release and Debug builds so far). Need to
1067// be in a separate main function because the jscmain function requires object
1068// unwinding.
1069
1070#if COMPILER(MSVC) && !defined(_DEBUG) && !OS(WINCE)
1071#define TRY __try {
1072#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1073#else
1074#define TRY
1075#define EXCEPT(x)
1076#endif
1077
1078int jscmain(int argc, char** argv);
1079
1080static double s_desiredTimeout;
1081
1082static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
1083{
1084 auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
1085 std::this_thread::sleep_for(timeout);
1086
1087 dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
1088 CRASH();
1089}
1090
1091int main(int argc, char** argv)
1092{
1093#if PLATFORM(IOS) && CPU(ARM_THUMB2)
1094 // Enabled IEEE754 denormal support.
1095 fenv_t env;
1096 fegetenv( &env );
1097 env.__fpscr &= ~0x01000000u;
1098 fesetenv( &env );
1099#endif
1100
1101#if OS(WINDOWS)
1102#if !OS(WINCE)
1103 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1104 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1105 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1106 ::SetErrorMode(0);
1107
1108#if defined(_DEBUG)
1109 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1110 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1111 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1112 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1113 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1114 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1115#endif
1116#endif
1117
1118 timeBeginPeriod(1);
1119#endif
1120
1121#if PLATFORM(EFL)
1122 ecore_init();
1123#endif
1124
1125 // Initialize JSC before getting VM.
1126#if ENABLE(SAMPLING_REGIONS)
1127 WTF::initializeMainThread();
1128#endif
1129 JSC::initializeThreading();
1130
1131#if !OS(WINCE)
1132 if (char* timeoutString = getenv("JSC_timeout")) {
1133 if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1134 dataLog(
1135 "WARNING: timeout string is malformed, got ", timeoutString,
1136 " but expected a number. Not using a timeout.\n");
1137 } else
1138 createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1139 }
1140#endif
1141
1142#if PLATFORM(IOS)
1143 Options::crashIfCantAllocateJITMemory() = true;
1144#endif
1145
1146 // We can't use destructors in the following code because it uses Windows
1147 // Structured Exception Handling
1148 int res = 0;
1149 TRY
1150 res = jscmain(argc, argv);
1151 EXCEPT(res = 3)
1152 if (Options::logHeapStatisticsAtExit())
1153 HeapStatistics::reportSuccess();
1154
1155#if PLATFORM(EFL)
1156 ecore_shutdown();
1157#endif
1158
1159 jscExit(res);
1160}
1161
1162static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
1163{
1164 const char* script;
1165 String fileName;
1166 Vector<char> scriptBuffer;
1167
1168 if (dump)
1169 JSC::Options::dumpGeneratedBytecodes() = true;
1170
1171 VM& vm = globalObject->vm();
1172
1173#if ENABLE(SAMPLING_FLAGS)
1174 SamplingFlags::start();
1175#endif
1176
1177 bool success = true;
1178 for (size_t i = 0; i < scripts.size(); i++) {
1179 if (scripts[i].isFile) {
1180 fileName = scripts[i].argument;
1181 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
1182 return false; // fail early so we can catch missing files
1183 script = scriptBuffer.data();
1184 } else {
1185 script = scripts[i].argument;
1186 fileName = "[Command Line]";
1187 }
1188
1189 vm.startSampling();
1190
1191 JSValue evaluationException;
1192 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), &evaluationException);
1193 success = success && !evaluationException;
1194 if (dump && !evaluationException)
1195 printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1196 if (evaluationException) {
1197 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1198 Identifier stackID(globalObject->globalExec(), "stack");
1199 JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID);
1200 if (!stackValue.isUndefinedOrNull())
1201 printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1202 }
1203
1204 vm.stopSampling();
1205 globalObject->globalExec()->clearException();
1206 }
1207
1208#if ENABLE(SAMPLING_FLAGS)
1209 SamplingFlags::stop();
1210#endif
1211#if ENABLE(SAMPLING_REGIONS)
1212 SamplingRegion::dump();
1213#endif
1214 vm.dumpSampleData(globalObject->globalExec());
1215#if ENABLE(SAMPLING_COUNTERS)
1216 AbstractSamplingCounter::dump();
1217#endif
1218#if ENABLE(REGEXP_TRACING)
1219 vm.dumpRegExpTrace();
1220#endif
1221 return success;
1222}
1223
1224#define RUNNING_FROM_XCODE 0
1225
1226static void runInteractive(GlobalObject* globalObject)
1227{
1228 String interpreterName("Interpreter");
1229
1230 bool shouldQuit = false;
1231 while (!shouldQuit) {
1232#if HAVE(READLINE) && !RUNNING_FROM_XCODE
1233 ParserError error;
1234 String source;
1235 do {
1236 error = ParserError();
1237 char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
1238 shouldQuit = !line;
1239 if (!line)
1240 break;
1241 source = source + line;
1242 source = source + '\n';
1243 checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
1244 if (!line[0])
1245 break;
1246 add_history(line);
1247 } while (error.m_syntaxErrorType == ParserError::SyntaxErrorRecoverable);
1248
1249 if (error.m_type != ParserError::ErrorNone) {
1250 printf("%s:%d\n", error.m_message.utf8().data(), error.m_line);
1251 continue;
1252 }
1253
1254
1255 JSValue evaluationException;
1256 JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), &evaluationException);
1257#else
1258 printf("%s", interactivePrompt);
1259 Vector<char, 256> line;
1260 int c;
1261 while ((c = getchar()) != EOF) {
1262 // FIXME: Should we also break on \r?
1263 if (c == '\n')
1264 break;
1265 line.append(c);
1266 }
1267 if (line.isEmpty())
1268 break;
1269 line.append('\0');
1270
1271 JSValue evaluationException;
1272 JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
1273#endif
1274 if (evaluationException)
1275 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1276 else
1277 printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1278
1279 globalObject->globalExec()->clearException();
1280 }
1281 printf("\n");
1282}
1283
1284static NO_RETURN void printUsageStatement(bool help = false)
1285{
1286 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
1287 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
1288 fprintf(stderr, " -e Evaluate argument as script code\n");
1289 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
1290 fprintf(stderr, " -h|--help Prints this help message\n");
1291 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
1292#if HAVE(SIGNAL_H)
1293 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
1294#endif
1295 fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
1296 fprintf(stderr, " -x Output exit code before terminating\n");
1297 fprintf(stderr, "\n");
1298 fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
1299 fprintf(stderr, " --dumpOptions Dumps all JSC VM options before continuing\n");
1300 fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
1301 fprintf(stderr, "\n");
1302
1303 jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
1304}
1305
1306void CommandLine::parseArguments(int argc, char** argv)
1307{
1308 int i = 1;
1309 bool needToDumpOptions = false;
1310 bool needToExit = false;
1311
1312 for (; i < argc; ++i) {
1313 const char* arg = argv[i];
1314 if (!strcmp(arg, "-f")) {
1315 if (++i == argc)
1316 printUsageStatement();
1317 m_scripts.append(Script(true, argv[i]));
1318 continue;
1319 }
1320 if (!strcmp(arg, "-e")) {
1321 if (++i == argc)
1322 printUsageStatement();
1323 m_scripts.append(Script(false, argv[i]));
1324 continue;
1325 }
1326 if (!strcmp(arg, "-i")) {
1327 m_interactive = true;
1328 continue;
1329 }
1330 if (!strcmp(arg, "-d")) {
1331 m_dump = true;
1332 continue;
1333 }
1334 if (!strcmp(arg, "-p")) {
1335 if (++i == argc)
1336 printUsageStatement();
1337 m_profile = true;
1338 m_profilerOutput = argv[i];
1339 continue;
1340 }
1341 if (!strcmp(arg, "-s")) {
1342#if HAVE(SIGNAL_H)
1343 signal(SIGILL, _exit);
1344 signal(SIGFPE, _exit);
1345 signal(SIGBUS, _exit);
1346 signal(SIGSEGV, _exit);
1347#endif
1348 continue;
1349 }
1350 if (!strcmp(arg, "-x")) {
1351 m_exitCode = true;
1352 continue;
1353 }
1354 if (!strcmp(arg, "--")) {
1355 ++i;
1356 break;
1357 }
1358 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
1359 printUsageStatement(true);
1360
1361 if (!strcmp(arg, "--options")) {
1362 needToDumpOptions = true;
1363 needToExit = true;
1364 continue;
1365 }
1366 if (!strcmp(arg, "--dumpOptions")) {
1367 needToDumpOptions = true;
1368 continue;
1369 }
1370
1371 // See if the -- option is a JSC VM option.
1372 // NOTE: At this point, we know that the arg starts with "--". Skip it.
1373 if (JSC::Options::setOption(&arg[2])) {
1374 // The arg was recognized as a VM option and has been parsed.
1375 continue; // Just continue with the next arg.
1376 }
1377
1378 // This arg is not recognized by the VM nor by jsc. Pass it on to the
1379 // script.
1380 m_scripts.append(Script(true, argv[i]));
1381 }
1382
1383 if (m_scripts.isEmpty())
1384 m_interactive = true;
1385
1386 for (; i < argc; ++i)
1387 m_arguments.append(argv[i]);
1388
1389 if (needToDumpOptions)
1390 JSC::Options::dumpAllOptions(stderr);
1391 if (needToExit)
1392 jscExit(EXIT_SUCCESS);
1393}
1394
1395int jscmain(int argc, char** argv)
1396{
1397 // Note that the options parsing can affect VM creation, and thus
1398 // comes first.
1399 CommandLine options(argc, argv);
1400 VM* vm = VM::create(LargeHeap).leakRef();
1401 int result;
1402 {
1403 JSLockHolder locker(vm);
1404
1405 if (options.m_profile && !vm->m_perBytecodeProfiler)
1406 vm->m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*vm));
1407
1408 GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
1409 bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump);
1410 if (options.m_interactive && success)
1411 runInteractive(globalObject);
1412
1413 result = success ? 0 : 3;
1414
1415 if (options.m_exitCode)
1416 printf("jsc exiting %d\n", result);
1417
1418 if (options.m_profile) {
1419 if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
1420 fprintf(stderr, "could not save profiler output.\n");
1421 }
1422
1423#if ENABLE(JIT)
1424 if (Options::enableExceptionFuzz())
1425 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
1426#endif
1427 }
1428
1429 return result;
1430}
1431
1432static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1433{
1434 FILE* f = fopen(fileName.utf8().data(), "r");
1435 if (!f) {
1436 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1437 return false;
1438 }
1439
1440 size_t bufferSize = 0;
1441 size_t bufferCapacity = 1024;
1442
1443 buffer.resize(bufferCapacity);
1444
1445 while (!feof(f) && !ferror(f)) {
1446 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
1447 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
1448 bufferCapacity *= 2;
1449 buffer.resize(bufferCapacity);
1450 }
1451 }
1452 fclose(f);
1453 buffer[bufferSize] = '\0';
1454
1455 if (buffer[0] == '#' && buffer[1] == '!')
1456 buffer[0] = buffer[1] = '/';
1457
1458 return true;
1459}
Note: See TracBrowser for help on using the repository browser.