diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-03-12 14:11:15 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-03-12 14:11:15 +0100 |
commit | dd91e772430dc294e3bf478c119ef8d43c0a3358 (patch) | |
tree | 6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/JavaScriptCore | |
parent | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff) | |
download | qtwebkit-dd91e772430dc294e3bf478c119ef8d43c0a3358.tar.gz |
Imported WebKit commit 3db4eb1820ac8fb03065d7ea73a4d9db1e8fea1a (http://svn.webkit.org/repository/webkit/trunk@110422)
This includes build fixes for the latest qtbase/qtdeclarative as well as the final QML2 API.
Diffstat (limited to 'Source/JavaScriptCore')
343 files changed, 14208 insertions, 4998 deletions
diff --git a/Source/JavaScriptCore/API/JSObjectRef.cpp b/Source/JavaScriptCore/API/JSObjectRef.cpp index cd8d7159e..17329ad87 100644 --- a/Source/JavaScriptCore/API/JSObjectRef.cpp +++ b/Source/JavaScriptCore/API/JSObjectRef.cpp @@ -312,7 +312,7 @@ void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned p JSObject* jsObject = toJS(object); JSValue jsValue = toJS(exec, value); - jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue); + jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); diff --git a/Source/JavaScriptCore/API/tests/JSNode.c b/Source/JavaScriptCore/API/tests/JSNode.c index d9ac0a913..052c88a02 100644 --- a/Source/JavaScriptCore/API/tests/JSNode.c +++ b/Source/JavaScriptCore/API/tests/JSNode.c @@ -30,7 +30,7 @@ #include "JSValueRef.h" #include "Node.h" #include "NodeList.h" -#include "UnusedParam.h" +#include <wtf/UnusedParam.h> #include <wtf/Assertions.h> static JSValueRef JSNode_appendChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) diff --git a/Source/JavaScriptCore/API/tests/JSNodeList.c b/Source/JavaScriptCore/API/tests/JSNodeList.c index bc4a8ad99..0d194845e 100644 --- a/Source/JavaScriptCore/API/tests/JSNodeList.c +++ b/Source/JavaScriptCore/API/tests/JSNodeList.c @@ -27,7 +27,7 @@ #include "JSNodeList.h" #include "JSObjectRef.h" #include "JSValueRef.h" -#include "UnusedParam.h" +#include <wtf/UnusedParam.h> #include <wtf/Assertions.h> static JSValueRef JSNodeList_item(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index 2afcbdc65..d4a51d214 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -40,6 +40,7 @@ SET(JavaScriptCore_SOURCES bytecode/CallLinkStatus.cpp bytecode/CodeBlock.cpp bytecode/DFGExitProfile.cpp + bytecode/ExecutionCounter.cpp bytecode/GetByIdStatus.cpp bytecode/JumpTable.cpp bytecode/LazyOperandValueProfile.cpp @@ -67,6 +68,7 @@ SET(JavaScriptCore_SOURCES dfg/DFGDriver.cpp dfg/DFGGraph.cpp dfg/DFGJITCompiler.cpp + dfg/DFGNode.cpp dfg/DFGOSREntry.cpp dfg/DFGOSRExit.cpp dfg/DFGOSRExitCompiler.cpp @@ -75,6 +77,7 @@ SET(JavaScriptCore_SOURCES dfg/DFGOperations.cpp dfg/DFGPhase.cpp dfg/DFGPredictionPropagationPhase.cpp + dfg/DFGRedundantPhiEliminationPhase.cpp dfg/DFGRepatch.cpp dfg/DFGSpeculativeJIT.cpp dfg/DFGSpeculativeJIT32_64.cpp @@ -300,6 +303,7 @@ INCLUDE_DIRECTORIES(${JavaScriptCore_INCLUDE_DIRECTORIES}) ADD_DEFINITIONS(-DBUILDING_JavaScriptCore) ADD_LIBRARY(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARY_TYPE} ${JavaScriptCore_HEADERS} ${JavaScriptCore_SOURCES}) TARGET_LINK_LIBRARIES(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARIES}) +SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "") IF (JavaScriptCore_LINK_FLAGS) ADD_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} LINK_FLAGS "${JavaScriptCore_LINK_FLAGS}") @@ -307,5 +311,5 @@ ENDIF () IF (SHARED_CORE) SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) - INSTALL(TARGETS ${JavaScriptCore_LIBRARY_NAME} DESTINATION lib) + INSTALL(TARGETS ${JavaScriptCore_LIBRARY_NAME} DESTINATION "${LIB_INSTALL_DIR}") ENDIF () diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 87b921f0f..0092392f0 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,3472 @@ +2012-03-12 Filip Pizlo <fpizlo@apple.com> + + All DFG nodes should have a mutable set of flags + https://bugs.webkit.org/show_bug.cgi?id=80779 + <rdar://problem/11026218> + + Reviewed by Gavin Barraclough. + + Got rid of NodeId, and placed all of the flags that distinguished NodeId + from NodeType into a separate Node::flags field. Combined what was previously + ArithNodeFlags into Node::flags. + + In the process of debugging, I found that the debug support in the virtual + register allocator was lacking, so I improved it. I also realized that the + virtual register allocator was assuming that the nodes in a basic block were + contiguous, which is no longer the case. So I fixed that. The fix also made + it natural to have more extreme assertions, so I added them. I suspect this + will make it easier to catch virtual register allocation bugs in the future. + + This is mostly performance neutral; if anything it looks like a slight + speed-up. + + This patch does leave some work for future refactorings; for example, Node::op + is unencapsulated. This was already the case, though now it feels even more + like it should be. I avoided doing that because this patch has already grown + way bigger than I wanted. + + Finally, this patch creates a DFGNode.cpp file and makes a slight effort to + move some unnecessarily inline stuff out of DFGNode.h. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * dfg/DFGArithNodeFlagsInferencePhase.cpp: + (JSC::DFG::ArithNodeFlagsInferencePhase::propagate): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::addToGraph): + (JSC::DFG::ByteCodeParser::makeSafe): + (JSC::DFG::ByteCodeParser::makeDivSafe): + (JSC::DFG::ByteCodeParser::handleMinMax): + (JSC::DFG::ByteCodeParser::handleIntrinsic): + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGCFAPhase.cpp: + (JSC::DFG::CFAPhase::performBlockCFA): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::endIndexForPureCSE): + (JSC::DFG::CSEPhase::pureCSE): + (JSC::DFG::CSEPhase::clobbersWorld): + (JSC::DFG::CSEPhase::impureCSE): + (JSC::DFG::CSEPhase::setReplacement): + (JSC::DFG::CSEPhase::eliminate): + (JSC::DFG::CSEPhase::performNodeCSE): + (JSC::DFG::CSEPhase::performBlockCSE): + (CSEPhase): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::opName): + (JSC::DFG::Graph::dump): + (DFG): + * dfg/DFGNode.cpp: Added. + (DFG): + (JSC::DFG::arithNodeFlagsAsString): + * dfg/DFGNode.h: + (DFG): + (JSC::DFG::nodeUsedAsNumber): + (JSC::DFG::nodeCanTruncateInteger): + (JSC::DFG::nodeCanIgnoreNegativeZero): + (JSC::DFG::nodeMayOverflow): + (JSC::DFG::nodeCanSpeculateInteger): + (JSC::DFG::defaultFlags): + (JSC::DFG::Node::Node): + (Node): + (JSC::DFG::Node::setOpAndDefaultFlags): + (JSC::DFG::Node::mustGenerate): + (JSC::DFG::Node::arithNodeFlags): + (JSC::DFG::Node::setArithNodeFlag): + (JSC::DFG::Node::mergeArithNodeFlags): + (JSC::DFG::Node::hasResult): + (JSC::DFG::Node::hasInt32Result): + (JSC::DFG::Node::hasNumberResult): + (JSC::DFG::Node::hasJSResult): + (JSC::DFG::Node::hasBooleanResult): + (JSC::DFG::Node::isJump): + (JSC::DFG::Node::isBranch): + (JSC::DFG::Node::isTerminal): + (JSC::DFG::Node::child1): + (JSC::DFG::Node::child2): + (JSC::DFG::Node::child3): + (JSC::DFG::Node::firstChild): + (JSC::DFG::Node::numChildren): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + (JSC::DFG::PredictionPropagationPhase::vote): + (JSC::DFG::PredictionPropagationPhase::fixupNode): + * dfg/DFGScoreBoard.h: + (ScoreBoard): + (JSC::DFG::ScoreBoard::~ScoreBoard): + (JSC::DFG::ScoreBoard::assertClear): + (JSC::DFG::ScoreBoard::use): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::useChildren): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGVirtualRegisterAllocationPhase.cpp: + (JSC::DFG::VirtualRegisterAllocationPhase::run): + +2012-03-10 Filip Pizlo <fpizlo@apple.com> + + LLInt should support JSVALUE64 + https://bugs.webkit.org/show_bug.cgi?id=79609 + <rdar://problem/10063437> + + Reviewed by Gavin Barraclough and Oliver Hunt. + + Ported the LLInt, which previously only worked on 32-bit, to 64-bit. This + patch moves a fair bit of code from LowLevelInterpreter32_64.asm to the common + file, LowLevelInterpreter.asm. About 1/3 of the LLInt did not have to be + specialized for value representation. + + Also made some minor changes to offlineasm and the slow-paths. + + * llint/LLIntData.cpp: + (JSC::LLInt::Data::performAssertions): + * llint/LLIntEntrypoints.cpp: + * llint/LLIntSlowPaths.cpp: + (LLInt): + (JSC::LLInt::llint_trace_value): + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + (JSC::LLInt::jitCompileAndSetHeuristics): + * llint/LLIntSlowPaths.h: + (LLInt): + (SlowPathReturnType): + (JSC::LLInt::SlowPathReturnType::SlowPathReturnType): + (JSC::LLInt::encodeResult): + * llint/LLIntThunks.cpp: + * llint/LowLevelInterpreter.asm: + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + * offlineasm/armv7.rb: + * offlineasm/asm.rb: + * offlineasm/ast.rb: + * offlineasm/backends.rb: + * offlineasm/instructions.rb: + * offlineasm/parser.rb: + * offlineasm/registers.rb: + * offlineasm/transform.rb: + * offlineasm/x86.rb: + * wtf/Platform.h: + +2012-03-10 Yong Li <yoli@rim.com> + + Web Worker crashes with WX_EXCLUSIVE + https://bugs.webkit.org/show_bug.cgi?id=80532 + + Let each JS global object own a meta allocator + for WX_EXCLUSIVE to avoid conflicts from Web Worker. + Also fix a mutex leak in MetaAllocator's dtor. + + Reviewed by Filip Pizlo. + + * jit/ExecutableAllocator.cpp: + (JSC::DemandExecutableAllocator::DemandExecutableAllocator): + (JSC::DemandExecutableAllocator::~DemandExecutableAllocator): + (JSC::DemandExecutableAllocator::bytesAllocatedByAllAllocators): + (DemandExecutableAllocator): + (JSC::DemandExecutableAllocator::bytesCommittedByAllocactors): + (JSC::DemandExecutableAllocator::dumpProfileFromAllAllocators): + (JSC::DemandExecutableAllocator::allocateNewSpace): + (JSC::DemandExecutableAllocator::allocators): + (JSC::DemandExecutableAllocator::allocatorsMutex): + (JSC): + (JSC::ExecutableAllocator::initializeAllocator): + (JSC::ExecutableAllocator::ExecutableAllocator): + (JSC::ExecutableAllocator::underMemoryPressure): + (JSC::ExecutableAllocator::memoryPressureMultiplier): + (JSC::ExecutableAllocator::allocate): + (JSC::ExecutableAllocator::committedByteCount): + (JSC::ExecutableAllocator::dumpProfile): + * jit/ExecutableAllocator.h: + (JSC): + (ExecutableAllocator): + (JSC::ExecutableAllocator::allocator): + * wtf/MetaAllocator.h: + (WTF::MetaAllocator::~MetaAllocator): Finalize the spin lock. + * wtf/TCSpinLock.h: + (TCMalloc_SpinLock::Finalize): Add empty Finalize() to some implementations. + +2012-03-09 Gavin Barraclough <barraclough@apple.com> + + Object.freeze broken on latest Nightly + https://bugs.webkit.org/show_bug.cgi?id=80577 + + Reviewed by Oliver Hunt. + + The problem here is that deleteProperty rejects deletion of prototype. + This is correct in most cases, however defineOwnPropery is presently + implemented internally to ensure the attributes change by deleting the + old property, and creating a new one. + + * runtime/JSFunction.cpp: + (JSC::JSFunction::deleteProperty): + - If deletePropery is called via defineOwnPropery, allow old prototype to be removed. + +2012-03-09 Gavin Barraclough <barraclough@apple.com> + + Array.prototype.toLocaleString visits elements in wrong order under certain conditions + https://bugs.webkit.org/show_bug.cgi?id=80663 + + Reviewed by Michael Saboff. + + The bug here is actually that we're continuing to process the array after an exception + has been thrown, and that the second value throw is overriding the first. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToLocaleString): + +2012-03-09 Ryosuke Niwa <rniwa@webkit.org> + + WebKit compiled by gcc (Xcode 3.2.6) hangs while running DOM/Accessors.html + https://bugs.webkit.org/show_bug.cgi?id=80080 + + Reviewed by Filip Pizlo. + + * bytecode/SamplingTool.cpp: + (JSC::SamplingRegion::Locker::Locker): + (JSC::SamplingRegion::Locker::~Locker): + * bytecode/SamplingTool.h: + (JSC::SamplingRegion::exchangeCurrent): + * wtf/Atomics.h: + (WTF): + (WTF::weakCompareAndSwap): + (WTF::weakCompareAndSwapUIntPtr): + +2012-03-09 Gavin Barraclough <barraclough@apple.com> + + REGRESSION: Date.parse("Tue Nov 23 20:40:05 2010 GMT") returns NaN + https://bugs.webkit.org/show_bug.cgi?id=49989 + + Reviewed by Oliver Hunt. + + Patch originally by chris reiss <christopher.reiss@nokia.com>, + allow the year to appear before the timezone in date strings. + + * wtf/DateMath.cpp: + (WTF::parseDateFromNullTerminatedCharacters): + +2012-03-09 Mark Rowe <mrowe@apple.com> + + Ensure that the WTF headers are copied at installhdrs time. + + Reviewed by Dan Bernstein and Jessie Berlin. + + * Configurations/JavaScriptCore.xcconfig: Set INSTALLHDRS_SCRIPT_PHASE = YES + so that our script phases are invoked at installhdrs time. The only one that + does any useful work at that time is the one that installs WTF headers. + +2012-03-09 Jon Lee <jonlee@apple.com> + + Add support for ENABLE(LEGACY_NOTIFICATIONS) + https://bugs.webkit.org/show_bug.cgi?id=80497 + + Reviewed by Adam Barth. + + Prep for b80472: Update API for Web Notifications + * Configurations/FeatureDefines.xcconfig: + +2012-03-09 Ashod Nakashian <ashodnakashian@yahoo.com> + + Bash scripts should support LF endings only + https://bugs.webkit.org/show_bug.cgi?id=79509 + + Reviewed by David Kilzer. + + * gyp/generate-derived-sources.sh: Added property svn:eol-style. + * gyp/run-if-exists.sh: Added property svn:eol-style. + * gyp/update-info-plist.sh: Added property svn:eol-style. + +2012-03-09 Jessie Berlin <jberlin@apple.com> + + Windows debug build fix. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::shouldBlind): + Fix unreachable code warnings (which we treat as errors). + +2012-03-09 Thouraya ANDOLSI <thouraya.andolsi@st.com> + + Reviewed by Zoltan Herczeg. + + [Qt] Fix the SH4 build after r109834 + https://bugs.webkit.org/show_bug.cgi?id=80492 + + * assembler/MacroAssemblerSH4.h: + (JSC::MacroAssemblerSH4::branchAdd32): + (JSC::MacroAssemblerSH4::branchSub32): + +2012-03-09 Andy Wingo <wingo@igalia.com> + + Refactor code feature analysis in the parser + https://bugs.webkit.org/show_bug.cgi?id=79112 + + Reviewed by Geoffrey Garen. + + This commit refactors the parser to more uniformly propagate flag + bits down and up the parse process, as the parser descends and + returns into nested blocks. Some flags get passed town to + subscopes, some apply to specific scopes only, and some get + unioned up after parsing subscopes. + + The goal is to eventually be very precise with scoping + information, once we have block scopes: one block scope might use + `eval', which would require the emission of a symbol table within + that block and containing blocks, whereas another block in the + same function might not, allowing us to not emit a symbol table. + + * parser/Nodes.h: + (JSC::ScopeFlags): Rename from CodeFeatures. + (JSC::ScopeNode::addScopeFlags): + (JSC::ScopeNode::scopeFlags): New accessors for m_scopeFlags. + (JSC::ScopeNode::isStrictMode): + (JSC::ScopeNode::usesEval): + (JSC::ScopeNode::usesArguments): + (JSC::ScopeNode::setUsesArguments): + (JSC::ScopeNode::usesThis): + (JSC::ScopeNode::needsActivationForMoreThanVariables): + (JSC::ScopeNode::needsActivation): Refactor these accessors to + operate on the m_scopeFlags member. + (JSC::ScopeNode::source): + (JSC::ScopeNode::sourceURL): + (JSC::ScopeNode::sourceID): Shuffle these definitions around; no + semantic change. + (JSC::ScopeNode::ScopeNode) + (JSC::ProgramNode::ProgramNode) + (JSC::EvalNode::EvalNode) + (JSC::FunctionBodyNode::FunctionBodyNode): Have these constructors + take a ScopeFlags as an argument, instead of a bool inStrictContext. + + * parser/Nodes.cpp: + (JSC::ScopeNode::ScopeNode): + (JSC::ProgramNode::ProgramNode): + (JSC::ProgramNode::create): + (JSC::EvalNode::EvalNode): + (JSC::EvalNode::create): + (JSC::FunctionBodyNode::FunctionBodyNode): + (JSC::FunctionBodyNode::create): Adapt constructors to change. + + * parser/ASTBuilder.h: + (JSC::ASTBuilder::ASTBuilder): + (JSC::ASTBuilder::thisExpr): + (JSC::ASTBuilder::createResolve): + (JSC::ASTBuilder::createFunctionBody): + (JSC::ASTBuilder::createFuncDeclStatement): + (JSC::ASTBuilder::createTryStatement): + (JSC::ASTBuilder::createWithStatement): + (JSC::ASTBuilder::addVar): + (JSC::ASTBuilder::Scope::Scope): + (Scope): + (ASTBuilder): + (JSC::ASTBuilder::makeFunctionCallNode): Don't track scope + features here. Instead rely on the base Parser mechanism to track + features. + + * parser/NodeInfo.h (NodeInfo, NodeDeclarationInfo): "ScopeFlags". + + * parser/Parser.h: + (JSC::Scope::Scope): Manage scope through flags, not + bit-booleans. This lets us uniformly propagate them up and down. + (JSC::Scope::declareWrite): + (JSC::Scope::declareParameter): + (JSC::Scope::useVariable): + (JSC::Scope::collectFreeVariables): + (JSC::Scope::getCapturedVariables): + (JSC::Scope::saveFunctionInfo): + (JSC::Scope::restoreFunctionInfo): + (JSC::Parser::pushScope): Adapt to use scope flags and their + accessors instead of bit-booleans. + * parser/Parser.cpp: + (JSC::::Parser): + (JSC::::parseInner): + (JSC::::didFinishParsing): + (JSC::::parseSourceElements): + (JSC::::parseVarDeclarationList): + (JSC::::parseConstDeclarationList): + (JSC::::parseWithStatement): + (JSC::::parseTryStatement): + (JSC::::parseFunctionBody): + (JSC::::parseFunctionInfo): + (JSC::::parseFunctionDeclaration): + (JSC::::parsePrimaryExpression): Hoist some of the flag handling + out of the "context" (ASTBuilder or SyntaxChecker) and to here. + Does not seem to have a performance impact. + + * parser/SourceProviderCacheItem.h (SourceProviderCacheItem): + Cache the scopeflags. + * parser/SyntaxChecker.h: Remove evalCount() decl. + + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + (JSC::ProgramExecutable::compileInternal): + (JSC::FunctionExecutable::produceCodeBlockFor): + * runtime/Executable.h: + (JSC::ScriptExecutable::ScriptExecutable): + (JSC::ScriptExecutable::usesEval): + (JSC::ScriptExecutable::usesArguments): + (JSC::ScriptExecutable::needsActivation): + (JSC::ScriptExecutable::isStrictMode): + (JSC::ScriptExecutable::recordParse): + (ScriptExecutable): ScopeFlags, not features. + +2012-03-08 Benjamin Poulain <bpoulain@apple.com> + + Build fix for MSVC after r110266 + + Unreviewed. A #ifdef for MSVC was left over in r110266. + + * runtime/RegExpObject.h: + (RegExpObject): + +2012-03-08 Benjamin Poulain <bpoulain@apple.com> + + Allocate the RegExpObject's data with the Cell + https://bugs.webkit.org/show_bug.cgi?id=80654 + + Reviewed by Gavin Barraclough. + + This patch removes the creation of RegExpObject's data to avoid the overhead + create by the allocation and destruction. + + We RegExp are created repeatedly, this provides some performance improvment. + The PeaceKeeper test stringDetectBrowser improves by 10%. + + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::RegExpObject): + (JSC::RegExpObject::visitChildren): + (JSC::RegExpObject::getOwnPropertyDescriptor): + (JSC::RegExpObject::defineOwnProperty): + (JSC::RegExpObject::match): + * runtime/RegExpObject.h: + (JSC::RegExpObject::setRegExp): + (JSC::RegExpObject::regExp): + (JSC::RegExpObject::setLastIndex): + (JSC::RegExpObject::getLastIndex): + (RegExpObject): + +2012-03-08 Steve Falkenburg <sfalken@apple.com> + + Separate WTF parts of JavaScriptCoreGenerated into WTFGenerated for Windows build + https://bugs.webkit.org/show_bug.cgi?id=80657 + + Preparation for WTF separation from JavaScriptCore. + The "Generated" vcproj files on Windows are necessary so Visual Studio can calculate correct + dependencies for generated files. + + This also removes the PGO build targets from the WTF code, since we can't build instrumentation/optimization + versions of the WTF code independent of the JavaScriptCore code. + + Reviewed by Jessie Berlin. + + * JavaScriptCore.vcproj/JavaScriptCore.sln: Add WTFGenerated, update dependent projects. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make: Removed WTF specific parts. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj: Removed WTF specific parts. + * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh: Removed WTF specific parts. + * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd: Removed WTF specific parts. + * JavaScriptCore.vcproj/JavaScriptCore/work-around-vs-dependency-tracking-bugs.py: Removed. + * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln: Add WTFGenerated, update dependent projects. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Remove PGO targets from WTF. + * JavaScriptCore.vcproj/WTF/WTFGenerated.make: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make. + * JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj. + * JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGeneratedCommon.vsprops. + * JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGeneratedDebug.vsprops. + * JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGeneratedDebugAll.vsprops. + * JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGeneratedDebugCairoCFLite.vsprops. + * JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGeneratedProduction.vsprops. + * JavaScriptCore.vcproj/WTF/WTFGeneratedRelease.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGeneratedRelease.vsprops. + * JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGeneratedReleaseCairoCFLite.vsprops. + * JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/build-generated-files.sh: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh. + * JavaScriptCore.vcproj/WTF/copy-files.cmd: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd. + * JavaScriptCore.vcproj/WTF/work-around-vs-dependency-tracking-bugs.py: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/work-around-vs-dependency-tracking-bugs.py. + +2012-03-08 Benjamin Poulain <benjamin@webkit.org> + + Fix the build of WebKit with WTFURL following the removal of ForwardingHeaders/wtf + https://bugs.webkit.org/show_bug.cgi?id=80652 + + Reviewed by Eric Seidel. + + Fix the header, URLSegments.h is not part of the API. + + * wtf/url/api/ParsedURL.h: + +2012-03-08 Ryosuke Niwa <rniwa@webkit.org> + + Mac build fix for micro data API. + + * Configurations/FeatureDefines.xcconfig: + +2012-03-08 Gavin Barraclough <barraclough@apple.com> + + String.prototype.match and replace do not clear global regexp lastIndex per ES5.1 15.5.4.10 + https://bugs.webkit.org/show_bug.cgi?id=26890 + + Reviewed by Oliver Hunt. + + Per 15.10.6.2 step 9.a.1 called via the action of the last iteration of 15.5.4.10 8.f.i. + + * runtime/StringPrototype.cpp: + (JSC::replaceUsingRegExpSearch): + (JSC::stringProtoFuncMatch): + - added calls to setLastIndex. + +2012-03-08 Matt Lilek <mrl@apple.com> + + Don't enable VIDEO_TRACK on all OS X platforms + https://bugs.webkit.org/show_bug.cgi?id=80635 + + Reviewed by Eric Carlson. + + * Configurations/FeatureDefines.xcconfig: + +2012-03-08 Oliver Hunt <oliver@apple.com> + + Build fix. That day is not today. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::shouldBlind): + * assembler/MacroAssemblerX86Common.h: + (MacroAssemblerX86Common): + (JSC::MacroAssemblerX86Common::shouldBlindForSpecificArch): + +2012-03-08 Oliver Hunt <oliver@apple.com> + + Build fix. One of these days I'll manage to commit something that works everywhere. + + * assembler/AbstractMacroAssembler.h: + (AbstractMacroAssembler): + * assembler/MacroAssemblerARMv7.h: + (MacroAssemblerARMv7): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::shouldBlindForSpecificArch): + (MacroAssemblerX86Common): + +2012-03-08 Chao-ying Fu <fu@mips.com> + + Update MIPS patchOffsetGetByIdSlowCaseCall + https://bugs.webkit.org/show_bug.cgi?id=80302 + + Reviewed by Oliver Hunt. + + * jit/JIT.h: + (JIT): + +2012-03-08 Oliver Hunt <oliver@apple.com> + + Missing some places where we should be blinding 64bit values (and blinding something we shouldn't) + https://bugs.webkit.org/show_bug.cgi?id=80633 + + Reviewed by Gavin Barraclough. + + Add 64-bit trap for shouldBlindForSpecificArch, so that we always blind + if there isn't a machine specific implementation (otherwise the 64bit value + got truncated and 32bit checks were used -- leaving 32bits untested). + Also add a bit of logic to ensure that we don't try to blind a few common + constants that go through the ImmPtr paths -- encoded numeric JSValues and + unencoded doubles with common "safe" values. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::shouldBlindForSpecificArch): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::shouldBlindDouble): + (MacroAssembler): + (JSC::MacroAssembler::shouldBlind): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::shouldBlindForSpecificArch): + +2012-03-08 Mark Rowe <mrowe@apple.com> + + <rdar://problem/11012572> Ensure that the staged frameworks path is in the search path for JavaScriptCore + + Reviewed by Dan Bernstein. + + * Configurations/Base.xcconfig: + +2012-03-08 Steve Falkenburg <sfalken@apple.com> + + Fix line endings for copy-files.cmd. + + If a cmd file doesn't have Windows line endings, it doesn't work properly. + In this case, the label :clean wasn't found, breaking the clean build. + + Reviewed by Jessie Berlin. + + * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd: + +2012-03-07 Filip Pizlo <fpizlo@apple.com> + + DFG CFA incorrectly handles ValueToInt32 + https://bugs.webkit.org/show_bug.cgi?id=80568 + + Reviewed by Gavin Barraclough. + + Changed it match exactly the decision pattern used in + DFG::SpeculativeJIT::compileValueToInt32 + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + +2012-03-08 Viatcheslav Ostapenko <ostapenko.viatcheslav@nokia.com> + + [Qt] [WK2] Webkit fails to link when compiled with force_static_libs_as_shared + https://bugs.webkit.org/show_bug.cgi?id=80524 + + Reviewed by Simon Hausmann. + + Move IdentifierTable methods defintion to WTFThreadData.cpp to fix linking + of WTF library. + + * runtime/Identifier.cpp: + * wtf/WTFThreadData.cpp: + (JSC): + (JSC::IdentifierTable::~IdentifierTable): + (JSC::IdentifierTable::add): + +2012-03-08 Filip Pizlo <fpizlo@apple.com> + + DFG instruction count threshold should be lifted to 10000 + https://bugs.webkit.org/show_bug.cgi?id=80579 + + Reviewed by Gavin Barraclough. + + * runtime/Options.cpp: + (JSC::Options::initializeOptions): + +2012-03-07 Filip Pizlo <fpizlo@apple.com> + + Incorrect tracking of abstract values of variables forced double + https://bugs.webkit.org/show_bug.cgi?id=80566 + <rdar://problem/11001442> + + Reviewed by Gavin Barraclough. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::mergeStateAtTail): + +2012-03-07 Chao-yng Fu <fu@mips.com> + + [Qt] Fix the MIPS/SH4 build after r109834 + https://bugs.webkit.org/show_bug.cgi?id=80492 + + Reviewed by Oliver Hunt. + + Implement three-argument branch(Add,Sub)32. + + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::add32): + (MacroAssemblerMIPS): + (JSC::MacroAssemblerMIPS::sub32): + (JSC::MacroAssemblerMIPS::branchAdd32): + (JSC::MacroAssemblerMIPS::branchSub32): + +2012-03-07 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r110127. + http://trac.webkit.org/changeset/110127 + https://bugs.webkit.org/show_bug.cgi?id=80562 + + compile failed on AppleWin (Requested by ukai on #webkit). + + * heap/Heap.cpp: + (JSC::Heap::collectAllGarbage): + * heap/Heap.h: + (JSC): + (Heap): + * runtime/Executable.cpp: + (JSC::FunctionExecutable::FunctionExecutable): + (JSC::FunctionExecutable::finalize): + * runtime/Executable.h: + (FunctionExecutable): + (JSC::FunctionExecutable::create): + * runtime/JSGlobalData.cpp: + (WTF): + (Recompiler): + (WTF::Recompiler::operator()): + (JSC::JSGlobalData::recompileAllJSFunctions): + (JSC): + * runtime/JSGlobalData.h: + (JSGlobalData): + * runtime/JSGlobalObject.cpp: + (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): + +2012-03-07 Hojong Han <hojong.han@samsung.com> + + The end atom of the marked block considered to filter invalid cells + https://bugs.webkit.org/show_bug.cgi?id=79191 + + Reviewed by Geoffrey Garen. + + Register file could have stale pointers beyond the end atom of marked block. + Those pointers can weasel out of filtering in-middle-of-cell pointer. + + * heap/MarkedBlock.h: + (JSC::MarkedBlock::isLiveCell): + +2012-03-07 Jessie Berlin <jberlin@apple.com> + + Clean Windows build fails after r110033 + https://bugs.webkit.org/show_bug.cgi?id=80553 + + Rubber-stamped by Jon Honeycutt and Eric Seidel. + + * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd: + Place the implementation files next to their header files in the wtf/text subdirectory. + Use echo -F to tell xcopy that these are files (since there is apparently no flag). + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + Update the path to those implementation files. + * JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj: + Ditto. + +2012-03-07 Yuqiang Xian <yuqiang.xian@intel.com> + + Eliminate redundant Phis in DFG + https://bugs.webkit.org/show_bug.cgi?id=80415 + + Reviewed by Filip Pizlo. + + Although this may not have any advantage at current stage, this is towards + minimal SSA to make more high level optimizations (like bug 76770) easier. + We have the choices either to build minimal SSA from scratch or to + keep current simple Phi insertion mechanism and remove the redundancy + in another phase. Currently we choose the latter because the change + could be smaller. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGRedundantPhiEliminationPhase.cpp: Added. + (DFG): + (RedundantPhiEliminationPhase): + (JSC::DFG::RedundantPhiEliminationPhase::RedundantPhiEliminationPhase): + (JSC::DFG::RedundantPhiEliminationPhase::run): + (JSC::DFG::RedundantPhiEliminationPhase::getRedundantReplacement): + (JSC::DFG::RedundantPhiEliminationPhase::replacePhiChild): + (JSC::DFG::RedundantPhiEliminationPhase::fixupPhis): + (JSC::DFG::RedundantPhiEliminationPhase::updateBlockVariableInformation): + (JSC::DFG::performRedundantPhiElimination): + * dfg/DFGRedundantPhiEliminationPhase.h: Added. + (DFG): + +2012-03-07 Mark Hahnenberg <mhahnenberg@apple.com> + + Refactor recompileAllJSFunctions() to be less expensive + https://bugs.webkit.org/show_bug.cgi?id=80330 + + Reviewed by Geoffrey Garen. + + This change is performance neutral on the JS benchmarks we track. It's mostly to improve page + load performance, which currently does at least a couple full GCs per navigation. + + * heap/Heap.cpp: + (JSC::Heap::discardAllCompiledCode): Rename recompileAllJSFunctions to discardAllCompiledCode + because the function doesn't actually recompile anything (and never did); it simply throws code + away for it to be recompiled later if we determine we should do so. + (JSC): + (JSC::Heap::collectAllGarbage): + (JSC::Heap::addFunctionExecutable): Adds a newly created FunctionExecutable to the Heap's list. + (JSC::Heap::removeFunctionExecutable): Removes the specified FunctionExecutable from the Heap's list. + * heap/Heap.h: + (JSC): + (Heap): + * runtime/Executable.cpp: Added next and prev fields to FunctionExecutables so that they can + be used in DoublyLinkedLists. + (JSC::FunctionExecutable::FunctionExecutable): + (JSC::FunctionExecutable::finalize): Removes the FunctionExecutable from the Heap's list. + * runtime/Executable.h: + (FunctionExecutable): + (JSC::FunctionExecutable::create): Adds the FunctionExecutable to the Heap's list. + * runtime/JSGlobalData.cpp: Remove recompileAllJSFunctions, as it's the Heap's job to own and manage + the list of FunctionExecutables. + * runtime/JSGlobalData.h: + (JSGlobalData): + * runtime/JSGlobalObject.cpp: + (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Use the new discardAllCompiledCode. + +2012-03-06 Oliver Hunt <oliver@apple.com> + + Further harden 64-bit JIT + https://bugs.webkit.org/show_bug.cgi?id=80457 + + Reviewed by Filip Pizlo. + + This patch implements blinding for ImmPtr. Rather than xor based blinding + we perform randomised pointer rotations in order to avoid the significant + cost in executable memory that would otherwise be necessary (and to avoid + the need for an additional scratch register in some cases). + + As with the prior blinding patch there's a moderate amount of noise as we + correct the use of ImmPtr vs. TrustedImmPtr. + + * assembler/AbstractMacroAssembler.h: + (ImmPtr): + (JSC::AbstractMacroAssembler::ImmPtr::asTrustedImmPtr): + * assembler/MacroAssembler.h: + (MacroAssembler): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::branchPtr): + (JSC::MacroAssembler::shouldBlind): + (JSC::MacroAssembler::RotatedImmPtr::RotatedImmPtr): + (RotatedImmPtr): + (JSC::MacroAssembler::rotationBlindConstant): + (JSC::MacroAssembler::loadRotationBlindedConstant): + (JSC::MacroAssembler::convertInt32ToDouble): + (JSC::MacroAssembler::move): + (JSC::MacroAssembler::poke): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::storeDouble): + (JSC::MacroAssemblerARMv7::branchAdd32): + * assembler/MacroAssemblerX86_64.h: + (MacroAssemblerX86_64): + (JSC::MacroAssemblerX86_64::rotateRightPtr): + (JSC::MacroAssemblerX86_64::xorPtr): + * assembler/X86Assembler.h: + (X86Assembler): + (JSC::X86Assembler::xorq_rm): + (JSC::X86Assembler::rorq_i8r): + * dfg/DFGCCallHelpers.h: + (CCallHelpers): + (JSC::DFG::CCallHelpers::setupArgumentsWithExecState): + * dfg/DFGOSRExitCompiler32_64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * dfg/DFGOSRExitCompiler64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::createOSREntries): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::silentFillGPR): + (JSC::DFG::SpeculativeJIT::callOperation): + (JSC::DFG::SpeculativeJIT::emitEdgeCode): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::fillInteger): + (JSC::DFG::SpeculativeJIT::fillDouble): + (JSC::DFG::SpeculativeJIT::fillJSValue): + (JSC::DFG::SpeculativeJIT::emitCall): + (JSC::DFG::SpeculativeJIT::compileObjectEquality): + (JSC::DFG::SpeculativeJIT::compileLogicalNot): + (JSC::DFG::SpeculativeJIT::emitBranch): + * jit/JIT.cpp: + (JSC::JIT::emitOptimizationCheck): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emitSlow_op_post_inc): + * jit/JITInlineMethods.h: + (JSC::JIT::emitValueProfilingSite): + (JSC::JIT::emitGetVirtualRegister): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_mov): + (JSC::JIT::emit_op_new_object): + (JSC::JIT::emit_op_strcat): + (JSC::JIT::emit_op_ensure_property_exists): + (JSC::JIT::emit_op_resolve_skip): + (JSC::JIT::emitSlow_op_resolve_global): + (JSC::JIT::emit_op_resolve_with_base): + (JSC::JIT::emit_op_resolve_with_this): + (JSC::JIT::emit_op_jmp_scopes): + (JSC::JIT::emit_op_switch_imm): + (JSC::JIT::emit_op_switch_char): + (JSC::JIT::emit_op_switch_string): + (JSC::JIT::emit_op_throw_reference_error): + (JSC::JIT::emit_op_debug): + (JSC::JIT::emitSlow_op_resolve_global_dynamic): + (JSC::JIT::emit_op_new_array): + (JSC::JIT::emitSlow_op_new_array): + (JSC::JIT::emit_op_new_array_buffer): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_new_object): + (JSC::JIT::emit_op_strcat): + (JSC::JIT::emit_op_ensure_property_exists): + (JSC::JIT::emit_op_resolve_skip): + (JSC::JIT::emitSlow_op_resolve_global): + (JSC::JIT::emit_op_resolve_with_base): + (JSC::JIT::emit_op_resolve_with_this): + (JSC::JIT::emit_op_jmp_scopes): + (JSC::JIT::emit_op_switch_imm): + (JSC::JIT::emit_op_switch_char): + (JSC::JIT::emit_op_switch_string): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::emit_op_put_by_index): + * jit/JITStubCall.h: + (JITStubCall): + (JSC::JITStubCall::addArgument): + +2012-03-07 Simon Hausmann <simon.hausmann@nokia.com> + + ARM build fix. + + Reviewed by Zoltan Herczeg. + + Implement three-argument branch(Add,Sub)32. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::add32): + (MacroAssemblerARM): + (JSC::MacroAssemblerARM::sub32): + (JSC::MacroAssemblerARM::branchAdd32): + (JSC::MacroAssemblerARM::branchSub32): + +2012-03-07 Andy Wingo <wingo@igalia.com> + + Parser: Inline ScopeNodeData into ScopeNode + https://bugs.webkit.org/show_bug.cgi?id=79776 + + Reviewed by Geoffrey Garen. + + It used to be that some ScopeNode members were kept in a separate + structure because sometimes they wouldn't be needed, and + allocating a ParserArena was expensive. This patch makes + ParserArena lazily allocate its IdentifierArena, allowing the + members to be included directly, which is simpler and easier to + reason about. + + * parser/ParserArena.cpp: + (JSC::ParserArena::ParserArena): + (JSC::ParserArena::reset): + (JSC::ParserArena::isEmpty): + * parser/ParserArena.h: + (JSC::ParserArena::identifierArena): Lazily allocate the + IdentifierArena. + + * parser/Nodes.cpp: + (JSC::ScopeNode::ScopeNode): + (JSC::ScopeNode::singleStatement): + (JSC::ProgramNode::create): + (JSC::EvalNode::create): + (JSC::FunctionBodyNode::create): + * parser/Nodes.h: + (JSC::ScopeNode::destroyData): + (JSC::ScopeNode::needsActivationForMoreThanVariables): + (JSC::ScopeNode::needsActivation): + (JSC::ScopeNode::hasCapturedVariables): + (JSC::ScopeNode::capturedVariableCount): + (JSC::ScopeNode::captures): + (JSC::ScopeNode::varStack): + (JSC::ScopeNode::functionStack): + (JSC::ScopeNode::neededConstants): + (ScopeNode): + * bytecompiler/NodesCodegen.cpp: + (JSC::ScopeNode::emitStatementsBytecode): Inline ScopeNodeData + into ScopeNode. Adapt accessors. + +2012-03-06 Eric Seidel <eric@webkit.org> + + Make WTF public headers use fully-qualified include paths and remove ForwardingHeaders/wtf + https://bugs.webkit.org/show_bug.cgi?id=80363 + + Reviewed by Mark Rowe. + + Historically WTF has been part of JavaScriptCore, and on Mac and Windows + its headers have appeared as part of the "private" headers exported by + JavaScriptCore. All of the WTF headers there are "flattened" into a single + private headers directory, and WebCore, WebKit and WebKit2 have used "ForwardingHeaders" + to re-map fully-qualified <wtf/text/Foo.h> includes to simple <JavaScriptCore/Foo.h> includes. + + However, very soon, we are moving the WTF source code out of JavaScriptCore into its + own directory and project. As part of such, the WTF headers will no longer be part of + the JavaScriptCore private interfaces. + In preparation for that, this change makes both the Mac and Win builds export + WTF headers in a non-flattened manner. On Mac, that means into usr/local/include/wtf + (and subdirectories), on Windows for now that means JavaScriptCore/wtf (and subdirectories). + + There are 5 parts to this change. + 1. Updates the JavaScriptCore XCode and VCProj files to actually install these headers + (and header directories) into the appropriate places in the build directory. + 2. Updates JavaScriptCore.xcodeproj to look for these WTF headers in this install location + (WebCore, WebKit, etc. had already been taught to look in previous patches). + 3. Fixes all JavaScriptCore source files, and WTF headers to include WTF headers + using fully qualified paths. + 4. Stops the Mac and Win builds from installing these WTF headers in their old "flattened" location. + 5. Removes WebCore and WebKit ForwardingHeaders/wtf directories now that the flattened headers no longer exist. + + Unfortunately we see no way to do this change in smaller parts, since all of these steps are interdependant. + It is possible there are internal Apple projects which depend on JavaScriptCore/Foo.h working for WTF + headers, those will have to be updated to use <wtf/Foo.h> after this change. + I've discussed this proposed change at length with Mark Rowe, and my understanding is they + are ready for (and interested in) this change happening. + + * API/tests/JSNode.c: + * API/tests/JSNodeList.c: + * Configurations/Base.xcconfig: + * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd: + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/MacroAssemblerCodeRef.h: + * bytecompiler/BytecodeGenerator.h: + * dfg/DFGOperations.cpp: + * heap/GCAssertions.h: + * heap/HandleHeap.h: + * heap/HandleStack.h: + * heap/MarkedSpace.h: + * heap/PassWeak.h: + * heap/Strong.h: + * heap/Weak.h: + * jit/HostCallReturnValue.cpp: + * jit/JIT.cpp: + * jit/JITStubs.cpp: + * jit/ThunkGenerators.cpp: + * parser/Lexer.cpp: + * runtime/Completion.cpp: + * runtime/Executable.cpp: + * runtime/Identifier.h: + * runtime/InitializeThreading.cpp: + * runtime/JSDateMath.cpp: + * runtime/JSGlobalObjectFunctions.cpp: + * runtime/JSStringBuilder.h: + * runtime/JSVariableObject.h: + * runtime/NumberPrototype.cpp: + * runtime/WriteBarrier.h: + * tools/CodeProfile.cpp: + * tools/TieredMMapArray.h: + * wtf/AVLTree.h: + * wtf/Alignment.h: + * wtf/AlwaysInline.h: + * wtf/ArrayBufferView.h: + * wtf/Assertions.h: + * wtf/Atomics.h: + * wtf/Bitmap.h: + * wtf/BoundsCheckedPointer.h: + * wtf/CheckedArithmetic.h: + * wtf/Deque.h: + * wtf/ExportMacros.h: + * wtf/FastAllocBase.h: + * wtf/FastMalloc.h: + * wtf/Float32Array.h: + * wtf/Float64Array.h: + * wtf/Functional.h: + * wtf/HashCountedSet.h: + * wtf/HashFunctions.h: + * wtf/HashMap.h: + * wtf/HashSet.h: + * wtf/HashTable.h: + * wtf/HashTraits.h: + * wtf/Int16Array.h: + * wtf/Int32Array.h: + * wtf/Int8Array.h: + * wtf/IntegralTypedArrayBase.h: + * wtf/ListHashSet.h: + * wtf/MainThread.h: + * wtf/MetaAllocator.h: + * wtf/Noncopyable.h: + * wtf/OwnArrayPtr.h: + * wtf/OwnPtr.h: + * wtf/PackedIntVector.h: + * wtf/ParallelJobs.h: + * wtf/PassOwnArrayPtr.h: + * wtf/PassOwnPtr.h: + * wtf/PassRefPtr.h: + * wtf/PassTraits.h: + * wtf/Platform.h: + * wtf/PossiblyNull.h: + * wtf/RefCounted.h: + * wtf/RefCountedLeakCounter.h: + * wtf/RefPtr.h: + * wtf/RetainPtr.h: + * wtf/SimpleStats.h: + * wtf/Spectrum.h: + * wtf/StdLibExtras.h: + * wtf/TCPageMap.h: + * wtf/TemporaryChange.h: + * wtf/ThreadSafeRefCounted.h: + * wtf/Threading.h: + * wtf/ThreadingPrimitives.h: + * wtf/TypeTraits.h: + * wtf/TypedArrayBase.h: + * wtf/Uint16Array.h: + * wtf/Uint32Array.h: + * wtf/Uint8Array.h: + * wtf/Uint8ClampedArray.h: + * wtf/UnusedParam.h: + * wtf/Vector.h: + * wtf/VectorTraits.h: + * wtf/dtoa/double-conversion.h: + * wtf/dtoa/utils.h: + * wtf/gobject/GRefPtr.h: + * wtf/gobject/GlibUtilities.h: + * wtf/text/AtomicString.h: + * wtf/text/AtomicStringImpl.h: + * wtf/text/CString.h: + * wtf/text/StringConcatenate.h: + * wtf/text/StringHash.h: + * wtf/text/WTFString.h: + * wtf/unicode/CharacterNames.h: + * wtf/unicode/UTF8.h: + * wtf/unicode/glib/UnicodeGLib.h: + * wtf/unicode/qt4/UnicodeQt4.h: + * wtf/unicode/wince/UnicodeWinCE.h: + * wtf/url/api/ParsedURL.h: + * wtf/url/api/URLString.h: + * wtf/wince/FastMallocWinCE.h: + * yarr/YarrJIT.cpp: + +2012-03-06 Gavin Barraclough <barraclough@apple.com> + + Array.prototype functions should throw if delete fails + https://bugs.webkit.org/show_bug.cgi?id=80467 + + Reviewed by Oliver Hunt. + + All calls to [[Delete]] from Array.prototype are specified to pass 'true' as the value of Throw. + In the case of shift/unshift, these are also missing a throw from the 'put' in the implementations + in JSArray.cpp. There are effectively three copies of each of the generic shift/unshift routines, + one in splice, one in ArrayPrototype's shift/unshift methods, and one in JSArray's shift/unshift + routines, for handling arrays with holes. These three copies should be unified. + + * runtime/ArrayPrototype.cpp: + (JSC::shift): + (JSC::unshift): + - Added - shared copies of the shift/unshift functionality. + (JSC::arrayProtoFuncPop): + - should throw if the delete fails. + (JSC::arrayProtoFuncReverse): + - should throw if the delete fails. + (JSC::arrayProtoFuncShift): + (JSC::arrayProtoFuncSplice): + (JSC::arrayProtoFuncUnShift): + - use shift/unshift. + * runtime/JSArray.cpp: + (JSC::JSArray::shiftCount): + (JSC::JSArray::unshiftCount): + - Don't try to handle arrays with holes; return a value indicating + the generic routine should be used instead. + * runtime/JSArray.h: + - declaration for shiftCount/unshiftCount changed. + * tests/mozilla/js1_6/Array/regress-304828.js: + - this was asserting incorrect behaviour. + +2012-03-06 Raphael Kubo da Costa <kubo@profusion.mobi> + + [CMake] Make the removal of transitive library dependencies work with CMake < 2.8.7. + https://bugs.webkit.org/show_bug.cgi?id=80469 + + Reviewed by Antonio Gomes. + + * CMakeLists.txt: Manually set the LINK_INTERFACE_LIBRARIES target + property on the library being created. + +2012-03-06 Yuqiang Xian <yuqiang.xian@intel.com> + + DFG BasicBlock should group the Phi nodes together and separate them + from the other nodes + https://bugs.webkit.org/show_bug.cgi?id=80361 + + Reviewed by Filip Pizlo. + + This would make it more efficient to remove the redundant Phi nodes or + insert new Phi nodes for SSA, besides providing a cleaner BasicBlock structure. + This is performance neutral on SunSpider, V8 and Kraken. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::clobberStructures): + (JSC::DFG::AbstractState::dump): + * dfg/DFGBasicBlock.h: + (JSC::DFG::BasicBlock::BasicBlock): + (BasicBlock): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::addToGraph): + (JSC::DFG::ByteCodeParser::insertPhiNode): + * dfg/DFGCFAPhase.cpp: + (JSC::DFG::CFAPhase::performBlockCFA): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::pureCSE): + (JSC::DFG::CSEPhase::impureCSE): + (JSC::DFG::CSEPhase::globalVarLoadElimination): + (JSC::DFG::CSEPhase::getByValLoadElimination): + (JSC::DFG::CSEPhase::checkFunctionElimination): + (JSC::DFG::CSEPhase::checkStructureLoadElimination): + (JSC::DFG::CSEPhase::getByOffsetLoadElimination): + (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getScopeChainLoadElimination): + (JSC::DFG::CSEPhase::performBlockCSE): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-03-06 Mark Hahnenberg <mhahnenberg@apple.com> + + GCActivityCallback timer should vary with the length of the previous GC + https://bugs.webkit.org/show_bug.cgi?id=80344 + + Reviewed by Geoffrey Garen. + + * heap/Heap.cpp: Gave Heap the ability to keep track of the length of its last + GC length so that the GC Activity Callback can use it. + (JSC::Heap::Heap): + (JSC::Heap::collect): + * heap/Heap.h: + (JSC::Heap::lastGCLength): + (Heap): + * runtime/GCActivityCallbackCF.cpp: + (JSC): + (JSC::DefaultGCActivityCallback::operator()): Use the length of the Heap's last + GC to determine the length of our timer trigger (currently set at 100x the duration + of the last GC). + +2012-03-06 Rob Buis <rbuis@rim.com> + + BlackBerry] Fix cast-align gcc warnings when compiling JSC + https://bugs.webkit.org/show_bug.cgi?id=80420 + + Reviewed by Gavin Barraclough. + + Fix warnings given in Blackberry build. + + * heap/CopiedBlock.h: + (JSC::CopiedBlock::CopiedBlock): + * wtf/RefCountedArray.h: + (WTF::RefCountedArray::Header::fromPayload): + +2012-03-06 Gavin Barraclough <barraclough@apple.com> + + writable/configurable not respected for some properties of Function/String/Arguments + https://bugs.webkit.org/show_bug.cgi?id=80436 + + Reviewed by Oliver Hunt. + + Special properties should behave like regular properties. + + * runtime/Arguments.cpp: + (JSC::Arguments::defineOwnProperty): + - Mis-nested logic for making read-only properties non-live. + * runtime/JSFunction.cpp: + (JSC::JSFunction::put): + - arguments/length/caller are non-writable, non-configurable - reject appropriately. + (JSC::JSFunction::deleteProperty): + - Attempting to delete prototype/caller should fail. + (JSC::JSFunction::defineOwnProperty): + - Ensure prototype is reified on attempt to reify it. + - arguments/length/caller are non-writable, non-configurable - reject appropriately. + * runtime/JSFunction.h: + - added declaration for defineOwnProperty. + (JSFunction): + * runtime/StringObject.cpp: + (JSC::StringObject::put): + - length is non-writable, non-configurable - reject appropriately. + +2012-03-06 Ulan Degenbaev <ulan@chromium.org> + + TypedArray subarray call for subarray does not clamp the end index parameter properly + https://bugs.webkit.org/show_bug.cgi?id=80285 + + Reviewed by Kenneth Russell. + + * wtf/ArrayBufferView.h: + (WTF::ArrayBufferView::calculateOffsetAndLength): + +2012-03-06 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r109837. + http://trac.webkit.org/changeset/109837 + https://bugs.webkit.org/show_bug.cgi?id=80399 + + breaks Mac Productions builds, too late to try and fix it + tonight (Requested by eseidel on #webkit). + + * API/tests/JSNode.c: + * API/tests/JSNodeList.c: + * Configurations/Base.xcconfig: + * JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd: + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/MacroAssemblerCodeRef.h: + * bytecompiler/BytecodeGenerator.h: + * dfg/DFGOperations.cpp: + * heap/GCAssertions.h: + * heap/HandleHeap.h: + * heap/HandleStack.h: + * heap/MarkedSpace.h: + * heap/PassWeak.h: + * heap/Strong.h: + * heap/Weak.h: + * jit/HostCallReturnValue.cpp: + * jit/JIT.cpp: + * jit/JITStubs.cpp: + * jit/ThunkGenerators.cpp: + * parser/Lexer.cpp: + * runtime/Completion.cpp: + * runtime/Executable.cpp: + * runtime/Identifier.h: + * runtime/InitializeThreading.cpp: + * runtime/JSDateMath.cpp: + * runtime/JSGlobalObjectFunctions.cpp: + * runtime/JSStringBuilder.h: + * runtime/JSVariableObject.h: + * runtime/NumberPrototype.cpp: + * runtime/WriteBarrier.h: + * tools/CodeProfile.cpp: + * tools/TieredMMapArray.h: + * yarr/YarrJIT.cpp: + +2012-03-06 Zoltan Herczeg <zherczeg@webkit.org> + + [Qt][ARM] Speculative buildfix after r109834. + + Reviewed by Csaba Osztrogonác. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::and32): + (MacroAssemblerARM): + +2012-03-05 Gavin Barraclough <barraclough@apple.com> + + Unreviewed windows build fix pt 2. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-05 Gavin Barraclough <barraclough@apple.com> + + Unreviewed windows build fix pt 1. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-05 Gavin Barraclough <barraclough@apple.com> + + putByIndex should throw in strict mode + https://bugs.webkit.org/show_bug.cgi?id=80335 + + Reviewed by Filip Pizlo. + + Make the MethodTable PutByIndex trap take a boolean 'shouldThrow' parameter. + + This is a largely mechanical change, simply adding an extra parameter to a number + of functions. Some call sites need perform additional exception checks, and + operationPutByValBeyondArrayBounds needs to know whether it is strict or not. + + This patch doesn't fix a missing throw from some cases of shift/unshift (this is + an existing bug), I'll follow up with a third patch to handle that. + + * API/JSObjectRef.cpp: + (JSObjectSetPropertyAtIndex): + * JSCTypedArrayStubs.h: + (JSC): + * dfg/DFGOperations.cpp: + (JSC::DFG::putByVal): + * dfg/DFGOperations.h: + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * jsc.cpp: + (GlobalObject::finishCreation): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * runtime/Arguments.cpp: + (JSC::Arguments::putByIndex): + * runtime/Arguments.h: + (Arguments): + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncPush): + (JSC::arrayProtoFuncReverse): + (JSC::arrayProtoFuncShift): + (JSC::arrayProtoFuncSort): + (JSC::arrayProtoFuncSplice): + (JSC::arrayProtoFuncUnShift): + * runtime/ClassInfo.h: + (MethodTable): + * runtime/JSArray.cpp: + (JSC::SparseArrayValueMap::put): + (JSC::JSArray::put): + (JSC::JSArray::putByIndex): + (JSC::JSArray::putByIndexBeyondVectorLength): + (JSC::JSArray::push): + (JSC::JSArray::shiftCount): + (JSC::JSArray::unshiftCount): + * runtime/JSArray.h: + (SparseArrayValueMap): + (JSArray): + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::putByIndex): + * runtime/JSByteArray.h: + (JSByteArray): + * runtime/JSCell.cpp: + (JSC::JSCell::putByIndex): + * runtime/JSCell.h: + (JSCell): + * runtime/JSNotAnObject.cpp: + (JSC::JSNotAnObject::putByIndex): + * runtime/JSNotAnObject.h: + (JSNotAnObject): + * runtime/JSONObject.cpp: + (JSC::Walker::walk): + * runtime/JSObject.cpp: + (JSC::JSObject::putByIndex): + * runtime/JSObject.h: + (JSC::JSValue::putByIndex): + * runtime/RegExpConstructor.cpp: + (JSC::RegExpMatchesArray::fillArrayInstance): + * runtime/RegExpMatchesArray.h: + (JSC::RegExpMatchesArray::putByIndex): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncSplit): + +2012-03-05 Yuqiang Xian <yuqiang.xian@intel.com> + + PredictNone is incorrectly treated as isDoublePrediction + https://bugs.webkit.org/show_bug.cgi?id=80365 + + Reviewed by Filip Pizlo. + + Also it is incorrectly treated as isFixedIndexedStorageObjectPrediction. + + * bytecode/PredictedType.h: + (JSC::isFixedIndexedStorageObjectPrediction): + (JSC::isDoublePrediction): + +2012-03-05 Filip Pizlo <fpizlo@apple.com> + + The LLInt should work even when the JIT is disabled + https://bugs.webkit.org/show_bug.cgi?id=80340 + <rdar://problem/10922235> + + Reviewed by Gavin Barraclough. + + * assembler/MacroAssemblerCodeRef.h: + (JSC::MacroAssemblerCodePtr::createLLIntCodePtr): + (MacroAssemblerCodeRef): + (JSC::MacroAssemblerCodeRef::createLLIntCodeRef): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::initialize): + (JSC::Interpreter::execute): + (JSC::Interpreter::executeCall): + (JSC::Interpreter::executeConstruct): + * jit/JIT.h: + (JSC::JIT::compileCTINativeCall): + * jit/JITStubs.h: + (JSC::JITThunks::ctiNativeCall): + (JSC::JITThunks::ctiNativeConstruct): + * llint/LLIntEntrypoints.cpp: + (JSC::LLInt::getFunctionEntrypoint): + (JSC::LLInt::getEvalEntrypoint): + (JSC::LLInt::getProgramEntrypoint): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + (LLInt): + * llint/LLIntSlowPaths.h: + (LLInt): + * llint/LowLevelInterpreter.h: + * llint/LowLevelInterpreter32_64.asm: + * runtime/Executable.h: + (NativeExecutable): + (JSC::NativeExecutable::create): + (JSC::NativeExecutable::finishCreation): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + (JSGlobalData): + * runtime/Options.cpp: + (Options): + (JSC::Options::parse): + (JSC::Options::initializeOptions): + * runtime/Options.h: + (Options): + * wtf/Platform.h: + +2012-03-05 Yuqiang Xian <yuqiang.xian@intel.com> + + Checks for dead variables are not sufficient when fixing the expected + values in DFG OSR entry + https://bugs.webkit.org/show_bug.cgi?id=80371 + + Reviewed by Filip Pizlo. + + A dead variable should be identified when there's no node referencing it. + But we currently failed to catch the case where there are some nodes + referencing a variable but those nodes are actually not referenced by + others so will be ignored in code generation. In such case we should + also consider that variable to be a dead variable in the block and fix + the expected values. + This is performance neutral on SunSpider, V8 and Kraken. + + * dfg/DFGJITCompiler.h: + (JSC::DFG::JITCompiler::noticeOSREntry): + +2012-03-05 Oliver Hunt <oliver@apple.com> + + Fix Qt build. + + * assembler/AbstractMacroAssembler.h: + * assembler/MacroAssembler.h: + (MacroAssembler): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileArithSub): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emitSub32Constant): + +2012-03-05 Eric Seidel <eric@webkit.org> + + Update JavaScriptCore files to use fully-qualified WTF include paths + https://bugs.webkit.org/show_bug.cgi?id=79960 + + Reviewed by Adam Barth. + + This change does 5 small/related things: + 1. Updates JavaScriptCore.xcodeproj to install WTF headers into $BUILD/usr/local/include + (WebCore, WebKit were already setup to look there, but JavaScriptCore.xcodeproj + was not installing headers there.) + 2. Makes JavaScriptCore targets include $BUILD/usr/local/include in their + header search path, as that's where the WTF headers will be installed. + 3. Similarly updates JavaScriptCore.vcproj/copy-files.cmd to copy WTF headers to PrivateHeaders/wtf/* + in addition to the current behavior of flattening all headers to PrivateHeaders/*.h. + 4. Updates a bunch of JSC files to use #include <wtf/Foo.h> instead of #include "Foo.h" + since soon the WTF headers will not be part of the JavaScriptCore Xcode project. + 5. Makes build-webkit build the WTF XCode project by default. + + * API/tests/JSNode.c: + * API/tests/JSNodeList.c: + * Configurations/Base.xcconfig: + * assembler/MacroAssemblerCodeRef.h: + * bytecompiler/BytecodeGenerator.h: + * dfg/DFGOperations.cpp: + * heap/GCAssertions.h: + * heap/HandleHeap.h: + * heap/HandleStack.h: + * heap/MarkedSpace.h: + * heap/PassWeak.h: + * heap/Strong.h: + * heap/Weak.h: + * jit/HostCallReturnValue.cpp: + * jit/JIT.cpp: + * jit/JITStubs.cpp: + * jit/ThunkGenerators.cpp: + * parser/Lexer.cpp: + * runtime/Completion.cpp: + * runtime/Executable.cpp: + * runtime/Identifier.h: + * runtime/InitializeThreading.cpp: + * runtime/JSDateMath.cpp: + * runtime/JSGlobalObjectFunctions.cpp: + * runtime/JSStringBuilder.h: + * runtime/JSVariableObject.h: + * runtime/NumberPrototype.cpp: + * runtime/WriteBarrier.h: + * tools/CodeProfile.cpp: + * tools/TieredMMapArray.h: + * yarr/YarrJIT.cpp: + +2012-03-05 Oliver Hunt <oliver@apple.com> + + Add basic support for constant blinding to the JIT + https://bugs.webkit.org/show_bug.cgi?id=80354 + + Reviewed by Filip Pizlo. + + This patch adds basic constant blinding support to the JIT, at the + MacroAssembler level. This means all JITs in JSC (Yarr, baseline, and DFG) + get constant blinding. Woo! + + This patch only introduces blinding for Imm32, a later patch will do similar + for ImmPtr. In order to make misuse of Imm32 as a trusted type essentially + impossible, we make TrustedImm32 a private parent of Imm32 and add an explicit + accessor that's needed to access the actual value. This also means you cannot + accidentally pass an untrusted value to a function that does not perform + blinding. + + To make everything work sensibly, this patch also corrects some code that was using + Imm32 when TrustedImm32 could be used, and refactors a few callers that use + untrusted immediates, so that they call slightly different varaints of the functions + that they used previously. This is largely necessary to deal with x86-32 not having + sufficient registers to handle the additional work required when we choose to blind + a constant. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::Imm32::asTrustedImm32): + (Imm32): + (JSC::AbstractMacroAssembler::beginUninterruptedSequence): + (JSC::AbstractMacroAssembler::endUninterruptedSequence): + (JSC::AbstractMacroAssembler::AbstractMacroAssembler): + (AbstractMacroAssembler): + (JSC::AbstractMacroAssembler::inUninterruptedSequence): + (JSC::AbstractMacroAssembler::random): + (JSC::AbstractMacroAssembler::scratchRegisterForBlinding): + (JSC::AbstractMacroAssembler::shouldBlindForSpecificArch): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::addressForPoke): + (MacroAssembler): + (JSC::MacroAssembler::poke): + (JSC::MacroAssembler::branchPtr): + (JSC::MacroAssembler::branch32): + (JSC::MacroAssembler::convertInt32ToDouble): + (JSC::MacroAssembler::shouldBlind): + (JSC::MacroAssembler::BlindedImm32::BlindedImm32): + (BlindedImm32): + (JSC::MacroAssembler::keyForConstant): + (JSC::MacroAssembler::xorBlindConstant): + (JSC::MacroAssembler::additionBlindedConstant): + (JSC::MacroAssembler::andBlindedConstant): + (JSC::MacroAssembler::orBlindedConstant): + (JSC::MacroAssembler::loadXorBlindedConstant): + (JSC::MacroAssembler::add32): + (JSC::MacroAssembler::addPtr): + (JSC::MacroAssembler::and32): + (JSC::MacroAssembler::andPtr): + (JSC::MacroAssembler::move): + (JSC::MacroAssembler::or32): + (JSC::MacroAssembler::store32): + (JSC::MacroAssembler::sub32): + (JSC::MacroAssembler::subPtr): + (JSC::MacroAssembler::xor32): + (JSC::MacroAssembler::branchAdd32): + (JSC::MacroAssembler::branchMul32): + (JSC::MacroAssembler::branchSub32): + (JSC::MacroAssembler::trustedImm32ForShift): + (JSC::MacroAssembler::lshift32): + (JSC::MacroAssembler::rshift32): + (JSC::MacroAssembler::urshift32): + * assembler/MacroAssemblerARMv7.h: + (MacroAssemblerARMv7): + (JSC::MacroAssemblerARMv7::scratchRegisterForBlinding): + (JSC::MacroAssemblerARMv7::shouldBlindForSpecificArch): + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::branchSubPtr): + (MacroAssemblerX86_64): + (JSC::MacroAssemblerX86_64::scratchRegisterForBlinding): + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::linkOSRExits): + (JSC::DFG::JITCompiler::compileBody): + (JSC::DFG::JITCompiler::compileFunction): + * dfg/DFGOSRExitCompiler32_64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * dfg/DFGOSRExitCompiler64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + (JSC::DFG::SpeculativeJIT::compileArithSub): + (JSC::DFG::SpeculativeJIT::compileStrictEqForConstant): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::emitCall): + (JSC::DFG::SpeculativeJIT::compileObjectEquality): + (JSC::DFG::SpeculativeJIT::compileDoubleCompare): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::emitCall): + (JSC::DFG::SpeculativeJIT::compileDoubleCompare): + (JSC::DFG::SpeculativeJIT::compile): + * jit/JIT.cpp: + (JSC::JIT::privateCompileSlowCases): + (JSC::JIT::privateCompile): + * jit/JITArithmetic.cpp: + (JSC::JIT::compileBinaryArithOp): + (JSC::JIT::emit_op_add): + (JSC::JIT::emit_op_mul): + (JSC::JIT::emit_op_div): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emitAdd32Constant): + (JSC::JIT::emitSub32Constant): + (JSC::JIT::emitBinaryDoubleOp): + (JSC::JIT::emitSlow_op_mul): + (JSC::JIT::emit_op_div): + * jit/JITCall.cpp: + (JSC::JIT::compileLoadVarargs): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileLoadVarargs): + * jit/JITInlineMethods.h: + (JSC::JIT::updateTopCallFrame): + (JSC::JIT::emitValueProfilingSite): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emitSlow_op_jfalse): + (JSC::JIT::emitSlow_op_jtrue): + * jit/JITStubCall.h: + (JITStubCall): + (JSC::JITStubCall::addArgument): + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::backtrack): + +2012-03-05 Gavin Barraclough <barraclough@apple.com> + + putByIndex should throw in strict mode + https://bugs.webkit.org/show_bug.cgi?id=80335 + + Reviewed by Filip Pizlo. + + We'll need to pass an additional parameter. + + Part 1 - rename JSValue::put() for integer indices to JSValue::putByIndex() + to match the method in the MethodTable, make this take a parameter indicating + whether the put should throw. This fixes the cases where the base of the put + is a primitive. + + * dfg/DFGOperations.cpp: + (DFG): + (JSC::DFG::putByVal): + (JSC::DFG::operationPutByValInternal): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * runtime/JSObject.h: + (JSC::JSValue::putByIndex): + * runtime/JSValue.cpp: + (JSC): + * runtime/JSValue.h: + (JSValue): + +2012-03-05 Sam Weinig <sam@webkit.org> + + Add support for hosting layers in the window server in WebKit2 + <rdar://problem/10400246> + https://bugs.webkit.org/show_bug.cgi?id=80310 + + Reviewed by Anders Carlsson. + + * wtf/Platform.h: + Add HAVE_LAYER_HOSTING_IN_WINDOW_SERVER. + +2012-03-05 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, attempted build fix for !ENABLE(JIT) after r109705. + + * bytecode/ExecutionCounter.cpp: + (JSC::ExecutionCounter::applyMemoryUsageHeuristics): + * bytecode/ExecutionCounter.h: + +2012-03-05 Patrick Gansterer <paroga@webkit.org> + + Unreviewed. Build fix for !ENABLE(JIT) after r109705. + + * bytecode/ExecutionCounter.cpp: + * bytecode/ExecutionCounter.h: + +2012-03-05 Andy Wingo <wingo@igalia.com> + + Lexer: Specialize character predicates for LChar, UChar + https://bugs.webkit.org/show_bug.cgi?id=79677 + + Reviewed by Oliver Hunt. + + This patch specializes isIdentStart, isIdentPart, isWhiteSpace, + and isLineTerminator to perform a more limited number of checks if + the lexer is being instantiated to work on LChar sequences. This + is about a 1.5% win on the --parse-only suite, here. + + * parser/Lexer.cpp: + (JSC::isLatin1): New static helper, specialized for LChar and + UChar. + (JSC::typesOfLatin1Characters): Rename from + typesOfASCIICharacters, and expand to the range of the LChar + type. All uses of isASCII are changed to use isLatin1. Generated + using libunistring. + (JSC::isNonLatin1IdentStart): + (JSC::isIdentStart): + (JSC::isNonLatin1IdentPart): + (JSC::isIdentPart): + (JSC::Lexer::shiftLineTerminator): + (JSC::Lexer::parseIdentifier): + (JSC::Lexer::parseIdentifierSlowCase): + (JSC::Lexer::parseStringSlowCase): + (JSC::Lexer::parseMultilineComment): + (JSC::Lexer::lex): + (JSC::Lexer::scanRegExp): + (JSC::Lexer::skipRegExp): Sprinkle static_cast<T>(_) around. + * parser/Lexer.h: + (JSC::Lexer::isWhiteSpace): + (JSC::Lexer::isLineTerminator): + * KeywordLookupGenerator.py: + (Trie.printAsC): Declare specialized isIdentPart static functions. + +2012-03-05 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck. + + * GNUmakefile.list.am: Add missing header file. + +2012-03-05 Andy Wingo <wingo@igalia.com> + + WTF: Micro-optimize cleanup of empty vectors and hash tables + https://bugs.webkit.org/show_bug.cgi?id=79903 + + Reviewed by Michael Saboff and Geoffrey Garen. + + This patch speeds up cleanup of vectors and hash tables whose + backing store was never allocated. This is the case by default + for most vectors / hash tables that never had any entries added. + + The result for me is that calling checkSyntax 1000 times on + concat-jquery-mootools-prototype.js goes from 6.234s to 6.068s, a + 2.4% speedup. + + * wtf/HashTable.h: + (WTF::HashTable::~HashTable): + (WTF::::clear): Don't deallocate the storage or frob member + variables if there is no backing storage. + * wtf/Vector.h: + (WTF::VectorBufferBase::deallocateBuffer): Likewise. + +2012-03-04 Filip Pizlo <fpizlo@apple.com> + + JIT heuristics should be hyperbolic + https://bugs.webkit.org/show_bug.cgi?id=80055 + <rdar://problem/10922260> + + Reviewed by Oliver Hunt. + + Added tracking of the amount of executable memory typically used for a bytecode + instruction. Modified the execution counter scheme to use this, and the amount + of free memory, to determine how long to wait before invoking the JIT. + + The result is that even if we bomb the VM with more code than can fit in our + executable memory pool, we still keep running and almost never run out of + executable memory - which ensures that if we have to JIT something critical, then + we'll likely have enough memory to do so. This also does not regress performance + on the three main benchmarks. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::predictedMachineCodeSize): + (JSC): + (JSC::CodeBlock::usesOpcode): + * bytecode/CodeBlock.h: + (CodeBlock): + (JSC::CodeBlock::checkIfJITThresholdReached): + (JSC::CodeBlock::dontJITAnytimeSoon): + (JSC::CodeBlock::jitAfterWarmUp): + (JSC::CodeBlock::jitSoon): + (JSC::CodeBlock::llintExecuteCounter): + (JSC::CodeBlock::counterValueForOptimizeAfterWarmUp): + (JSC::CodeBlock::counterValueForOptimizeAfterLongWarmUp): + (JSC::CodeBlock::addressOfJITExecuteCounter): + (JSC::CodeBlock::offsetOfJITExecuteCounter): + (JSC::CodeBlock::offsetOfJITExecutionActiveThreshold): + (JSC::CodeBlock::offsetOfJITExecutionTotalCount): + (JSC::CodeBlock::jitExecuteCounter): + (JSC::CodeBlock::checkIfOptimizationThresholdReached): + (JSC::CodeBlock::optimizeNextInvocation): + (JSC::CodeBlock::dontOptimizeAnytimeSoon): + (JSC::CodeBlock::optimizeAfterWarmUp): + (JSC::CodeBlock::optimizeAfterLongWarmUp): + (JSC::CodeBlock::optimizeSoon): + * bytecode/ExecutionCounter.cpp: Added. + (JSC): + (JSC::ExecutionCounter::ExecutionCounter): + (JSC::ExecutionCounter::checkIfThresholdCrossedAndSet): + (JSC::ExecutionCounter::setNewThreshold): + (JSC::ExecutionCounter::deferIndefinitely): + (JSC::ExecutionCounter::applyMemoryUsageHeuristics): + (JSC::ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt): + (JSC::ExecutionCounter::hasCrossedThreshold): + (JSC::ExecutionCounter::setThreshold): + (JSC::ExecutionCounter::reset): + * bytecode/ExecutionCounter.h: Added. + (JSC): + (ExecutionCounter): + (JSC::ExecutionCounter::formattedTotalCount): + * dfg/DFGOSRExitCompiler32_64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * dfg/DFGOSRExitCompiler64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * jit/ExecutableAllocator.cpp: + (JSC::DemandExecutableAllocator::allocateNewSpace): + (JSC::ExecutableAllocator::underMemoryPressure): + (JSC): + (JSC::ExecutableAllocator::memoryPressureMultiplier): + * jit/ExecutableAllocator.h: + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::ExecutableAllocator::memoryPressureMultiplier): + (JSC): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::jitCompileAndSetHeuristics): + * llint/LowLevelInterpreter32_64.asm: + * runtime/JSGlobalData.h: + (JSGlobalData): + * runtime/Options.cpp: + (Options): + (JSC::Options::initializeOptions): + * runtime/Options.h: + (Options): + * wtf/SimpleStats.h: Added. + (WTF): + (SimpleStats): + (WTF::SimpleStats::SimpleStats): + (WTF::SimpleStats::add): + (WTF::SimpleStats::operator!): + (WTF::SimpleStats::count): + (WTF::SimpleStats::sum): + (WTF::SimpleStats::sumOfSquares): + (WTF::SimpleStats::mean): + (WTF::SimpleStats::variance): + (WTF::SimpleStats::standardDeviation): + +2012-03-04 Raphael Kubo da Costa <kubo@profusion.mobi> + + [CMake] Libraries are installed to /usr/lib and not /usr/lib64 on x86_64 + https://bugs.webkit.org/show_bug.cgi?id=71507 + + Reviewed by Antonio Gomes. + + * CMakeLists.txt: Use ${LIB_INSTALL_DIR} instead of hardcoding "lib". + +2012-03-04 David Kilzer <ddkilzer@apple.com> + + Fix build when the classic interpreter is enabled + + Reviewed by Gavin Barraclough. + + Fixes the following build error when running the "Generate + Derived Sources" build phase script: + + offlineasm: Parsing JavaScriptCore/llint/LowLevelInterpreter.asm and ../../JSCLLIntOffsetsExtractor and creating assembly file LLIntAssembly.h. + ./JavaScriptCore/offlineasm/offsets.rb:145:in `offsetsAndConfigurationIndex': unhandled exception + from JavaScriptCore/offlineasm/asm.rb:131 + Command /bin/sh failed with exit code 1 + + Gavin's fix in r109674 avoided the #error statement in + JITStubs.h when compiling LLIntOffsetsExtractor.cpp, but it + caused the "Generate Derived Sources" build phase script to fail + when JavaScriptCore/offlineasm/asm.rb was run. The solution is + to detect when the classic interpreter is being built and simply + exit early from asm.rb in that case. + + * llint/LLIntOffsetsExtractor.cpp: + (JSC::LLIntOffsetsExtractor::dummy): Return NULL pointer if the + JIT is disabled. Note that offsets.rb doesn't care about the + return value here, but instead it cares about finding the magic + values in the binary. The magic values are no longer present + when the JIT is disabled. + * offlineasm/asm.rb: Catch MissingMagicValuesException and exit + early with a status message. + * offlineasm/offsets.rb: + (MissingMagicValuesException): Add new exception class. + (offsetsAndConfigurationIndex): Throw + MissingMagicValuesException when no magic values are found. + +2012-03-04 Jurij Smakov <jurij@wooyd.org> + + SPARC also needs aligned accesses. + + Rubber-stamped by Gustavo Noronha Silva. + + * wtf/Platform.h: + +2012-03-04 Gavin Barraclough <barraclough@apple.com> + + Unreviewed build fix. + + * jit/JITStubs.h: + - Move ENABLE(JIT) to head of file. + +2012-03-03 Gavin Barraclough <barraclough@apple.com> + + Split JSArray's [[Put]] & [[DefineOwnProperty]] traps. + https://bugs.webkit.org/show_bug.cgi?id=80217 + + Reviewed by Filip Pizlo. + + putByIndex() provides similar behavior to put(), but for indexed property names. + Many places in ArrayPrototype call putByIndex() where they really mean to call + [[DefineOwnProperty]]. This is only okay due to a bug – putByIndex should be + calling numeric accessors (& respecting numeric read only properties) on the + prototype chain, but isn't. Add a new putDirectIndex (matching JSObject's + putDirect* methods), to correctly provide a fast [[DefineOwnProperty]] interface. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncConcat): + (JSC::arrayProtoFuncSlice): + (JSC::arrayProtoFuncFilter): + (JSC::arrayProtoFuncMap): + * runtime/JSArray.cpp: + (JSC): + (JSC::reject): + (JSC::SparseArrayValueMap::putDirect): + (JSC::JSArray::defineOwnNumericProperty): + (JSC::JSArray::putByIndexBeyondVectorLength): + (JSC::JSArray::putDirectIndexBeyondVectorLength): + * runtime/JSArray.h: + (SparseArrayValueMap): + (JSArray): + (JSC::JSArray::putDirectIndex): + +2012-03-03 Benjamin Poulain <benjamin@webkit.org> + + Implement the basis of KURLWTFURL + https://bugs.webkit.org/show_bug.cgi?id=79600 + + Reviewed by Adam Barth. + + Add an API to know if a ParsedURL is valid. + + * wtf/url/api/ParsedURL.cpp: + (WTF::ParsedURL::ParsedURL): + (WTF): + (WTF::ParsedURL::isolatedCopy): This is needed by APIs moving URL objects between thread + and by KURL's detach() on write. + (WTF::ParsedURL::baseAsString): + (WTF::ParsedURL::segment): + Add a stronger constraint on accessors: the client of this API should never ask for the segments + on an invalid URL. + * wtf/url/api/ParsedURL.h: + (WTF): + (WTF::ParsedURL::ParsedURL): + (ParsedURL): + (WTF::ParsedURL::isValid): + +2012-03-03 Hans Wennborg <hans@chromium.org> + + Implement Speech JavaScript API + https://bugs.webkit.org/show_bug.cgi?id=80019 + + Reviewed by Adam Barth. + + Add ENABLE_SCRIPTED_SPEECH. + + * Configurations/FeatureDefines.xcconfig: + +2012-03-02 Filip Pizlo <fpizlo@apple.com> + + When getting the line number of a call into a call frame with no code block, it's + incorrect to rely on the returnPC + https://bugs.webkit.org/show_bug.cgi?id=80195 + + Reviewed by Oliver Hunt. + + * interpreter/Interpreter.cpp: + (JSC::getCallerInfo): + * jit/JITCall.cpp: + (JSC::JIT::compileLoadVarargs): + +2012-03-02 Han Hojong <hojong.han@samsung.com> + + Expected results updated for checking type conversion + https://bugs.webkit.org/show_bug.cgi?id=80138 + + Reviewed by Gavin Barraclough. + + * tests/mozilla/ecma/TypeConversion/9.3.1-3.js: + +2012-03-02 Kenichi Ishibashi <bashi@chromium.org> + + Adding WebSocket per-frame DEFLATE extension + https://bugs.webkit.org/show_bug.cgi?id=77522 + + Added USE(ZLIB) flag. + + Reviewed by Kent Tamura. + + * wtf/Platform.h: + +2012-03-02 Filip Pizlo <fpizlo@apple.com> + + Unreviewed build fix for platforms that have DFG_JIT disabled but PARALLEL_GC enabled. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::visitAggregate): + +2012-03-01 Filip Pizlo <fpizlo@apple.com> + + DFGCodeBlocks should not trace CodeBlocks that are also going to be traced by + virtue of being in the transitive closure + https://bugs.webkit.org/show_bug.cgi?id=80098 + + Reviewed by Anders Carlsson. + + If DFGCodeBlocks traces a CodeBlock that might also be traced via its owner Executable, + then you might have the visitAggregate() method called concurrently by multiple threads. + This is benign on 64-bit -- visitAggregate() and everything it calls turns out to be + racy and slightly imprecise but not unsound. But on 32-bit, visitAggregate() may crash + due to word tearing in ValueProfile bucket updates inside of computeUpdatedPrediction(). + + It would seem that the fix is just to have DFGCodeBlocks not trace CodeBlocks that are + not jettisoned. But CodeBlocks may be jettisoned later during the GC, so it must trace + any CodeBlock that it knows to be live by virtue of it being reachable from the stack. + Hence the real fix is to make sure that concurrent calls into CodeBlock::visitAggregate() + don't lead to two threads racing over each other as they clobber state. This patch + achieves this with a simple CAS loop: whichever thread wins the CAS race (which is + trivially linearizable) will get to trace the CodeBlock; all other threads give up and + go home. + + Unfortunately there will be no new tests. It's possible to reproduce this maybe 1/10 + times by running V8-v6's raytrace repeatedly, using the V8 harness hacked to rerun it + even when it's gotten sufficient counts. But that takes a while - sometimes up to a + minute to get a crash. I have no other reliable repro case. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::visitAggregate): + * bytecode/CodeBlock.h: + (DFGData): + * heap/DFGCodeBlocks.cpp: + (JSC::DFGCodeBlocks::clearMarks): + +2012-03-01 Filip Pizlo <fpizlo@apple.com> + + The JIT should not crash the entire process just because there is not enough executable + memory, if the LLInt is enabled + https://bugs.webkit.org/show_bug.cgi?id=79962 + + Reviewed by Csaba Osztrogonác. + + Fix for ARM, SH4. + + * assembler/AssemblerBufferWithConstantPool.h: + (JSC::AssemblerBufferWithConstantPool::executableCopy): + +2012-03-01 Ryosuke Niwa <rniwa@webkit.org> + + Revert my change. Broke builds. + Source/JavaScriptCore/wtf/Atomics.h:188: error: redefinition of 'bool WTF::weakCompareAndSwap(volatile uintptr_t*, uintptr_t, uintptr_t)' + Source/JavaScriptCore/wtf/Atomics.h:122: error: 'bool WTF::weakCompareAndSwap(volatile unsigned int*, unsigned int, unsigned i + + * wtf/Atomics.h: + (WTF): + (WTF::weakCompareAndSwap): + +2012-03-01 Ryosuke Niwa <rniwa@webkit.org> + + Gcc build fix. + + Rubber-stamped by Filip Pizlo. + + * wtf/Atomics.h: + (WTF): + (WTF::weakCompareAndSwap): + +2012-03-01 Gavin Barraclough <barraclough@apple.com> + + ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller + https://bugs.webkit.org/show_bug.cgi?id=80011 + + Reviewed by Oliver Hunt. + + Also, fix getting the caller from within a bound function, for within a getter, + or setter (make our implementation match other browsers). + + * interpreter/Interpreter.cpp: + (JSC::getCallerInfo): + - Allow this to get the caller of host functions. + (JSC::Interpreter::retrieveCallerFromVMCode): + - This should use getCallerInfo, and should skip over function bindings. + * runtime/JSFunction.cpp: + (JSC::JSFunction::callerGetter): + - This should never return a strict-mode function. + +2012-03-01 Yuqiang Xian <yuqiang.xian@intel.com> + + DFG local CSE for a node can be terminated earlier + https://bugs.webkit.org/show_bug.cgi?id=80014 + + Reviewed by Filip Pizlo. + + When one of the node's childredn is met in the process of back traversing + the nodes, we don't need to traverse the remaining nodes. + This is performance neutral on SunSpider, V8 and Kraken. + + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::pureCSE): + (JSC::DFG::CSEPhase::impureCSE): + (JSC::DFG::CSEPhase::getByValLoadElimination): + (JSC::DFG::CSEPhase::checkFunctionElimination): + (JSC::DFG::CSEPhase::checkStructureLoadElimination): + (JSC::DFG::CSEPhase::getByOffsetLoadElimination): + (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): + +2012-02-29 Yuqiang Xian <yuqiang.xian@intel.com> + + DFG BasicBlocks should not require that their nodes have continuous indices in the graph + https://bugs.webkit.org/show_bug.cgi?id=79899 + + Reviewed by Filip Pizlo. + + This will make it more convenient to insert nodes into the DFG. + With this capability we now place the Phi nodes in the corresponding + blocks. + Local CSE is modified to not to rely on the assumption of continuous + node indices in a block. + This is performance neutral on SunSpider, V8 and Kraken. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::AbstractState): + (JSC::DFG::AbstractState::beginBasicBlock): + (JSC::DFG::AbstractState::execute): + (JSC::DFG::AbstractState::clobberStructures): + (JSC::DFG::AbstractState::mergeToSuccessors): + (JSC::DFG::AbstractState::dump): + * dfg/DFGAbstractState.h: + (JSC::DFG::AbstractState::forNode): + (AbstractState): + * dfg/DFGArithNodeFlagsInferencePhase.cpp: + (ArithNodeFlagsInferencePhase): + * dfg/DFGBasicBlock.h: + (JSC::DFG::BasicBlock::BasicBlock): + (BasicBlock): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::addToGraph): + (ByteCodeParser): + (JSC::DFG::ByteCodeParser::insertPhiNode): + (JSC::DFG::ByteCodeParser::handleInlining): + (JSC::DFG::ByteCodeParser::parseBlock): + (JSC::DFG::ByteCodeParser::processPhiStack): + (JSC::DFG::ByteCodeParser::linkBlock): + (JSC::DFG::ByteCodeParser::determineReachability): + (JSC::DFG::ByteCodeParser::parseCodeBlock): + * dfg/DFGCFAPhase.cpp: + (JSC::DFG::CFAPhase::performBlockCFA): + (CFAPhase): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::CSEPhase): + (JSC::DFG::CSEPhase::endIndexForPureCSE): + (JSC::DFG::CSEPhase::pureCSE): + (JSC::DFG::CSEPhase::impureCSE): + (JSC::DFG::CSEPhase::globalVarLoadElimination): + (JSC::DFG::CSEPhase::getByValLoadElimination): + (JSC::DFG::CSEPhase::checkFunctionElimination): + (JSC::DFG::CSEPhase::checkStructureLoadElimination): + (JSC::DFG::CSEPhase::getByOffsetLoadElimination): + (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getScopeChainLoadElimination): + (JSC::DFG::CSEPhase::performNodeCSE): + (JSC::DFG::CSEPhase::performBlockCSE): + (CSEPhase): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGPhase.cpp: + (JSC::DFG::Phase::beginPhase): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativeCompare): + (JSC::DFG::SpeculativeJIT::nonSpeculativeStrictEq): + (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch): + (JSC::DFG::SpeculativeJIT::compile): + (JSC::DFG::SpeculativeJIT::compileStrictEqForConstant): + (JSC::DFG::SpeculativeJIT::compileStrictEq): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + (JSC::DFG::SpeculativeJIT::detectPeepHoleBranch): + (JSC::DFG::SpeculativeJIT::SpeculativeJIT): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull): + * dfg/DFGVirtualRegisterAllocationPhase.cpp: + (JSC::DFG::VirtualRegisterAllocationPhase::run): + +2012-02-29 Filip Pizlo <fpizlo@apple.com> + + The JIT should not crash the entire process just because there is not + enough executable memory, if the LLInt is enabled + https://bugs.webkit.org/show_bug.cgi?id=79962 + <rdar://problem/10922215> + + Unreviewed, adding forgotten file. + + * jit/JITCompilationEffort.h: Added. + (JSC): + +2012-02-29 Filip Pizlo <fpizlo@apple.com> + + The JIT should not crash the entire process just because there is not + enough executable memory, if the LLInt is enabled + https://bugs.webkit.org/show_bug.cgi?id=79962 + <rdar://problem/10922215> + + Reviewed by Gavin Barraclough. + + Added the notion of JITCompilationEffort. If we're JIT'ing as a result of + a tier-up, then we set it to JITCompilationCanFail. Otherwise it's + JITCompilationMustSucceed. This preserves the old behavior of LLInt is + disabled or if we're compiling something that can't be interpreted (like + an OSR exit stub). + + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::executableCopy): + * assembler/ARMAssembler.h: + (ARMAssembler): + * assembler/AssemblerBuffer.h: + (JSC::AssemblerBuffer::executableCopy): + * assembler/LinkBuffer.h: + (JSC::LinkBuffer::LinkBuffer): + (JSC::LinkBuffer::~LinkBuffer): + (LinkBuffer): + (JSC::LinkBuffer::didFailToAllocate): + (JSC::LinkBuffer::isValid): + (JSC::LinkBuffer::linkCode): + (JSC::LinkBuffer::performFinalization): + * assembler/MIPSAssembler.h: + (JSC::MIPSAssembler::executableCopy): + * assembler/SH4Assembler.h: + (JSC::SH4Assembler::executableCopy): + * assembler/X86Assembler.h: + (JSC::X86Assembler::executableCopy): + (JSC::X86Assembler::X86InstructionFormatter::executableCopy): + * bytecode/CodeBlock.cpp: + (JSC::ProgramCodeBlock::jitCompileImpl): + (JSC::EvalCodeBlock::jitCompileImpl): + (JSC::FunctionCodeBlock::jitCompileImpl): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::jitCompile): + (CodeBlock): + (ProgramCodeBlock): + (EvalCodeBlock): + (FunctionCodeBlock): + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::compile): + (JSC::DFG::JITCompiler::compileFunction): + * dfg/DFGJITCompiler.h: + (JITCompiler): + * jit/ExecutableAllocator.cpp: + (JSC::DemandExecutableAllocator::allocateNewSpace): + (JSC::ExecutableAllocator::allocate): + * jit/ExecutableAllocator.h: + (ExecutableAllocator): + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::ExecutableAllocator::allocate): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + * jit/JIT.h: + (JSC::JIT::compile): + (JIT): + * jit/JITCompilationEffort.h: Added. + (JSC): + * jit/JITDriver.h: + (JSC::jitCompileIfAppropriate): + (JSC::jitCompileFunctionIfAppropriate): + * llint/LLIntSlowPaths.cpp: + (LLInt): + (JSC::LLInt::jitCompileAndSetHeuristics): + (JSC::LLInt::entryOSR): + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * runtime/Executable.cpp: + (JSC::EvalExecutable::jitCompile): + (JSC::ProgramExecutable::jitCompile): + (JSC::FunctionExecutable::jitCompileForCall): + (JSC::FunctionExecutable::jitCompileForConstruct): + * runtime/Executable.h: + (EvalExecutable): + (ProgramExecutable): + (FunctionExecutable): + (JSC::FunctionExecutable::jitCompileFor): + * runtime/ExecutionHarness.h: + (JSC::prepareForExecution): + (JSC::prepareFunctionForExecution): + +2012-02-29 No'am Rosenthal <noam.rosenthal@nokia.com> + + [Qt][WK2] Get rid of the #ifdef mess in LayerTreeHost[Proxy] + https://bugs.webkit.org/show_bug.cgi?id=79501 + + Enable WTF_USE_UI_SIDE_COMPOSITING for Qt. + + Reviewed by Kenneth Rohde Christiansen. + + * wtf/Platform.h: + +2012-02-29 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Oliver Hunt. + + * tests/mozilla/ecma_2/RegExp/constructor-001.js: + * tests/mozilla/ecma_2/RegExp/function-001.js: + * tests/mozilla/ecma_2/RegExp/properties-001.js: + - Check in new test cases results. + +2012-02-29 Mark Rowe <mrowe@apple.com> + + Stop installing JSCLLIntOffsetsExtractor. + + Replace the separate TestRegExp and TestAPI xcconfig files with a single ToolExecutable xcconfig file + that derives the product name from the target name. We can then use that xcconfig file for JSCLLIntOffsetsExtractor. + This has the results of setting SKIP_INSTALL = YES for JSCLLIntOffsetsExtractor. + + While I was doing this fiddling I noticed that the JSCLLIntOffsetsExtractor target had a custom value + for USER_HEADER_SEARCH_PATHS to allow it to find LLIntDesiredOffsets.h. A better way of doing that is + to add LLIntDesiredOffsets.h to the Xcode project so that it'll be included in the header map. That + allows us to remove the override of USER_HEADER_SEARCH_PATHS entirely. So I did that too! + + Reviewed by Filip Pizlo. + + * Configurations/TestRegExp.xcconfig: Removed. + * Configurations/ToolExecutable.xcconfig: Renamed from Source/JavaScriptCore/Configurations/TestAPI.xcconfig. + * JavaScriptCore.xcodeproj/project.pbxproj: + +2012-02-28 Filip Pizlo <fpizlo@apple.com> + + RefCounted::deprecatedTurnOffVerifier() should not be deprecated + https://bugs.webkit.org/show_bug.cgi?id=79864 + + Reviewed by Oliver Hunt. + + Removed the word "deprecated" from the name of this method, since this method + should not be deprecated. It works just fine as it is, and there is simply no + alternative to calling this method for many interesting JSC classes. + + * parser/SourceProvider.h: + (JSC::SourceProvider::SourceProvider): + * runtime/SymbolTable.h: + (JSC::SharedSymbolTable::SharedSymbolTable): + * wtf/MetaAllocator.cpp: + (WTF::MetaAllocatorHandle::MetaAllocatorHandle): + (WTF::MetaAllocator::allocate): + * wtf/RefCounted.h: + (RefCountedBase): + (WTF::RefCountedBase::turnOffVerifier): + +2012-02-29 Gavin Barraclough <barraclough@apple.com> + + 'source' property of RegExp instance cannot be "" + https://bugs.webkit.org/show_bug.cgi?id=79938 + + Reviewed by Oliver Hunt. + + 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/', + and also states that the result must be a valid RegularExpressionLiteral. '//' is + not a valid RegularExpressionLiteral (since it is a single line comment), and hence + source cannot ever validly be "". If the source is empty, return a different Pattern + that would match the same thing. + + * runtime/RegExpObject.cpp: + (JSC::regExpObjectSource): + - Do not return "" if the source is empty, this would lead to invalid behaviour in toString. + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncToString): + - No need to special case the empty string - this should be being done by 'source'. + +2012-02-29 Gavin Barraclough <barraclough@apple.com> + + Writable attribute not set correctly when redefining an accessor to a data descriptor + https://bugs.webkit.org/show_bug.cgi?id=79931 + + Reviewed by Oliver Hunt. + + * runtime/JSObject.cpp: + (JSC::JSObject::defineOwnProperty): + - use attributesOverridingCurrent instead of attributesWithOverride. + * runtime/PropertyDescriptor.cpp: + * runtime/PropertyDescriptor.h: + - remove attributesWithOverride - attributesOverridingCurrent does the same thing. + +2012-02-29 Kevin Ollivier <kevino@theolliviers.com> + + Add JSCore symbol exports needed by wx port + https://bugs.webkit.org/show_bug.cgi?id=77280 + + Reviewed by Hajime Morita. + + * wtf/ArrayBufferView.h: + * wtf/ExportMacros.h: + +2012-02-28 Raphael Kubo da Costa <kubo@profusion.mobi> + + [CMake] Always build wtf as a static library. + https://bugs.webkit.org/show_bug.cgi?id=79857 + + Reviewed by Eric Seidel. + + To help the efforts in bug 75673 to move WTF out of + JavaScriptCore, act more like the other ports and remove the + possibility of building WTF as a shared library. + + It does not make much sense to, for example, ship WTF as a + separate .so with webkit-efl packages, and it should be small + enough not to cause problems during linking. + + * wtf/CMakeLists.txt: + +2012-02-28 Dmitry Lomov <dslomov@google.com> + + [JSC] Implement ArrayBuffer transfer + https://bugs.webkit.org/show_bug.cgi?id=73493. + Implement ArrayBuffer transfer, per Khronos spec: http://www.khronos.org/registry/typedarray/specs/latest/#9. + This brings parity with V8 implementation of transferable typed arrays. + + Reviewed by Oliver Hunt. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Extra export. + * wtf/ArrayBuffer.h: + (ArrayBuffer): Added extra export. + +2012-02-28 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Unreviewed. Build fix after recent LLInt additions. + + * wscript: + +2012-02-28 Mark Hahnenberg <mhahnenberg@apple.com> + + Refactor SpeculativeJIT::emitAllocateJSFinalObject + https://bugs.webkit.org/show_bug.cgi?id=79801 + + Reviewed by Filip Pizlo. + + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject): Split emitAllocateJSFinalObject out to form this + function, which is more generic in that it can allocate a variety of classes. + (SpeculativeJIT): + (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject): Changed to use the new helper function. + +2012-02-28 Gavin Barraclough <barraclough@apple.com> + + [[Get]]/[[Put]] for primitives should not wrap on strict accessor call + https://bugs.webkit.org/show_bug.cgi?id=79588 + + Reviewed by Oliver Hunt. + + In the case of [[Get]], this is a pretty trivial bug - just don't wrap + primitives at the point you call a getter. + + For setters, this is a little more involved, since we have already wrapped + the value up in a synthesized object. Stop doing so. There is also a further + subtely, that in strict mode all attempts to create a new data property on + the object should throw. + + * runtime/JSCell.cpp: + (JSC::JSCell::put): + - [[Put]] to a string primitive should use JSValue::putToPrimitive. + * runtime/JSObject.cpp: + (JSC::JSObject::put): + - Remove static function called in one place. + * runtime/JSObject.h: + (JSC::JSValue::put): + - [[Put]] to a non-cell JSValue should use JSValue::putToPrimitive. + * runtime/JSValue.cpp: + (JSC::JSValue::synthesizePrototype): + - Add support for synthesizing the prototype of strings. + (JSC::JSValue::putToPrimitive): + - Added, implements [[Put]] for primitive bases, per 8.7.2. + * runtime/JSValue.h: + (JSValue): + - Add declaration for JSValue::putToPrimitive. + * runtime/PropertySlot.cpp: + (JSC::PropertySlot::functionGetter): + - Don't call ToObject on primitive this values. + +2012-02-28 Mark Hahnenberg <mhahnenberg@apple.com> + + Re-enable parallel GC on Mac + https://bugs.webkit.org/show_bug.cgi?id=79837 + + Rubber stamped by Filip Pizlo. + + * runtime/Options.cpp: + (JSC::Options::initializeOptions): We accidentally disabled parallel GC with this line, + so we removed it and things should go back to normal. + +2012-02-28 Filip Pizlo <fpizlo@apple.com> + + Some run-javascriptcore-tests broken for 32-bit debug + https://bugs.webkit.org/show_bug.cgi?id=79844 + + Rubber stamped by Oliver Hunt. + + These assertions are just plain wrong for 32-bit. We could either have a massive + assertion that depends on value representation, that has to be changed every + time we change the JITs, resulting in a bug tail of debug-mode crashes, or we + could get rid of the assertions. I pick the latter. + + * dfg/DFGOperations.cpp: + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + +2012-02-28 Mark Hahnenberg <mhahnenberg@apple.com> + + Get rid of padding cruft in CopiedBlock + https://bugs.webkit.org/show_bug.cgi?id=79686 + + Reviewed by Filip Pizlo. + + * heap/CopiedBlock.h: + (CopiedBlock): Removed the extra padding that was used for alignment purposes until + the calculation of the payload offset into CopiedBlocks was redone recently. + +2012-02-28 Anders Carlsson <andersca@apple.com> + + Fix build with newer versions of clang. + + Clang now warns since we're not passing a CFString literal to CFStringCreateWithFormatAndArguments, + but it's OK to ignore this warning since clang is also checking that the caller (vprintf_stderr_common) + takes a string literal. + + * wtf/Assertions.cpp: + +2012-02-28 Mario Sanchez Prada <msanchez@igalia.com> + + [GTK] Add GMainLoop and GMainContext to be handled by GRefPtr + https://bugs.webkit.org/show_bug.cgi?id=79496 + + Reviewed by Martin Robinson. + + Handle GMainLoop and GMainContext in GRefPtr, by calling + g_main_loop_(un)ref and g_main_context_(un)ref in the + implementation of the refGPtr and derefGPtr template functions. + + * wtf/gobject/GRefPtr.cpp: + (WTF::refGPtr): + (WTF): + (WTF::derefGPtr): + * wtf/gobject/GRefPtr.h: + (WTF): + * wtf/gobject/GTypedefs.h: + +2012-02-28 Yong Li <yoli@rim.com> + + JSString::resolveRope() should report extra memory cost to the heap. + https://bugs.webkit.org/show_bug.cgi?id=79555 + + Reviewed by Michael Saboff. + + At the time a JSString is constructed with fibers, it doesn't report + extra memory cost, which is reasonable because it hasn't allocate + new memory. However when the rope is resolved, it should report meory + cost for the new buffer. + + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + +2012-02-27 Oliver Hunt <oliver@apple.com> + + sputnik/Unicode/Unicode_500/S7.2_A1.6_T1.html crashes in the interpreter + https://bugs.webkit.org/show_bug.cgi?id=79728 + + Reviewed by Gavin Barraclough. + + When initialising a chained get instruction we may end up in a state where + the instruction stream says we have a scopechain, but it has not yet been set + (eg. if allocating the StructureChain itself is what leads to the GC). We could + re-order the allocation, but it occurs in a couple of places, so it seems less + fragile simply to null check the scopechain slot before we actually visit the slot. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::visitStructures): + +2012-02-27 Filip Pizlo <fpizlo@apple.com> + + Old JIT's style of JSVALUE64 strict equality is subtly wrong + https://bugs.webkit.org/show_bug.cgi?id=79700 + + Reviewed by Oliver Hunt. + + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::comparePtr): + (MacroAssemblerX86_64): + * dfg/DFGOperations.cpp: + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativeStrictEq): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeStrictEq): + (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq): + * jit/JITOpcodes.cpp: + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::emitSlow_op_stricteq): + (JSC::JIT::emitSlow_op_nstricteq): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + +2012-02-27 Gavin Barraclough <barraclough@apple.com> + + Implement support for op_negate and op_bitnot in the DFG JIT + https://bugs.webkit.org/show_bug.cgi?id=79617 + + Reviewed by Filip Pizlo. + + Add an ArithNegate op to the DFG JIT, to implement op_negate. + + This patch also adds support for op_negate to the JSVALUE64 baseline JIT + (JSVALUE32_64 already had this), so that we can profile the slowpath usage. + + This is a 2.5%-3% Sunspider progression and a 1% win on Kraken. + + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::sub_S): + - Added sub_S from immediate. + (ARMv7Assembler): + (JSC::ARMv7Assembler::vneg): + - Added double negate. + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::negateDouble): + - Added double negate. + (MacroAssemblerARMv7): + (JSC::MacroAssemblerARMv7::branchNeg32): + - Added. + * assembler/MacroAssemblerX86.h: + (MacroAssemblerX86): + - moved loadDouble, absDouble to common. + * assembler/MacroAssemblerX86Common.h: + (MacroAssemblerX86Common): + (JSC::MacroAssemblerX86Common::absDouble): + - implementation can be shared. + (JSC::MacroAssemblerX86Common::negateDouble): + - Added. + (JSC::MacroAssemblerX86Common::loadDouble): + - allow absDouble to have a common implementation. + * assembler/MacroAssemblerX86_64.h: + (MacroAssemblerX86_64): + - moved loadDouble, absDouble to common. + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + - support ArithNegate. + * dfg/DFGArithNodeFlagsInferencePhase.cpp: + (JSC::DFG::ArithNodeFlagsInferencePhase::propagate): + - support ArithNegate. + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::makeSafe): + - support ArithNegate. + (JSC::DFG::ByteCodeParser::parseBlock): + - support op_negate. + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::performNodeCSE): + - support ArithNegate. + * dfg/DFGCapabilities.h: + (JSC::DFG::canCompileOpcode): + - support op_negate. + * dfg/DFGGraph.h: + (JSC::DFG::Graph::negateShouldSpeculateInteger): + - support ArithNegate. + * dfg/DFGNode.h: + (JSC::DFG::Node::hasArithNodeFlags): + - support ArithNegate. + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + - support ArithNegate. + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileArithNegate): + - support ArithNegate. + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + - support ArithNegate. + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + - support ArithNegate. + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + - support ArithNegate. + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + - Add support for op_negate in JSVALUE64. + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_negate): + (JSC::JIT::emitSlow_op_negate): + - Add support for op_negate in JSVALUE64. + +2012-02-27 Mahesh Kulkarni <mahesh.kulkarni@nokia.com> + + Unreviewed. Build fix for linux-bot (qt) after r109021. + + * runtime/Error.cpp: + +2012-02-27 Oliver Hunt <oliver@apple.com> + + REGRESSION (r108112): AWS Management Console at amazon.com fails to initialize + https://bugs.webkit.org/show_bug.cgi?id=79693 + + Reviewed by Filip Pizlo. + + Alas we can't provide the stack trace as an array, as despite everyone wanting + an array, everyone arbitrarily creates the array by calling split on the stack + trace. To create the array we would have provided them in the first place. + + This changes the exception's stack property to a \n separated string. To get the + old array just do <exception>.stack.split("\n"). + + * runtime/Error.cpp: + (JSC::addErrorInfo): + +2012-02-27 Gavin Barraclough <barraclough@apple.com> + + RegExp lastIndex should behave as a regular property + https://bugs.webkit.org/show_bug.cgi?id=79446 + + Reviewed by Sam Weinig. + + lastIndex should be a regular data descriptor, with the attributes configurable:false, + enumerable:false, writable:true. As such, it should be possible to reconfigure writable + as false. If the lastIndex property is reconfigured to be read-only, we should respect + this correctly. + + * runtime/CommonIdentifiers.h: + - Removed some unused identifiers, added lastIndex. + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::getOwnPropertySlot): + - lastIndex is no longer a static value, provided specific handling. + (JSC::RegExpObject::getOwnPropertyDescriptor): + - lastIndex is no longer a static value, provided specific handling. + (JSC::RegExpObject::deleteProperty): + - lastIndex is no longer a static value, provided specific handling. + (JSC::RegExpObject::getOwnPropertyNames): + - lastIndex is no longer a static value, provided specific handling. + (JSC::RegExpObject::getPropertyNames): + - lastIndex is no longer a static value, provided specific handling. + (JSC::reject): + - helper function for defineOwnProperty. + (JSC::RegExpObject::defineOwnProperty): + - lastIndex is no longer a static value, provided specific handling. + (JSC::RegExpObject::put): + - lastIndex is no longer a static value, provided specific handling. + (JSC::RegExpObject::match): + - Pass setLastIndex an ExecState, so it can throw if read-only. + * runtime/RegExpObject.h: + (JSC::RegExpObject::setLastIndex): + - Pass setLastIndex an ExecState, so it can throw if read-only. + (RegExpObjectData): + - Added lastIndexIsWritable. + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncCompile): + - Pass setLastIndex an ExecState, so it can throw if read-only. + +2012-02-27 Gavin Barraclough <barraclough@apple.com> + + Implement support for op_negate and op_bitnot in the DFG JIT + https://bugs.webkit.org/show_bug.cgi?id=79617 + + Reviewed by Sam Weinig. + + Remove op_bitnop - this is redundant, ~x === x^-1. + This is a fractional (<1%) progression. + + Remove not32(X) from the MacroAssemblers - make this an optimization to add32(-1, X). + Remove CanReuse from the result type - this was unused. + Remove op_bitnot. + + * assembler/MacroAssemblerARM.h: + (MacroAssemblerARM): + (JSC::MacroAssemblerARM::xor32): + * assembler/MacroAssemblerARMv7.h: + (MacroAssemblerARMv7): + (JSC::MacroAssemblerARMv7::xor32): + * assembler/MacroAssemblerMIPS.h: + (MacroAssemblerMIPS): + (JSC::MacroAssemblerMIPS::xor32): + * assembler/MacroAssemblerSH4.h: + (MacroAssemblerSH4): + (JSC::MacroAssemblerSH4::xor32): + * assembler/MacroAssemblerX86Common.h: + (MacroAssemblerX86Common): + (JSC::MacroAssemblerX86Common::xor32): + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Opcode.h: + (JSC): + (JSC::padOpcodeName): + * bytecompiler/NodesCodegen.cpp: + (JSC): + (JSC::BitwiseNotNode::emitBytecode): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + (JIT): + * jit/JITArithmetic32_64.cpp: + (JSC): + * jit/JITOpcodes.cpp: + (JSC): + * jit/JITStubs.cpp: + (JSC): + * jit/JITStubs.h: + * llint/LLIntSlowPaths.cpp: + (LLInt): + * llint/LLIntSlowPaths.h: + (LLInt): + * llint/LowLevelInterpreter32_64.asm: + * parser/NodeConstructors.h: + (JSC::NegateNode::NegateNode): + (JSC::BitwiseNotNode::BitwiseNotNode): + (JSC::MultNode::MultNode): + (JSC::DivNode::DivNode): + (JSC::ModNode::ModNode): + (JSC::SubNode::SubNode): + (JSC::UnsignedRightShiftNode::UnsignedRightShiftNode): + * parser/Nodes.h: + (BitwiseNotNode): + (JSC::BitwiseNotNode::expr): + (JSC): + * parser/ResultType.h: + (ResultType): + (JSC::ResultType::numberTypeIsInt32): + (JSC::ResultType::stringOrNumberType): + (JSC::ResultType::forAdd): + (JSC::ResultType::forBitOp): + +2012-02-27 Michael Saboff <msaboff@apple.com> + + Error check regexp min quantifier + https://bugs.webkit.org/show_bug.cgi?id=70648 + + Reviewed by Gavin Barraclough. + + Added checking for min or only quantifier being UINT_MAX. + When encountered this becomes a SyntaxError during parsing. + + * yarr/YarrParser.h: + (JSC::Yarr::Parser::parseQuantifier): + (JSC::Yarr::Parser::parse): + (Parser): + +2012-02-27 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck. + + * GNUmakefile.list.am: Add missing files. + +2012-02-26 Hajime Morrita <morrita@chromium.org> + + Move ChromeClient::showContextMenu() to ContextMenuClient + https://bugs.webkit.org/show_bug.cgi?id=79427 + + Reviewed by Adam Barth. + + Added ACCESSIBILITY_CONTEXT_MENUS. + + * wtf/Platform.h: + +2012-02-26 Filip Pizlo <fpizlo@apple.com> + + LayoutTests/fast/xpath/xpath-functional-test.html is crashing in the DFG + https://bugs.webkit.org/show_bug.cgi?id=79616 + + Reviewed by Oliver Hunt. + + Guard against the fact that in JSVALUE64, JSValue().isCell() == true. + + * dfg/DFGAbstractValue.h: + (JSC::DFG::AbstractValue::validate): + +2012-02-26 Filip Pizlo <fpizlo@apple.com> + + DFG should support activations and nested functions + https://bugs.webkit.org/show_bug.cgi?id=79554 + + Reviewed by Sam Weinig. + + Fix 32-bit. The 32-bit function+activation code had some really weird + register reuse bugs. + + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-02-26 Filip Pizlo <fpizlo@apple.com> + + Getting the instruction stream for a code block should not require two loads + https://bugs.webkit.org/show_bug.cgi?id=79608 + + Reviewed by Sam Weinig. + + Introduced the RefCountedArray class, which contains a single inline pointer + to a ref-counted non-resizeable vector backing store. This satisfies the + requirements of CodeBlock, which desires the ability to share instruction + streams with other CodeBlocks. It also reduces the number of loads required + for getting the instruction stream by one. + + This patch also gets rid of the bytecode discarding logic, since we don't + use it anymore and it's unlikely to ever work right with DFG or LLInt. And + I didn't feel like porting dead code to use RefCountedArray. + + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/CodeBlock.cpp: + (JSC::instructionOffsetForNth): + (JSC::CodeBlock::dump): + (JSC::CodeBlock::CodeBlock): + (JSC::CodeBlock::finalizeUnconditionally): + (JSC::CodeBlock::handlerForBytecodeOffset): + (JSC::CodeBlock::lineNumberForBytecodeOffset): + (JSC::CodeBlock::expressionRangeForBytecodeOffset): + (JSC::CodeBlock::shrinkToFit): + * bytecode/CodeBlock.h: + (CodeBlock): + (JSC::CodeBlock::numberOfInstructions): + (JSC::CodeBlock::instructions): + (JSC::CodeBlock::instructionCount): + (JSC::CodeBlock::valueProfileForBytecodeOffset): + (JSC): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::Label::setLocation): + (JSC): + (JSC::BytecodeGenerator::generate): + (JSC::BytecodeGenerator::newLabel): + * bytecompiler/BytecodeGenerator.h: + (JSC): + (BytecodeGenerator): + (JSC::BytecodeGenerator::instructions): + * bytecompiler/Label.h: + (JSC::Label::Label): + (Label): + * dfg/DFGByteCodeCache.h: + (JSC::DFG::ByteCodeCache::~ByteCodeCache): + (JSC::DFG::ByteCodeCache::get): + * jit/JITExceptions.cpp: + (JSC::genericThrow): + * llint/LowLevelInterpreter32_64.asm: + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + (JSC::ProgramExecutable::compileInternal): + (JSC::FunctionExecutable::codeBlockWithBytecodeFor): + (JSC::FunctionExecutable::produceCodeBlockFor): + * wtf/RefCountedArray.h: Added. + (WTF): + (RefCountedArray): + (WTF::RefCountedArray::RefCountedArray): + (WTF::RefCountedArray::operator=): + (WTF::RefCountedArray::~RefCountedArray): + (WTF::RefCountedArray::size): + (WTF::RefCountedArray::data): + (WTF::RefCountedArray::begin): + (WTF::RefCountedArray::end): + (WTF::RefCountedArray::at): + (WTF::RefCountedArray::operator[]): + (Header): + (WTF::RefCountedArray::Header::size): + (WTF::RefCountedArray::Header::payload): + (WTF::RefCountedArray::Header::fromPayload): + * wtf/Platform.h: + +2012-02-26 Yusuke Suzuki <utatane.tea@gmail.com> + + StringLiteral and NumericLiteral are allowed as ObjectLiteral getter / setter name + https://bugs.webkit.org/show_bug.cgi?id=79571 + + Reviewed by Gavin Barraclough. + + * parser/ASTBuilder.h: + (JSC::ASTBuilder::createGetterOrSetterProperty): + * parser/Parser.cpp: + (JSC::::parseProperty): + * parser/SyntaxChecker.h: + (JSC::SyntaxChecker::createGetterOrSetterProperty): + +2012-02-26 Mark Hahnenberg <mhahnenberg@apple.com> + + Implement fast path for op_new_array in the baseline JIT + https://bugs.webkit.org/show_bug.cgi?id=78612 + + Reviewed by Filip Pizlo. + + heap/CopiedAllocator.h: + (CopiedAllocator): Friended the JIT to allow access to m_currentOffset. + * heap/CopiedSpace.h: + (CopiedSpace): Friended the JIT to allow access to isOversize. + (JSC::CopiedSpace::allocator): + * heap/Heap.h: + (JSC::Heap::storageAllocator): Added a getter for the CopiedAllocator class so the JIT + can use it for simple allocation i.e. when we can just bump the offset without having to + do anything else. + * jit/JIT.cpp: + (JSC::JIT::privateCompileSlowCases): Added new slow case for op_new_array for when + we have to bail out because the fast allocation path fails for whatever reason. + * jit/JIT.h: + (JIT): + * jit/JITInlineMethods.h: + (JSC::JIT::emitAllocateBasicStorage): Added utility function that allows objects to + allocate generic backing stores. This function is used by emitAllocateJSArray. + (JSC): + (JSC::JIT::emitAllocateJSArray): Added utility function that allows the client to + more easily allocate JSArrays. This function is used by emit_op_new_array and I expect + it will also be used for emit_op_new_array_buffer. + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_new_array): Changed to do inline allocation of JSArrays. Still does + a stub call for oversize arrays. + (JSC): + (JSC::JIT::emitSlow_op_new_array): New slow path that just bails out to a stub call if we + fail in any way on the fast path. + * runtime/JSArray.cpp: + (JSC): + * runtime/JSArray.h: Added lots of offset functions for all the fields that we need to + initialize in the JIT. + (ArrayStorage): + (JSC::ArrayStorage::lengthOffset): + (JSC::ArrayStorage::numValuesInVectorOffset): + (JSC::ArrayStorage::allocBaseOffset): + (JSC::ArrayStorage::vectorOffset): + (JSArray): + (JSC::JSArray::sparseValueMapOffset): + (JSC::JSArray::subclassDataOffset): + (JSC::JSArray::indexBiasOffset): + (JSC): + (JSC::JSArray::storageSize): Moved this function from being a static function in the cpp file + to being a static function in the JSArray class. This move allows the JIT to call it to + see what size it should allocate. + +2012-02-26 Patrick Gansterer <paroga@webkit.org> + + Unreviewed. Build fix for ENABLE(CLASSIC_INTERPRETER) after r108681. + + * interpreter/Interpreter.cpp: + (JSC::getLineNumberForCallFrame): + (JSC::Interpreter::getStackTrace): + +2012-02-26 Patrick Gansterer <paroga@webkit.org> + + Unreviewed. Build fix for !ENABLE(JIT) after r108681. + + * interpreter/Interpreter.cpp: + (JSC::getLineNumberForCallFrame): + +2012-02-25 Filip Pizlo <fpizlo@apple.com> + + LLInt assembly file should be split into 32-bit and 64-bit parts + https://bugs.webkit.org/show_bug.cgi?id=79584 + + Reviewed by Sam Weinig. + + Moved LowLevelInterpreter.asm to LowLevelInterpreter32_64.asm. Gave offlineasm + the ability to include files, and correctly track dependencies: it restricts + the include mechanism to using the same directory as the source file, and uses + the SHA1 hash of all .asm files in that directory as an input hash. + + * llint/LLIntOfflineAsmConfig.h: + * llint/LowLevelInterpreter.asm: + * llint/LowLevelInterpreter32_64.asm: Added. + - This is just the entire contents of what was previously LowLevelInterpreter.asm + * llint/LowLevelInterpreter64.asm: Added. + * offlineasm/asm.rb: + * offlineasm/ast.rb: + * offlineasm/generate_offset_extractor.rb: + * offlineasm/parser.rb: + * offlineasm/self_hash.rb: + +2012-02-25 Filip Pizlo <fpizlo@apple.com> + + Offlineasm should support X86_64 + https://bugs.webkit.org/show_bug.cgi?id=79581 + + Reviewed by Oliver Hunt. + + * llint/LLIntOfflineAsmConfig.h: + * offlineasm/backends.rb: + * offlineasm/instructions.rb: + * offlineasm/settings.rb: + * offlineasm/x86.rb: + +2012-02-25 Filip Pizlo <fpizlo@apple.com> + + DFG should support activations and nested functions + https://bugs.webkit.org/show_bug.cgi?id=79554 + + Reviewed by Oliver Hunt. + + Wrote the simplest possible implementation of activations. Big speed-up on + code that uses activations, no speed-up on major benchmarks (SunSpider, V8, + Kraken) because they do not appear to have sufficient coverage over code + that uses activations. + + * bytecode/PredictedType.cpp: + (JSC::predictionToString): + (JSC::predictionFromValue): + * bytecode/PredictedType.h: + (JSC): + (JSC::isEmptyPrediction): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::ByteCodeParser): + (ByteCodeParser): + (JSC::DFG::ByteCodeParser::parseBlock): + (JSC::DFG::ByteCodeParser::buildOperandMapsIfNecessary): + (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry): + (JSC::DFG::ByteCodeParser::parse): + * dfg/DFGCapabilities.h: + (JSC::DFG::canCompileOpcode): + (JSC::DFG::canInlineOpcode): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::needsActivation): + * dfg/DFGNode.h: + (DFG): + (JSC::DFG::Node::storageAccessDataIndex): + (Node): + (JSC::DFG::Node::hasFunctionDeclIndex): + (JSC::DFG::Node::functionDeclIndex): + (JSC::DFG::Node::hasFunctionExprIndex): + (JSC::DFG::Node::functionExprIndex): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileNewFunctionNoCheck): + (DFG): + (JSC::DFG::SpeculativeJIT::compileNewFunctionExpression): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-02-25 Benjamin Poulain <benjamin@webkit.org> + + Add an empty skeleton of KURL for WTFURL + https://bugs.webkit.org/show_bug.cgi?id=78990 + + Reviewed by Adam Barth. + + * JavaScriptCore.xcodeproj/project.pbxproj: Export the relevant classes from WTFURL + so that can use them in WebCore. + +2012-02-25 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, fix build for DFG disabled and LLInt enabled. + + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + * llint/LLIntSlowPaths.cpp: + (LLInt): + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + +2012-02-25 Mark Hahnenberg <mhahnenberg@apple.com> + + Fix the CopiedBlock offset alignment in a cross platform fashion + https://bugs.webkit.org/show_bug.cgi?id=79556 + + Reviewed by Filip Pizlo. + + Replaced m_payload with a payload() method that calculates the offset + of the payload with the proper alignment. This change allows us to + avoid alignment-related issues in a cross-platform manner. + + * heap/CopiedAllocator.h: + (JSC::CopiedAllocator::currentUtilization): + * heap/CopiedBlock.h: + (JSC::CopiedBlock::CopiedBlock): + (JSC::CopiedBlock::payload): + (CopiedBlock): + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::doneFillingBlock): + * heap/CopiedSpaceInlineMethods.h: + (JSC::CopiedSpace::borrowBlock): + (JSC::CopiedSpace::allocateFromBlock): + +2012-02-24 Michael Saboff <msaboff@apple.com> + + Unreviewed, Windows build fix. Changed signature in export to match + change made in r108858. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-02-24 Filip Pizlo <fpizlo@apple.com> + + DFG support for op_new_regexp should be enabled + https://bugs.webkit.org/show_bug.cgi?id=79538 + + Reviewed by Oliver Hunt. + + No performance change. + + * dfg/DFGCapabilities.h: + (JSC::DFG::canCompileOpcode): + * dfg/DFGCommon.h: + +2012-02-24 Michael Saboff <msaboff@apple.com> + + ASSERT(position < 0) in JSC::Yarr::Interpreter::InputStream::readChecked + https://bugs.webkit.org/show_bug.cgi?id=73728 + + Reviewed by Gavin Barraclough. + + Fixed the mixing of signed and unsigned character indeces in YARR + interpreter. + + * runtime/RegExp.cpp: + (JSC::RegExp::match): Added code to check for match longer than 2^31 and + return no match after resetting the offsets. + * yarr/YarrInterpreter.cpp: Changed to use unsigned for all character index + handling except when matching back references. + (JSC::Yarr::Interpreter::InputStream::readChecked): + (JSC::Yarr::Interpreter::InputStream::checkInput): + (JSC::Yarr::Interpreter::InputStream::uncheckInput): + (JSC::Yarr::Interpreter::InputStream::atStart): + (JSC::Yarr::Interpreter::InputStream::atEnd): + (JSC::Yarr::Interpreter::InputStream::isAvailableInput): + (JSC::Yarr::Interpreter::checkCharacter): + (JSC::Yarr::Interpreter::checkCasedCharacter): + (JSC::Yarr::Interpreter::checkCharacterClass): + (JSC::Yarr::Interpreter::tryConsumeBackReference): + (JSC::Yarr::Interpreter::matchAssertionBOL): + (JSC::Yarr::Interpreter::matchAssertionWordBoundary): + (JSC::Yarr::Interpreter::backtrackPatternCharacter): + (JSC::Yarr::Interpreter::backtrackPatternCasedCharacter): + (JSC::Yarr::Interpreter::matchCharacterClass): + (JSC::Yarr::Interpreter::backtrackCharacterClass): + (JSC::Yarr::Interpreter::matchParenthesesOnceBegin): + (JSC::Yarr::Interpreter::matchDisjunction): + (JSC::Yarr::Interpreter::interpret): + (JSC::Yarr::ByteCompiler::assertionBOL): + (JSC::Yarr::ByteCompiler::assertionEOL): + (JSC::Yarr::ByteCompiler::assertionWordBoundary): + (JSC::Yarr::ByteCompiler::atomPatternCharacter): + (JSC::Yarr::ByteCompiler::atomCharacterClass): + (JSC::Yarr::ByteCompiler::atomBackReference): + (JSC::Yarr::ByteCompiler::atomParenthesesOnceBegin): + (JSC::Yarr::ByteCompiler::atomParenthesesTerminalBegin): + (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternBegin): + (JSC::Yarr::ByteCompiler::atomParentheticalAssertionEnd): + (JSC::Yarr::ByteCompiler::emitDisjunction): + * yarr/YarrInterpreter.h: + +2012-02-24 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, build fix for builds where the DFG is disabled but the LLInt is + enabled. + + * llint/LLIntOfflineAsmConfig.h: + * llint/LowLevelInterpreter.asm: + +2012-02-24 Filip Pizlo <fpizlo@apple.com> + + DFG should be able to handle variables getting captured + https://bugs.webkit.org/show_bug.cgi?id=79469 + + Reviewed by Oliver Hunt. + + Made captured variables work by placing a Flush on the SetLocal and + forcing the emission of the GetLocal even if copy propagation tells us + who has the value. + + Changed the CFA and various prediction codes to understand that we can't + really prove anything about captured variables. Well, we could in the + future by just looking at what side effects are happening, but in this + first cut we just assume that we can't reason about captured variables. + + Also added a mode where the DFG pretends that all variables and arguments + got captured. Used this mode to harden the code. + + This is performance neutral. Capturing all variables is a slow down, but + not too big of one. This seems to predict that when we add activation + support, the amount of speed benefit we'll get from increased coverage + will far outweigh the pessimism that we'll have to endure for captured + variables. + + * bytecode/CodeType.h: + (JSC::codeTypeToString): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::initialize): + (JSC::DFG::AbstractState::endBasicBlock): + (JSC::DFG::AbstractState::execute): + (JSC::DFG::AbstractState::merge): + * dfg/DFGAbstractState.h: + (AbstractState): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::getLocal): + (JSC::DFG::ByteCodeParser::setLocal): + (JSC::DFG::ByteCodeParser::getArgument): + (JSC::DFG::ByteCodeParser::setArgument): + (JSC::DFG::ByteCodeParser::flushArgument): + (JSC::DFG::ByteCodeParser::handleInlining): + (JSC::DFG::ByteCodeParser::processPhiStack): + (JSC::DFG::ByteCodeParser::parseCodeBlock): + (JSC::DFG::ByteCodeParser::parse): + * dfg/DFGCapabilities.h: + (JSC::DFG::mightInlineFunctionForCall): + (JSC::DFG::mightInlineFunctionForConstruct): + * dfg/DFGCommon.h: + * dfg/DFGGraph.h: + (JSC::DFG::Graph::needsActivation): + (Graph): + (JSC::DFG::Graph::argumentIsCaptured): + (JSC::DFG::Graph::localIsCaptured): + (JSC::DFG::Graph::isCaptured): + * dfg/DFGNode.h: + (JSC::DFG::Node::shouldGenerate): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): + * dfg/DFGSpeculativeJIT.cpp: + (DFG): + (JSC::DFG::ValueSource::dump): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT.h: + (ValueSource): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGVirtualRegisterAllocationPhase.cpp: + (JSC::DFG::VirtualRegisterAllocationPhase::run): + +2012-02-24 Gavin Barraclough <barraclough@apple.com> + + Should not allow malformed \x escapes + https://bugs.webkit.org/show_bug.cgi?id=79462 + + Reviewed by Oliver Hunt. + + * parser/Lexer.cpp: + (JSC::::parseString): + (JSC::::parseStringSlowCase): + - Prohibit malformed '\x' escapes + * tests/mozilla/ecma/Array/15.4.5.1-1.js: + * tests/mozilla/ecma/LexicalConventions/7.7.4.js: + * tests/mozilla/ecma_2/RegExp/hex-001.js: + * tests/mozilla/js1_2/regexp/hexadecimal.js: + - Remove erroneous test cases (correct behaviour is tested by LayoutTests/sputnik). + +2012-02-24 Daniel Bates <dbates@webkit.org> + + Fix change log entry for changeset r108819; add bug URL + https://bugs.webkit.org/show_bug.cgi?id=79504 + + Changeset r108819 is associated with bug #79504. + + * ChangeLog + +2012-02-24 Daniel Bates <dbates@webkit.org> + + Substitute ENABLE(CLASSIC_INTERPRETER) for ENABLE(INTERPRETER) in Interpreter.cpp + https://bugs.webkit.org/show_bug.cgi?id=79504 + + Reviewed by Oliver Hunt. + + There are a few places in Interpreter.cpp that need to be updated to use + ENABLE(CLASSIC_INTERPRETER) following the renaming of ENABLE_INTERPRETER to + ENABLE_CLASSIC_INTERPRETER in changeset <http://trac.webkit.org/changeset/108020> + (https://bugs.webkit.org/show_bug.cgi?id=78791). + + * interpreter/Interpreter.cpp: + (JSC::getLineNumberForCallFrame): + (JSC::getCallerInfo): + (JSC::getSourceURLFromCallFrame): + +2012-02-24 Adam Roben <aroben@apple.com> + + Undo the BUILDING_WTF part of r108808 + + This broke the build, which is obviously worse than the linker warning it was trying to + solve. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + +2012-02-24 Adam Roben <aroben@apple.com> + + Fix linker warnings on Windows + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Removed symbols that are already + exported via JS_EXPORTDATA. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: Define BUILDING_WTF. We + aren't actually building WTF, but we are statically linking it, so we need to define this + symbol so that we export WTF's exports. + +2012-02-24 Philippe Normand <pnormand@igalia.com> + + Fix GTK WebAudio build for WebKitGTK 1.7.90. + + Patch by Priit Laes <plaes@plaes.org> on 2012-02-24 + Rubber-stamped by Philippe Normand. + + * GNUmakefile.list.am: Add Complex.h to the list of files so it + gets disted in the tarballs. + 2012-02-24 Zoltan Herczeg <zherczeg@webkit.org> [Qt] Buildfix for "Zero out CopiedBlocks on initialization". diff --git a/Source/JavaScriptCore/Configurations/Base.xcconfig b/Source/JavaScriptCore/Configurations/Base.xcconfig index 40c11b647..e4d3617fd 100644 --- a/Source/JavaScriptCore/Configurations/Base.xcconfig +++ b/Source/JavaScriptCore/Configurations/Base.xcconfig @@ -71,7 +71,7 @@ WARNING_CFLAGS_macosx_ppc = $(WARNING_CFLAGS_BASE) -Wshorten-64-to-32; // FIXME: JavaScriptCore 64-bit builds should build with -Wshorten-64-to-32 WARNING_CFLAGS_macosx_ppc64 = $(WARNING_CFLAGS_BASE); WARNING_CFLAGS_macosx_x86_64 = $(WARNING_CFLAGS_BASE); -HEADER_SEARCH_PATHS = . icu $(HEADER_SEARCH_PATHS); +HEADER_SEARCH_PATHS = . icu "${BUILT_PRODUCTS_DIR}/usr/local/include" $(HEADER_SEARCH_PATHS); CLANG_CXX_LIBRARY = $(CLANG_CXX_LIBRARY_$(TARGET_MAC_OS_X_VERSION_MAJOR)); CLANG_CXX_LIBRARY_1060 = libstdc++; @@ -87,6 +87,11 @@ REAL_PLATFORM_NAME_macosx = macosx; TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR); +FRAMEWORK_SEARCH_PATHS = $(STAGED_FRAMEWORKS_SEARCH_PATH); + +STAGED_FRAMEWORKS_SEARCH_PATH = $(STAGED_FRAMEWORKS_SEARCH_PATH_$(USE_STAGING_INSTALL_PATH)); +STAGED_FRAMEWORKS_SEARCH_PATH_YES = $(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/StagedFrameworks/Safari; + NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_$(REAL_PLATFORM_NAME)); NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks; NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_iphonesimulator = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR_iphoneos); diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig index 576e746ad..58a02f521 100644 --- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -90,12 +90,14 @@ ENABLE_INDEXED_DATABASE = ; ENABLE_INPUT_COLOR = ; ENABLE_INPUT_SPEECH = ; ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER; +ENABLE_LEGACY_NOTIFICATIONS = ENABLE_LEGACY_NOTIFICATIONS; ENABLE_LINK_PREFETCH = ; ENABLE_MATHML = ENABLE_MATHML; ENABLE_MEDIA_SOURCE = ; ENABLE_MEDIA_STATISTICS = ; ENABLE_METER_TAG = ENABLE_METER_TAG; ENABLE_MHTML = ; +ENABLE_MICRODATA = ; ENABLE_MUTATION_OBSERVERS = ENABLE_MUTATION_OBSERVERS; ENABLE_NOTIFICATIONS = $(ENABLE_NOTIFICATIONS_$(REAL_PLATFORM_NAME)); @@ -109,6 +111,7 @@ ENABLE_PROGRESS_TAG = ENABLE_PROGRESS_TAG; ENABLE_QUOTA = ; ENABLE_REGISTER_PROTOCOL_HANDLER = ; ENABLE_REQUEST_ANIMATION_FRAME = ENABLE_REQUEST_ANIMATION_FRAME; +ENABLE_SCRIPTED_SPEECH = ; ENABLE_SHADOW_DOM = ; ENABLE_SHARED_WORKERS = ENABLE_SHARED_WORKERS; ENABLE_SQL_DATABASE = ENABLE_SQL_DATABASE; @@ -118,7 +121,10 @@ ENABLE_SVG_FONTS = ENABLE_SVG_FONTS; ENABLE_TEXT_NOTIFICATIONS_ONLY = ENABLE_TEXT_NOTIFICATIONS_ONLY; ENABLE_TOUCH_ICON_LOADING = ; ENABLE_VIDEO = ENABLE_VIDEO; -ENABLE_VIDEO_TRACK = ; + +ENABLE_VIDEO_TRACK = $(ENABLE_VIDEO_TRACK_$(REAL_PLATFORM_NAME)); +ENABLE_VIDEO_TRACK_macosx = ENABLE_VIDEO_TRACK; + ENABLE_WEBGL = ENABLE_WEBGL; ENABLE_WEB_AUDIO = ENABLE_WEB_AUDIO; ENABLE_WEB_SOCKETS = ENABLE_WEB_SOCKETS; @@ -126,4 +132,4 @@ ENABLE_WEB_TIMING = ; ENABLE_WORKERS = ENABLE_WORKERS; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT); diff --git a/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig b/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig index d88b46e4e..fcef7550c 100644 --- a/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig +++ b/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig @@ -50,3 +50,5 @@ INFOPLIST_FILE = Info.plist; INSTALL_PATH = $(JAVASCRIPTCORE_FRAMEWORKS_DIR); DYLIB_INSTALL_NAME_BASE = $(NORMAL_JAVASCRIPTCORE_FRAMEWORKS_DIR); PRODUCT_NAME = JavaScriptCore; + +INSTALLHDRS_SCRIPT_PHASE = YES; diff --git a/Source/JavaScriptCore/Configurations/TestRegExp.xcconfig b/Source/JavaScriptCore/Configurations/TestRegExp.xcconfig deleted file mode 100644 index 963ec34b3..000000000 --- a/Source/JavaScriptCore/Configurations/TestRegExp.xcconfig +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2011 Apple Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -INSTALL_PATH = $(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources -PRODUCT_NAME = testRegExp; - -SKIP_INSTALL = $(SKIP_INSTALL_$(FORCE_TOOL_INSTALL)); -SKIP_INSTALL_ = YES; -SKIP_INSTALL_NO = YES; -SKIP_INSTALL_YES = NO; diff --git a/Source/JavaScriptCore/Configurations/TestAPI.xcconfig b/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig index 65ac95ea0..194c240fa 100644 --- a/Source/JavaScriptCore/Configurations/TestAPI.xcconfig +++ b/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. INSTALL_PATH = $(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources -PRODUCT_NAME = testapi; +PRODUCT_NAME = $(TARGET_NAME); SKIP_INSTALL = $(SKIP_INSTALL_$(FORCE_TOOL_INSTALL)); SKIP_INSTALL_ = YES; diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig index 7e3f57ea8..7477f4b74 100644 --- a/Source/JavaScriptCore/Configurations/Version.xcconfig +++ b/Source/JavaScriptCore/Configurations/Version.xcconfig @@ -21,8 +21,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -MAJOR_VERSION = 535; -MINOR_VERSION = 23; +MAJOR_VERSION = 536; +MINOR_VERSION = 3; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am index 36b64a375..430b564c0 100644 --- a/Source/JavaScriptCore/GNUmakefile.list.am +++ b/Source/JavaScriptCore/GNUmakefile.list.am @@ -95,6 +95,8 @@ javascriptcore_sources += \ Source/JavaScriptCore/bytecode/DFGExitProfile.cpp \ Source/JavaScriptCore/bytecode/DFGExitProfile.h \ Source/JavaScriptCore/bytecode/EvalCodeCache.h \ + Source/JavaScriptCore/bytecode/ExecutionCounter.cpp \ + Source/JavaScriptCore/bytecode/ExecutionCounter.h \ Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h \ Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \ Source/JavaScriptCore/bytecode/GetByIdStatus.h \ @@ -167,6 +169,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/dfg/DFGGraph.h \ Source/JavaScriptCore/dfg/DFGJITCompiler.cpp \ Source/JavaScriptCore/dfg/DFGJITCompiler.h \ + Source/JavaScriptCore/dfg/DFGNode.cpp \ Source/JavaScriptCore/dfg/DFGNode.h \ Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h \ Source/JavaScriptCore/dfg/DFGNodeUse.h \ @@ -185,6 +188,8 @@ javascriptcore_sources += \ Source/JavaScriptCore/dfg/DFGPhase.h \ Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp \ Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.h \ + Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp \ + Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.h \ Source/JavaScriptCore/dfg/DFGRegisterBank.h \ Source/JavaScriptCore/dfg/DFGRepatch.cpp \ Source/JavaScriptCore/dfg/DFGRepatch.h \ @@ -309,6 +314,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/jit/JITCall32_64.cpp \ Source/JavaScriptCore/jit/JITCall.cpp \ Source/JavaScriptCore/jit/JITCode.h \ + Source/JavaScriptCore/jit/JITCompilationEffort.h \ Source/JavaScriptCore/jit/JITDriver.h \ Source/JavaScriptCore/jit/JIT.cpp \ Source/JavaScriptCore/jit/JIT.h \ @@ -328,6 +334,10 @@ javascriptcore_sources += \ Source/JavaScriptCore/jit/ThunkGenerators.cpp \ Source/JavaScriptCore/jit/ThunkGenerators.h \ Source/JavaScriptCore/llint/LLIntData.h \ + Source/JavaScriptCore/llint/LLIntEntrypoints.cpp \ + Source/JavaScriptCore/llint/LLIntEntrypoints.h \ + Source/JavaScriptCore/llint/LowLevelInterpreter.cpp \ + Source/JavaScriptCore/llint/LowLevelInterpreter.h \ Source/JavaScriptCore/os-win32/stdbool.h \ Source/JavaScriptCore/os-win32/stdint.h \ Source/JavaScriptCore/parser/ASTBuilder.h \ @@ -583,7 +593,9 @@ javascriptcore_sources += \ Source/JavaScriptCore/wtf/ByteArray.h \ Source/JavaScriptCore/wtf/CheckedArithmetic.h \ Source/JavaScriptCore/wtf/CheckedBoolean.h \ + Source/JavaScriptCore/wtf/RefCountedArray.h \ Source/JavaScriptCore/wtf/Compiler.h \ + Source/JavaScriptCore/wtf/Complex.h \ Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp \ Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h \ Source/JavaScriptCore/wtf/CurrentTime.cpp \ @@ -710,6 +722,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/wtf/SentinelLinkedList.h \ Source/JavaScriptCore/wtf/SHA1.cpp \ Source/JavaScriptCore/wtf/SHA1.h \ + Source/JavaScriptCore/wtf/SimpleStats.h \ Source/JavaScriptCore/wtf/SinglyLinkedList.h \ Source/JavaScriptCore/wtf/Spectrum.h \ Source/JavaScriptCore/wtf/StackBounds.cpp \ @@ -831,4 +844,5 @@ Programs_minidom_SOURCES = \ Source/JavaScriptCore/API/tests/minidom.c Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_SOURCES = \ + Source/JavaScriptCore/JSCTypedArrayStubs.h \ Source/JavaScriptCore/jsc.cpp diff --git a/Source/JavaScriptCore/JSCTypedArrayStubs.h b/Source/JavaScriptCore/JSCTypedArrayStubs.h index cda55fc9b..e3546ee65 100644 --- a/Source/JavaScriptCore/JSCTypedArrayStubs.h +++ b/Source/JavaScriptCore/JSCTypedArrayStubs.h @@ -151,7 +151,7 @@ void JS##name##Array::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSV m_impl->set(index, value.toNumber(exec));\ }\ \ -void JS##name##Array::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value)\ +void JS##name##Array::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool)\ {\ JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\ ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\ diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln index 009a8a044..0834a3fe8 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaScriptCore", "JavaScriptCore\JavaScriptCore.vcproj", "{011D10F1-B656-4A1B-A0C3-3842F02122C5}" ProjectSection(ProjectDependencies) = postProject - {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6} + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} = {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsc", "jsc\jsc.vcproj", "{C59E5129-B453-49B7-A52B-1E104715F76E}" @@ -13,16 +13,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsc", "jsc\jsc.vcproj", "{C EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTF", "WTF\WTF.vcproj", "{AA8A5A85-592B-4357-BC60-E0E91E026AF6}" ProjectSection(ProjectDependencies) = postProject - {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} = {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} = {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaScriptCoreGenerated", "JavaScriptCore\JavaScriptCoreGenerated.vcproj", "{4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}" + ProjectSection(ProjectDependencies) = postProject + {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testRegExp", "testRegExp\testRegExp.vcproj", "{14C94979-1ED3-4E1D-9B55-A80FCF4677D0}" ProjectSection(ProjectDependencies) = postProject {C59E5129-B453-49B7-A52B-1E104715F76E} = {C59E5129-B453-49B7-A52B-1E104715F76E} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTFGenerated", "WTF\WTFGenerated.vcproj", "{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_All|Win32 = Debug_All|Win32 @@ -77,10 +82,10 @@ Global {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.Build.0 = Production|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.Build.0 = Release_PGO|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.ActiveCfg = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.Build.0 = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.ActiveCfg = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.Build.0 = Production|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.ActiveCfg = Release|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.Build.0 = Release|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 @@ -115,6 +120,22 @@ Global {14C94979-1ED3-4E1D-9B55-A80FCF4677D0}.Release_PGO|Win32.Build.0 = Release_PGO|Win32 {14C94979-1ED3-4E1D-9B55-A80FCF4677D0}.Release|Win32.ActiveCfg = Release|Win32 {14C94979-1ED3-4E1D-9B55-A80FCF4677D0}.Release|Win32.Build.0 = Release|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_All|Win32.Build.0 = Debug_All|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug|Win32.ActiveCfg = Debug|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug|Win32.Build.0 = Debug|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Production|Win32.ActiveCfg = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Production|Win32.Build.0 = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO_Optimize|Win32.ActiveCfg = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO_Optimize|Win32.Build.0 = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO|Win32.ActiveCfg = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO|Win32.Build.0 = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release|Win32.ActiveCfg = Release|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index acdf47b7c..c50a4252b 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -137,7 +137,6 @@ EXPORTS ?dayInMonthFromDayInYear@WTF@@YAHH_N@Z ?dayInYear@WTF@@YAHNH@Z ?decrement@RefCountedLeakCounter@WTF@@QAEXXZ - ?defaultAttributes@PropertyDescriptor@JSC@@0IA ?defaultValue@JSObject@JSC@@SA?AVJSValue@2@PBV12@PAVExecState@2@W4PreferredPrimitiveType@2@@Z ?defineOwnProperty@JSGlobalObject@JSC@@SA_NPAVJSObject@2@PAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@_N@Z ?defineOwnProperty@JSObject@JSC@@SA_NPAV12@PAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@_N@Z @@ -230,7 +229,7 @@ EXPORTS ?initializeMainThread@WTF@@YAXXZ ?initializeThreading@JSC@@YAXXZ ?initializeThreading@WTF@@YAXXZ - ?interpret@Yarr@JSC@@YAHPAUBytecodePattern@12@ABVUString@2@IIPAH@Z + ?interpret@Yarr@JSC@@YAIPAUBytecodePattern@12@ABVUString@2@IIPAI@Z ?isAccessorDescriptor@PropertyDescriptor@JSC@@QBE_NXZ ?isBusy@Heap@JSC@@QAE_NXZ ?isDataDescriptor@PropertyDescriptor@JSC@@QBE_NXZ @@ -276,8 +275,8 @@ EXPORTS ?put@JSByteArray@JSC@@SAXPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@AAVPutPropertySlot@2@@Z ?put@JSGlobalObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@AAVPutPropertySlot@2@@Z ?put@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@AAVPutPropertySlot@2@@Z - ?putByIndex@JSByteArray@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@@Z - ?putByIndex@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@@Z + ?putByIndex@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@_N@Z + ?putDirectIndexBeyondVectorLength@JSArray@JSC@@AAE_NPAVExecState@2@IVJSValue@2@_N@Z ?putDirectVirtual@JSGlobalObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@I@Z ?putDirectVirtual@JSObject@JSC@@SAXPAV12@PAVExecState@2@ABVIdentifier@2@VJSValue@2@I@Z ?randomNumber@WTF@@YANXZ @@ -298,7 +297,6 @@ EXPORTS ?restoreAll@Profile@JSC@@QAEXXZ ?retrieveCallerFromVMCode@Interpreter@JSC@@QBE?AVJSValue@2@PAVExecState@2@PAVJSFunction@2@@Z ?retrieveLastCaller@Interpreter@JSC@@QBEXPAVExecState@2@AAH1AAVUString@2@AAVJSValue@2@@Z - ?s_globalObjectMethodTable@JSGlobalObject@JSC@@1UGlobalObjectMethodTable@2@B ?setConfigurable@PropertyDescriptor@JSC@@QAEX_N@Z ?setDescriptor@PropertyDescriptor@JSC@@QAEXVJSValue@2@I@Z ?setDumpsGeneratedCode@BytecodeGenerator@JSC@@SAX_N@Z @@ -350,6 +348,7 @@ EXPORTS ?toThisObject@JSObject@JSC@@SAPAV12@PAVJSCell@2@PAVExecState@2@@Z ?toThisObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z ?toUInt32@Identifier@JSC@@SAIABVUString@2@AA_N@Z + ?transfer@ArrayBuffer@WTF@@QAE_NAAVArrayBufferContents@2@AAV?$Vector@V?$RefPtr@VArrayBufferView@WTF@@@WTF@@$0A@@2@@Z ?tryFastCalloc@WTF@@YA?AUTryMallocReturnValue@1@II@Z ?tryFastMalloc@WTF@@YA?AUTryMallocReturnValue@1@I@Z ?tryFastRealloc@WTF@@YA?AUTryMallocReturnValue@1@PAXI@Z diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index b9e0f3152..8599dedb8 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -1478,6 +1478,10 @@ Name="bytecode" > <File + RelativePath="..\..\bytecode\ExecutionCounter.cpp" + > + </File> + <File RelativePath="..\..\bytecode\MethodOfGettingAValueProfile.cpp" > </File> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make index 20a9a5078..c7c640b0d 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make @@ -1,9 +1,6 @@ all: touch "%ConfigurationBuildDir%\buildfailed" bash build-generated-files.sh "%ConfigurationBuildDir%" "$(WEBKITLIBRARIESDIR)" -!IF "$(OFFICIAL_BUILD)"!="1" - bash -c "python work-around-vs-dependency-tracking-bugs.py" -!ENDIF copy-files.cmd -del "%ConfigurationBuildDir%\include\private\JavaScriptCore\stdbool.h" "%ConfigurationBuildDir%\include\private\JavaScriptCore\stdint.h" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj index 6d3351ee1..5e91b148b 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj @@ -69,15 +69,6 @@ Name="VCNMakeTool" /> </Configuration> - <Configuration - Name="Release_PGO|Win32" - ConfigurationType="0" - InheritedPropertySheets=".\JavaScriptCoreGeneratedReleasePGO.vsprops" - > - <Tool - Name="VCNMakeTool" - /> - </Configuration> </Configurations> <References> </References> @@ -98,10 +89,6 @@ RelativePath=".\JavaScriptCoreGenerated.make" > </File> - <File - RelativePath=".\work-around-vs-dependency-tracking-bugs.py" - > - </File> </Files> <Globals> </Globals> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh index 3998c65f9..56316e9d7 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh @@ -1,15 +1,5 @@ #!/usr/bin/bash -# Determine whether we have the versioned ICU 4.0 or the unversioned ICU 4.4 -UNVERSIONED_ICU_LIB_PATH=$(cygpath -u "${WEBKITLIBRARIESDIR}/lib/libicuuc.lib") -ICUVERSION_H_PATH=$(cygpath -u "${CONFIGURATIONBUILDDIR}/include/private/ICUVersion.h") -if test \( ! -f "${ICUVERSION_H_PATH}" \) -o \( -f "${UNVERSIONED_ICU_LIB_PATH}" -a \( "${UNVERSIONED_ICU_LIB_PATH}" -nt "${ICUVERSION_H_PATH}" \) \) -then - mkdir -p "$(dirname "${ICUVERSION_H_PATH}")" - test ! -f "${UNVERSIONED_ICU_LIB_PATH}" - echo "#define U_DISABLE_RENAMING $?" > "${ICUVERSION_H_PATH}" -fi - NUMCPUS=`../../../../Tools/Scripts/num-cpus` XSRCROOT="`pwd`/../.." diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd index 2c0cfad02..524e38037 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd @@ -1,83 +1,66 @@ -@echo off - -set PublicHeadersDirectory=%CONFIGURATIONBUILDDIR%\include\JavaScriptCore -set PrivateHeadersDirectory=%CONFIGURATIONBUILDDIR%\include\private\JavaScriptCore -set ResourcesDirectory=%CONFIGURATIONBUILDDIR%\bin\JavaScriptCore.resources - -if "%1" EQU "clean" goto :clean -if "%1" EQU "rebuild" call :clean - -echo Copying public headers... -mkdir "%PublicHeadersDirectory%" 2>NUL -for %%f in ( - APICast.h - APIShims.h - JSBase.h - JSContextRef.h - JSContextRefPrivate.h - JSObjectRef.h - JSObjectRefPrivate.h - JSRetainPtr.h - JSRetainPtr.h - JSStringRef.h - JSStringRefBSTR.h - JSStringRefCF.h - JSValueRef.h - JSWeakObjectMapRefInternal.h - JSWeakObjectMapRefPrivate.h - JavaScript.h - JavaScriptCore.h - OpaqueJSString.h - WebKitAvailability.h -) do ( - xcopy /y /d ..\..\API\%%f "%PublicHeadersDirectory%" >NUL -) - -echo Copying private headers... -mkdir "%PrivateHeadersDirectory%" 2>NUL -for %%d in ( - assembler - bytecode - dfg - heap - debugger - interpreter - jit - llint - parser - profiler - runtime - wtf - wtf\dtoa - wtf\text - wtf\threads - wtf\unicode - wtf\unicode\icu - yarr -) do ( - xcopy /y /d ..\..\%%d\*.h "%PrivateHeadersDirectory%" >NUL -) - -echo Copying resources... -mkdir "%ResourcesDirectory%" 2>NUL -xcopy /y /d ..\JavaScriptCore.resources\* "%ResourcesDirectory%" >NUL - -echo Copying other files... -for %%f in ( - create_hash_table - wtf\text\AtomicString.cpp - wtf\text\StringBuilder.cpp - wtf\text\StringImpl.cpp - wtf\text\WTFString.cpp -) do ( - xcopy /y /d ..\..\%%f "%PrivateHeadersDirectory%" >NUL -) - -goto :EOF - -:clean - -echo Deleting copied files... -if exist "%PublicHeadersDirectory%" rmdir /s /q "%PublicHeadersDirectory%" >NUL -if exist "%PrivateHeadersDirectory%" rmdir /s /q "%PrivateHeadersDirectory%" >NUL -if exist "%ResourcesDirectory%" rmdir /s /q "%ResourcesDirectory%" >NUL +@echo off
+
+set PublicHeadersDirectory=%CONFIGURATIONBUILDDIR%\include\JavaScriptCore
+set PrivateHeadersDirectory=%CONFIGURATIONBUILDDIR%\include\private\JavaScriptCore
+set ResourcesDirectory=%CONFIGURATIONBUILDDIR%\bin\JavaScriptCore.resources
+
+if "%1" EQU "clean" goto :clean
+if "%1" EQU "rebuild" call :clean
+
+echo Copying public headers...
+mkdir "%PublicHeadersDirectory%" 2>NUL
+for %%f in (
+ APICast.h
+ APIShims.h
+ JSBase.h
+ JSContextRef.h
+ JSContextRefPrivate.h
+ JSObjectRef.h
+ JSObjectRefPrivate.h
+ JSRetainPtr.h
+ JSRetainPtr.h
+ JSStringRef.h
+ JSStringRefBSTR.h
+ JSStringRefCF.h
+ JSValueRef.h
+ JSWeakObjectMapRefInternal.h
+ JSWeakObjectMapRefPrivate.h
+ JavaScript.h
+ JavaScriptCore.h
+ OpaqueJSString.h
+ WebKitAvailability.h
+) do (
+ xcopy /y /d ..\..\API\%%f "%PublicHeadersDirectory%" >NUL
+)
+
+echo Copying private headers...
+mkdir "%PrivateHeadersDirectory%" 2>NUL
+for %%d in (
+ assembler
+ bytecode
+ dfg
+ heap
+ debugger
+ interpreter
+ jit
+ llint
+ parser
+ profiler
+ runtime
+ yarr
+) do (
+ xcopy /y /d ..\..\%%d\*.h "%PrivateHeadersDirectory%" >NUL
+)
+
+echo Copying resources...
+mkdir "%ResourcesDirectory%" 2>NUL
+xcopy /y /d ..\JavaScriptCore.resources\* "%ResourcesDirectory%" >NUL
+
+goto :EOF
+
+:clean
+
+echo Deleting copied files...
+if exist "%PublicHeadersDirectory%" rmdir /s /q "%PublicHeadersDirectory%" >NUL
+if exist "%PrivateHeadersDirectory%" rmdir /s /q "%PrivateHeadersDirectory%" >NUL
+if exist "%ResourcesDirectory%" rmdir /s /q "%ResourcesDirectory%" >NUL
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln index 1e24f2870..2ff339fb1 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln @@ -3,26 +3,33 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaScriptCore", "JavaScriptCore\JavaScriptCore.vcproj", "{011D10F1-B656-4A1B-A0C3-3842F02122C5}" ProjectSection(ProjectDependencies) = postProject - {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTF", "WTF\WTF.vcproj", "{AA8A5A85-592B-4357-BC60-E0E91E026AF6}" - ProjectSection(ProjectDependencies) = postProject {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} = {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaScriptCoreGenerated", "JavaScriptCore\JavaScriptCoreGenerated.vcproj", "{4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}" + ProjectSection(ProjectDependencies) = postProject + {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsc", "jsc\jsc.vcproj", "{C59E5129-B453-49B7-A52B-1E104715F76E}" ProjectSection(ProjectDependencies) = postProject {011D10F1-B656-4A1B-A0C3-3842F02122C5} = {011D10F1-B656-4A1B-A0C3-3842F02122C5} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTF", "WTF\WTF.vcproj", "{AA8A5A85-592B-4357-BC60-E0E91E026AF6}" + ProjectSection(ProjectDependencies) = postProject + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} = {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTFGenerated", "WTF\WTFGenerated.vcproj", "{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_All|Win32 = Debug_All|Win32 + Debug_Cairo_CFLite|Win32 = Debug_Cairo_CFLite|Win32 Debug|Win32 = Debug|Win32 Production|Win32 = Production|Win32 + Release_Cairo_CFLite|Win32 = Release_Cairo_CFLite|Win32 Release_PGO_Optimize|Win32 = Release_PGO_Optimize|Win32 Release_PGO|Win32 = Release_PGO|Win32 Release|Win32 = Release|Win32 @@ -30,34 +37,30 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug_All|Win32.Build.0 = Debug_All|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug|Win32.ActiveCfg = Debug|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug|Win32.Build.0 = Debug|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Production|Win32.ActiveCfg = Production|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Production|Win32.Build.0 = Production|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO_Optimize|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO_Optimize|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO|Win32.Build.0 = Release_PGO|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release|Win32.ActiveCfg = Release|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release|Win32.Build.0 = Release|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.ActiveCfg = Debug|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.Build.0 = Debug|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.ActiveCfg = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.Build.0 = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.Build.0 = Release_PGO|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.ActiveCfg = Release|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.Build.0 = Release|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug_All|Win32.Build.0 = Debug_All|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug|Win32.ActiveCfg = Debug|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug|Win32.Build.0 = Debug|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Production|Win32.ActiveCfg = Production|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Production|Win32.Build.0 = Production|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -66,16 +69,52 @@ Global {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release|Win32.Build.0 = Release|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug_All|Win32.Build.0 = Debug_All|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug|Win32.ActiveCfg = Debug|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug|Win32.Build.0 = Debug|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Production|Win32.ActiveCfg = Production|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Production|Win32.Build.0 = Production|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO|Win32.Build.0 = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release|Win32.ActiveCfg = Release|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release|Win32.Build.0 = Release|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.Build.0 = Debug_All|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.Build.0 = Debug|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.ActiveCfg = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.Build.0 = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.ActiveCfg = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.Build.0 = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.ActiveCfg = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.Build.0 = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.ActiveCfg = Release|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.Build.0 = Release|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_All|Win32.Build.0 = Debug_All|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug|Win32.ActiveCfg = Debug|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug|Win32.Build.0 = Debug|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Production|Win32.ActiveCfg = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Production|Win32.Build.0 = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO_Optimize|Win32.ActiveCfg = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO_Optimize|Win32.Build.0 = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO|Win32.ActiveCfg = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO|Win32.Build.0 = Production|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release|Win32.ActiveCfg = Release|Win32 + {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index 5689b2608..3bf7817f3 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -328,58 +328,6 @@ Name="VCPostBuildEventTool" /> </Configuration> - <Configuration - Name="Release_PGO|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\WTFReleasePGO.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> </Configurations> <References> </References> @@ -512,93 +460,85 @@ > </File> </Filter> - <Filter - Name="dtoa" - > - <File - RelativePath="..\..\wtf\dtoa\bignum-dtoa.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\bignum-dtoa.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\bignum.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\bignum.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\cached-powers.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\cached-powers.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\diy-fp.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\diy-fp.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\double-conversion.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\double-conversion.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\double.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fast-dtoa.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fast-dtoa.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fixed-dtoa.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fixed-dtoa.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\strtod.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\strtod.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\utils.h" - > - </File> - </Filter> + <Filter + Name="dtoa" + > + <File + RelativePath="..\..\wtf\dtoa\bignum-dtoa.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\bignum-dtoa.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\bignum.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\bignum.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\cached-powers.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\cached-powers.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\diy-fp.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\diy-fp.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\double-conversion.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\double-conversion.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\double.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\fast-dtoa.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\fast-dtoa.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\fixed-dtoa.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\fixed-dtoa.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\strtod.cc" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\strtod.h" + > + </File> + <File + RelativePath="..\..\wtf\dtoa\utils.h" + > + </File> + </Filter> <Filter Name="threads" > - <Filter - Name="win" - > - <File - RelativePath="..\..\wtf\threads\win\BinarySemaphoreWin.cpp" - > - </File> - </Filter> <File RelativePath="..\..\wtf\threads\BinarySemaphore.cpp" > @@ -607,6 +547,14 @@ RelativePath="..\..\wtf\threads\BinarySemaphore.h" > </File> + <Filter + Name="win" + > + <File + RelativePath="..\..\wtf\threads\win\BinarySemaphoreWin.cpp" + > + </File> + </Filter> </Filter> <File RelativePath="..\..\wtf\Alignment.h" @@ -653,15 +601,15 @@ > </File> <File - RelativePath="..\..\wtf\BitVector.cpp" + RelativePath="..\..\wtf\Bitmap.h" > </File> <File - RelativePath="..\..\wtf\BitVector.h" + RelativePath="..\..\wtf\BitVector.cpp" > </File> <File - RelativePath="..\..\wtf\Bitmap.h" + RelativePath="..\..\wtf\BitVector.h" > </File> <File @@ -721,23 +669,23 @@ > </File> <File - RelativePath="..\..\wtf\DecimalNumber.cpp" + RelativePath="..\..\wtf\DataLog.cpp" > </File> <File - RelativePath="..\..\wtf\DecimalNumber.h" + RelativePath="..\..\wtf\DataLog.h" > </File> <File - RelativePath="..\..\wtf\Decoder.h" + RelativePath="..\..\wtf\DecimalNumber.cpp" > </File> <File - RelativePath="..\..\wtf\DataLog.cpp" + RelativePath="..\..\wtf\DecimalNumber.h" > </File> <File - RelativePath="..\..\wtf\DataLog.h" + RelativePath="..\..\wtf\Decoder.h" > </File> <File @@ -753,27 +701,19 @@ > </File> <File - RelativePath="..\..\wtf\DynamicAnnotations.cpp" - > - </File> - <File - RelativePath="..\..\wtf\DynamicAnnotations.h" - > - </File> - <File - RelativePath="..\..\wtf\Float32Array.h" + RelativePath="..\..\wtf\dtoa.cpp" > </File> <File - RelativePath="..\..\wtf\Float64Array.h" + RelativePath="..\..\wtf\dtoa.h" > </File> <File - RelativePath="..\..\wtf\dtoa.cpp" + RelativePath="..\..\wtf\DynamicAnnotations.cpp" > </File> <File - RelativePath="..\..\wtf\dtoa.h" + RelativePath="..\..\wtf\DynamicAnnotations.h" > </File> <File @@ -811,14 +751,6 @@ DisableSpecificWarnings="4702" /> </FileConfiguration> - <FileConfiguration - Name="Release_PGO|Win32" - > - <Tool - Name="VCCLCompilerTool" - DisableSpecificWarnings="4702" - /> - </FileConfiguration> </File> <File RelativePath="..\..\wtf\FastMalloc.h" @@ -829,6 +761,14 @@ > </File> <File + RelativePath="..\..\wtf\Float32Array.h" + > + </File> + <File + RelativePath="..\..\wtf\Float64Array.h" + > + </File> + <File RelativePath="..\..\wtf\Forward.h" > </File> @@ -917,27 +857,27 @@ > </File> <File - RelativePath="..\..\wtf\MetaAllocator.cpp" + RelativePath="..\..\wtf\MD5.cpp" > </File> <File - RelativePath="..\..\wtf\MetaAllocator.h" + RelativePath="..\..\wtf\MD5.h" > </File> <File - RelativePath="..\..\wtf\MetaAllocatorHandle.h" + RelativePath="..\..\wtf\MessageQueue.h" > </File> <File - RelativePath="..\..\wtf\MD5.cpp" + RelativePath="..\..\wtf\MetaAllocator.cpp" > </File> <File - RelativePath="..\..\wtf\MD5.h" + RelativePath="..\..\wtf\MetaAllocator.h" > </File> <File - RelativePath="..\..\wtf\MessageQueue.h" + RelativePath="..\..\wtf\MetaAllocatorHandle.h" > </File> <File @@ -1021,39 +961,39 @@ > </File> <File - RelativePath="..\..\wtf\PassOwnArrayPtr.h" + RelativePath="..\..\wtf\ParallelJobs.h" > </File> <File - RelativePath="..\..\wtf\PassOwnPtr.h" + RelativePath="..\..\wtf\ParallelJobsGeneric.cpp" > </File> <File - RelativePath="..\..\wtf\PassRefPtr.h" + RelativePath="..\..\wtf\ParallelJobsGeneric.h" > </File> <File - RelativePath="..\..\wtf\PassTraits.h" + RelativePath="..\..\wtf\ParallelJobsLibdispatch.h" > </File> <File - RelativePath="..\..\wtf\ParallelJobs.h" + RelativePath="..\..\wtf\ParallelJobsOpenMP.h" > </File> <File - RelativePath="..\..\wtf\ParallelJobsGeneric.cpp" + RelativePath="..\..\wtf\PassOwnArrayPtr.h" > </File> <File - RelativePath="..\..\wtf\ParallelJobsGeneric.h" + RelativePath="..\..\wtf\PassOwnPtr.h" > </File> <File - RelativePath="..\..\wtf\ParallelJobsLibdispatch.h" + RelativePath="..\..\wtf\PassRefPtr.h" > </File> <File - RelativePath="..\..\wtf\ParallelJobsOpenMP.h" + RelativePath="..\..\wtf\PassTraits.h" > </File> <File diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.make b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.make new file mode 100644 index 000000000..e7896fdfb --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.make @@ -0,0 +1,13 @@ +all: + touch "%ConfigurationBuildDir%\buildfailed" + bash build-generated-files.sh "%ConfigurationBuildDir%" "$(WEBKITLIBRARIESDIR)" +!IF "$(OFFICIAL_BUILD)"!="1" + bash -c "python work-around-vs-dependency-tracking-bugs.py" +!ENDIF + copy-files.cmd + + -del "%ConfigurationBuildDir%\buildfailed" + +clean: + -del "%ConfigurationBuildDir%\buildfailed" + copy-files.cmd clean diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj new file mode 100644 index 000000000..3cb825062 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="WTFGenerated" + ProjectGUID="{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}" + RootNamespace="WTFGenerated" + Keyword="MakeFileProj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="0" + InheritedPropertySheets=".\WTFGeneratedDebug.vsprops" + > + <Tool + Name="VCNMakeTool" + /> + </Configuration> + <Configuration + Name="Debug_All|Win32" + ConfigurationType="0" + InheritedPropertySheets=".\WTFGeneratedDebugAll.vsprops" + > + <Tool + Name="VCNMakeTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="0" + InheritedPropertySheets=".\WTFGeneratedRelease.vsprops" + > + <Tool + Name="VCNMakeTool" + /> + </Configuration> + <Configuration + Name="Production|Win32" + ConfigurationType="0" + InheritedPropertySheets=".\WTFGeneratedProduction.vsprops" + > + <Tool + Name="VCNMakeTool" + /> + </Configuration> + <Configuration + Name="Release_Cairo_CFLite|Win32" + ConfigurationType="0" + InheritedPropertySheets=".\WTFGeneratedReleaseCairoCFLite.vsprops" + > + <Tool + Name="VCNMakeTool" + /> + </Configuration> + <Configuration + Name="Debug_Cairo_CFLite|Win32" + ConfigurationType="0" + InheritedPropertySheets=".\WTFGeneratedDebugCairoCFLite.vsprops" + > + <Tool + Name="VCNMakeTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath=".\build-generated-files.sh" + > + </File> + <File + RelativePath=".\copy-files.cmd" + > + </File> + <File + RelativePath=".\work-around-vs-dependency-tracking-bugs.py" + > + </File> + <File + RelativePath=".\WTFGenerated.make" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops new file mode 100644 index 000000000..5173df8ef --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFGeneratedCommon" + OutputDirectory="$(ConfigurationBuildDir)\lib" + > + <Tool + Name="VCNMakeTool" + BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f WTFGenerated.make" + ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f WTFGenerated.make clean
nmake -f WTFGenerated.make" + CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f WTFGenerated.make clean" + /> +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops new file mode 100644 index 000000000..bc16aca94 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFGeneratedDebug" + InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\WTFGeneratedCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops new file mode 100644 index 000000000..cacea402c --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFGeneratedDebugAll" + InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops;.\WTFGeneratedCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops new file mode 100644 index 000000000..fbc371372 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFGeneratedDebugCairoCFLite" + InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\WTFGeneratedCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops new file mode 100644 index 000000000..3e49ed6ea --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFGeneratedProduction" + InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\WTFGeneratedCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedRelease.vsprops index 41b7f7bfa..74a4debaa 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedRelease.vsprops @@ -2,7 +2,7 @@ <VisualStudioPropertySheet ProjectType="Visual C++" Version="8.00" - Name="WTFReleasePGO" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\WTFCommon.vsprops" + Name="WTFGeneratedRelease" + InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\WTFGeneratedCommon.vsprops" > </VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops new file mode 100644 index 000000000..730d71941 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFGeneratedReleaseCairoCFLite" + InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\WTFGeneratedCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/build-generated-files.sh b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/build-generated-files.sh new file mode 100755 index 000000000..d1a4e560f --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/build-generated-files.sh @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +# Determine whether we have the versioned ICU 4.0 or the unversioned ICU 4.4 +UNVERSIONED_ICU_LIB_PATH=$(cygpath -u "${WEBKITLIBRARIESDIR}/lib/libicuuc.lib") +ICUVERSION_H_PATH=$(cygpath -u "${CONFIGURATIONBUILDDIR}/include/private/ICUVersion.h") +if test \( ! -f "${ICUVERSION_H_PATH}" \) -o \( -f "${UNVERSIONED_ICU_LIB_PATH}" -a \( "${UNVERSIONED_ICU_LIB_PATH}" -nt "${ICUVERSION_H_PATH}" \) \) +then + mkdir -p "$(dirname "${ICUVERSION_H_PATH}")" + test ! -f "${UNVERSIONED_ICU_LIB_PATH}" + echo "#define U_DISABLE_RENAMING $?" > "${ICUVERSION_H_PATH}" +fi diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/copy-files.cmd b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/copy-files.cmd new file mode 100755 index 000000000..3160e5cc1 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/copy-files.cmd @@ -0,0 +1,37 @@ +@echo off
+
+set PrivateHeadersDirectory=%CONFIGURATIONBUILDDIR%\include\private\JavaScriptCore
+
+if "%1" EQU "clean" goto :clean
+if "%1" EQU "rebuild" call :clean
+
+echo Copying WTF headers...
+for %%d in (
+ wtf
+ wtf\dtoa
+ wtf\text
+ wtf\threads
+ wtf\unicode
+ wtf\unicode\icu
+) do (
+ mkdir "%PrivateHeadersDirectory%\%%d" 2>NUL
+ xcopy /y /d ..\..\%%d\*.h "%PrivateHeadersDirectory%\%%d" >NUL
+)
+
+echo Copying other files...
+for %%f in (
+ create_hash_table
+ wtf\text\AtomicString.cpp
+ wtf\text\StringBuilder.cpp
+ wtf\text\StringImpl.cpp
+ wtf\text\WTFString.cpp
+) do (
+ echo F | xcopy /y /d ..\..\%%f "%PrivateHeadersDirectory%\%%f" >NUL
+)
+
+goto :EOF
+
+:clean
+
+echo Deleting copied files...
+if exist "%PrivateHeadersDirectory%" rmdir /s /q "%PrivateHeadersDirectory%" >NUL
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/work-around-vs-dependency-tracking-bugs.py b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/work-around-vs-dependency-tracking-bugs.py index 5060f69c4..5060f69c4 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/work-around-vs-dependency-tracking-bugs.py +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/work-around-vs-dependency-tracking-bugs.py diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj index a650cd2e5..21f13fc47 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj @@ -448,7 +448,7 @@ </References> <Files> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\AtomicString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\AtomicString.cpp" > </File> <File @@ -456,15 +456,15 @@ > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\StringBuilder.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringBuilder.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\StringImpl.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringImpl.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\WTFString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\WTFString.cpp" > </File> </Files> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj index b80b059f6..6d44dce91 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj @@ -448,15 +448,15 @@ </References> <Files> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\AtomicString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\AtomicString.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\StringBuilder.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringBuilder.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\StringImpl.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringImpl.cpp" > </File> <File @@ -464,7 +464,7 @@ > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\WTFString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\WTFString.cpp" > </File> </Files> diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index d9d8e1631..a72046e2c 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -49,17 +49,13 @@ /* Begin PBXBuildFile section */ 06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06D358A20DAAD9C4003B174E /* MainThread.cpp */; }; 06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 06D358A10DAAD9C4003B174E /* MainThreadMac.mm */; }; - 081469491264378500DFF935 /* StringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 081469481264375E00DFF935 /* StringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 088FA5BB0EF76D4300578E6F /* RandomNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */; }; - 088FA5BC0EF76D4300578E6F /* RandomNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 088FA5BA0EF76D4300578E6F /* RandomNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 08CABBA61265AB3900B206CE /* StringConcatenate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0896C29E1265AB0900B1CDD3 /* StringConcatenate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 08DDA5C11264631700751732 /* UStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 08DDA5BB12645F1D00751732 /* UStringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 08E279E90EF83B10007DB523 /* RandomNumberSeed.h in Headers */ = {isa = PBXBuildFile; fileRef = 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */; }; + 0A4337BB1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A4337BA1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp */; }; + 0A4337BE1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A4337BD1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h */; }; 0B330C270F38C62300692DE3 /* TypeTraits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0B330C260F38C62300692DE3 /* TypeTraits.cpp */; }; - 0B4D7E630F319AC800AD7E58 /* TypeTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0BAC94A01338728400CF135B /* ThreadRestrictionVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0BCD83571485845200EA2003 /* TemporaryChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BCD83541485841200EA2003 /* TemporaryChange.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; }; + 0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */; }; 0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; }; @@ -77,6 +73,7 @@ 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; }; + 0F1D0861150C5A860074D109 /* DFGNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1D085F150C5A800074D109 /* DFGNode.cpp */; }; 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C26614BE5F5E00ADC64B /* JITDriver.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -84,7 +81,6 @@ 0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */; }; - 0F2E5BF7146357D5003EB2EB /* Spectrum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2E5BF5146357D2003EB2EB /* Spectrum.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A451460CBAB00131F8F /* ValueRecovery.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A461460CBAB00131F8F /* VirtualRegister.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A4A1460CD6B00131F8F /* DataFormat.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -105,6 +101,8 @@ 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */; }; 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F55F0F214D1063600AC7649 /* AbstractPC.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56A1D115000F31002992B1 /* ExecutionCounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */; }; 0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620175143FCD370068B77C /* DFGOperands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620171143FCD2F0068B77C /* DFGOperands.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -112,7 +110,6 @@ 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; }; - 0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636D9F142D27D200B2E66A /* PackedIntVector.h */; }; 0F66E16B14DF3F1600B7B2E4 /* DFGNodeReferenceBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGNodeReferenceBlob.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F66E16C14DF3F1600B7B2E4 /* DFGNodeUse.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGNodeUse.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; }; @@ -129,16 +126,12 @@ 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */; }; 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0F963B2713F753BB0002D9B2 /* RedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2613F753990002D9B2 /* RedBlackTree.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F963B2C13F853EC0002D9B2 /* MetaAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; }; - 0F963B2D13F854020002D9B2 /* MetaAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0F963B2F13FC66BB0002D9B2 /* MetaAllocatorHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */; }; 0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F9FC8D014E612D800D52AE0 /* DataLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FC8CD14E612D500D52AE0 /* DataLog.cpp */; }; - 0F9FC8D114E612DA00D52AE0 /* DataLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8CE14E612D500D52AE0 /* DataLog.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */; }; 0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -164,16 +157,13 @@ 0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC815121405118600CFA603 /* VTableSpectrum.cpp */; }; 0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3C82014115CF800FD81CB /* DFGDriver.cpp */; }; 0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3C82214115D0E00FD81CB /* DFGDriver.h */; }; - 0FD52AAE143035A00026DC9F /* UnionFind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD52AAC1430359D0026DC9F /* UnionFind.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */; }; 0FD82E39141AB14D00179C94 /* CompactJITCodeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E54141DAEEE00179C94 /* PredictedType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E4F141DAEA100179C94 /* PredictedType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E55141DAEEE00179C94 /* PredictionTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E50141DAEA100179C94 /* PredictionTracker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */; }; 0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0FD82E85141F3FE300179C94 /* BoundsCheckedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E82141F3FC900179C94 /* BoundsCheckedPointer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */; }; - 0FD82F4B142806A100179C94 /* BitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82F491428069200179C94 /* BitVector.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; }; 0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; }; @@ -189,7 +179,6 @@ 0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */; }; 0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; }; 140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */; }; 140566D1107EC267005DBC8D /* JSStaticScopeObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */; }; @@ -253,7 +242,6 @@ 1440F8920A508B100005F061 /* JSCallbackFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1440F8900A508B100005F061 /* JSCallbackFunction.cpp */; }; 1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1440F8AD0A508D200005F061 /* JSCallbackConstructor.cpp */; }; 1440FCE40A51E46B0005F061 /* JSClassRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1440FCE20A51E46B0005F061 /* JSClassRef.cpp */; }; - 14456A321314657800212CA3 /* DoublyLinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = 14456A311314657800212CA3 /* DoublyLinkedList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14469DD7107EC79E00650446 /* dtoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 651F6412039D5B5F0078395C /* dtoa.cpp */; }; 14469DDE107EC7E700650446 /* Lookup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8680255597D01FF60F7 /* Lookup.cpp */; }; 14469DDF107EC7E700650446 /* MathObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A86A0255597D01FF60F7 /* MathObject.cpp */; }; @@ -318,7 +306,6 @@ 14A42E3F0F4F60EE00599099 /* TimeoutChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14A42E3D0F4F60EE00599099 /* TimeoutChecker.cpp */; }; 14A42E400F4F60EE00599099 /* TimeoutChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A42E3E0F4F60EE00599099 /* TimeoutChecker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */; }; - 14B3EF0512BC24DD00D29EFF /* PageBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B3EF0312BC24DD00D29EFF /* PageBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14B3EF0612BC24DD00D29EFF /* PageBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */; }; 14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */; }; 14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -338,43 +325,20 @@ 14F8BA43107EC88C009892DC /* TCSystemAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6541BD7008E80A17002CBEE7 /* TCSystemAlloc.cpp */; }; 14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F97446138C853E00DA1C67 /* HeapRootVisitor.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14FFF98C12BFFF7500795BB8 /* PageAllocationAligned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14FFF98A12BFFF7500795BB8 /* PageAllocationAligned.cpp */; }; - 14FFF98D12BFFF7500795BB8 /* PageAllocationAligned.h in Headers */ = {isa = PBXBuildFile; fileRef = 14FFF98B12BFFF7500795BB8 /* PageAllocationAligned.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 180B9AF00F16C569009BDBC5 /* CurrentTime.h */; settings = {ATTRIBUTES = (Private, ); }; }; 180B9BFE0F16E94D009BDBC5 /* CurrentTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */; }; 18BAB55310DAE054000D945B /* ThreadIdentifierDataPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18BAB52710DADFCD000D945B /* ThreadIdentifierDataPthreads.cpp */; }; - 18BAB55410DAE066000D945B /* ThreadIdentifierDataPthreads.h in Headers */ = {isa = PBXBuildFile; fileRef = 18BAB52810DADFCD000D945B /* ThreadIdentifierDataPthreads.h */; }; 1A082779142168D70090CCAC /* BinarySemaphore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A082777142168D70090CCAC /* BinarySemaphore.cpp */; }; 1A08277A142168D70090CCAC /* BinarySemaphore.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A082778142168D70090CCAC /* BinarySemaphore.h */; }; - 1AA9E5511498093500001A8A /* Functional.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA9E5501498093500001A8A /* Functional.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2684B2D314D4A9B20072C0B6 /* ParsedURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2C414D4A9B20072C0B6 /* ParsedURL.cpp */; }; - 2684B2D414D4A9B20072C0B6 /* ParsedURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2C514D4A9B20072C0B6 /* ParsedURL.h */; }; - 2684B2D514D4A9B20072C0B6 /* URLString.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2C614D4A9B20072C0B6 /* URLString.h */; }; - 2684B2D614D4A9B20072C0B6 /* RawURLBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2C814D4A9B20072C0B6 /* RawURLBuffer.h */; }; - 2684B2D714D4A9B20072C0B6 /* URLBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2C914D4A9B20072C0B6 /* URLBuffer.h */; }; 2684B2D814D4A9B20072C0B6 /* URLCharacterTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2CA14D4A9B20072C0B6 /* URLCharacterTypes.cpp */; }; - 2684B2D914D4A9B20072C0B6 /* URLCharacterTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2CB14D4A9B20072C0B6 /* URLCharacterTypes.h */; }; - 2684B2DA14D4A9B20072C0B6 /* URLComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2CC14D4A9B20072C0B6 /* URLComponent.h */; }; 2684B2DB14D4A9B20072C0B6 /* URLEscape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2CD14D4A9B20072C0B6 /* URLEscape.cpp */; }; - 2684B2DC14D4A9B20072C0B6 /* URLEscape.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2CE14D4A9B20072C0B6 /* URLEscape.h */; }; - 2684B2DD14D4A9B20072C0B6 /* URLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2CF14D4A9B20072C0B6 /* URLParser.h */; }; - 2684B2DE14D4A9B20072C0B6 /* URLQueryCanonicalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2D014D4A9B20072C0B6 /* URLQueryCanonicalizer.h */; }; 2684B2DF14D4A9B20072C0B6 /* URLSegments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2D114D4A9B20072C0B6 /* URLSegments.cpp */; }; - 2684B2E014D4A9B20072C0B6 /* URLSegments.h in Headers */ = {isa = PBXBuildFile; fileRef = 2684B2D214D4A9B20072C0B6 /* URLSegments.h */; }; - 2CFC5D1E12F45B48004914E2 /* CharacterNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CFC5B7A12F44714004914E2 /* CharacterNames.h */; settings = {ATTRIBUTES = (Private, ); }; }; 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateConversion.h */; }; 41359CF60FDD89CB00206180 /* DateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41359CF40FDD89CB00206180 /* DateMath.cpp */; }; - 41359CF70FDD89CB00206180 /* DateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 41359CF50FDD89CB00206180 /* DateMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 434A8E7114956A50009126F7 /* ASCIIFastPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 434A8E7014956A50009126F7 /* ASCIIFastPath.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4409D8470FAF80A200523B87 /* OwnPtrCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 440B7AED0FAF7FCB0073323E /* OwnPtrCommon.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 44DD48530FAEA85000D6B4EB /* PassOwnPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 44DD48520FAEA85000D6B4EB /* PassOwnPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; 451539B912DC994500EF7AC4 /* Yarr.h in Headers */ = {isa = PBXBuildFile; fileRef = 451539B812DC994500EF7AC4 /* Yarr.h */; settings = {ATTRIBUTES = (Private, ); }; }; 511FC4C9117EE28700425272 /* MD5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511FC4C7117EE23D00425272 /* MD5.cpp */; }; - 511FC4CB117EE2A800425272 /* MD5.h in Headers */ = {isa = PBXBuildFile; fileRef = 511FC4CA117EE2A800425272 /* MD5.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 5135FAF212D26ACE003C083B /* Decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5135FAD512D26856003C083B /* Decoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 5135FAF312D26AD1003C083B /* Encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5135FAD612D26856003C083B /* Encoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; }; 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; - 5D63E9AD10F2BD6E00FC8AE9 /* StringHasher.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D63E9AC10F2BD6E00FC8AE9 /* StringHasher.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5D6A566B0F05995500266145 /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D6A566A0F05995500266145 /* Threading.cpp */; }; 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; }; 5DBB1525131D0BD70056AD36 /* minidom.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 1412110D0A48788700480255 /* minidom.js */; }; @@ -383,21 +347,12 @@ 651122FD14046A4C002B101D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; }; 651122FE14046A4C002B101D /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; 6511230714046B0A002B101D /* testRegExp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 651122E5140469BA002B101D /* testRegExp.cpp */; }; - 651DCA04136A6FEF00F74194 /* PassTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 651DCA02136A6FAB00F74194 /* PassTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; 65303D641447B9E100D3F904 /* ParserTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = 65303D631447B9E100D3F904 /* ParserTokens.h */; settings = {ATTRIBUTES = (Private, ); }; }; 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 655EB29A10CE2581001A990E /* NodesCodegen.cpp */; }; 65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65DFC92D08EA173A00F7300B /* HashTable.cpp */; }; - 65E1A3DF122B894500B26097 /* NonCopyingSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E1A2F4122B880D00B26097 /* NonCopyingSort.h */; settings = {ATTRIBUTES = (Private, ); }; }; 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B808E7EECC0023E5F6 /* Assertions.cpp */; }; - 7186A6EC13100BA5004479E1 /* HexNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 7186A6E813100B57004479E1 /* HexNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 71DA9D82134F3F3D00B767E7 /* StringOperators.h in Headers */ = {isa = PBXBuildFile; fileRef = 718A8482134F3A1200B87529 /* StringOperators.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 76FB9F0F12E851860051A2EB /* SHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = 76FB9F0E12E851860051A2EB /* SHA1.h */; settings = {ATTRIBUTES = (Private, ); }; }; 76FB9F1112E851960051A2EB /* SHA1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76FB9F1012E851960051A2EB /* SHA1.cpp */; }; - 7934BB7B1361979300CB99A1 /* ParallelJobs.h in Headers */ = {isa = PBXBuildFile; fileRef = 7934BB761361979300CB99A1 /* ParallelJobs.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7934BB7C1361979400CB99A1 /* ParallelJobsGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7934BB771361979300CB99A1 /* ParallelJobsGeneric.cpp */; }; - 7934BB7D1361979400CB99A1 /* ParallelJobsGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 7934BB781361979300CB99A1 /* ParallelJobsGeneric.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 7934BB7E1361979400CB99A1 /* ParallelJobsLibdispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 7934BB791361979300CB99A1 /* ParallelJobsLibdispatch.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 7934BB7F1361979400CB99A1 /* ParallelJobsOpenMP.h in Headers */ = {isa = PBXBuildFile; fileRef = 7934BB7A1361979300CB99A1 /* ParallelJobsOpenMP.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E4EE7080EBB7963005934AA /* StructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */; }; 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */; }; @@ -409,16 +364,13 @@ 8604F505143CE1C200B295F5 /* JSGlobalThis.h in Headers */ = {isa = PBXBuildFile; fileRef = 8604F503143CE1C100B295F5 /* JSGlobalThis.h */; settings = {ATTRIBUTES = (Private, ); }; }; 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BF642A148DB2B5004DE36A /* Intrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; }; 8626BECF11928E3900782FAB /* StringStatics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8626BECE11928E3900782FAB /* StringStatics.cpp */; }; - 8627E5EC11F1281900A313B5 /* PageAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8627E5EA11F1281900A313B5 /* PageAllocation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86438FC41265503E00E0DFCA /* StringBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86438FC31265503E00E0DFCA /* StringBuilder.cpp */; }; 86565742115BE3DA00291F40 /* CString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86565740115BE3DA00291F40 /* CString.cpp */; }; - 86565743115BE3DA00291F40 /* CString.h in Headers */ = {isa = PBXBuildFile; fileRef = 86565741115BE3DA00291F40 /* CString.h */; settings = {ATTRIBUTES = (Private, ); }; }; 865A30F1135007E100CDB49E /* JSValueInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 865A30F0135007E100CDB49E /* JSValueInlineMethods.h */; settings = {ATTRIBUTES = (Private, ); }; }; 865F408810E7D56300947361 /* APIShims.h in Headers */ = {isa = PBXBuildFile; fileRef = 865F408710E7D56300947361 /* APIShims.h */; settings = {ATTRIBUTES = (Private, ); }; }; 866739D213BFDE710023D87C /* BigInteger.h in Headers */ = {isa = PBXBuildFile; fileRef = 866739D013BFDE710023D87C /* BigInteger.h */; }; 866739D313BFDE710023D87C /* Uint16WithFraction.h in Headers */ = {isa = PBXBuildFile; fileRef = 866739D113BFDE710023D87C /* Uint16WithFraction.h */; }; - 86676D5211FED9BC004B6863 /* BumpPointerAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 86676D4D11FED55D004B6863 /* BumpPointerAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */; }; 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */; }; 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */; }; @@ -431,15 +383,8 @@ 86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */; }; 86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */; }; 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA00117CEFD100B908B1 /* AtomicString.cpp */; }; - 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA01117CEFD100B908B1 /* AtomicString.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA02117CEFD100B908B1 /* AtomicStringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 868BFA0D117CEFD100B908B1 /* StringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA05117CEFD100B908B1 /* StringHash.h */; settings = {ATTRIBUTES = (Private, ); }; }; 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA06117CEFD100B908B1 /* StringImpl.cpp */; }; - 868BFA0F117CEFD100B908B1 /* StringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA07117CEFD100B908B1 /* StringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA15117CF19900B908B1 /* WTFString.cpp */; }; - 868BFA18117CF19900B908B1 /* WTFString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA16117CF19900B908B1 /* WTFString.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA5F117D048200B908B1 /* StaticConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8690231512092D5C00630AF9 /* PageReservation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8690231412092D5C00630AF9 /* PageReservation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */; }; @@ -452,7 +397,6 @@ 86AE6C4E136A11E400963012 /* DFGGPRInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 86AE6C4C136A11E400963012 /* DFGGPRInfo.h */; }; 86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86B5822E14D2373B00A9C306 /* CodeProfile.cpp */; }; 86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8603CEF214C7546400AE59E3 /* CodeProfiling.cpp */; }; - 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86BB09BE138E381B0056702F /* DFGRepatch.cpp */; }; 86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; }; 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -466,7 +410,6 @@ 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */; }; 86CCEFDE0F413F8900FD7F9E /* JITCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CCEFDD0F413F8900FD7F9E /* JITCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D08D5111793613006E5ED0 /* WTFThreadData.cpp */; }; - 86D08D5411793613006E5ED0 /* WTFThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D08D5211793613006E5ED0 /* WTFThreadData.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D3B2BF10156BDE002865E7 /* ARMAssembler.cpp */; }; 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C010156BDE002865E7 /* ARMAssembler.h */; }; 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */; }; @@ -474,7 +417,6 @@ 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; }; 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; }; 86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */; }; - 86D87DDB12BCAF94008E73A1 /* StackBounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D87DA612BC4B14008E73A1 /* StackBounds.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; }; 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; }; @@ -492,14 +434,11 @@ 86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */; }; 86ECA3EA132DEF1C002B2AD7 /* DFGNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */; }; 86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */; }; - 86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F38858121130CA007A7CE3 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */; }; 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; }; 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; }; 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */; }; - 90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 91A3905614C0F47200F67901 /* Uint8ClampedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 91A3905514C0F47200F67901 /* Uint8ClampedArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; 93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93052C320FB792190048FDC3 /* ParserArena.cpp */; }; 93052C350FB792190048FDC3 /* ParserArena.h in Headers */ = {isa = PBXBuildFile; fileRef = 93052C330FB792190048FDC3 /* ParserArena.h */; settings = {ATTRIBUTES = (Private, ); }; }; 932F5BD30822A1C700736975 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; }; @@ -510,7 +449,6 @@ 933040040E6A749400786E6A /* SmallStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 93303FEA0E6A72C000786E6A /* SmallStrings.h */; settings = {ATTRIBUTES = (Private, ); }; }; 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93303FE80E6A72B500786E6A /* SmallStrings.cpp */; }; 9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93345A8712D838C400302BE3 /* StringRecursionChecker.cpp */; }; - 933F5CDC1269229B0049191E /* NullPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 933F5CDB126922690049191E /* NullPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; 93854A9A12C93D3B00DAAF77 /* NullPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93854A9912C93D3B00DAAF77 /* NullPtr.cpp */; }; 9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 95742F650DD11F5A000917FB /* Profile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95742F630DD11F5A000917FB /* Profile.cpp */; }; @@ -527,25 +465,20 @@ 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */; }; 969A072A0ED1CE6900F1F681 /* Label.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07270ED1CE6900F1F681 /* Label.h */; }; 969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07280ED1CE6900F1F681 /* RegisterID.h */; }; - 969A072C0ED1CE6900F1F681 /* SegmentedVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07290ED1CE6900F1F681 /* SegmentedVector.h */; settings = {ATTRIBUTES = (Private, ); }; }; 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 969A07900ED1D3AE00F1F681 /* CodeBlock.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; }; 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07910ED1D3AE00F1F681 /* CodeBlock.h */; settings = {ATTRIBUTES = (); }; }; 969A07980ED1D3AE00F1F681 /* EvalCodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */; }; 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07930ED1D3AE00F1F681 /* Instruction.h */; }; 969A079A0ED1D3AE00F1F681 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 969A07940ED1D3AE00F1F681 /* Opcode.cpp */; }; 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07950ED1D3AE00F1F681 /* Opcode.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 96DD73790F9DA3100027FBCC /* VMTags.h in Headers */ = {isa = PBXBuildFile; fileRef = 96DD73780F9DA3100027FBCC /* VMTags.h */; settings = {ATTRIBUTES = (Private, ); }; }; 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97F6903A1169DF7F00A6BB46 /* Terminator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 978801401471AD920041B016 /* JSDateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */; }; 978801411471AD920041B016 /* JSDateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9788FC231471AD0C0068CE2D /* JSDateMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; 97941A5713029AAB004A3447 /* OSRandomSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97941A3F130299DB004A3447 /* OSRandomSource.cpp */; }; - 97941A5A13029ACC004A3447 /* OSRandomSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 97941A40130299DB004A3447 /* OSRandomSource.h */; }; 97941A7E1302A098004A3447 /* CryptographicallyRandomNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97941A7C1302A098004A3447 /* CryptographicallyRandomNumber.cpp */; }; - 97941A7F1302A098004A3447 /* CryptographicallyRandomNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 97941A7D1302A098004A3447 /* CryptographicallyRandomNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1712B3A11C7B212007A5315 /* RegExpCache.cpp */; }; A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B3E11C7B228007A5315 /* RegExpCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B4011C7B235007A5315 /* RegExpKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A1D764521354448B00C5C7C0 /* Alignment.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D764511354448B00C5C7C0 /* Alignment.h */; settings = {ATTRIBUTES = (Private, ); }; }; A71236E51195F33C00BD2174 /* JITOpcodes32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */; }; A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; }; A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; }; @@ -559,19 +492,7 @@ A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7386552118697B400540279 /* ThunkGenerators.cpp */; }; A7386556118697B400540279 /* ThunkGenerators.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386553118697B400540279 /* ThunkGenerators.h */; settings = {ATTRIBUTES = (Private, ); }; }; A73BE168148420520091204B /* ArrayBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73BE154148420520091204B /* ArrayBuffer.cpp */; }; - A73BE169148420520091204B /* ArrayBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE155148420520091204B /* ArrayBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; }; A73BE16A148420520091204B /* ArrayBufferView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73BE156148420520091204B /* ArrayBufferView.cpp */; }; - A73BE16B148420520091204B /* ArrayBufferView.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE157148420520091204B /* ArrayBufferView.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE16D148420520091204B /* Float32Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE159148420520091204B /* Float32Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE16F148420520091204B /* Float64Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE15B148420520091204B /* Float64Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE171148420520091204B /* Int8Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE15D148420520091204B /* Int8Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE173148420520091204B /* Int16Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE15F148420520091204B /* Int16Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE175148420520091204B /* Int32Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE161148420520091204B /* Int32Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE177148420520091204B /* Uint8Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE163148420520091204B /* Uint8Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE179148420520091204B /* Uint16Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE165148420520091204B /* Uint16Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE17B148420520091204B /* Uint32Array.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE167148420520091204B /* Uint32Array.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE17E148420840091204B /* TypedArrayBase.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE17D148420840091204B /* TypedArrayBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE180148420A80091204B /* IntegralTypedArrayBase.h in Headers */ = {isa = PBXBuildFile; fileRef = A73BE17F148420A80091204B /* IntegralTypedArrayBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7482B9411671147003B0712 /* JSWeakObjectMapRefPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */; }; A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -587,24 +508,16 @@ A791EF280F11E07900AE1F68 /* JSByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A791EF260F11E07900AE1F68 /* JSByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; A791EF290F11E07900AE1F68 /* JSByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A791EF270F11E07900AE1F68 /* JSByteArray.cpp */; }; A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */; }; - A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; }; A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A7BC0C82140608B000B1BB71 /* CheckedArithmetic.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BC0C81140608B000B1BB71 /* CheckedArithmetic.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7C1E8E4112E72EF00A37F98 /* JITPropertyAccess32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */; }; - A7C40C0A130B057D00D002A1 /* BlockStack.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C40C07130B057D00D002A1 /* BlockStack.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A7C40C0B130B057D00D002A1 /* SentinelLinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C40C08130B057D00D002A1 /* SentinelLinkedList.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A7C40C0C130B057D00D002A1 /* SinglyLinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C40C09130B057D00D002A1 /* SinglyLinkedList.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A7D649AA1015224E009B2E1B /* PossiblyNull.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D649A91015224E009B2E1B /* PossiblyNull.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7DCB97312E5193F00911940 /* WriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DCB77912E3D90500911940 /* WriteBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */ = {isa = PBXBuildFile; fileRef = A7E2EA690FB460CF00601F06 /* LiteralParser.h */; }; A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E2EA6A0FB460CF00601F06 /* LiteralParser.cpp */; }; - A7F19ECE11DD490900931E70 /* FixedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F19ECD11DD490900931E70 /* FixedArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7F9935F0FD7325100A0B2D0 /* JSONObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F9935D0FD7325100A0B2D0 /* JSONObject.h */; }; A7F993600FD7325100A0B2D0 /* JSONObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */; }; A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */; }; A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A7FEE67614837B32005DC1A6 /* ExportMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A275F514837A8E001DBB39 /* ExportMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; }; BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; }; BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9090E1839DB000F9297 /* NativeErrorConstructor.h */; }; @@ -613,38 +526,20 @@ BC1166020E1997B4008066DD /* DateInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1166010E1997B1008066DD /* DateInstance.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC11667B0E199C05008066DD /* InternalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = BC11667A0E199C05008066DD /* InternalFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC1167DA0E19BCC9008066DD /* JSCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1167D80E19BCC9008066DD /* JSCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3E40E16F5CD00B34460 /* AlwaysInline.h in Headers */ = {isa = PBXBuildFile; fileRef = 93AA4F770957251F0084B3A7 /* AlwaysInline.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3E50E16F5CD00B34460 /* APICast.h in Headers */ = {isa = PBXBuildFile; fileRef = 1482B78A0A4305AB00517CFC /* APICast.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7952070E15E8A800A898AB /* ArrayConstructor.h */; }; BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A84E0255597D01FF60F7 /* ArrayPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3E90E16F5CD00B34460 /* ASCIICType.h in Headers */ = {isa = PBXBuildFile; fileRef = 938C4F690CA06BC700D9310A /* ASCIICType.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3EA0E16F5CD00B34460 /* Assertions.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E217B708E7EECC0023E5F6 /* Assertions.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3EB0E16F5CD00B34460 /* AVLTree.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A596370DE3E1C300C17E37 /* AVLTree.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 704FD35305697E6D003DBED9 /* BooleanObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */ = {isa = PBXBuildFile; fileRef = 145C507F0D9DF63B0088F6B9 /* CallData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3F00E16F5CD00B34460 /* Collator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A862AA0D7EBB7D001EC6AA /* Collator.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */ = {isa = PBXBuildFile; fileRef = 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BB2BC5030F772101FCFE1D /* Completion.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F50E16F5CD00B34460 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F68EBB8C0255D4C601FF60F7 /* config.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8F3CCF0DAF17BA00577A80 /* ConstructData.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3FA0E16F5CD00B34460 /* Debugger.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8590255597D01FF60F7 /* Debugger.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C3FB0E16F5CD00B34460 /* DebuggerCallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 1480DB9B0DDC227F003CFDF2 /* DebuggerCallFrame.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3FC0E16F5CD00B34460 /* Deque.h in Headers */ = {isa = PBXBuildFile; fileRef = 5186111D0CC824830081412B /* Deque.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */ = {isa = PBXBuildFile; fileRef = 938C4F6B0CA06BCE00D9310A /* DisallowCType.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C3FE0E16F5CD00B34460 /* dtoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 651F6413039D5B5F0078395C /* dtoa.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4000E16F5CD00B34460 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4020E16F5CD00B34460 /* FastMalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E217BA08E7EECC0023E5F6 /* FastMalloc.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4030E16F5CD00B34460 /* Forward.h in Headers */ = {isa = PBXBuildFile; fileRef = 935AF46909E9D9DB00ACD1D8 /* Forward.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A85D0255597D01FF60F7 /* FunctionPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4060E16F5CD00B34460 /* GetPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 93B6A0DE0AA64DA40076DE27 /* GetPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4080E16F5CD00B34460 /* HashCountedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 657EEBBF094E445E008C9C7B /* HashCountedSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4090E16F5CD00B34460 /* HashFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92A08EA173A00F7300B /* HashFunctions.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C40A0E16F5CD00B34460 /* HashIterators.h in Headers */ = {isa = PBXBuildFile; fileRef = 652246A40C8D7A0E007BDAF7 /* HashIterators.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C40B0E16F5CD00B34460 /* HashMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92B08EA173A00F7300B /* HashMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C40C0E16F5CD00B34460 /* HashSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92C08EA173A00F7300B /* HashSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92E08EA173A00F7300B /* HashTable.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DFC92F08EA173A00F7300B /* HashTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 933A349A038AE7C6008635CE /* Identifier.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */ = {isa = PBXBuildFile; fileRef = E178633F0D9BEC0000D74E75 /* InitializeThreading.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4130E16F5CD00B34460 /* JavaScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -675,17 +570,9 @@ BC18C42D0E16F5CD00B34460 /* JSVariableObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F252560D08DD8D004ECFFF /* JSVariableObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C42E0E16F5CD00B34460 /* JSWrapperObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C7A1720A8EAACB00FA37EA /* JSWrapperObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8660255597D01FF60F7 /* Lexer.h */; }; - BC18C4340E16F5CD00B34460 /* ListHashSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 657EB7450B708F540063461B /* ListHashSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4350E16F5CD00B34460 /* ListRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1626095D16BB00666D0D /* ListRefPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4360E16F5CD00B34460 /* Locker.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE79270D6C964500FEA3BA /* Locker.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4370E16F5CD00B34460 /* Lookup.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8690255597D01FF60F7 /* Lookup.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4390E16F5CD00B34460 /* MainThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 06D358A30DAAD9C4003B174E /* MainThread.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C43A0E16F5CD00B34460 /* MallocZoneSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */; settings = {ATTRIBUTES = (); }; }; - BC18C43B0E16F5CD00B34460 /* MathExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF6553B0A2048DE0038A194 /* MathExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A86B0255597D01FF60F7 /* MathObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C43E0E16F5CD00B34460 /* MessageQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE798B0D6CA53D00FEA3BA /* MessageQueue.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A86E0255597D01FF60F7 /* Nodes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4400E16F5CD00B34460 /* Noncopyable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9303F5690991190000AD71B8 /* Noncopyable.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C30E16D4E900A06E92 /* NumberConstructor.h */; }; BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680E60E16D52300A06E92 /* NumberConstructor.lut.h */; }; BC18C4430E16F5CD00B34460 /* NumberObject.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8710255597D01FF60F7 /* NumberObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -693,46 +580,25 @@ BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C70E16D4E900A06E92 /* ObjectConstructor.h */; }; BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4480E16F5CD00B34460 /* Operations.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8780255597D01FF60F7 /* Operations.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4490E16F5CD00B34460 /* OwnArrayPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C44A0E16F5CD00B34460 /* OwnPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 9303F567099118FA00AD71B8 /* OwnPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F0B3AA09BB4DC00068FCE3 /* Parser.h */; settings = {ATTRIBUTES = (); }; }; - BC18C44C0E16F5CD00B34460 /* PassRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 6580F795094070560082C219 /* PassRefPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C44F0E16F5CD00B34460 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 65D6D87E09B5A32E0002E4D7 /* Platform.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4500E16F5CD00B34460 /* Profile.h in Headers */ = {isa = PBXBuildFile; fileRef = 95742F640DD11F5A000917FB /* Profile.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB83550DA43B4400BC83F3 /* ProfileNode.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4520E16F5CD00B34460 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AB832F0DA42CAD00BC83F3 /* Profiler.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4540E16F5CD00B34460 /* PropertyNameArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 65400C100A69BAF200509887 /* PropertyNameArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 65621E6C089E859700760F35 /* PropertySlot.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4560E16F5CD00B34460 /* Protect.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C02FBB0637462A003E7EE6 /* Protect.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4570E16F5CD00B34460 /* RefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 1419D32C0CEA7CDE00FF507A /* RefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4580E16F5CD00B34460 /* RefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C647B3093EF8D60022C380 /* RefPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4590E16F5CD00B34460 /* RefPtrHashMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1ECD0D10C23B0069A47C /* RefPtrHashMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87E0255597D01FF60F7 /* RegExp.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C45B0E16F5CD00B34460 /* RegExpObject.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87C0255597D01FF60F7 /* RegExpObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C45D0E16F5CD00B34460 /* Register.h in Headers */ = {isa = PBXBuildFile; fileRef = 149B24FF0D8AF6D1009CB8C7 /* Register.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C45E0E16F5CD00B34460 /* RegisterFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D792640DAA03FB001A9F05 /* RegisterFile.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4600E16F5CD00B34460 /* RetainPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F648D60BB4E2CA0033D760 /* RetainPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4610E16F5CD00B34460 /* ScopeChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 9374D3A7038D9D74008635CE /* ScopeChain.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E866ED0DD59AFA00A2B2A1 /* SourceProvider.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E866EE0DD59AFA00A2B2A1 /* SourceCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C3C10E16EE3300B34460 /* StringConstructor.h */; }; - BC18C4670E16F5CD00B34460 /* StringExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = E11D51750B2E798D0056C188 /* StringExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4680E16F5CD00B34460 /* StringObject.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C3C30E16EE3300B34460 /* StringObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C46A0E16F5CD00B34460 /* StringPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C3C60E16EE3300B34460 /* StringPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A396A60CD2933100B5B4FF /* SymbolTable.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C46C0E16F5CD00B34460 /* TCPackedCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA479650CFBCF56009328A0 /* TCPackedCache.h */; }; - BC18C46D0E16F5CD00B34460 /* TCPageMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */; }; - BC18C46E0E16F5CD00B34460 /* TCSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C46F0E16F5CD00B34460 /* TCSystemAlloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD7108E80A17002CBEE7 /* TCSystemAlloc.h */; }; - BC18C4700E16F5CD00B34460 /* Threading.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE79220D6C95CD00FEA3BA /* Threading.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4710E16F5CD00B34460 /* ThreadSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4730E16F5CD00B34460 /* Unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = E195679409E7CF1200B89D13 /* Unicode.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4740E16F5CD00B34460 /* UnicodeIcu.h in Headers */ = {isa = PBXBuildFile; fileRef = E195678F09E7CF1200B89D13 /* UnicodeIcu.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4750E16F5CD00B34460 /* UnusedParam.h in Headers */ = {isa = PBXBuildFile; fileRef = 935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C4760E16F5CD00B34460 /* UString.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8860255597D01FF60F7 /* UString.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EF79A90CE97BA60088D500 /* UTF8.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4780E16F5CD00B34460 /* Vector.h in Headers */ = {isa = PBXBuildFile; fileRef = 6592C316098B7DE10003D4F6 /* Vector.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC18C4790E16F5CD00B34460 /* VectorTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 6592C317098B7DE10003D4F6 /* VectorTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC18C47A0E16F5CD00B34460 /* WebKitAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; }; BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C5230E16FC8A00B34460 /* ArrayPrototype.lut.h */; }; BC18C5260E16FCA700B34460 /* StringPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C5250E16FCA700B34460 /* StringPrototype.lut.h */; }; @@ -744,10 +610,6 @@ BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3135620F302FA3003DFD3A /* DebuggerActivation.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */; }; BC3C4CA01458F5450025FB62 /* JSGlobalThis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3C4C9F1458F5450025FB62 /* JSGlobalThis.cpp */; }; - BC5F7BBE11823B590052C02C /* Atomics.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBB11823B590052C02C /* Atomics.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC5F7BC011823B590052C02C /* ThreadSafeRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBD11823B590052C02C /* ThreadSafeRefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC66BAE413F492CC00C23FAE /* Compiler.h in Headers */ = {isa = PBXBuildFile; fileRef = BC66BAE213F4928F00C23FAE /* Compiler.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */; }; BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC87CDB810712ACA000614CF /* JSONObject.lut.h */; }; @@ -766,63 +628,40 @@ BCDE3AB80E6C82F5001453A7 /* Structure.h in Headers */ = {isa = PBXBuildFile; fileRef = BCDE3AB10E6C82CF001453A7 /* Structure.h */; settings = {ATTRIBUTES = (Private, ); }; }; BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCDE3AB00E6C82CF001453A7 /* Structure.cpp */; }; BCF605140E203EF800B9A64D /* ArgList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF605120E203EF800B9A64D /* ArgList.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BCFBE696122560E800309E9D /* PassOwnArrayPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFBE695122560E800309E9D /* PassOwnArrayPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFD8C900EEB2EE700283848 /* JumpTable.cpp */; }; BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; }; - C0A272630E50A06300E96E15 /* NotFound.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A2723F0E509F1E00E96E15 /* NotFound.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C52F113FAF6EF00B7DC0D /* bignum-dtoa.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529013FAF6EF00B7DC0D /* bignum-dtoa.cc */; }; - C22C52F213FAF6EF00B7DC0D /* bignum-dtoa.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529113FAF6EF00B7DC0D /* bignum-dtoa.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C52F313FAF6EF00B7DC0D /* bignum.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529213FAF6EF00B7DC0D /* bignum.cc */; }; - C22C52F413FAF6EF00B7DC0D /* bignum.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529313FAF6EF00B7DC0D /* bignum.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C52F513FAF6EF00B7DC0D /* cached-powers.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529413FAF6EF00B7DC0D /* cached-powers.cc */; }; - C22C52F613FAF6EF00B7DC0D /* cached-powers.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529513FAF6EF00B7DC0D /* cached-powers.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C52F713FAF6EF00B7DC0D /* diy-fp.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529713FAF6EF00B7DC0D /* diy-fp.cc */; }; - C22C52F813FAF6EF00B7DC0D /* diy-fp.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529813FAF6EF00B7DC0D /* diy-fp.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C52F913FAF6EF00B7DC0D /* double-conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529913FAF6EF00B7DC0D /* double-conversion.cc */; }; - C22C52FA13FAF6EF00B7DC0D /* double-conversion.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529A13FAF6EF00B7DC0D /* double-conversion.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C22C52FB13FAF6EF00B7DC0D /* double.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529B13FAF6EF00B7DC0D /* double.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C52FC13FAF6EF00B7DC0D /* fast-dtoa.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529C13FAF6EF00B7DC0D /* fast-dtoa.cc */; }; - C22C52FD13FAF6EF00B7DC0D /* fast-dtoa.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529D13FAF6EF00B7DC0D /* fast-dtoa.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C52FE13FAF6EF00B7DC0D /* fixed-dtoa.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529E13FAF6EF00B7DC0D /* fixed-dtoa.cc */; }; - C22C52FF13FAF6EF00B7DC0D /* fixed-dtoa.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C529F13FAF6EF00B7DC0D /* fixed-dtoa.h */; settings = {ATTRIBUTES = (Private, ); }; }; C22C531313FAF6EF00B7DC0D /* strtod.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C52B913FAF6EF00B7DC0D /* strtod.cc */; }; - C22C531413FAF6EF00B7DC0D /* strtod.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C52BA13FAF6EF00B7DC0D /* strtod.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C22C531513FAF6EF00B7DC0D /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C52BB13FAF6EF00B7DC0D /* utils.h */; settings = {ATTRIBUTES = (Private, ); }; }; C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C240305314B404C90079EB64 /* CopiedSpace.cpp */; }; C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B916C114DA014E00CBAC86 /* MarkedAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B916C414DA040C00CBAC86 /* MarkedAllocator.cpp */; }; C2C8D02D14A3C6E000578E65 /* CopiedSpaceInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlineMethods.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2C8D03014A3CEFC00578E65 /* CopiedBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02E14A3CEFC00578E65 /* CopiedBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2C8D03114A3CEFC00578E65 /* HeapBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2D9CA1314BCC04600304B46 /* CheckedBoolean.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAA3F8149A830800FCE112 /* CopiedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2EE59A013FC973F009CEAFE /* DecimalNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EE599E13FC972A009CEAFE /* DecimalNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2EE59A113FC9768009CEAFE /* DecimalNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2EE599D13FC972A009CEAFE /* DecimalNumber.cpp */; }; - D7A46A4F1338FFEA00ED695C /* DynamicAnnotations.h in Headers */ = {isa = PBXBuildFile; fileRef = D75AF59612F8CB9500FC0ADF /* DynamicAnnotations.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DD377CBC12072C18006A2517 /* Bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = DD377CBB12072C18006A2517 /* Bitmap.h */; settings = {ATTRIBUTES = (Private, ); }; }; DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; }; DDF7ABD511F60ED200108E36 /* GCActivityCallbackCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */; }; E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; }; E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; }; E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */; }; - E17FF771112131D200076A19 /* ValueCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = E17FF770112131D200076A19 /* ValueCheck.h */; settings = {ATTRIBUTES = (Private, ); }; }; E18E3A590DF9278C00D90B34 /* JSGlobalData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18E3A570DF9278C00D90B34 /* JSGlobalData.cpp */; }; E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; }; E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */; }; E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */; }; E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EF79A80CE97BA60088D500 /* UTF8.cpp */; }; - E48E0F2D0F82151700A8CA37 /* FastAllocBase.h in Headers */ = {isa = PBXBuildFile; fileRef = E48E0F2C0F82151700A8CA37 /* FastAllocBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E49DC15512EF277200184A1F /* SourceProviderCache.cpp */; }; E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC15112EF272200184A1F /* SourceProviderCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */; settings = {ATTRIBUTES = (Private, ); }; }; - E4D8CEFB12FC439600BC9F5A /* BloomFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D8CE9B12FC42E100BC9F5A /* BloomFilter.h */; settings = {ATTRIBUTES = (Private, ); }; }; - F3BD31ED126735770065467F /* TextPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = F3BD31D0126730180065467F /* TextPosition.h */; settings = {ATTRIBUTES = (Private, ); }; }; F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F69E86C114C6E551002C2C62 /* NumberOfCores.cpp */; }; - F69E86C414C6E551002C2C62 /* NumberOfCores.h in Headers */ = {isa = PBXBuildFile; fileRef = F69E86C214C6E551002C2C62 /* NumberOfCores.h */; }; - FDA15C1E12B0305C003A583A /* Complex.h in Headers */ = {isa = PBXBuildFile; fileRef = FDA15C1612B03028003A583A /* Complex.h */; settings = {ATTRIBUTES = (Private, ); }; }; - FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -920,11 +759,14 @@ 0896C29E1265AB0900B1CDD3 /* StringConcatenate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringConcatenate.h; path = text/StringConcatenate.h; sourceTree = "<group>"; }; 08DDA5BB12645F1D00751732 /* UStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UStringBuilder.h; sourceTree = "<group>"; }; 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumberSeed.h; sourceTree = "<group>"; }; + 0A4337BA1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGRedundantPhiEliminationPhase.cpp; path = dfg/DFGRedundantPhiEliminationPhase.cpp; sourceTree = "<group>"; }; + 0A4337BD1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRedundantPhiEliminationPhase.h; path = dfg/DFGRedundantPhiEliminationPhase.h; sourceTree = "<group>"; }; 0B330C260F38C62300692DE3 /* TypeTraits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeTraits.cpp; sourceTree = "<group>"; }; 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeTraits.h; sourceTree = "<group>"; }; 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadRestrictionVerifier.h; sourceTree = "<group>"; }; 0BCD83541485841200EA2003 /* TemporaryChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporaryChange.h; sourceTree = "<group>"; }; 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; }; + 0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; }; 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoints.cpp; path = llint/LLIntEntrypoints.cpp; sourceTree = "<group>"; }; 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoints.h; path = llint/LLIntEntrypoints.h; sourceTree = "<group>"; }; 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; }; @@ -942,6 +784,7 @@ 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; }; 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; }; 0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; }; + 0F1D085F150C5A800074D109 /* DFGNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNode.cpp; path = dfg/DFGNode.cpp; sourceTree = "<group>"; }; 0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; }; 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = "<group>"; }; 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionHarness.h; sourceTree = "<group>"; }; @@ -971,6 +814,9 @@ 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostCallReturnValue.h; sourceTree = "<group>"; }; 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractPC.cpp; sourceTree = "<group>"; }; 0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; }; + 0F56A1D115000F31002992B1 /* ExecutionCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionCounter.h; sourceTree = "<group>"; }; + 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutionCounter.cpp; sourceTree = "<group>"; }; + 0F56A1D6150028B9002992B1 /* SimpleStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleStats.h; sourceTree = "<group>"; }; 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeCache.h; path = dfg/DFGByteCodeCache.h; sourceTree = "<group>"; }; 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; }; 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractState.cpp; path = dfg/DFGAbstractState.cpp; sourceTree = "<group>"; }; @@ -1008,6 +854,7 @@ 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyOperandValueProfile.cpp; sourceTree = "<group>"; }; 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodOfGettingAValueProfile.h; sourceTree = "<group>"; }; 0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MethodOfGettingAValueProfile.cpp; sourceTree = "<group>"; }; + 0FB5468E14FADA6F002C2989 /* RefCountedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedArray.h; sourceTree = "<group>"; }; 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGExitProfile.cpp; sourceTree = "<group>"; }; 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = "<group>"; }; 0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; }; @@ -1216,8 +1063,8 @@ 5D6A566A0F05995500266145 /* Threading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Threading.cpp; sourceTree = "<group>"; }; 5DA479650CFBCF56009328A0 /* TCPackedCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCPackedCache.h; sourceTree = "<group>"; }; 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = JSC.xcconfig; sourceTree = "<group>"; }; - 5DAFD6CC146B68B900FBEFB4 /* TestRegExp.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TestRegExp.xcconfig; sourceTree = "<group>"; }; 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MallocZoneSupport.h; sourceTree = "<group>"; }; + 5DDDF44614FEE72200B4FB4D /* LLIntDesiredOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntDesiredOffsets.h; path = LLIntOffsets/LLIntDesiredOffsets.h; sourceTree = BUILT_PRODUCTS_DIR; }; 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAvailability.h; sourceTree = "<group>"; }; 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypeInfo.h; sourceTree = "<group>"; }; 651122E5140469BA002B101D /* testRegExp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = testRegExp.cpp; sourceTree = "<group>"; }; @@ -1526,7 +1373,7 @@ A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; }; A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; }; BC021BF1136900C300FC5467 /* CompilerVersion.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = CompilerVersion.xcconfig; sourceTree = "<group>"; }; - BC021BF2136900C300FC5467 /* TestAPI.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TestAPI.xcconfig; sourceTree = "<group>"; }; + BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ToolExecutable.xcconfig; sourceTree = "<group>"; }; BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorConstructor.cpp; sourceTree = "<group>"; }; BC02E9050E1839DB000F9297 /* ErrorConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorConstructor.h; sourceTree = "<group>"; }; BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorPrototype.cpp; sourceTree = "<group>"; }; @@ -1867,6 +1714,7 @@ 0F46809C14BA7F4D00BFE272 /* llint */ = { isa = PBXGroup; children = ( + 5DDDF44614FEE72200B4FB4D /* LLIntDesiredOffsets.h */, 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */, 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */, 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */, @@ -1920,6 +1768,7 @@ 1429D92C0ED22D7000B89619 /* jit */ = { isa = PBXGroup; children = ( + 0F0776BD14FF002800102332 /* JITCompilationEffort.h */, 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */, 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */, 0F46807F14BA572700BFE272 /* JITExceptions.cpp */, @@ -2104,8 +1953,7 @@ 449097EE0F8F81B50076A327 /* FeatureDefines.xcconfig */, 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */, 1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */, - BC021BF2136900C300FC5467 /* TestAPI.xcconfig */, - 5DAFD6CC146B68B900FBEFB4 /* TestRegExp.xcconfig */, + BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */, 1C9051420BA9E8A70081E9D0 /* Version.xcconfig */, ); path = Configurations; @@ -2204,6 +2052,7 @@ A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */, A7BC0C81140608B000B1BB71 /* CheckedArithmetic.h */, C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */, + 0FB5468E14FADA6F002C2989 /* RefCountedArray.h */, BC66BAE213F4928F00C23FAE /* Compiler.h */, FDA15C1612B03028003A583A /* Complex.h */, 97941A7C1302A098004A3447 /* CryptographicallyRandomNumber.cpp */, @@ -2308,6 +2157,7 @@ A7C40C08130B057D00D002A1 /* SentinelLinkedList.h */, 76FB9F1012E851960051A2EB /* SHA1.cpp */, 76FB9F0E12E851860051A2EB /* SHA1.h */, + 0F56A1D6150028B9002992B1 /* SimpleStats.h */, A7C40C09130B057D00D002A1 /* SinglyLinkedList.h */, 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */, 0F2E5BF5146357D2003EB2EB /* Spectrum.h */, @@ -2656,6 +2506,7 @@ 86EC9DB31328DF44002B2AD7 /* dfg */ = { isa = PBXGroup; children = ( + 0F1D085F150C5A800074D109 /* DFGNode.cpp */, 0FFFC94914EF909500C72532 /* DFGArithNodeFlagsInferencePhase.cpp */, 0FFFC94A14EF909500C72532 /* DFGArithNodeFlagsInferencePhase.h */, 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */, @@ -2704,6 +2555,8 @@ 0FFFC95014EF909500C72532 /* DFGPhase.h */, 0FFFC95114EF909500C72532 /* DFGPredictionPropagationPhase.cpp */, 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */, + 0A4337BA1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp */, + 0A4337BD1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h */, 86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */, 86BB09BE138E381B0056702F /* DFGRepatch.cpp */, 86BB09BF138E381B0056702F /* DFGRepatch.h */, @@ -2782,6 +2635,8 @@ 969A078F0ED1D3AE00F1F681 /* bytecode */ = { isa = PBXGroup; children = ( + 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */, + 0F56A1D115000F31002992B1 /* ExecutionCounter.h */, 0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */, 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */, 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */, @@ -2910,89 +2765,54 @@ buildActionMask = 2147483647; files = ( 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */, - A1D764521354448B00C5C7C0 /* Alignment.h in Headers */, - BC18C3E40E16F5CD00B34460 /* AlwaysInline.h in Headers */, BC18C3E50E16F5CD00B34460 /* APICast.h in Headers */, 865F408810E7D56300947361 /* APIShims.h in Headers */, BCF605140E203EF800B9A64D /* ArgList.h in Headers */, BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */, 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */, 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */, - A73BE169148420520091204B /* ArrayBuffer.h in Headers */, - C2D9CA1314BCC04600304B46 /* CheckedBoolean.h in Headers */, - A73BE16B148420520091204B /* ArrayBufferView.h in Headers */, C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */, C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */, BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */, BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */, BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */, - BC18C3E90E16F5CD00B34460 /* ASCIICType.h in Headers */, - 434A8E7114956A50009126F7 /* ASCIIFastPath.h in Headers */, 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */, 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */, - BC18C3EA0E16F5CD00B34460 /* Assertions.h in Headers */, A784A26111D16622005776AC /* ASTBuilder.h in Headers */, - BC5F7BBE11823B590052C02C /* Atomics.h in Headers */, - 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */, - 86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */, - 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */, - BC18C3EB0E16F5CD00B34460 /* AVLTree.h in Headers */, 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */, 866739D213BFDE710023D87C /* BigInteger.h in Headers */, - C22C52F213FAF6EF00B7DC0D /* bignum-dtoa.h in Headers */, - C22C52F413FAF6EF00B7DC0D /* bignum.h in Headers */, 1A08277A142168D70090CCAC /* BinarySemaphore.h in Headers */, - DD377CBC12072C18006A2517 /* Bitmap.h in Headers */, - 0FD82F4B142806A100179C94 /* BitVector.h in Headers */, - A7C40C0A130B057D00D002A1 /* BlockStack.h in Headers */, - E4D8CEFB12FC439600BC9F5A /* BloomFilter.h in Headers */, BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */, - 0FD82E85141F3FE300179C94 /* BoundsCheckedPointer.h in Headers */, C2C8D03014A3CEFC00578E65 /* CopiedBlock.h in Headers */, - 86676D5211FED9BC004B6863 /* BumpPointerAllocator.h in Headers */, C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */, C2C8D02D14A3C6E000578E65 /* CopiedSpaceInlineMethods.h in Headers */, - A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */, 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */, - C22C52F613FAF6EF00B7DC0D /* cached-powers.h in Headers */, 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */, BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */, 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */, 95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */, A7521E131429169A003C8D0C /* CardSet.h in Headers */, - 2CFC5D1E12F45B48004914E2 /* CharacterNames.h in Headers */, - A7BC0C82140608B000B1BB71 /* CheckedArithmetic.h in Headers */, BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */, 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */, 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */, 0FBD7E691447999600481315 /* CodeOrigin.h in Headers */, - BC18C3F00E16F5CD00B34460 /* Collator.h in Headers */, BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */, 0FD82E39141AB14D00179C94 /* CompactJITCodeMap.h in Headers */, - BC66BAE413F492CC00C23FAE /* Compiler.h in Headers */, BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */, - FDA15C1E12B0305C003A583A /* Complex.h in Headers */, BC18C3F50E16F5CD00B34460 /* config.h in Headers */, 144836E7132DA7BE005BE785 /* ConservativeRoots.h in Headers */, BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */, 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */, - 97941A7F1302A098004A3447 /* CryptographicallyRandomNumber.h in Headers */, - 86565743115BE3DA00291F40 /* CString.h in Headers */, - 180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */, 0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */, BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */, 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */, BC1166020E1997B4008066DD /* DateInstance.h in Headers */, 14A1563210966365006FA260 /* DateInstanceCache.h in Headers */, - 41359CF70FDD89CB00206180 /* DateMath.h in Headers */, BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */, BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */, BC18C3FA0E16F5CD00B34460 /* Debugger.h in Headers */, BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */, BC18C3FB0E16F5CD00B34460 /* DebuggerCallFrame.h in Headers */, - C2EE59A013FC973F009CEAFE /* DecimalNumber.h in Headers */, - 5135FAF212D26ACE003C083B /* Decoder.h in Headers */, - BC18C3FC0E16F5CD00B34460 /* Deque.h in Headers */, 0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */, 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */, 0FC0976D1468AB4E00CF2442 /* DFGAssemblyHelpers.h in Headers */, @@ -3019,14 +2839,6 @@ 86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */, 0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */, 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */, - BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */, - C22C52F813FAF6EF00B7DC0D /* diy-fp.h in Headers */, - C22C52FA13FAF6EF00B7DC0D /* double-conversion.h in Headers */, - C22C52FB13FAF6EF00B7DC0D /* double.h in Headers */, - 14456A321314657800212CA3 /* DoublyLinkedList.h in Headers */, - BC18C3FE0E16F5CD00B34460 /* dtoa.h in Headers */, - D7A46A4F1338FFEA00ED695C /* DynamicAnnotations.h in Headers */, - 5135FAF312D26AD1003C083B /* Encoder.h in Headers */, BC3046070E1F497F003232CF /* Error.h in Headers */, BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */, BC02E98D0E183E38000F9297 /* ErrorInstance.h in Headers */, @@ -3035,42 +2847,19 @@ BC18C4000E16F5CD00B34460 /* ExceptionHelpers.h in Headers */, 86CAFEE31035DDE60028A609 /* Executable.h in Headers */, A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */, - A7FEE67614837B32005DC1A6 /* ExportMacros.h in Headers */, - C22C52FD13FAF6EF00B7DC0D /* fast-dtoa.h in Headers */, - E48E0F2D0F82151700A8CA37 /* FastAllocBase.h in Headers */, - BC18C4020E16F5CD00B34460 /* FastMalloc.h in Headers */, - C22C52FF13FAF6EF00B7DC0D /* fixed-dtoa.h in Headers */, - A7F19ECE11DD490900931E70 /* FixedArray.h in Headers */, - A73BE16D148420520091204B /* Float32Array.h in Headers */, - A73BE16F148420520091204B /* Float64Array.h in Headers */, - BC18C4030E16F5CD00B34460 /* Forward.h in Headers */, - 1AA9E5511498093500001A8A /* Functional.h in Headers */, BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */, BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */, DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */, - BC18C4060E16F5CD00B34460 /* GetPtr.h in Headers */, 142E3134134FF0A600AFADB5 /* Handle.h in Headers */, 142E3136134FF0A600AFADB5 /* HandleHeap.h in Headers */, 142E3138134FF0A600AFADB5 /* HandleStack.h in Headers */, 1478297B1379E8A800A7C2A3 /* HandleTypes.h in Headers */, - BC18C4080E16F5CD00B34460 /* HashCountedSet.h in Headers */, - BC18C4090E16F5CD00B34460 /* HashFunctions.h in Headers */, - BC18C40A0E16F5CD00B34460 /* HashIterators.h in Headers */, - BC18C40B0E16F5CD00B34460 /* HashMap.h in Headers */, - BC18C40C0E16F5CD00B34460 /* HashSet.h in Headers */, - BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */, - BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */, 14BA7A9813AADFF8005B7C2C /* Heap.h in Headers */, C2C8D03114A3CEFC00578E65 /* HeapBlock.h in Headers */, 14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */, - 7186A6EC13100BA5004479E1 /* HexNumber.h in Headers */, BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */, BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */, 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */, - A73BE173148420520091204B /* Int16Array.h in Headers */, - A73BE175148420520091204B /* Int32Array.h in Headers */, - A73BE171148420520091204B /* Int8Array.h in Headers */, - A73BE180148420A80091204B /* IntegralTypedArrayBase.h in Headers */, BC11667B0E199C05008066DD /* InternalFunction.h in Headers */, 1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */, 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */, @@ -3135,12 +2924,9 @@ BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */, 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */, 0F431738146BAC69007E3890 /* ListableHandler.h in Headers */, - BC18C4340E16F5CD00B34460 /* ListHashSet.h in Headers */, - BC18C4350E16F5CD00B34460 /* ListRefPtr.h in Headers */, A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */, 142E3139134FF0A600AFADB5 /* Local.h in Headers */, 142E313A134FF0A600AFADB5 /* LocalScope.h in Headers */, - BC18C4360E16F5CD00B34460 /* Locker.h in Headers */, BC18C4370E16F5CD00B34460 /* Lookup.h in Headers */, 14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */, 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */, @@ -3152,29 +2938,18 @@ 860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */, 860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */, 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */, - BC18C4390E16F5CD00B34460 /* MainThread.h in Headers */, - BC18C43A0E16F5CD00B34460 /* MallocZoneSupport.h in Headers */, 142D6F0913539A2800B02E86 /* MarkedBlock.h in Headers */, 141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */, 14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */, 142D6F1213539A4100B02E86 /* MarkStack.h in Headers */, - BC18C43B0E16F5CD00B34460 /* MathExtras.h in Headers */, BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */, BC18C52A0E16FCC200B34460 /* MathObject.lut.h in Headers */, - 511FC4CB117EE2A800425272 /* MD5.h in Headers */, 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */, - BC18C43E0E16F5CD00B34460 /* MessageQueue.h in Headers */, - 0F963B2D13F854020002D9B2 /* MetaAllocator.h in Headers */, - 0F963B2F13FC66BB0002D9B2 /* MetaAllocatorHandle.h in Headers */, 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */, BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */, BC02E9130E1839DB000F9297 /* NativeErrorPrototype.h in Headers */, 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */, BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */, - BC18C4400E16F5CD00B34460 /* Noncopyable.h in Headers */, - 65E1A3DF122B894500B26097 /* NonCopyingSort.h in Headers */, - C0A272630E50A06300E96E15 /* NotFound.h in Headers */, - 933F5CDC1269229B0049191E /* NullPtr.h in Headers */, BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */, BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */, BC18C4430E16F5CD00B34460 /* NumberObject.h in Headers */, @@ -3186,34 +2961,12 @@ 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */, BC18C4480E16F5CD00B34460 /* Operations.h in Headers */, 0FE228ED1436AB2700196C48 /* Options.h in Headers */, - 1400067712A6F7830064D123 /* OSAllocator.h in Headers */, - 97941A5A13029ACC004A3447 /* OSRandomSource.h in Headers */, - BC18C4490E16F5CD00B34460 /* OwnArrayPtr.h in Headers */, - BC18C44A0E16F5CD00B34460 /* OwnPtr.h in Headers */, - 4409D8470FAF80A200523B87 /* OwnPtrCommon.h in Headers */, - 0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */, - 8627E5EC11F1281900A313B5 /* PageAllocation.h in Headers */, - 14FFF98D12BFFF7500795BB8 /* PageAllocationAligned.h in Headers */, - 14B3EF0512BC24DD00D29EFF /* PageBlock.h in Headers */, - 8690231512092D5C00630AF9 /* PageReservation.h in Headers */, - 7934BB7B1361979300CB99A1 /* ParallelJobs.h in Headers */, - 7934BB7D1361979400CB99A1 /* ParallelJobsGeneric.h in Headers */, - 7934BB7E1361979400CB99A1 /* ParallelJobsLibdispatch.h in Headers */, - 7934BB7F1361979400CB99A1 /* ParallelJobsOpenMP.h in Headers */, - 2684B2D414D4A9B20072C0B6 /* ParsedURL.h in Headers */, BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */, 93052C350FB792190048FDC3 /* ParserArena.h in Headers */, 65303D641447B9E100D3F904 /* ParserTokens.h in Headers */, - BCFBE696122560E800309E9D /* PassOwnArrayPtr.h in Headers */, - 44DD48530FAEA85000D6B4EB /* PassOwnPtr.h in Headers */, - BC18C44C0E16F5CD00B34460 /* PassRefPtr.h in Headers */, - 651DCA04136A6FEF00F74194 /* PassTraits.h in Headers */, - BC18C44F0E16F5CD00B34460 /* Platform.h in Headers */, - A7D649AA1015224E009B2E1B /* PossiblyNull.h in Headers */, 0FD82E54141DAEEE00179C94 /* PredictedType.h in Headers */, 0FD82E55141DAEEE00179C94 /* PredictionTracker.h in Headers */, BC18C4500E16F5CD00B34460 /* Profile.h in Headers */, - 95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */, BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */, BC18C4520E16F5CD00B34460 /* Profiler.h in Headers */, A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */, @@ -3222,14 +2975,6 @@ BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */, BC18C4560E16F5CD00B34460 /* Protect.h in Headers */, 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */, - 088FA5BC0EF76D4300578E6F /* RandomNumber.h in Headers */, - 08E279E90EF83B10007DB523 /* RandomNumberSeed.h in Headers */, - 2684B2D614D4A9B20072C0B6 /* RawURLBuffer.h in Headers */, - 0F963B2713F753BB0002D9B2 /* RedBlackTree.h in Headers */, - BC18C4570E16F5CD00B34460 /* RefCounted.h in Headers */, - 90D3469C0E285280009492EE /* RefCountedLeakCounter.h in Headers */, - BC18C4580E16F5CD00B34460 /* RefPtr.h in Headers */, - BC18C4590E16F5CD00B34460 /* RefPtrHashMap.h in Headers */, BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */, A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */, BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */, @@ -3243,15 +2988,10 @@ 969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */, 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */, 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */, - BC18C4600E16F5CD00B34460 /* RetainPtr.h in Headers */, C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */, 1429D8860ED21C3D00B89619 /* SamplingTool.h in Headers */, BC18C4610E16F5CD00B34460 /* ScopeChain.h in Headers */, - 969A072C0ED1CE6900F1F681 /* SegmentedVector.h in Headers */, - A7C40C0B130B057D00D002A1 /* SentinelLinkedList.h in Headers */, 86AE64AA135E5E1C00963012 /* SH4Assembler.h in Headers */, - 76FB9F0F12E851860051A2EB /* SHA1.h in Headers */, - A7C40C0C130B057D00D002A1 /* SinglyLinkedList.h in Headers */, 14BA78F113AAB88F005B7C2C /* SlotVisitor.h in Headers */, 933040040E6A749400786E6A /* SmallStrings.h in Headers */, BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */, @@ -3259,80 +2999,32 @@ E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */, E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */, A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */, - 0F2E5BF7146357D5003EB2EB /* Spectrum.h in Headers */, - 86D87DDB12BCAF94008E73A1 /* StackBounds.h in Headers */, - 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */, - FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */, A781E359141970C700094D90 /* StorageBarrier.h in Headers */, A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */, - 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */, - 081469491264378500DFF935 /* StringBuilder.h in Headers */, - 08CABBA61265AB3900B206CE /* StringConcatenate.h in Headers */, BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */, - BC18C4670E16F5CD00B34460 /* StringExtras.h in Headers */, - 868BFA0D117CEFD100B908B1 /* StringHash.h in Headers */, - 5D63E9AD10F2BD6E00FC8AE9 /* StringHasher.h in Headers */, - 868BFA0F117CEFD100B908B1 /* StringImpl.h in Headers */, BC18C4680E16F5CD00B34460 /* StringObject.h in Headers */, - 71DA9D82134F3F3D00B767E7 /* StringOperators.h in Headers */, BC18C46A0E16F5CD00B34460 /* StringPrototype.h in Headers */, BC18C5260E16FCA700B34460 /* StringPrototype.lut.h in Headers */, 142E313B134FF0A600AFADB5 /* Strong.h in Headers */, 145722861437E140005FDE26 /* StrongInlines.h in Headers */, - C22C531413FAF6EF00B7DC0D /* strtod.h in Headers */, BCDE3AB80E6C82F5001453A7 /* Structure.h in Headers */, 7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */, BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */, BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */, BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */, A784A26411D16622005776AC /* SyntaxChecker.h in Headers */, - BC18C46C0E16F5CD00B34460 /* TCPackedCache.h in Headers */, - BC18C46D0E16F5CD00B34460 /* TCPageMap.h in Headers */, - BC18C46E0E16F5CD00B34460 /* TCSpinLock.h in Headers */, - BC18C46F0E16F5CD00B34460 /* TCSystemAlloc.h in Headers */, - 0BCD83571485845200EA2003 /* TemporaryChange.h in Headers */, 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */, - F3BD31ED126735770065467F /* TextPosition.h in Headers */, - 18BAB55410DAE066000D945B /* ThreadIdentifierDataPthreads.h in Headers */, - BC18C4700E16F5CD00B34460 /* Threading.h in Headers */, - BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */, - 0BAC94A01338728400CF135B /* ThreadRestrictionVerifier.h in Headers */, - BC5F7BC011823B590052C02C /* ThreadSafeRefCounted.h in Headers */, - BC18C4710E16F5CD00B34460 /* ThreadSpecific.h in Headers */, A7386556118697B400540279 /* ThunkGenerators.h in Headers */, 14A42E400F4F60EE00599099 /* TimeoutChecker.h in Headers */, 141448CD13A1783700F5BA1A /* TinyBloomFilter.h in Headers */, 5D53726F0E1C54880021E549 /* Tracing.h in Headers */, - A73BE17E148420840091204B /* TypedArrayBase.h in Headers */, - 0B4D7E630F319AC800AD7E58 /* TypeTraits.h in Headers */, - A73BE179148420520091204B /* Uint16Array.h in Headers */, 866739D313BFDE710023D87C /* Uint16WithFraction.h in Headers */, - A73BE17B148420520091204B /* Uint32Array.h in Headers */, - A73BE177148420520091204B /* Uint8Array.h in Headers */, 0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */, - BC18C4730E16F5CD00B34460 /* Unicode.h in Headers */, - BC18C4740E16F5CD00B34460 /* UnicodeIcu.h in Headers */, - 0FD52AAE143035A00026DC9F /* UnionFind.h in Headers */, - BC18C4750E16F5CD00B34460 /* UnusedParam.h in Headers */, - 2684B2D514D4A9B20072C0B6 /* URLString.h in Headers */, - 2684B2D714D4A9B20072C0B6 /* URLBuffer.h in Headers */, - 2684B2D914D4A9B20072C0B6 /* URLCharacterTypes.h in Headers */, - 2684B2DA14D4A9B20072C0B6 /* URLComponent.h in Headers */, - 2684B2DC14D4A9B20072C0B6 /* URLEscape.h in Headers */, - 2684B2DD14D4A9B20072C0B6 /* URLParser.h in Headers */, - 2684B2DE14D4A9B20072C0B6 /* URLQueryCanonicalizer.h in Headers */, - 2684B2E014D4A9B20072C0B6 /* URLSegments.h in Headers */, BC18C4760E16F5CD00B34460 /* UString.h in Headers */, 08DDA5C11264631700751732 /* UStringBuilder.h in Headers */, - BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */, - C22C531513FAF6EF00B7DC0D /* utils.h in Headers */, - E17FF771112131D200076A19 /* ValueCheck.h in Headers */, 0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */, 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */, - BC18C4780E16F5CD00B34460 /* Vector.h in Headers */, - BC18C4790E16F5CD00B34460 /* VectorTraits.h in Headers */, 0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */, - 96DD73790F9DA3100027FBCC /* VMTags.h in Headers */, 0FC815151405119B00CFA603 /* VTableSpectrum.h in Headers */, 142E313C134FF0A600AFADB5 /* Weak.h in Headers */, 14BFCE6910CDB1FC00364CCE /* WeakGCMap.h in Headers */, @@ -3341,8 +3033,6 @@ BC18C47A0E16F5CD00B34460 /* WebKitAvailability.h in Headers */, A7DCB97312E5193F00911940 /* WriteBarrier.h in Headers */, 0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */, - 868BFA18117CF19900B908B1 /* WTFString.h in Headers */, - 86D08D5411793613006E5ED0 /* WTFThreadData.h in Headers */, 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, 451539B912DC994500EF7AC4 /* Yarr.h in Headers */, 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */, @@ -3371,6 +3061,7 @@ 0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */, 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */, 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */, + 95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */, 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */, 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */, 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */, @@ -3378,8 +3069,6 @@ 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */, 0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */, 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */, - 91A3905614C0F47200F67901 /* Uint8ClampedArray.h in Headers */, - F69E86C414C6E551002C2C62 /* NumberOfCores.h in Headers */, 0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */, 0F9332A014CA7DCD0085F3C6 /* GetByIdStatus.h in Headers */, 0F9332A214CA7DD30085F3C6 /* MethodCallLinkStatus.h in Headers */, @@ -3388,7 +3077,6 @@ 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */, 0F66E16B14DF3F1600B7B2E4 /* DFGNodeReferenceBlob.h in Headers */, 0F66E16C14DF3F1600B7B2E4 /* DFGNodeUse.h in Headers */, - 0F9FC8D114E612DA00D52AE0 /* DataLog.h in Headers */, 0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */, 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */, BCBE2CAE14E985AA000593AD /* GCAssertions.h in Headers */, @@ -3401,6 +3089,9 @@ 1497209114EB831500FEB1B7 /* PassWeak.h in Headers */, 0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */, 0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */, + 0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */, + 0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */, + 0A4337BE1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3483,6 +3174,7 @@ buildConfigurationList = 149C275D08902AFE008A9EFC /* Build configuration list for PBXNativeTarget "JavaScriptCore" */; buildPhases = ( 5D2F7CF90C6875BB00B5B72B /* Update Info.plist with version information */, + A8D7082715049EA2001063BC /* Copy WTF Headers */, 932F5B3F0822A1C700736975 /* Headers */, 932F5B910822A1C700736975 /* Sources */, 932F5BD20822A1C700736975 /* Frameworks */, @@ -3711,6 +3403,20 @@ shellPath = /bin/sh; shellScript = "if [ \"${TARGET_GCC_VERSION}\" = \"LLVM_COMPILER\" ]; then\n exit 0;\nfi\n\nif [ -f ../../Tools/Scripts/check-for-exit-time-destructors ]; then\n ../../Tools/Scripts/check-for-exit-time-destructors || exit $?\nfi"; }; + A8D7082715049EA2001063BC /* Copy WTF Headers */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy WTF Headers"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# WTF_PRIVATE_HEADERS_PATH will be replaced by PRIVATE_HEADERS_FOLDER_PATH\n# in the equivalent build-phase when WTF is its own project.\nWTF_PRIVATE_HEADERS_PATH=\"/usr/local/include\"\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\nPRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%%/}${WTF_PRIVATE_HEADERS_PATH}\"\nelse\nPRIVATE_HEADERS_PATH=\"${DSTROOT%%/}${WTF_PRIVATE_HEADERS_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\nrsync -av --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --exclude \"DerivedSources\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/wtf\" \"${PRIVATE_HEADERS_PATH}\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -4010,6 +3716,9 @@ 0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */, 0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */, 0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */, + 0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */, + 0A4337BB1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp in Sources */, + 0F1D0861150C5A860074D109 /* DFGNode.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4097,37 +3806,29 @@ }; 0FF922CB14F46B130041A24E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = JSCLLIntOffsetsExtractor; - USER_HEADER_SEARCH_PATHS = ". icu $(HEADER_SEARCH_PATHS) $(BUILT_PRODUCTS_DIR)/LLIntOffsets"; }; name = Debug; }; 0FF922CC14F46B130041A24E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = JSCLLIntOffsetsExtractor; - USER_HEADER_SEARCH_PATHS = ". icu $(HEADER_SEARCH_PATHS) $(BUILT_PRODUCTS_DIR)/LLIntOffsets"; }; name = Release; }; 0FF922CD14F46B130041A24E /* Profiling */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = JSCLLIntOffsetsExtractor; - USER_HEADER_SEARCH_PATHS = ". icu $(HEADER_SEARCH_PATHS) $(BUILT_PRODUCTS_DIR)/LLIntOffsets"; }; name = Profiling; }; 0FF922CE14F46B130041A24E /* Production */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = JSCLLIntOffsetsExtractor; - USER_HEADER_SEARCH_PATHS = ". icu $(HEADER_SEARCH_PATHS) $(BUILT_PRODUCTS_DIR)/LLIntOffsets"; }; name = Production; }; @@ -4249,49 +3950,49 @@ }; 14BD59D70A3E8FC900BAF59C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BC021BF2136900C300FC5467 /* TestAPI.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Debug; }; 14BD59D80A3E8FC900BAF59C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BC021BF2136900C300FC5467 /* TestAPI.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Release; }; 14BD59D90A3E8FC900BAF59C /* Production */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BC021BF2136900C300FC5467 /* TestAPI.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Production; }; 6511230114046A4C002B101D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CC146B68B900FBEFB4 /* TestRegExp.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Debug; }; 6511230214046A4C002B101D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CC146B68B900FBEFB4 /* TestRegExp.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Release; }; 6511230314046A4C002B101D /* Profiling */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CC146B68B900FBEFB4 /* TestRegExp.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Profiling; }; 6511230414046A4C002B101D /* Production */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5DAFD6CC146B68B900FBEFB4 /* TestRegExp.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Production; @@ -4357,7 +4058,7 @@ }; A76148420E6402F700E357FA /* Profiling */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BC021BF2136900C300FC5467 /* TestAPI.xcconfig */; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { }; name = Profiling; diff --git a/Source/JavaScriptCore/KeywordLookupGenerator.py b/Source/JavaScriptCore/KeywordLookupGenerator.py index dc779e0c5..29f50dfe0 100644 --- a/Source/JavaScriptCore/KeywordLookupGenerator.py +++ b/Source/JavaScriptCore/KeywordLookupGenerator.py @@ -169,7 +169,8 @@ class Trie: def printAsC(self): print("namespace JSC {") print("") - print("static ALWAYS_INLINE bool isIdentPart(int c);") + print("static ALWAYS_INLINE bool isIdentPart(LChar c);") + print("static ALWAYS_INLINE bool isIdentPart(UChar c);") # max length + 1 so we don't need to do any bounds checking at all print("static const int maxTokenLength = %d;" % (self.maxLength() + 1)) print("") diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri index 8fa498c08..1480ae74b 100644 --- a/Source/JavaScriptCore/Target.pri +++ b/Source/JavaScriptCore/Target.pri @@ -53,6 +53,7 @@ SOURCES += \ bytecode/CallLinkStatus.cpp \ bytecode/CodeBlock.cpp \ bytecode/DFGExitProfile.cpp \ + bytecode/ExecutionCounter.cpp \ bytecode/GetByIdStatus.cpp \ bytecode/JumpTable.cpp \ bytecode/LazyOperandValueProfile.cpp \ @@ -94,6 +95,7 @@ SOURCES += \ dfg/DFGDriver.cpp \ dfg/DFGGraph.cpp \ dfg/DFGJITCompiler.cpp \ + dfg/DFGNode.cpp \ dfg/DFGOperations.cpp \ dfg/DFGOSREntry.cpp \ dfg/DFGOSRExit.cpp \ @@ -102,6 +104,7 @@ SOURCES += \ dfg/DFGOSRExitCompiler32_64.cpp \ dfg/DFGPhase.cpp \ dfg/DFGPredictionPropagationPhase.cpp \ + dfg/DFGRedundantPhiEliminationPhase.cpp \ dfg/DFGRepatch.cpp \ dfg/DFGSpeculativeJIT.cpp \ dfg/DFGSpeculativeJIT32_64.cpp \ diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.cpp b/Source/JavaScriptCore/assembler/ARMAssembler.cpp index 4ded0e88e..b880f50bf 100644 --- a/Source/JavaScriptCore/assembler/ARMAssembler.cpp +++ b/Source/JavaScriptCore/assembler/ARMAssembler.cpp @@ -344,14 +344,14 @@ void ARMAssembler::doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID b fdtr_u(isLoad, srcDst, ARMRegisters::S0, 0); } -PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(JSGlobalData& globalData, void* ownerUID) +PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) { // 64-bit alignment is required for next constant pool and JIT code as well m_buffer.flushWithoutBarrier(true); if (!m_buffer.isAligned(8)) bkpt(0); - RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID); + RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID, effort); char* data = reinterpret_cast<char*>(result->start()); for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) { diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.h b/Source/JavaScriptCore/assembler/ARMAssembler.h index ef199d2d1..a9ecf5091 100644 --- a/Source/JavaScriptCore/assembler/ARMAssembler.h +++ b/Source/JavaScriptCore/assembler/ARMAssembler.h @@ -30,6 +30,7 @@ #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #include "AssemblerBufferWithConstantPool.h" +#include "JITCompilationEffort.h" #include <wtf/Assertions.h> namespace JSC { @@ -679,7 +680,7 @@ namespace JSC { return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData&, void* ownerUID); + PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData&, void* ownerUID, JITCompilationEffort); unsigned debugOffset() { return m_buffer.debugOffset(); } diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h index 5f376bf3d..51788da08 100644 --- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h @@ -584,6 +584,7 @@ private: OP_VMOV_T2 = 0xEEB0, OP_VMOV_IMM_T2 = 0xEEB0, OP_VMRS = 0xEEB0, + OP_VNEG_T2 = 0xEEB0, OP_VSQRT_T1 = 0xEEB0, OP_B_T3a = 0xF000, OP_B_T4a = 0xF000, @@ -601,6 +602,7 @@ private: OP_SUB_S_imm_T3 = 0xF1B0, OP_CMP_imm_T2 = 0xF1B0, OP_RSB_imm_T2 = 0xF1C0, + OP_RSB_S_imm_T2 = 0xF1D0, OP_ADD_imm_T4 = 0xF200, OP_MOV_imm_T3 = 0xF240, OP_SUB_imm_T4 = 0xF2A0, @@ -649,6 +651,7 @@ private: OP_VABS_T2b = 0x0A40, OP_VCMPb = 0x0A40, OP_VCVT_FPIVFPb = 0x0A40, + OP_VNEG_T2b = 0x0A40, OP_VSUB_T2b = 0x0A40, OP_VSQRT_T1b = 0x0A40, OP_NOP_T2b = 0x8000, @@ -1584,6 +1587,16 @@ public: m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm); } + ALWAYS_INLINE void sub_S(RegisterID rd, ARMThumbImmediate imm, RegisterID rn) + { + ASSERT(rd != ARMRegisters::pc); + ASSERT(rn != ARMRegisters::pc); + ASSERT(imm.isValid()); + ASSERT(imm.isUInt12()); + + m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_S_imm_T2, rn, rd, imm); + } + // Not allowed in an IT (if then) block? ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) { @@ -1734,6 +1747,11 @@ public: m_formatter.vfpOp(OP_VABS_T2, OP_VABS_T2b, true, VFPOperand(16), rd, rm); } + void vneg(FPDoubleRegisterID rd, FPDoubleRegisterID rm) + { + m_formatter.vfpOp(OP_VNEG_T2, OP_VNEG_T2b, true, VFPOperand(1), rd, rm); + } + void vsqrt(FPDoubleRegisterID rd, FPDoubleRegisterID rm) { m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm); diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index b4262e894..ab343977e 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -28,11 +28,21 @@ #include "CodeLocation.h" #include "MacroAssemblerCodeRef.h" +#include <wtf/CryptographicallyRandomNumber.h> #include <wtf/Noncopyable.h> #include <wtf/UnusedParam.h> #if ENABLE(ASSEMBLER) + +#if PLATFORM(QT) +#define ENABLE_JIT_CONSTANT_BLINDING 0 +#endif + +#ifndef ENABLE_JIT_CONSTANT_BLINDING +#define ENABLE_JIT_CONSTANT_BLINDING 1 +#endif + namespace JSC { class LinkBuffer; @@ -186,11 +196,19 @@ public: const void* m_value; }; - struct ImmPtr : public TrustedImmPtr { + struct ImmPtr : +#if ENABLE(JIT_CONSTANT_BLINDING) + private TrustedImmPtr +#else + public TrustedImmPtr +#endif + { explicit ImmPtr(const void* value) : TrustedImmPtr(value) { } + + TrustedImmPtr asTrustedImmPtr() { return *this; } }; // TrustedImm32: @@ -232,7 +250,13 @@ public: }; - struct Imm32 : public TrustedImm32 { + struct Imm32 : +#if ENABLE(JIT_CONSTANT_BLINDING) + private TrustedImm32 +#else + public TrustedImm32 +#endif + { explicit Imm32(int32_t value) : TrustedImm32(value) { @@ -243,6 +267,8 @@ public: { } #endif + const TrustedImm32& asTrustedImm32() const { return *this; } + }; // Section 2: MacroAssembler code buffer handles @@ -535,14 +561,41 @@ public: return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress()); } - void beginUninterruptedSequence() { } - void endUninterruptedSequence() { } + void beginUninterruptedSequence() { m_inUninterruptedSequence = true; } + void endUninterruptedSequence() { m_inUninterruptedSequence = false; } unsigned debugOffset() { return m_assembler.debugOffset(); } protected: + AbstractMacroAssembler() + : m_inUninterruptedSequence(false) + , m_randomSource(cryptographicallyRandomNumber()) + { + } + AssemblerType m_assembler; + bool inUninterruptedSequence() + { + return m_inUninterruptedSequence; + } + + bool m_inUninterruptedSequence; + + + uint32_t random() + { + return m_randomSource.getUint32(); + } + + WeakRandom m_randomSource; + +#if ENABLE(JIT_CONSTANT_BLINDING) + static bool scratchRegisterForBlinding() { return false; } + static bool shouldBlindForSpecificArch(uint32_t) { return true; } + static bool shouldBlindForSpecificArch(uint64_t) { return true; } +#endif + friend class LinkBuffer; friend class RepatchBuffer; diff --git a/Source/JavaScriptCore/assembler/AssemblerBuffer.h b/Source/JavaScriptCore/assembler/AssemblerBuffer.h index 55706c1ab..d1deef234 100644 --- a/Source/JavaScriptCore/assembler/AssemblerBuffer.h +++ b/Source/JavaScriptCore/assembler/AssemblerBuffer.h @@ -28,6 +28,7 @@ #if ENABLE(ASSEMBLER) +#include "JITCompilationEffort.h" #include "JSGlobalData.h" #include "stdint.h" #include <string.h> @@ -129,12 +130,12 @@ namespace JSC { return AssemblerLabel(m_index); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID) + PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) { if (!m_index) return 0; - RefPtr<ExecutableMemoryHandle> result = globalData.executableAllocator.allocate(globalData, m_index, ownerUID); + RefPtr<ExecutableMemoryHandle> result = globalData.executableAllocator.allocate(globalData, m_index, ownerUID, effort); if (!result) return 0; diff --git a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h index 68afa766b..e2ea261ee 100644 --- a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h +++ b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h @@ -195,10 +195,10 @@ public: putIntegralUnchecked(value.low); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID) + PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) { flushConstantPool(false); - return AssemblerBuffer::executableCopy(globalData, ownerUID); + return AssemblerBuffer::executableCopy(globalData, ownerUID, effort); } void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false) diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h index 2c07d13fc..6ec9a7eb9 100644 --- a/Source/JavaScriptCore/assembler/LinkBuffer.h +++ b/Source/JavaScriptCore/assembler/LinkBuffer.h @@ -34,6 +34,7 @@ #define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1)) #define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2)) +#include "JITCompilationEffort.h" #include "MacroAssembler.h" #include <wtf/DataLog.h> #include <wtf/Noncopyable.h> @@ -73,7 +74,7 @@ class LinkBuffer { #endif public: - LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID) + LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed) : m_size(0) #if ENABLE(BRANCH_COMPACTION) , m_initialSize(0) @@ -83,16 +84,27 @@ public: , m_globalData(&globalData) #ifndef NDEBUG , m_completed(false) + , m_effort(effort) #endif { - linkCode(ownerUID); + linkCode(ownerUID, effort); } ~LinkBuffer() { - ASSERT(m_completed); + ASSERT(m_completed || (!m_executableMemory && m_effort == JITCompilationCanFail)); + } + + bool didFailToAllocate() const + { + return !m_executableMemory; } + bool isValid() const + { + return !didFailToAllocate(); + } + // These methods are used to link or set values at code generation time. void link(Call call, FunctionPtr function) @@ -218,11 +230,11 @@ private: return m_code; } - void linkCode(void* ownerUID) + void linkCode(void* ownerUID, JITCompilationEffort effort) { ASSERT(!m_code); #if !ENABLE(BRANCH_COMPACTION) - m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID); + m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort); if (!m_executableMemory) return; m_code = m_executableMemory->start(); @@ -230,7 +242,7 @@ private: ASSERT(m_code); #else m_initialSize = m_assembler->m_assembler.codeSize(); - m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID); + m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort); if (!m_executableMemory) return; m_code = (uint8_t*)m_executableMemory->start(); @@ -307,6 +319,7 @@ private: { #ifndef NDEBUG ASSERT(!m_completed); + ASSERT(isValid()); m_completed = true; #endif @@ -375,6 +388,7 @@ private: JSGlobalData* m_globalData; #ifndef NDEBUG bool m_completed; + JITCompilationEffort m_effort; #endif }; diff --git a/Source/JavaScriptCore/assembler/MIPSAssembler.h b/Source/JavaScriptCore/assembler/MIPSAssembler.h index b59fa0b8f..5e0645129 100644 --- a/Source/JavaScriptCore/assembler/MIPSAssembler.h +++ b/Source/JavaScriptCore/assembler/MIPSAssembler.h @@ -32,6 +32,7 @@ #if ENABLE(ASSEMBLER) && CPU(MIPS) #include "AssemblerBuffer.h" +#include "JITCompilationEffort.h" #include <wtf/Assertions.h> #include <wtf/SegmentedVector.h> @@ -645,9 +646,9 @@ public: return m_buffer.codeSize(); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID) + PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) { - RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID); + RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID, effort); if (!result) return 0; diff --git a/Source/JavaScriptCore/assembler/MacroAssembler.h b/Source/JavaScriptCore/assembler/MacroAssembler.h index 347cd0ea0..4c54e29aa 100644 --- a/Source/JavaScriptCore/assembler/MacroAssembler.h +++ b/Source/JavaScriptCore/assembler/MacroAssembler.h @@ -60,7 +60,6 @@ typedef MacroAssemblerSH4 MacroAssemblerBase; #error "The MacroAssembler is not supported on this platform." #endif - namespace JSC { class MacroAssembler : public MacroAssemblerBase { @@ -73,6 +72,22 @@ public: using MacroAssemblerBase::branchPtr; using MacroAssemblerBase::branchTestPtr; #endif + using MacroAssemblerBase::move; + +#if ENABLE(JIT_CONSTANT_BLINDING) + using MacroAssemblerBase::add32; + using MacroAssemblerBase::and32; + using MacroAssemblerBase::branchAdd32; + using MacroAssemblerBase::branchMul32; + using MacroAssemblerBase::branchSub32; + using MacroAssemblerBase::lshift32; + using MacroAssemblerBase::or32; + using MacroAssemblerBase::rshift32; + using MacroAssemblerBase::store32; + using MacroAssemblerBase::sub32; + using MacroAssemblerBase::urshift32; + using MacroAssemblerBase::xor32; +#endif // Utilities used by the DFG JIT. #if ENABLE(DFG_JIT) @@ -148,19 +163,24 @@ public: loadPtr(Address(stackPointerRegister, (index * sizeof(void*))), dest); } + Address addressForPoke(int index) + { + return Address(stackPointerRegister, (index * sizeof(void*))); + } + void poke(RegisterID src, int index = 0) { - storePtr(src, Address(stackPointerRegister, (index * sizeof(void*)))); + storePtr(src, addressForPoke(index)); } void poke(TrustedImm32 value, int index = 0) { - store32(value, Address(stackPointerRegister, (index * sizeof(void*)))); + store32(value, addressForPoke(index)); } void poke(TrustedImmPtr imm, int index = 0) { - storePtr(imm, Address(stackPointerRegister, (index * sizeof(void*)))); + storePtr(imm, addressForPoke(index)); } @@ -169,6 +189,10 @@ public: { branchPtr(cond, op1, imm).linkTo(target, this); } + void branchPtr(RelationalCondition cond, RegisterID op1, ImmPtr imm, Label target) + { + branchPtr(cond, op1, imm).linkTo(target, this); + } void branch32(RelationalCondition cond, RegisterID op1, RegisterID op2, Label target) { @@ -179,6 +203,11 @@ public: { branch32(cond, op1, imm).linkTo(target, this); } + + void branch32(RelationalCondition cond, RegisterID op1, Imm32 imm, Label target) + { + branch32(cond, op1, imm).linkTo(target, this); + } void branch32(RelationalCondition cond, RegisterID left, Address right, Label target) { @@ -190,6 +219,11 @@ public: return branch32(commute(cond), right, left); } + Jump branch32(RelationalCondition cond, Imm32 left, RegisterID right) + { + return branch32(commute(cond), right, left); + } + void branchTestPtr(ResultCondition cond, RegisterID reg, Label target) { branchTestPtr(cond, reg).linkTo(target, this); @@ -340,6 +374,11 @@ public: return load32WithCompactAddressOffsetPatch(address, dest); } + void move(ImmPtr imm, RegisterID dest) + { + move(Imm32(imm.asTrustedImmPtr()), dest); + } + void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { compare32(cond, left, right, dest); @@ -364,6 +403,11 @@ public: { store32(TrustedImm32(imm), address); } + + void storePtr(ImmPtr imm, Address address) + { + store32(Imm32(imm.asTrustedImmPtr()), address); + } void storePtr(TrustedImmPtr imm, void* address) { @@ -375,7 +419,6 @@ public: return store32WithAddressOffsetPatch(src, address); } - Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right) { return branch32(cond, left, right); @@ -385,6 +428,11 @@ public: { return branch32(cond, left, TrustedImm32(right)); } + + Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right) + { + return branch32(cond, left, Imm32(right.asTrustedImmPtr())); + } Jump branchPtr(RelationalCondition cond, RegisterID left, Address right) { @@ -405,7 +453,7 @@ public: { return branch32(cond, left, TrustedImm32(right)); } - + Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, TrustedImmPtr right) { return branch32(cond, left, TrustedImm32(right)); @@ -431,7 +479,6 @@ public: return branchTest32(cond, address, mask); } - Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest) { return branchAdd32(cond, src, dest); @@ -446,8 +493,499 @@ public: { return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask); } +#else + +#if ENABLE(JIT_CONSTANT_BLINDING) + using MacroAssemblerBase::addPtr; + using MacroAssemblerBase::andPtr; + using MacroAssemblerBase::branchSubPtr; + using MacroAssemblerBase::convertInt32ToDouble; + using MacroAssemblerBase::storePtr; + using MacroAssemblerBase::subPtr; + using MacroAssemblerBase::xorPtr; + + bool shouldBlindDouble(double value) + { + // Don't trust NaN or +/-Infinity + if (!isfinite(value)) + return true; + + // Try to force normalisation, and check that there's no change + // in the bit pattern + if (bitwise_cast<uintptr_t>(value * 1.0) != bitwise_cast<uintptr_t>(value)) + return true; + + value = abs(value); + // Only allow a limited set of fractional components + double scaledValue = value * 8; + if (scaledValue / 8 != value) + return true; + double frac = scaledValue - floor(scaledValue); + if (frac != 0.0) + return true; + + return value > 0xff; + } + + bool shouldBlind(ImmPtr imm) + { + ASSERT(!inUninterruptedSequence()); +#if !defined(NDEBUG) + UNUSED_PARAM(imm); + // Debug always blind all constants, if only so we know + // if we've broken blinding during patch development. + return true; +#endif + + // First off we'll special case common, "safe" values to avoid hurting + // performance too much + uintptr_t value = imm.asTrustedImmPtr().asIntptr(); + switch (value) { + case 0xffff: + case 0xffffff: + case 0xffffffffL: + case 0xffffffffffL: + case 0xffffffffffffL: + case 0xffffffffffffffL: + case 0xffffffffffffffffL: + return false; + default: { + if (value <= 0xff) + return false; +#if CPU(X86_64) + JSValue jsValue = JSValue::decode(reinterpret_cast<void*>(value)); + if (jsValue.isInt32()) + return shouldBlind(Imm32(jsValue.asInt32())); + if (jsValue.isDouble() && !shouldBlindDouble(jsValue.asDouble())) + return false; + + if (!shouldBlindDouble(bitwise_cast<double>(value))) + return false; +#endif + } + } + return shouldBlindForSpecificArch(value); + } + + struct RotatedImmPtr { + RotatedImmPtr(uintptr_t v1, uint8_t v2) + : value(v1) + , rotation(v2) + { + } + TrustedImmPtr value; + TrustedImm32 rotation; + }; + + RotatedImmPtr rotationBlindConstant(ImmPtr imm) + { + uint8_t rotation = random() % (sizeof(void*) * 8); + uintptr_t value = imm.asTrustedImmPtr().asIntptr(); + value = (value << rotation) | (value >> (sizeof(void*) * 8 - rotation)); + return RotatedImmPtr(value, rotation); + } + + void loadRotationBlindedConstant(RotatedImmPtr constant, RegisterID dest) + { + move(constant.value, dest); + rotateRightPtr(constant.rotation, dest); + } + + void convertInt32ToDouble(Imm32 imm, FPRegisterID dest) + { + if (shouldBlind(imm)) { + RegisterID scratchRegister = scratchRegisterForBlinding(); + loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister); + convertInt32ToDouble(scratchRegister, dest); + } else + convertInt32ToDouble(imm.asTrustedImm32(), dest); + } + + void move(ImmPtr imm, RegisterID dest) + { + if (shouldBlind(imm)) + loadRotationBlindedConstant(rotationBlindConstant(imm), dest); + else + move(imm.asTrustedImmPtr(), dest); + } + + Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right) + { + if (shouldBlind(right)) { + RegisterID scratchRegister = scratchRegisterForBlinding(); + loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegister); + return branchPtr(cond, left, scratchRegister); + } + return branchPtr(cond, left, right.asTrustedImmPtr()); + } + + void storePtr(ImmPtr imm, Address dest) + { + if (shouldBlind(imm)) { + RegisterID scratchRegister = scratchRegisterForBlinding(); + loadRotationBlindedConstant(rotationBlindConstant(imm), scratchRegister); + storePtr(scratchRegister, dest); + } else + storePtr(imm.asTrustedImmPtr(), dest); + } + +#endif + #endif // !CPU(X86_64) +#if ENABLE(JIT_CONSTANT_BLINDING) + bool shouldBlind(Imm32 imm) + { + ASSERT(!inUninterruptedSequence()); +#if !defined(NDEBUG) + UNUSED_PARAM(imm); + // Debug always blind all constants, if only so we know + // if we've broken blinding during patch development. + return true; +#else + + // First off we'll special case common, "safe" values to avoid hurting + // performance too much + uint32_t value = imm.asTrustedImm32().m_value; + switch (value) { + case 0xffff: + case 0xffffff: + case 0xffffffff: + return false; + default: + if (value <= 0xff) + return false; + } + return shouldBlindForSpecificArch(value); +#endif + } + + struct BlindedImm32 { + BlindedImm32(int32_t v1, int32_t v2) + : value1(v1) + , value2(v2) + { + } + TrustedImm32 value1; + TrustedImm32 value2; + }; + + uint32_t keyForConstant(uint32_t value, uint32_t& mask) + { + uint32_t key = random(); + if (value <= 0xff) + mask = 0xff; + else if (value <= 0xffff) + mask = 0xffff; + else if (value <= 0xffffff) + mask = 0xffffff; + else + mask = 0xffffffff; + return key & mask; + } + + uint32_t keyForConstant(uint32_t value) + { + uint32_t mask = 0; + return keyForConstant(value, mask); + } + + BlindedImm32 xorBlindConstant(Imm32 imm) + { + uint32_t baseValue = imm.asTrustedImm32().m_value; + uint32_t key = keyForConstant(baseValue); + return BlindedImm32(baseValue ^ key, key); + } + + BlindedImm32 additionBlindedConstant(Imm32 imm) + { + uint32_t baseValue = imm.asTrustedImm32().m_value; + uint32_t key = keyForConstant(baseValue); + if (key > baseValue) + key = key - baseValue; + return BlindedImm32(baseValue - key, key); + } + + BlindedImm32 andBlindedConstant(Imm32 imm) + { + uint32_t baseValue = imm.asTrustedImm32().m_value; + uint32_t mask = 0; + uint32_t key = keyForConstant(baseValue, mask); + ASSERT((baseValue & mask) == baseValue); + return BlindedImm32(((baseValue & key) | ~key) & mask, ((baseValue & ~key) | key) & mask); + } + + BlindedImm32 orBlindedConstant(Imm32 imm) + { + uint32_t baseValue = imm.asTrustedImm32().m_value; + uint32_t mask = 0; + uint32_t key = keyForConstant(baseValue, mask); + ASSERT((baseValue & mask) == baseValue); + return BlindedImm32((baseValue & key) & mask, (baseValue & ~key) & mask); + } + + void loadXorBlindedConstant(BlindedImm32 constant, RegisterID dest) + { + move(constant.value1, dest); + xor32(constant.value2, dest); + } + + void add32(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 key = additionBlindedConstant(imm); + add32(key.value1, dest); + add32(key.value2, dest); + } else + add32(imm.asTrustedImm32(), dest); + } + + void addPtr(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 key = additionBlindedConstant(imm); + addPtr(key.value1, dest); + addPtr(key.value2, dest); + } else + addPtr(imm.asTrustedImm32(), dest); + } + + void and32(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 key = andBlindedConstant(imm); + and32(key.value1, dest); + and32(key.value2, dest); + } else + and32(imm.asTrustedImm32(), dest); + } + + void andPtr(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 key = andBlindedConstant(imm); + andPtr(key.value1, dest); + andPtr(key.value2, dest); + } else + andPtr(imm.asTrustedImm32(), dest); + } + + void and32(Imm32 imm, RegisterID src, RegisterID dest) + { + if (shouldBlind(imm)) { + if (src == dest) + return and32(imm.asTrustedImm32(), dest); + loadXorBlindedConstant(xorBlindConstant(imm), dest); + and32(src, dest); + } else + and32(imm.asTrustedImm32(), src, dest); + } + + void move(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) + loadXorBlindedConstant(xorBlindConstant(imm), dest); + else + move(imm.asTrustedImm32(), dest); + } + + void or32(Imm32 imm, RegisterID src, RegisterID dest) + { + if (shouldBlind(imm)) { + if (src == dest) + return or32(imm, dest); + loadXorBlindedConstant(xorBlindConstant(imm), dest); + or32(src, dest); + } else + or32(imm.asTrustedImm32(), src, dest); + } + + void or32(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 key = orBlindedConstant(imm); + or32(key.value1, dest); + or32(key.value2, dest); + } else + or32(imm.asTrustedImm32(), dest); + } + + void poke(Imm32 value, int index = 0) + { + store32(value, addressForPoke(index)); + } + + void poke(ImmPtr value, int index = 0) + { + storePtr(value, addressForPoke(index)); + } + + void store32(Imm32 imm, Address dest) + { + if (shouldBlind(imm)) { +#if CPU(X86) || CPU(X86_64) + BlindedImm32 blind = xorBlindConstant(imm); + store32(blind.value1, dest); + xor32(blind.value2, dest); +#else + RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding(); + loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister); + store32(scratchRegister, dest); +#endif + } else + store32(imm.asTrustedImm32(), dest); + } + + void sub32(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 key = additionBlindedConstant(imm); + sub32(key.value1, dest); + sub32(key.value2, dest); + } else + sub32(imm.asTrustedImm32(), dest); + } + + void subPtr(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 key = additionBlindedConstant(imm); + subPtr(key.value1, dest); + subPtr(key.value2, dest); + } else + subPtr(imm.asTrustedImm32(), dest); + } + + void xor32(Imm32 imm, RegisterID src, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 blind = xorBlindConstant(imm); + xor32(blind.value1, src, dest); + xor32(blind.value2, dest); + } else + xor32(imm.asTrustedImm32(), src, dest); + } + + void xor32(Imm32 imm, RegisterID dest) + { + if (shouldBlind(imm)) { + BlindedImm32 blind = xorBlindConstant(imm); + xor32(blind.value1, dest); + xor32(blind.value2, dest); + } else + xor32(imm.asTrustedImm32(), dest); + } + + Jump branch32(RelationalCondition cond, RegisterID left, Imm32 right) + { + if (shouldBlind(right)) { + if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) { + loadXorBlindedConstant(xorBlindConstant(right), scratchRegister); + return branch32(cond, left, scratchRegister); + } + // If we don't have a scratch register available for use, we'll just + // place a random number of nops. + uint32_t nopCount = random() & 3; + while (nopCount--) + nop(); + return branch32(cond, left, right.asTrustedImm32()); + } + + return branch32(cond, left, right.asTrustedImm32()); + } + + Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest) + { + if (src == dest) { + if (!scratchRegisterForBlinding()) { + // Release mode ASSERT, if this fails we will perform incorrect codegen. + CRASH(); + } + } + if (shouldBlind(imm)) { + if (src == dest) { + if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) { + move(src, scratchRegister); + src = scratchRegister; + } + } + loadXorBlindedConstant(xorBlindConstant(imm), dest); + return branchAdd32(cond, src, dest); + } + return branchAdd32(cond, src, imm.asTrustedImm32(), dest); + } + + Jump branchMul32(ResultCondition cond, Imm32 imm, RegisterID src, RegisterID dest) + { + if (src == dest) { + if (!scratchRegisterForBlinding()) { + // Release mode ASSERT, if this fails we will perform incorrect codegen. + CRASH(); + } + } + if (shouldBlind(imm)) { + if (src == dest) { + if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) { + move(src, scratchRegister); + src = scratchRegister; + } + } + loadXorBlindedConstant(xorBlindConstant(imm), dest); + return branchMul32(cond, src, dest); + } + return branchMul32(cond, imm.asTrustedImm32(), src, dest); + } + + // branchSub32 takes a scratch register as 32 bit platforms make use of this, + // with src == dst, and on x86-32 we don't have a platform scratch register. + Jump branchSub32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest, RegisterID scratch) + { + if (shouldBlind(imm)) { + ASSERT(scratch != dest); + ASSERT(scratch != src); + loadXorBlindedConstant(xorBlindConstant(imm), scratch); + return branchSub32(cond, src, scratch, dest); + } + return branchSub32(cond, src, imm.asTrustedImm32(), dest); + } + + // Immediate shifts only have 5 controllable bits + // so we'll consider them safe for now. + TrustedImm32 trustedImm32ForShift(Imm32 imm) + { + return TrustedImm32(imm.asTrustedImm32().m_value & 31); + } + + void lshift32(Imm32 imm, RegisterID dest) + { + lshift32(trustedImm32ForShift(imm), dest); + } + + void lshift32(RegisterID src, Imm32 amount, RegisterID dest) + { + lshift32(src, trustedImm32ForShift(amount), dest); + } + + void rshift32(Imm32 imm, RegisterID dest) + { + rshift32(trustedImm32ForShift(imm), dest); + } + + void rshift32(RegisterID src, Imm32 amount, RegisterID dest) + { + rshift32(src, trustedImm32ForShift(amount), dest); + } + + void urshift32(Imm32 imm, RegisterID dest) + { + urshift32(trustedImm32ForShift(imm), dest); + } + + void urshift32(RegisterID src, Imm32 amount, RegisterID dest) + { + urshift32(src, trustedImm32ForShift(amount), dest); + } +#endif }; } // namespace JSC diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index 51173895a..c0cd766cb 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -108,6 +108,11 @@ public: add32(ARMRegisters::S1, dest); } + void add32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.adds_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); + } + void and32(RegisterID src, RegisterID dest) { m_assembler.ands_r(dest, dest, src); @@ -122,6 +127,15 @@ public: m_assembler.ands_r(dest, dest, w); } + void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true); + if (w & ARMAssembler::OP2_INV_IMM) + m_assembler.bics_r(dest, src, w & ~ARMAssembler::OP2_INV_IMM); + else + m_assembler.ands_r(dest, src, w); + } + void lshift32(RegisterID shift_amount, RegisterID dest) { ARMWord w = ARMAssembler::getOp2(0x1f); @@ -156,11 +170,6 @@ public: m_assembler.rsbs_r(srcDest, srcDest, ARMAssembler::getOp2(0)); } - void not32(RegisterID dest) - { - m_assembler.mvns_r(dest, dest); - } - void or32(RegisterID src, RegisterID dest) { m_assembler.orrs_r(dest, dest, src); @@ -232,6 +241,11 @@ public: sub32(ARMRegisters::S1, dest); } + void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.subs_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); + } + void xor32(RegisterID src, RegisterID dest) { m_assembler.eors_r(dest, dest, src); @@ -239,7 +253,10 @@ public: void xor32(TrustedImm32 imm, RegisterID dest) { - m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); + if (imm.m_value == -1) + m_assembler.mvns_r(dest, dest); + else + m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } void countLeadingZeros32(RegisterID src, RegisterID dest) @@ -547,6 +564,13 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } + Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + add32(src, imm, dest); + return Jump(m_assembler.jmp(ARMCondition(cond))); + } + void mull32(RegisterID src1, RegisterID src2, RegisterID dest) { if (src1 == dest) { @@ -596,6 +620,13 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } + Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + sub32(src, imm, dest); + return Jump(m_assembler.jmp(ARMCondition(cond))); + } + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index d883abf4f..43ea2ed5a 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -51,14 +51,7 @@ public: // Magic number is the biggest useful offset we can get on ARMv7 with // a LDR_imm_T2 encoding static const int MaximumCompactPtrAlignedAddressOffset = 124; - - MacroAssemblerARMv7() - : m_inUninterruptedSequence(false) - { - } - void beginUninterruptedSequence() { m_inUninterruptedSequence = true; } - void endUninterruptedSequence() { m_inUninterruptedSequence = false; } Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); } void* unlinkedCode() { return m_assembler.unlinkedCode(); } bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); } @@ -303,11 +296,6 @@ public: m_assembler.neg(srcDest, srcDest); } - void not32(RegisterID srcDest) - { - m_assembler.mvn(srcDest, srcDest); - } - void or32(RegisterID src, RegisterID dest) { m_assembler.orr(dest, dest, src); @@ -447,6 +435,11 @@ public: void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) { + if (imm.m_value == -1) { + m_assembler.mvn(dest, src); + return; + } + ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); if (armImm.isValid()) m_assembler.eor(dest, src, armImm); @@ -463,7 +456,10 @@ public: void xor32(TrustedImm32 imm, RegisterID dest) { - xor32(imm, dest, dest); + if (imm.m_value == -1) + m_assembler.mvn(dest, dest); + else + xor32(imm, dest, dest); } @@ -527,6 +523,7 @@ private: unreachableForPlatform(); } +protected: void store32(RegisterID src, ArmAddress address) { if (address.type == ArmAddress::HasIndex) @@ -541,6 +538,7 @@ private: } } +private: void store8(RegisterID src, ArmAddress address) { if (address.type == ArmAddress::HasIndex) @@ -723,6 +721,26 @@ public: store16(src, setupArmAddress(address)); } +#if ENABLE(JIT_CONSTANT_BLINDING) + static RegisterID scratchRegisterForBlinding() { return dataTempRegister; } + static bool shouldBlindForSpecificArch(uint32_t value) + { + ARMThumbImmediate immediate = ARMThumbImmediate::makeEncodedImm(value); + + // Couldn't be encoded as an immediate, so assume it's untrusted. + if (!immediate.isValid()) + return true; + + // If we can encode the immediate, we have less than 16 attacker + // controlled bits. + if (immediate.isEncodedImm()) + return false; + + // Don't let any more than 12 bits of an instruction word + // be controlled by an attacker. + return !immediate.isUInt12(); + } +#endif // Floating-point operations: @@ -789,7 +807,7 @@ public: void storeDouble(FPRegisterID src, const void* address) { - move(ImmPtr(address), addressTempRegister); + move(TrustedImmPtr(address), addressTempRegister); storeDouble(src, addressTempRegister); } @@ -883,6 +901,11 @@ public: m_assembler.vabs(dest, src); } + void negateDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.vneg(dest, src); + } + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.vmov(fpTempRegisterAsSingle(), src); @@ -954,7 +977,7 @@ public: // clamped to 0x80000000, so 2x dest is zero in this case. In the case of // overflow the result will be equal to -2. Jump underflow = branchAdd32(Zero, dest, dest, dataTempRegister); - Jump noOverflow = branch32(NotEqual, dataTempRegister, Imm32(-2)); + Jump noOverflow = branch32(NotEqual, dataTempRegister, TrustedImm32(-2)); // For BranchIfTruncateSuccessful, we branch if 'noOverflow' jumps. underflow.link(this); @@ -1356,7 +1379,7 @@ public: { // Move the high bits of the address into addressTempRegister, // and load the value into dataTempRegister. - move(ImmPtr(dest.m_ptr), addressTempRegister); + move(TrustedImmPtr(dest.m_ptr), addressTempRegister); m_assembler.ldr(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt16(0)); // Do the add. @@ -1369,7 +1392,7 @@ public: // we'll need to reload it with the high bits of the address afterwards. move(imm, addressTempRegister); m_assembler.add_S(dataTempRegister, dataTempRegister, addressTempRegister); - move(ImmPtr(dest.m_ptr), addressTempRegister); + move(TrustedImmPtr(dest.m_ptr), addressTempRegister); } // Store the result. @@ -1401,6 +1424,13 @@ public: return branchMul32(cond, dataTempRegister, src, dest); } + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) + { + ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0); + m_assembler.sub_S(srcDest, zero, srcDest); + return Jump(makeBranch(cond)); + } + Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) { m_assembler.orr_S(dest, dest, src); @@ -1586,10 +1616,6 @@ public: } protected: - bool inUninterruptedSequence() - { - return m_inUninterruptedSequence; - } ALWAYS_INLINE Jump jump() { @@ -1697,8 +1723,7 @@ private: { ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); } - - bool m_inUninterruptedSequence; + }; } // namespace JSC diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h index 3d7d84534..ac62c4221 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h @@ -27,9 +27,9 @@ #define MacroAssemblerCodeRef_h #include "ExecutableAllocator.h" -#include "PassRefPtr.h" -#include "RefPtr.h" -#include "UnusedParam.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/UnusedParam.h> // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid // instruction address on the platform (for example, check any alignment requirements). @@ -280,6 +280,10 @@ public: return result; } + static MacroAssemblerCodePtr createLLIntCodePtr(void (*function)()) + { + return createFromExecutableAddress(bitwise_cast<void*>(function)); + } explicit MacroAssemblerCodePtr(ReturnAddressPtr ra) : m_value(ra.value()) { @@ -340,6 +344,12 @@ public: return MacroAssemblerCodeRef(codePtr); } + // Helper for creating self-managed code refs from LLInt. + static MacroAssemblerCodeRef createLLIntCodeRef(void (*function)()) + { + return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(bitwise_cast<void*>(function))); + } + ExecutableMemoryHandle* executableMemory() const { return m_executableMemory.get(); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index f1aa6d4ad..910bc5a47 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -132,6 +132,11 @@ public: } } + void add32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + add32(imm, src, dest); + } + void add32(TrustedImm32 imm, Address address) { if (address.offset >= -32768 && address.offset <= 32767 @@ -291,11 +296,6 @@ public: m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest); } - void not32(RegisterID srcDest) - { - m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero); - } - void or32(RegisterID src, RegisterID dest) { m_assembler.orInsn(dest, dest, src); @@ -373,6 +373,24 @@ public: } } + void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 + && !m_fixedWidth) { + /* + addiu dest, src, imm + */ + m_assembler.addiu(dest, src, -imm.m_value); + } else { + /* + li immTemp, imm + subu dest, src, immTemp + */ + move(imm, immTempRegister); + m_assembler.subu(dest, src, immTempRegister); + } + } + void sub32(TrustedImm32 imm, Address address) { if (address.offset >= -32768 && address.offset <= 32767 @@ -458,6 +476,11 @@ public: void xor32(TrustedImm32 imm, RegisterID dest) { + if (imm.m_value == -1) { + m_assembler.nor(dest, dest, MIPSRegisters::zero); + return; + } + /* li immTemp, imm xor dest, dest, immTemp @@ -1203,6 +1226,13 @@ public: return branchAdd32(cond, immTempRegister, dest); } + Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + move(src, dest); + return branchAdd32(cond, immTempRegister, dest); + } + Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -1308,6 +1338,13 @@ public: return branchSub32(cond, immTempRegister, dest); } + Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + move(src, dest); + return branchSub32(cond, immTempRegister, dest); + } + Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h index a84f33748..2b5c0cc44 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h @@ -209,11 +209,6 @@ public: releaseScratch(scr); } - void not32(RegisterID src, RegisterID dest) - { - m_assembler.notlReg(src, dest); - } - void or32(RegisterID src, RegisterID dest) { m_assembler.orlRegReg(src, dest); @@ -380,6 +375,11 @@ public: void xor32(TrustedImm32 imm, RegisterID srcDest) { + if (imm.m_value == -1) { + m_assembler.notlReg(srcDest, srcDest); + return; + } + if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) { RegisterID scr = claimScratch(); m_assembler.loadConstant((imm.m_value), scr); @@ -1565,6 +1565,33 @@ public: return branchAdd32(cond, scratchReg3, dest); } + Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + + if (src != dest) + move(src, dest); + + if (cond == Overflow) { + move(imm, scratchReg3); + m_assembler.addvlRegReg(scratchReg3, dest); + return branchTrue(); + } + + add32(imm, dest); + + if (cond == Signed) { + m_assembler.cmppz(dest); + return branchFalse(); + } + + compare32(0, dest, Equal); + + if (cond == NotEqual) + return branchFalse(); + return branchTrue(); + } + Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -1642,6 +1669,14 @@ public: return branchSub32(cond, scratchReg3, dest); } + Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) + { + move(imm, scratchReg3); + if (src != dest) + move(src, dest); + return branchSub32(cond, scratchReg3, dest); + } + Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -1681,11 +1716,6 @@ public: m_assembler.neg(dst, dst); } - void not32(RegisterID dst) - { - m_assembler.notlReg(dst, dst); - } - void urshift32(RegisterID shiftamount, RegisterID dest) { if (shiftamount == SH4Registers::r0) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h index cb2450f62..088fe196b 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h @@ -93,12 +93,6 @@ public: m_assembler.addsd_mr(address.m_ptr, dest); } - void loadDouble(const void* address, FPRegisterID dest) - { - ASSERT(isSSE2Present()); - m_assembler.movsd_mr(address, dest); - } - void storeDouble(FPRegisterID src, const void* address) { ASSERT(isSSE2Present()); @@ -110,14 +104,6 @@ public: m_assembler.cvtsi2sd_mr(src.m_ptr, dest); } - void absDouble(FPRegisterID src, FPRegisterID dst) - { - ASSERT(src != dst); - static const double negativeZeroConstant = -0.0; - loadDouble(&negativeZeroConstant, dst); - m_assembler.andnpd_rr(src, dst); - } - void store32(TrustedImm32 imm, void* address) { m_assembler.movl_i32m(imm.m_value, address); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h index e6c39598b..8cb442cc5 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -34,6 +34,11 @@ namespace JSC { class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> { +protected: +#if CPU(X86_64) + static const X86Registers::RegisterID scratchRegister = X86Registers::r11; +#endif + static const int DoubleConditionBitInvert = 0x10; static const int DoubleConditionBitSpecial = 0x20; static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial; @@ -86,6 +91,13 @@ public: static const RegisterID stackPointerRegister = X86Registers::esp; +#if ENABLE(JIT_CONSTANT_BLINDING) + static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; } +#if CPU(X86_64) + static bool shouldBlindForSpecificArch(uintptr_t value) { return value >= 0x00ffffff; } +#endif +#endif + // Integer arithmetic operations: // // Operations are typically two operand - operation(source, srcDst) @@ -223,16 +235,6 @@ public: m_assembler.negl_m(srcDest.offset, srcDest.base); } - void not32(RegisterID srcDest) - { - m_assembler.notl_r(srcDest); - } - - void not32(Address srcDest) - { - m_assembler.notl_m(srcDest.offset, srcDest.base); - } - void or32(RegisterID src, RegisterID dest) { m_assembler.orl_rr(src, dest); @@ -375,7 +377,6 @@ public: m_assembler.subl_rm(src, dest.offset, dest.base); } - void xor32(RegisterID src, RegisterID dest) { m_assembler.xorl_rr(src, dest); @@ -383,11 +384,17 @@ public: void xor32(TrustedImm32 imm, Address dest) { - m_assembler.xorl_im(imm.m_value, dest.offset, dest.base); + if (imm.m_value == -1) + m_assembler.notl_m(dest.offset, dest.base); + else + m_assembler.xorl_im(imm.m_value, dest.offset, dest.base); } void xor32(TrustedImm32 imm, RegisterID dest) { + if (imm.m_value == -1) + m_assembler.notl_r(dest); + else m_assembler.xorl_ir(imm.m_value, dest); } @@ -424,6 +431,23 @@ public: m_assembler.sqrtsd_rr(src, dst); } + void absDouble(FPRegisterID src, FPRegisterID dst) + { + ASSERT(src != dst); + static const double negativeZeroConstant = -0.0; + loadDouble(&negativeZeroConstant, dst); + m_assembler.andnpd_rr(src, dst); + } + + void negateDouble(FPRegisterID src, FPRegisterID dst) + { + ASSERT(src != dst); + static const double negativeZeroConstant = -0.0; + loadDouble(&negativeZeroConstant, dst); + m_assembler.xorpd_rr(src, dst); + } + + // Memory access operations: // // Loads are of the form load(address, destination) and stores of the form @@ -620,6 +644,17 @@ public: m_assembler.movsd_rr(src, dest); } + void loadDouble(const void* address, FPRegisterID dest) + { +#if CPU(X86) + ASSERT(isSSE2Present()); + m_assembler.movsd_mr(address, dest); +#else + move(TrustedImmPtr(address), scratchRegister); + loadDouble(scratchRegister, dest); +#endif + } + void loadDouble(ImplicitAddress address, FPRegisterID dest) { ASSERT(isSSE2Present()); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h index 846049999..a2b4311e5 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -35,9 +35,6 @@ namespace JSC { class MacroAssemblerX86_64 : public MacroAssemblerX86Common { -protected: - static const X86Registers::RegisterID scratchRegister = X86Registers::r11; - public: static const Scale ScalePtr = TimesEight; @@ -88,12 +85,6 @@ public: } } - void loadDouble(const void* address, FPRegisterID dest) - { - move(TrustedImmPtr(address), scratchRegister); - loadDouble(scratchRegister, dest); - } - void addDouble(AbsoluteAddress address, FPRegisterID dest) { move(TrustedImmPtr(address.m_ptr), scratchRegister); @@ -106,14 +97,6 @@ public: m_assembler.cvtsi2sd_rr(scratchRegister, dest); } - void absDouble(FPRegisterID src, FPRegisterID dst) - { - ASSERT(src != dst); - static const double negativeZeroConstant = -0.0; - loadDouble(&negativeZeroConstant, dst); - m_assembler.andnpd_rr(src, dst); - } - void store32(TrustedImm32 imm, void* address) { move(TrustedImmPtr(address), scratchRegister); @@ -233,6 +216,11 @@ public: move(src, dest); orPtr(imm, dest); } + + void rotateRightPtr(TrustedImm32 imm, RegisterID srcDst) + { + m_assembler.rorq_i8r(imm.m_value, srcDst); + } void subPtr(RegisterID src, RegisterID dest) { @@ -254,13 +242,17 @@ public: { m_assembler.xorq_rr(src, dest); } + + void xorPtr(RegisterID src, Address dest) + { + m_assembler.xorq_rm(src, dest.offset, dest.base); + } void xorPtr(TrustedImm32 imm, RegisterID srcDest) { m_assembler.xorq_ir(imm.m_value, srcDest); } - void loadPtr(ImplicitAddress address, RegisterID dest) { m_assembler.movq_mr(address.offset, address.base, dest); @@ -351,6 +343,13 @@ public: m_assembler.movzbl_rr(dest, dest); } + void comparePtr(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) + { + m_assembler.cmpq_rr(right, left); + m_assembler.setCC_r(x86Condition(cond), dest); + m_assembler.movzbl_rr(dest, dest); + } + Jump branchAdd32(ResultCondition cond, TrustedImm32 src, AbsoluteAddress dest) { move(TrustedImmPtr(dest.m_ptr), scratchRegister); @@ -459,6 +458,12 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } + Jump branchSubPtr(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest) + { + move(src1, dest); + return branchSubPtr(cond, src2, dest); + } + DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) { m_assembler.movq_i64r(initialValue.asIntptr(), dest); @@ -503,6 +508,8 @@ public: return FunctionPtr(X86Assembler::readPointer(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).dataLocation())); } + static RegisterID scratchRegisterForBlinding() { return scratchRegister; } + private: friend class LinkBuffer; friend class RepatchBuffer; diff --git a/Source/JavaScriptCore/assembler/SH4Assembler.h b/Source/JavaScriptCore/assembler/SH4Assembler.h index 280a5de85..1cf96b735 100644 --- a/Source/JavaScriptCore/assembler/SH4Assembler.h +++ b/Source/JavaScriptCore/assembler/SH4Assembler.h @@ -31,6 +31,7 @@ #include "AssemblerBuffer.h" #include "AssemblerBufferWithConstantPool.h" +#include "JITCompilationEffort.h" #include <stdarg.h> #include <stdint.h> #include <stdio.h> @@ -1514,9 +1515,9 @@ public: return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr & 0xff), instructionPtr)); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID) + PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) { - return m_buffer.executableCopy(globalData, ownerUID); + return m_buffer.executableCopy(globalData, ownerUID, effort); } void prefix(uint16_t pre) diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index 25f8602e8..b24fffb8f 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -29,6 +29,7 @@ #if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64)) #include "AssemblerBuffer.h" +#include "JITCompilationEffort.h" #include <stdint.h> #include <wtf/Assertions.h> #include <wtf/Vector.h> @@ -215,7 +216,12 @@ private: GROUP1_OP_CMP = 7, GROUP1A_OP_POP = 0, - + + GROUP2_OP_ROL = 0, + GROUP2_OP_ROR = 1, + GROUP2_OP_RCL = 2, + GROUP2_OP_RCR = 3, + GROUP2_OP_SHL = 4, GROUP2_OP_SHR = 5, GROUP2_OP_SAR = 7, @@ -635,6 +641,22 @@ public: m_formatter.immediate32(imm); } } + + void xorq_rm(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp64(OP_XOR_EvGv, src, base, offset); + } + + void rorq_i8r(int imm, RegisterID dst) + { + if (imm == 1) + m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_ROR, dst); + else { + m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_ROR, dst); + m_formatter.immediate8(imm); + } + } + #endif void sarl_i8r(int imm, RegisterID dst) @@ -1782,9 +1804,9 @@ public: return b.m_offset - a.m_offset; } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID) + PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) { - return m_formatter.executableCopy(globalData, ownerUID); + return m_formatter.executableCopy(globalData, ownerUID, effort); } unsigned debugOffset() { return m_formatter.debugOffset(); } @@ -2130,9 +2152,9 @@ private: bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } void* data() const { return m_buffer.data(); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID) + PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) { - return m_buffer.executableCopy(globalData, ownerUID); + return m_buffer.executableCopy(globalData, ownerUID, effort); } unsigned debugOffset() { return m_buffer.debugOffset(); } diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index ab89ad965..20972cc63 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -226,7 +226,7 @@ static bool isPropertyAccess(OpcodeID opcodeID) } } -static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID)) +static unsigned instructionOffsetForNth(ExecState* exec, const RefCountedArray<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID)) { size_t i = 0; while (i < instructions.size()) { @@ -347,18 +347,13 @@ void CodeBlock::printStructures(const Instruction* vPC) const void CodeBlock::dump(ExecState* exec) const { - if (!m_instructions) { - dataLog("No instructions available.\n"); - return; - } - size_t instructionCount = 0; for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)]) ++instructionCount; dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n", - static_cast<unsigned long>(instructionCount), + static_cast<unsigned long>(instructions().size()), static_cast<unsigned long>(instructions().size() * sizeof(Instruction)), this, m_numParameters, m_numCalleeRegisters, m_numVars); @@ -689,10 +684,6 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& ++it; break; } - case op_bitnot: { - printUnaryOp(exec, location, it, "bitnot"); - break; - } case op_check_has_instance: { int base = (++it)->u.operand; dataLog("[%4d] check_has_instance\t\t %s\n", location, registerName(exec, base).data()); @@ -1424,11 +1415,9 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab) , m_numVars(other.m_numVars) , m_numCapturedVars(other.m_numCapturedVars) , m_isConstructor(other.m_isConstructor) - , m_shouldDiscardBytecode(false) , m_ownerExecutable(*other.m_globalData, other.m_ownerExecutable.get(), other.m_ownerExecutable.get()) , m_globalData(other.m_globalData) , m_instructions(other.m_instructions) - , m_instructionCount(other.m_instructionCount) , m_thisRegister(other.m_thisRegister) , m_argumentsRegister(other.m_argumentsRegister) , m_activationRegister(other.m_activationRegister) @@ -1484,12 +1473,9 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo , m_numCalleeRegisters(0) , m_numVars(0) , m_isConstructor(isConstructor) - , m_shouldDiscardBytecode(false) , m_numParameters(0) , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable) , m_globalData(0) - , m_instructions(adoptRef(new Instructions)) - , m_instructionCount(0) , m_argumentsRegister(-1) , m_needsFullScopeChain(ownerExecutable->needsActivation()) , m_usesEval(ownerExecutable->usesEval()) @@ -1595,13 +1581,15 @@ void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { visitor.append(&vPC[4].u.structure); - visitor.append(&vPC[5].u.structureChain); + if (vPC[5].u.structureChain) + visitor.append(&vPC[5].u.structureChain); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { visitor.append(&vPC[4].u.structure); visitor.append(&vPC[5].u.structure); - visitor.append(&vPC[6].u.structureChain); + if (vPC[6].u.structureChain) + visitor.append(&vPC[6].u.structureChain); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) && vPC[4].u.structure) { @@ -1631,6 +1619,32 @@ void EvalCodeCache::visitAggregate(SlotVisitor& visitor) void CodeBlock::visitAggregate(SlotVisitor& visitor) { +#if ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT) + if (!!m_dfgData) { + // I may be asked to scan myself more than once, and it may even happen concurrently. + // To this end, use a CAS loop to check if I've been called already. Only one thread + // may proceed past this point - whichever one wins the CAS race. + unsigned oldValue; + do { + oldValue = m_dfgData->visitAggregateHasBeenCalled; + if (oldValue) { + // Looks like someone else won! Return immediately to ensure that we don't + // trace the same CodeBlock concurrently. Doing so is hazardous since we will + // be mutating the state of ValueProfiles, which contain JSValues, which can + // have word-tearing on 32-bit, leading to awesome timing-dependent crashes + // that are nearly impossible to track down. + + // Also note that it must be safe to return early as soon as we see the + // value true (well, (unsigned)1), since once a GC thread is in this method + // and has won the CAS race (i.e. was responsible for setting the value true) + // it will definitely complete the rest of this method before declaring + // termination. + return; + } + } while (!WTF::weakCompareAndSwap(&m_dfgData->visitAggregateHasBeenCalled, 0, 1)); + } +#endif // ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT) + if (!!m_alternative) m_alternative->visitAggregate(visitor); @@ -1903,12 +1917,6 @@ void CodeBlock::finalizeUnconditionally() } } #endif - - // Handle the bytecode discarding chore. - if (m_shouldDiscardBytecode) { - discardBytecode(); - m_shouldDiscardBytecode = false; - } } void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor) @@ -1980,7 +1988,7 @@ void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor) HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) { - ASSERT(bytecodeOffset < m_instructionCount); + ASSERT(bytecodeOffset < instructions().size()); if (!m_rareData) return 0; @@ -1998,7 +2006,7 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset) { - ASSERT(bytecodeOffset < m_instructionCount); + ASSERT(bytecodeOffset < instructions().size()); if (!m_rareData) return m_ownerExecutable->source().firstLine(); @@ -2022,7 +2030,7 @@ int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset) void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset) { - ASSERT(bytecodeOffset < m_instructionCount); + ASSERT(bytecodeOffset < instructions().size()); if (!m_rareData) { startOffset = 0; @@ -2102,8 +2110,6 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) void CodeBlock::shrinkToFit() { - instructions().shrinkToFit(); - #if ENABLE(CLASSIC_INTERPRETER) m_propertyAccessInstructions.shrinkToFit(); m_globalResolveInstructions.shrinkToFit(); @@ -2345,21 +2351,21 @@ void FunctionCodeBlock::jettison() static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall); } -void ProgramCodeBlock::jitCompileImpl(JSGlobalData& globalData) +bool ProgramCodeBlock::jitCompileImpl(JSGlobalData& globalData) { ASSERT(getJITType() == JITCode::InterpreterThunk); ASSERT(this == replacement()); return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(globalData); } -void EvalCodeBlock::jitCompileImpl(JSGlobalData& globalData) +bool EvalCodeBlock::jitCompileImpl(JSGlobalData& globalData) { ASSERT(getJITType() == JITCode::InterpreterThunk); ASSERT(this == replacement()); return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(globalData); } -void FunctionCodeBlock::jitCompileImpl(JSGlobalData& globalData) +bool FunctionCodeBlock::jitCompileImpl(JSGlobalData& globalData) { ASSERT(getJITType() == JITCode::InterpreterThunk); ASSERT(this == replacement()); @@ -2467,7 +2473,38 @@ void CodeBlock::dumpValueProfiles() } #endif -#ifndef NDEBUG +size_t CodeBlock::predictedMachineCodeSize() +{ + // This will be called from CodeBlock::CodeBlock before either m_globalData or the + // instructions have been initialized. It's OK to return 0 because what will really + // matter is the recomputation of this value when the slow path is triggered. + if (!m_globalData) + return 0; + + if (!m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT) + return 0; // It's as good of a prediction as we'll get. + + // Be conservative: return a size that will be an overestimation 84% of the time. + double multiplier = m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.mean() + + m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.standardDeviation(); + + // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing + // here is OK, since this whole method is just a heuristic. + if (multiplier < 0 || multiplier > 1000) + return 0; + + double doubleResult = multiplier * m_instructions.size(); + + // Be even more paranoid: silently reject values that won't fit into a size_t. If + // the function is so huge that we can't even fit it into virtual memory then we + // should probably have some other guards in place to prevent us from even getting + // to this point. + if (doubleResult > std::numeric_limits<size_t>::max()) + return 0; + + return static_cast<size_t>(doubleResult); +} + bool CodeBlock::usesOpcode(OpcodeID opcodeID) { Interpreter* interpreter = globalData()->interpreter; @@ -2492,6 +2529,5 @@ bool CodeBlock::usesOpcode(OpcodeID opcodeID) return false; } -#endif } // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 195aa62ca..469028097 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -41,6 +41,7 @@ #include "DFGOSREntry.h" #include "DFGOSRExit.h" #include "EvalCodeCache.h" +#include "ExecutionCounter.h" #include "ExpressionRangeInfo.h" #include "GlobalResolveInfo.h" #include "HandlerInfo.h" @@ -61,6 +62,7 @@ #include "UString.h" #include "UnconditionalFinalizer.h" #include "ValueProfile.h" +#include <wtf/RefCountedArray.h> #include <wtf/FastAllocBase.h> #include <wtf/PassOwnPtr.h> #include <wtf/RefPtr.h> @@ -127,8 +129,6 @@ namespace JSC { } #endif - bool canProduceCopyWithBytecode() { return hasInstructions(); } - void visitAggregate(SlotVisitor&); static void dumpStatistics(); @@ -341,20 +341,15 @@ namespace JSC { void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; } bool isNumericCompareFunction() { return m_isNumericCompareFunction; } - bool hasInstructions() const { return !!m_instructions; } - unsigned numberOfInstructions() const { return !m_instructions ? 0 : m_instructions->m_instructions.size(); } - Vector<Instruction>& instructions() { return m_instructions->m_instructions; } - const Vector<Instruction>& instructions() const { return m_instructions->m_instructions; } - void discardBytecode() { m_instructions.clear(); } - void discardBytecodeLater() - { - m_shouldDiscardBytecode = true; - } + unsigned numberOfInstructions() const { return m_instructions.size(); } + RefCountedArray<Instruction>& instructions() { return m_instructions; } + const RefCountedArray<Instruction>& instructions() const { return m_instructions; } + + size_t predictedMachineCodeSize(); bool usesOpcode(OpcodeID); - unsigned instructionCount() { return m_instructionCount; } - void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; } + unsigned instructionCount() { return m_instructions.size(); } #if ENABLE(JIT) void setJITCode(const JITCode& code, MacroAssemblerCodePtr codeWithArityCheck) @@ -374,18 +369,20 @@ namespace JSC { ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); } virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0; virtual void jettison() = 0; - bool jitCompile(JSGlobalData& globalData) + enum JITCompilationResult { AlreadyCompiled, CouldNotCompile, CompiledSuccessfully }; + JITCompilationResult jitCompile(JSGlobalData& globalData) { if (getJITType() != JITCode::InterpreterThunk) { ASSERT(getJITType() == JITCode::BaselineJIT); - return false; + return AlreadyCompiled; } #if ENABLE(JIT) - jitCompileImpl(globalData); - return true; + if (jitCompileImpl(globalData)) + return CompiledSuccessfully; + return CouldNotCompile; #else UNUSED_PARAM(globalData); - return false; + return CouldNotCompile; #endif } virtual CodeBlock* replacement() = 0; @@ -541,11 +538,10 @@ namespace JSC { { ValueProfile* result = WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset); ASSERT(result->m_bytecodeOffset != -1); - ASSERT(!hasInstructions() - || instructions()[bytecodeOffset + opcodeLength( - m_globalData->interpreter->getOpcodeID( - instructions()[ - bytecodeOffset].u.opcode)) - 1].u.profile == result); + ASSERT(instructions()[bytecodeOffset + opcodeLength( + m_globalData->interpreter->getOpcodeID( + instructions()[ + bytecodeOffset].u.opcode)) - 1].u.profile == result); return result; } PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset) @@ -839,24 +835,29 @@ namespace JSC { // Functions for controlling when JITting kicks in, in a mixed mode // execution world. + bool checkIfJITThresholdReached() + { + return m_llintExecuteCounter.checkIfThresholdCrossedAndSet(this); + } + void dontJITAnytimeSoon() { - m_llintExecuteCounter = Options::executionCounterValueForDontJITAnytimeSoon; + m_llintExecuteCounter.deferIndefinitely(); } void jitAfterWarmUp() { - m_llintExecuteCounter = Options::executionCounterValueForJITAfterWarmUp; + m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITAfterWarmUp, this); } void jitSoon() { - m_llintExecuteCounter = Options::executionCounterValueForJITSoon; + m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITSoon, this); } int32_t llintExecuteCounter() const { - return m_llintExecuteCounter; + return m_llintExecuteCounter.m_counter; } // Functions for controlling when tiered compilation kicks in. This @@ -895,31 +896,41 @@ namespace JSC { int32_t counterValueForOptimizeAfterWarmUp() { - return Options::executionCounterValueForOptimizeAfterWarmUp << reoptimizationRetryCounter(); + return Options::thresholdForOptimizeAfterWarmUp << reoptimizationRetryCounter(); } int32_t counterValueForOptimizeAfterLongWarmUp() { - return Options::executionCounterValueForOptimizeAfterLongWarmUp << reoptimizationRetryCounter(); + return Options::thresholdForOptimizeAfterLongWarmUp << reoptimizationRetryCounter(); } int32_t* addressOfJITExecuteCounter() { - return &m_jitExecuteCounter; + return &m_jitExecuteCounter.m_counter; } - static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter); } + static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_counter); } + static ptrdiff_t offsetOfJITExecutionActiveThreshold() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_activeThreshold); } + static ptrdiff_t offsetOfJITExecutionTotalCount() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_totalCount); } - int32_t jitExecuteCounter() const { return m_jitExecuteCounter; } + int32_t jitExecuteCounter() const { return m_jitExecuteCounter.m_counter; } unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; } + // Check if the optimization threshold has been reached, and if not, + // adjust the heuristics accordingly. Returns true if the threshold has + // been reached. + bool checkIfOptimizationThresholdReached() + { + return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this); + } + // Call this to force the next optimization trigger to fire. This is // rarely wise, since optimization triggers are typically more // expensive than executing baseline code. void optimizeNextInvocation() { - m_jitExecuteCounter = Options::executionCounterValueForOptimizeNextInvocation; + m_jitExecuteCounter.setNewThreshold(0, this); } // Call this to prevent optimization from happening again. Note that @@ -929,7 +940,7 @@ namespace JSC { // the future as well. void dontOptimizeAnytimeSoon() { - m_jitExecuteCounter = Options::executionCounterValueForDontOptimizeAnytimeSoon; + m_jitExecuteCounter.deferIndefinitely(); } // Call this to reinitialize the counter to its starting state, @@ -940,14 +951,14 @@ namespace JSC { // counter that this corresponds to is also available directly. void optimizeAfterWarmUp() { - m_jitExecuteCounter = counterValueForOptimizeAfterWarmUp(); + m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterWarmUp(), this); } // Call this to force an optimization trigger to fire only after // a lot of warm-up. void optimizeAfterLongWarmUp() { - m_jitExecuteCounter = counterValueForOptimizeAfterLongWarmUp(); + m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterLongWarmUp(), this); } // Call this to cause an optimization trigger to fire soon, but @@ -970,7 +981,7 @@ namespace JSC { // in the baseline code. void optimizeSoon() { - m_jitExecuteCounter = Options::executionCounterValueForOptimizeSoon << reoptimizationRetryCounter(); + m_jitExecuteCounter.setNewThreshold(Options::thresholdForOptimizeSoon << reoptimizationRetryCounter(), this); } // The speculative JIT tracks its success rate, so that we can @@ -1047,12 +1058,9 @@ namespace JSC { int m_numCapturedVars; bool m_isConstructor; - // This is public because otherwise we would have many friends. - bool m_shouldDiscardBytecode; - protected: #if ENABLE(JIT) - virtual void jitCompileImpl(JSGlobalData&) = 0; + virtual bool jitCompileImpl(JSGlobalData&) = 0; #endif virtual void visitWeakReferences(SlotVisitor&); virtual void finalizeUnconditionally(); @@ -1115,11 +1123,7 @@ namespace JSC { WriteBarrier<ScriptExecutable> m_ownerExecutable; JSGlobalData* m_globalData; - struct Instructions : public RefCounted<Instructions> { - Vector<Instruction> m_instructions; - }; - RefPtr<Instructions> m_instructions; - unsigned m_instructionCount; + RefCountedArray<Instruction> m_instructions; int m_thisRegister; int m_argumentsRegister; @@ -1186,6 +1190,7 @@ namespace JSC { bool isJettisoned; bool livenessHasBeenProved; // Initialized and used on every GC. bool allTransitionsHaveBeenMarked; // Initialized and used on every GC. + unsigned visitAggregateHasBeenCalled; // Unsigned to make it work seamlessly with the broadest set of CAS implementations. }; OwnPtr<DFGData> m_dfgData; @@ -1217,13 +1222,14 @@ namespace JSC { OwnPtr<CodeBlock> m_alternative; - int32_t m_llintExecuteCounter; + ExecutionCounter m_llintExecuteCounter; - int32_t m_jitExecuteCounter; + ExecutionCounter m_jitExecuteCounter; + int32_t m_totalJITExecutions; uint32_t m_speculativeSuccessCounter; uint32_t m_speculativeFailCounter; - uint8_t m_optimizationDelayCounter; - uint8_t m_reoptimizationRetryCounter; + uint16_t m_optimizationDelayCounter; + uint16_t m_reoptimizationRetryCounter; struct RareData { WTF_MAKE_FAST_ALLOCATED; @@ -1300,7 +1306,7 @@ namespace JSC { protected: virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); virtual void jettison(); - virtual void jitCompileImpl(JSGlobalData&); + virtual bool jitCompileImpl(JSGlobalData&); virtual CodeBlock* replacement(); virtual bool canCompileWithDFGInternal(); #endif @@ -1335,7 +1341,7 @@ namespace JSC { protected: virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); virtual void jettison(); - virtual void jitCompileImpl(JSGlobalData&); + virtual bool jitCompileImpl(JSGlobalData&); virtual CodeBlock* replacement(); virtual bool canCompileWithDFGInternal(); #endif @@ -1373,33 +1379,12 @@ namespace JSC { protected: virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*); virtual void jettison(); - virtual void jitCompileImpl(JSGlobalData&); + virtual bool jitCompileImpl(JSGlobalData&); virtual CodeBlock* replacement(); virtual bool canCompileWithDFGInternal(); #endif }; - // Use this if you want to copy a code block and you're paranoid about a GC - // happening. - class BytecodeDestructionBlocker { - public: - BytecodeDestructionBlocker(CodeBlock* codeBlock) - : m_codeBlock(codeBlock) - , m_oldValueOfShouldDiscardBytecode(codeBlock->m_shouldDiscardBytecode) - { - codeBlock->m_shouldDiscardBytecode = false; - } - - ~BytecodeDestructionBlocker() - { - m_codeBlock->m_shouldDiscardBytecode = m_oldValueOfShouldDiscardBytecode; - } - - private: - CodeBlock* m_codeBlock; - bool m_oldValueOfShouldDiscardBytecode; - }; - inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock) { if (codeOrigin.inlineCallFrame) { diff --git a/Source/JavaScriptCore/bytecode/CodeType.h b/Source/JavaScriptCore/bytecode/CodeType.h index 03485e564..d33677ae7 100644 --- a/Source/JavaScriptCore/bytecode/CodeType.h +++ b/Source/JavaScriptCore/bytecode/CodeType.h @@ -26,11 +26,28 @@ #ifndef CodeType_h #define CodeType_h +#include <wtf/Platform.h> + namespace JSC { enum CodeType { GlobalCode, EvalCode, FunctionCode }; +inline const char* codeTypeToString(CodeType codeType) +{ + switch (codeType) { + case GlobalCode: + return "GlobalCode"; + case EvalCode: + return "EvalCode"; + case FunctionCode: + return "FunctionCode"; + default: + ASSERT_NOT_REACHED(); + return 0; + } } +} // namespace JSC + #endif // CodeType_h diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp new file mode 100644 index 000000000..b3fd3ef26 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ExecutionCounter.h" + +#include "CodeBlock.h" +#include "ExecutableAllocator.h" +#include <wtf/DataLog.h> + +namespace JSC { + +ExecutionCounter::ExecutionCounter() +{ + reset(); +} + +bool ExecutionCounter::checkIfThresholdCrossedAndSet(CodeBlock* codeBlock) +{ + if (hasCrossedThreshold(codeBlock)) + return true; + + if (setThreshold(codeBlock)) + return true; + + return false; +} + +void ExecutionCounter::setNewThreshold(int32_t threshold, CodeBlock* codeBlock) +{ + reset(); + m_activeThreshold = threshold; + setThreshold(codeBlock); +} + +void ExecutionCounter::deferIndefinitely() +{ + m_totalCount = 0; + m_activeThreshold = std::numeric_limits<int32_t>::max(); + m_counter = std::numeric_limits<int32_t>::min(); +} + +double ExecutionCounter::applyMemoryUsageHeuristics(int32_t value, CodeBlock* codeBlock) +{ +#if ENABLE(JIT) + double multiplier = + ExecutableAllocator::memoryPressureMultiplier( + codeBlock->predictedMachineCodeSize()); +#else + // This code path will probably not be taken, but if it is, we fake it. + double multiplier = 1.0; + UNUSED_PARAM(codeBlock); +#endif + ASSERT(multiplier >= 1.0); + return multiplier * value; +} + +int32_t ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt( + int32_t value, CodeBlock* codeBlock) +{ + double doubleResult = applyMemoryUsageHeuristics(value, codeBlock); + + ASSERT(doubleResult >= 0); + + if (doubleResult > std::numeric_limits<int32_t>::max()) + return std::numeric_limits<int32_t>::max(); + + return static_cast<int32_t>(doubleResult); +} + +bool ExecutionCounter::hasCrossedThreshold(CodeBlock* codeBlock) const +{ + // This checks if the current count rounded up to the threshold we were targeting. + // For example, if we are using half of available executable memory and have + // m_activeThreshold = 1000, applyMemoryUsageHeuristics(m_activeThreshold) will be + // 2000, but we will pretend as if the threshold was crossed if we reach 2000 - + // 1000 / 2, or 1500. The reasoning here is that we want to avoid thrashing. If + // this method returns false, then the JIT's threshold for when it will again call + // into the slow path (which will call this method a second time) will be set + // according to the difference between the current count and the target count + // according to *current* memory usage. But by the time we call into this again, we + // may have JIT'ed more code, and so the target count will increase slightly. This + // may lead to a repeating pattern where the target count is slightly incremented, + // the JIT immediately matches that increase, calls into the slow path again, and + // again the target count is slightly incremented. Instead of having this vicious + // cycle, we declare victory a bit early if the difference between the current + // total and our target according to memory heuristics is small. Our definition of + // small is arbitrarily picked to be half of the original threshold (i.e. + // m_activeThreshold). + + double modifiedThreshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock); + + return static_cast<double>(m_totalCount) + m_counter >= + modifiedThreshold - static_cast<double>(m_activeThreshold) / 2; +} + +bool ExecutionCounter::setThreshold(CodeBlock* codeBlock) +{ + if (m_activeThreshold == std::numeric_limits<int32_t>::max()) { + deferIndefinitely(); + return false; + } + + ASSERT(!hasCrossedThreshold(codeBlock)); + + // Compute the true total count. + double trueTotalCount = static_cast<double>(m_totalCount) + m_counter; + + // Correct the threshold for current memory usage. + double threshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock); + + // Threshold must be non-negative and not NaN. + ASSERT(threshold >= 0); + + // Adjust the threshold according to the number of executions we have already + // seen. This shouldn't go negative, but it might, because of round-off errors. + threshold -= trueTotalCount; + + if (threshold <= 0) { + m_counter = 0; + m_totalCount = trueTotalCount; + return true; + } + + if (threshold > std::numeric_limits<int32_t>::max()) + threshold = std::numeric_limits<int32_t>::max(); + + m_counter = static_cast<int32_t>(-threshold); + + m_totalCount = trueTotalCount + threshold; + + return false; +} + +void ExecutionCounter::reset() +{ + m_counter = 0; + m_totalCount = 0; + m_activeThreshold = 0; +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.h b/Source/JavaScriptCore/bytecode/ExecutionCounter.h new file mode 100644 index 000000000..d2ffbb649 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ExecutionCounter_h +#define ExecutionCounter_h + +#include <wtf/SimpleStats.h> + +namespace JSC { + +class CodeBlock; + +class ExecutionCounter { +public: + ExecutionCounter(); + bool checkIfThresholdCrossedAndSet(CodeBlock*); + void setNewThreshold(int32_t threshold, CodeBlock*); + void deferIndefinitely(); + static double applyMemoryUsageHeuristics(int32_t value, CodeBlock*); + static int32_t applyMemoryUsageHeuristicsAndConvertToInt(int32_t value, CodeBlock*); + + static int32_t formattedTotalCount(float value) + { + union { + int32_t i; + float f; + } u; + u.f = value; + return u.i; + } + +private: + bool hasCrossedThreshold(CodeBlock*) const; + bool setThreshold(CodeBlock*); + void reset(); + +public: + + // NB. These are intentionally public because it will be modified from machine code. + + // This counter is incremented by the JIT or LLInt. It starts out negative and is + // counted up until it becomes non-negative. At the start of a counting period, + // the threshold we wish to reach is m_totalCount + m_counter, in the sense that + // we will add X to m_totalCount and subtract X from m_counter. + int32_t m_counter; + + // Counts the total number of executions we have seen plus the ones we've set a + // threshold for in m_counter. Because m_counter's threshold is negative, the + // total number of actual executions can always be computed as m_totalCount + + // m_counter. + float m_totalCount; + + // This is the threshold we were originally targetting, without any correction for + // the memory usage heuristics. + int32_t m_activeThreshold; +}; + +} // namespace JSC + +#endif // ExecutionCounter_h + diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h index a47fa5e9b..45598f899 100644 --- a/Source/JavaScriptCore/bytecode/Opcode.h +++ b/Source/JavaScriptCore/bytecode/Opcode.h @@ -82,7 +82,6 @@ namespace JSC { macro(op_bitand, 5) \ macro(op_bitxor, 5) \ macro(op_bitor, 5) \ - macro(op_bitnot, 3) \ \ macro(op_check_has_instance, 2) \ macro(op_instanceof, 5) \ diff --git a/Source/JavaScriptCore/bytecode/PredictedType.cpp b/Source/JavaScriptCore/bytecode/PredictedType.cpp index 2b490c24e..b04ff1f57 100644 --- a/Source/JavaScriptCore/bytecode/PredictedType.cpp +++ b/Source/JavaScriptCore/bytecode/PredictedType.cpp @@ -153,8 +153,13 @@ const char* predictionToString(PredictedType value) else isTop = false; - if (isTop) - return "Top"; + if (isTop) { + ptr = description; + ptr.strcat("Top"); + } + + if (value & PredictEmpty) + ptr.strcat("Empty"); *ptr++ = 0; @@ -221,6 +226,8 @@ PredictedType predictionFromCell(JSCell* cell) PredictedType predictionFromValue(JSValue value) { + if (value.isEmpty()) + return PredictEmpty; if (value.isInt32()) return PredictInt32; if (value.isDouble()) { diff --git a/Source/JavaScriptCore/bytecode/PredictedType.h b/Source/JavaScriptCore/bytecode/PredictedType.h index efbe9b30d..0b7916610 100644 --- a/Source/JavaScriptCore/bytecode/PredictedType.h +++ b/Source/JavaScriptCore/bytecode/PredictedType.h @@ -61,8 +61,10 @@ static const PredictedType PredictDoubleNaN = 0x00040000; // It's defini static const PredictedType PredictDouble = 0x00060000; // It's either a non-NaN or a NaN double. static const PredictedType PredictNumber = 0x00070000; // It's either an Int32 or a Double. static const PredictedType PredictBoolean = 0x00080000; // It's definitely a Boolean. -static const PredictedType PredictOther = 0x40000000; // It's definitely none of the above. -static const PredictedType PredictTop = 0x7fffffff; // It can be any of the above. +static const PredictedType PredictOther = 0x08000000; // It's definitely none of the above. +static const PredictedType PredictTop = 0x0fffffff; // It can be any of the above. +static const PredictedType PredictEmpty = 0x10000000; // It's definitely an empty value marker. +static const PredictedType PredictEmptyOrTop = 0x1fffffff; // It can be any of the above. static const PredictedType FixedIndexedStorageMask = PredictByteArray | PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array; typedef bool (*PredictionChecker)(PredictedType); @@ -89,7 +91,7 @@ inline bool isFinalObjectOrOtherPrediction(PredictedType value) inline bool isFixedIndexedStorageObjectPrediction(PredictedType value) { - return (value & FixedIndexedStorageMask) == value; + return !!value && (value & FixedIndexedStorageMask) == value; } inline bool isStringPrediction(PredictedType value) @@ -199,7 +201,7 @@ inline bool isDoubleRealPrediction(PredictedType value) inline bool isDoublePrediction(PredictedType value) { - return (value & PredictDouble) == value; + return !!value && (value & PredictDouble) == value; } inline bool isNumberPrediction(PredictedType value) @@ -217,6 +219,11 @@ inline bool isOtherPrediction(PredictedType value) return value == PredictOther; } +inline bool isEmptyPrediction(PredictedType value) +{ + return value == PredictEmpty; +} + const char* predictionToString(PredictedType value); // Merge two predictions. Note that currently this just does left | right. It may diff --git a/Source/JavaScriptCore/bytecode/SamplingTool.cpp b/Source/JavaScriptCore/bytecode/SamplingTool.cpp index 077f041f4..f07dc79fb 100644 --- a/Source/JavaScriptCore/bytecode/SamplingTool.cpp +++ b/Source/JavaScriptCore/bytecode/SamplingTool.cpp @@ -100,7 +100,7 @@ SamplingRegion::Locker::Locker() #endif continue; } - if (WTF::weakCompareAndSwap(&s_currentOrReserved, previous, previous | 1)) + if (WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, previous | 1)) break; } } @@ -113,7 +113,7 @@ SamplingRegion::Locker::~Locker() uintptr_t previous; do { previous = s_currentOrReserved; - } while (!WTF::weakCompareAndSwap(&s_currentOrReserved, previous, previous & ~1)); + } while (!WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, previous & ~1)); } void SamplingRegion::sample() diff --git a/Source/JavaScriptCore/bytecode/SamplingTool.h b/Source/JavaScriptCore/bytecode/SamplingTool.h index 28fd528d0..fcb1986fd 100644 --- a/Source/JavaScriptCore/bytecode/SamplingTool.h +++ b/Source/JavaScriptCore/bytecode/SamplingTool.h @@ -148,7 +148,7 @@ namespace JSC { if (previousPtr) *previousPtr = bitwise_cast<SamplingRegion*>(previous); - if (WTF::weakCompareAndSwap(&s_currentOrReserved, previous, bitwise_cast<uintptr_t>(current))) + if (WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, bitwise_cast<uintptr_t>(current))) break; } } diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 6fa0ce96b..4a6f4653e 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -119,6 +119,15 @@ namespace JSC { expected by the callee. */ +void Label::setLocation(unsigned location) +{ + m_location = location; + + unsigned size = m_unresolvedJumps.size(); + for (unsigned i = 0; i < size; ++i) + m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first; +} + #ifndef NDEBUG void ResolveResult::checkValidity() { @@ -171,8 +180,8 @@ JSObject* BytecodeGenerator::generate() m_codeBlock->setThisRegister(m_thisRegister.index()); m_scopeNode->emitBytecode(*this); - - m_codeBlock->setInstructionCount(m_codeBlock->instructions().size()); + + m_codeBlock->instructions() = RefCountedArray<Instruction>(m_instructions); if (s_dumpsGeneratedCode) m_codeBlock->dump(m_scopeChain->globalObject->globalExec()); @@ -607,7 +616,7 @@ PassRefPtr<Label> BytecodeGenerator::newLabel() m_labels.removeLast(); // Allocate new label ID. - m_labels.append(m_codeBlock); + m_labels.append(this); return &m_labels.last(); } diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h index d61b42b76..e7fe236e5 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -32,7 +32,7 @@ #define BytecodeGenerator_h #include "CodeBlock.h" -#include "HashTraits.h" +#include <wtf/HashTraits.h> #include "Instruction.h" #include "Label.h" #include "LabelScope.h" @@ -48,6 +48,7 @@ namespace JSC { class Identifier; + class Label; class ScopeChainNode; class CallArguments { @@ -532,6 +533,8 @@ namespace JSC { ScopeChainNode* scopeChain() const { return m_scopeChain.get(); } private: + friend class Label; + void emitOpcode(OpcodeID); ValueProfile* emitProfiledOpcode(OpcodeID); void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index); @@ -611,7 +614,7 @@ namespace JSC { RegisterID* emitInitLazyRegister(RegisterID*); - Vector<Instruction>& instructions() { return m_codeBlock->instructions(); } + Vector<Instruction>& instructions() { return m_instructions; } SymbolTable& symbolTable() { return *m_symbolTable; } bool shouldOptimizeLocals() @@ -644,6 +647,8 @@ namespace JSC { void createArgumentsIfNecessary(); void createActivationIfNecessary(); RegisterID* createLazyRegisterIfNecessary(RegisterID*); + + Vector<Instruction> m_instructions; bool m_shouldEmitDebugHooks; bool m_shouldEmitProfileHooks; diff --git a/Source/JavaScriptCore/bytecompiler/Label.h b/Source/JavaScriptCore/bytecompiler/Label.h index 8cab1dbc0..21fa46309 100644 --- a/Source/JavaScriptCore/bytecompiler/Label.h +++ b/Source/JavaScriptCore/bytecompiler/Label.h @@ -39,21 +39,14 @@ namespace JSC { class Label { public: - explicit Label(CodeBlock* codeBlock) + explicit Label(BytecodeGenerator* generator) : m_refCount(0) , m_location(invalidLocation) - , m_codeBlock(codeBlock) + , m_generator(generator) { } - void setLocation(unsigned location) - { - m_location = location; - - unsigned size = m_unresolvedJumps.size(); - for (unsigned i = 0; i < size; ++i) - m_codeBlock->instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first; - } + void setLocation(unsigned); int bind(int opcode, int offset) const { @@ -81,7 +74,7 @@ namespace JSC { int m_refCount; unsigned m_location; - CodeBlock* m_codeBlock; + BytecodeGenerator* m_generator; mutable JumpVector m_unresolvedJumps; }; diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp index 2d4181912..bb95cafb6 100644 --- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -871,7 +871,15 @@ RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); } - +// ------------------------------ BitwiseNotNode ----------------------------------- + +RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1)); + RegisterID* src1 = generator.emitNode(m_expr); + return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32())); +} + // ------------------------------ LogicalNotNode ----------------------------------- void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) @@ -2009,8 +2017,8 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (m_data->m_statements) - m_data->m_statements->emitBytecode(generator, dst); + if (m_statements) + m_statements->emitBytecode(generator, dst); } // ------------------------------ ProgramNode ----------------------------- diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index ee0cc9ab7..7ab05f329 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -54,13 +54,7 @@ AbstractState::AbstractState(Graph& graph) , m_variables(m_codeBlock->numParameters(), graph.m_localVars) , m_block(0) { - size_t maxBlockSize = 0; - for (size_t i = 0; i < graph.m_blocks.size(); ++i) { - BasicBlock* block = graph.m_blocks[i].get(); - if (block->end - block->begin > maxBlockSize) - maxBlockSize = block->end - block->begin; - } - m_nodes.resize(maxBlockSize); + m_nodes.resize(graph.size()); } AbstractState::~AbstractState() { } @@ -75,8 +69,9 @@ void AbstractState::beginBasicBlock(BasicBlock* basicBlock) ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals()); ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals()); - for (size_t i = 0; i < basicBlock->end - basicBlock->begin; ++i) - m_nodes[i].clear(); + for (size_t i = 0; i < basicBlock->size(); i++) + m_nodes[basicBlock->at(i)].clear(); + m_variables = basicBlock->valuesAtHead; m_haveStructures = false; for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) { @@ -113,6 +108,11 @@ void AbstractState::initialize(Graph& graph) continue; } + if (graph.argumentIsCaptured(i)) { + root->valuesAtHead.argument(i).makeTop(); + continue; + } + PredictedType prediction = node.variableAccessData()->prediction(); if (isInt32Prediction(prediction)) root->valuesAtHead.argument(i).set(PredictInt32); @@ -143,6 +143,11 @@ void AbstractState::initialize(Graph& graph) else root->valuesAtHead.argument(i).makeTop(); } + for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) { + if (!graph.localIsCaptured(i)) + continue; + root->valuesAtHead.local(i).makeTop(); + } } bool AbstractState::endBasicBlock(MergeMode mergeMode) @@ -164,14 +169,28 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode) #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Merging state for argument %zu.\n", argument); #endif - changed |= mergeStateAtTail(block->valuesAtTail.argument(argument), m_variables.argument(argument), block->variablesAtTail.argument(argument)); + AbstractValue& destination = block->valuesAtTail.argument(argument); + if (m_graph.argumentIsCaptured(argument)) { + if (!destination.isTop()) { + destination.makeTop(); + changed = true; + } + } else + changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument)); } for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Merging state for local %zu.\n", local); #endif - changed |= mergeStateAtTail(block->valuesAtTail.local(local), m_variables.local(local), block->variablesAtTail.local(local)); + AbstractValue& destination = block->valuesAtTail.local(local); + if (m_graph.localIsCaptured(local)) { + if (!destination.isTop()) { + destination.makeTop(); + changed = true; + } + } else + changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local)); } } @@ -191,12 +210,13 @@ void AbstractState::reset() m_isValid = false; } -bool AbstractState::execute(NodeIndex nodeIndex) +bool AbstractState::execute(unsigned indexInBlock) { PROFILE(FLAG_FOR_EXECUTION); ASSERT(m_block); ASSERT(m_isValid); + NodeIndex nodeIndex = m_block->at(indexInBlock); Node& node = m_graph[nodeIndex]; if (!node.shouldGenerate()) @@ -216,11 +236,17 @@ bool AbstractState::execute(NodeIndex nodeIndex) } case GetLocal: { - forNode(nodeIndex) = m_variables.operand(node.local()); + if (m_graph.isCaptured(node.local())) + forNode(nodeIndex).makeTop(); + else + forNode(nodeIndex) = m_variables.operand(node.local()); break; } case SetLocal: { + if (m_graph.isCaptured(node.local())) + break; + if (node.variableAccessData()->shouldUseDoubleFormat()) { forNode(node.child1()).filter(PredictNumber); m_variables.operand(node.local()).set(PredictDouble); @@ -265,12 +291,12 @@ bool AbstractState::execute(NodeIndex nodeIndex) break; case ValueToInt32: - if (!m_graph[node.child1()].shouldNotSpeculateInteger()) { + if (m_graph[node.child1()].shouldNotSpeculateInteger()) { if (m_graph[node.child1()].shouldSpeculateDouble()) forNode(node.child1()).filter(PredictNumber); - else - forNode(node.child1()).filter(PredictInt32); - } + } else + forNode(node.child1()).filter(PredictInt32); + forNode(nodeIndex).set(PredictInt32); break; @@ -289,7 +315,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) break; } if (node.op == ValueAdd) { - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); forNode(nodeIndex).set(PredictString | PredictInt32 | PredictNumber); break; } @@ -311,6 +337,17 @@ bool AbstractState::execute(NodeIndex nodeIndex) break; } + case ArithNegate: { + if (m_graph.negateShouldSpeculateInteger(node)) { + forNode(node.child1()).filter(PredictInt32); + forNode(nodeIndex).set(PredictInt32); + break; + } + forNode(node.child1()).filter(PredictNumber); + forNode(nodeIndex).set(PredictDouble); + break; + } + case ArithMul: case ArithDiv: case ArithMin: @@ -368,7 +405,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) else if (child.shouldSpeculateNumber()) forNode(node.child1()).filter(PredictNumber); else - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); forNode(nodeIndex).set(PredictBoolean); break; } @@ -391,7 +428,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) filter = PredictArray; else { filter = PredictTop; - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); } forNode(node.child1()).filter(filter); forNode(node.child2()).filter(filter); @@ -421,7 +458,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) break; } if (!isActionableArrayPrediction(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) { - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); forNode(nodeIndex).makeTop(); break; } @@ -507,7 +544,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) } if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArrayPrediction(m_graph[node.child1()].prediction())) { ASSERT(node.op == PutByVal); - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); forNode(nodeIndex).makeTop(); break; } @@ -693,10 +730,25 @@ bool AbstractState::execute(NodeIndex nodeIndex) } case NewObject: - forNode(nodeIndex).set(m_codeBlock->globalObject()->emptyObjectStructure()); + forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure()); m_haveStructures = true; break; - + + case CreateActivation: + forNode(nodeIndex).set(m_graph.m_globalData.activationStructure.get()); + m_haveStructures = true; + break; + + case TearOffActivation: + // Does nothing that is user-visible. + break; + + case NewFunction: + case NewFunctionExpression: + case NewFunctionNoCheck: + forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure()); + break; + case GetCallee: forNode(nodeIndex).set(PredictFunction); break; @@ -710,7 +762,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) break; case PutScopedVar: - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); break; case GetById: @@ -721,7 +773,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) } if (isCellPrediction(m_graph[node.child1()].prediction())) forNode(node.child1()).filter(PredictCell); - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); forNode(nodeIndex).makeTop(); break; @@ -783,7 +835,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) break; case PutStructure: - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); forNode(node.child1()).set(node.structureTransitionData().newStructure); m_haveStructures = true; break; @@ -874,7 +926,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) case PutById: case PutByIdDirect: forNode(node.child1()).filter(PredictCell); - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); break; case GetGlobalVar: @@ -910,7 +962,7 @@ bool AbstractState::execute(NodeIndex nodeIndex) case ResolveBase: case ResolveBaseStrictPut: case ResolveGlobal: - clobberStructures(nodeIndex); + clobberStructures(indexInBlock); forNode(nodeIndex).makeTop(); break; @@ -927,13 +979,13 @@ bool AbstractState::execute(NodeIndex nodeIndex) return m_isValid; } -inline void AbstractState::clobberStructures(NodeIndex nodeIndex) +inline void AbstractState::clobberStructures(unsigned indexInBlock) { PROFILE(FLAG_FOR_STRUCTURE_CLOBBERING); if (!m_haveStructures) return; - for (size_t i = nodeIndex - m_block->begin + 1; i-- > 0;) - m_nodes[i].clobberStructures(); + for (size_t i = indexInBlock + 1; i--;) + forNode(m_block->at(i)).clobberStructures(); for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) m_variables.argument(i).clobberStructures(); for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) @@ -946,7 +998,7 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract if (nodeIndex == NoNode) return false; - AbstractValue* source; + AbstractValue source; Node& node = m_graph[nodeIndex]; if (!node.refCount()) @@ -961,7 +1013,7 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract case SetArgument: case Flush: // The block transfers the value from head to tail. - source = &inVariable; + source = inVariable; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Transfering from head to tail.\n"); #endif @@ -969,7 +1021,7 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract case GetLocal: // The block refines the value with additional speculations. - source = &forNode(nodeIndex); + source = forNode(nodeIndex); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Refining.\n"); #endif @@ -978,7 +1030,10 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract case SetLocal: // The block sets the variable, and potentially refines it, both // before and after setting it. - source = &forNode(node.child1()); + if (node.variableAccessData()->shouldUseDoubleFormat()) + source.set(PredictDouble); + else + source = forNode(node.child1()); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Setting.\n"); #endif @@ -986,11 +1041,10 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract default: ASSERT_NOT_REACHED(); - source = 0; break; } - if (destination == *source) { + if (destination == source) { // Abstract execution did not change the output value of the variable, for this // basic block, on this iteration. #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) @@ -1002,7 +1056,7 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract // Abstract execution reached a new conclusion about the speculations reached about // this variable after execution of this basic block. Update the state, and return // true to indicate that the fixpoint must go on! - destination = *source; + destination = source; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Changed!\n"); #endif @@ -1016,11 +1070,29 @@ inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to) bool changed = false; - for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) - changed |= mergeVariableBetweenBlocks(to->valuesAtHead.argument(argument), from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument)); + for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) { + AbstractValue& destination = to->valuesAtHead.argument(argument); + if (m_graph.argumentIsCaptured(argument)) { + if (destination.isTop()) + continue; + destination.makeTop(); + changed = true; + continue; + } + changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument)); + } - for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) - changed |= mergeVariableBetweenBlocks(to->valuesAtHead.local(local), from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local)); + for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) { + AbstractValue& destination = to->valuesAtHead.local(local); + if (m_graph.localIsCaptured(local)) { + if (destination.isTop()) + continue; + destination.makeTop(); + changed = true; + continue; + } + changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local)); + } if (!to->cfaHasVisited) changed = true; @@ -1034,7 +1106,7 @@ inline bool AbstractState::mergeToSuccessors(Graph& graph, BasicBlock* basicBloc { PROFILE(FLAG_FOR_MERGE_TO_SUCCESSORS); - Node& terminal = graph[basicBlock->end - 1]; + Node& terminal = graph[basicBlock->last()]; ASSERT(terminal.isTerminal()); @@ -1073,15 +1145,17 @@ inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination void AbstractState::dump(FILE* out) { bool first = true; - for (size_t i = 0; i < m_nodes.size(); ++i) { - if (m_nodes[i].isClear()) + for (size_t i = 0; i < m_block->size(); ++i) { + NodeIndex index = m_block->at(i); + AbstractValue& value = m_nodes[index]; + if (value.isClear()) continue; if (first) first = false; else fprintf(out, " "); - fprintf(out, "@%lu:", static_cast<unsigned long>(i + m_block->begin)); - m_nodes[i].dump(out); + fprintf(out, "@%lu:", static_cast<unsigned long>(index)); + value.dump(out); } } #endif diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h index 256e7495f..d9d5cc0f8 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h @@ -98,7 +98,7 @@ public: AbstractValue& forNode(NodeIndex nodeIndex) { - return m_nodes[nodeIndex - m_block->begin]; + return m_nodes[nodeIndex]; } AbstractValue& forNode(NodeUse nodeUse) @@ -152,7 +152,7 @@ public: // if execution should continue past this node. Notably, it will return true // for block terminals, so long as those terminals are not Return or variants // of Throw. - bool execute(NodeIndex); + bool execute(unsigned); // Is the execution state still valid? This will be false if execute() has // returned false previously. @@ -163,20 +163,20 @@ public: // that block must be abstractly interpreted again. This also sets // to->cfaShouldRevisit to true, if it returns true, or if to has not been // visited yet. - static bool merge(BasicBlock* from, BasicBlock* to); + bool merge(BasicBlock* from, BasicBlock* to); // Merge the abstract state stored at the block's tail into all of its // successors. Returns true if any of the successors' states changed. Note // that this is automatically called in endBasicBlock() if MergeMode is // MergeToSuccessors. - static bool mergeToSuccessors(Graph&, BasicBlock*); + bool mergeToSuccessors(Graph&, BasicBlock*); #ifndef NDEBUG void dump(FILE* out); #endif private: - void clobberStructures(NodeIndex); + void clobberStructures(unsigned); bool mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex); @@ -185,7 +185,7 @@ private: CodeBlock* m_codeBlock; Graph& m_graph; - Vector<AbstractValue, 32> m_nodes; + Vector<AbstractValue, 64> m_nodes; Operands<AbstractValue> m_variables; BasicBlock* m_block; bool m_haveStructures; diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h index aa5518187..682c7a90f 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h @@ -442,6 +442,11 @@ struct AbstractValue { if (mergePredictions(m_type, predictionFromValue(value)) != m_type) return false; + if (value.isEmpty()) { + ASSERT(m_type & PredictEmpty); + return true; + } + if (m_structure.isTop()) return true; diff --git a/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp b/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp index f55533a61..9a49364dd 100644 --- a/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp @@ -80,11 +80,8 @@ private: if (!node.shouldGenerate()) return; - NodeType op = node.op; - ArithNodeFlags flags = 0; - - if (node.hasArithNodeFlags()) - flags = node.rawArithNodeFlags(); + NodeType op = static_cast<NodeType>(node.op); + NodeFlags flags = node.flags; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" %s @%u: %s ", Graph::opName(op), m_compileIndex, arithNodeFlagsAsString(flags)); @@ -131,6 +128,11 @@ private: break; } + case ArithNegate: { + changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); + break; + } + case ArithMul: case ArithDiv: { // As soon as a multiply happens, we can easily end up in the part @@ -173,7 +175,7 @@ private: default: flags |= NodeUsedAsNumber | NodeNeedsNegZero; - if (op & NodeHasVarArgs) { + if (node.flags & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeArithNodeFlags(flags); } else { @@ -217,6 +219,9 @@ private: NodeIndex m_compileIndex; bool m_changed; +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + unsigned m_count; +#endif }; void performArithNodeFlagsInference(Graph& graph) diff --git a/Source/JavaScriptCore/dfg/DFGBasicBlock.h b/Source/JavaScriptCore/dfg/DFGBasicBlock.h index 9d464bdc2..1c890b498 100644 --- a/Source/JavaScriptCore/dfg/DFGBasicBlock.h +++ b/Source/JavaScriptCore/dfg/DFGBasicBlock.h @@ -38,11 +38,9 @@ namespace JSC { namespace DFG { typedef Vector <BlockIndex, 2> PredecessorList; -struct BasicBlock { - BasicBlock(unsigned bytecodeBegin, NodeIndex begin, unsigned numArguments, unsigned numLocals) +struct BasicBlock : Vector<NodeIndex, 8> { + BasicBlock(unsigned bytecodeBegin, unsigned numArguments, unsigned numLocals) : bytecodeBegin(bytecodeBegin) - , begin(begin) - , end(NoNode) , isOSRTarget(false) , cfaHasVisited(false) , cfaShouldRevisit(false) @@ -69,8 +67,6 @@ struct BasicBlock { // for other purposes due to inlining. unsigned bytecodeBegin; - NodeIndex begin; - NodeIndex end; bool isOSRTarget; bool cfaHasVisited; bool cfaShouldRevisit; @@ -79,6 +75,7 @@ struct BasicBlock { #endif bool isReachable; + Vector<NodeIndex> phis; PredecessorList m_predecessors; Operands<NodeIndex, NodeIndexTraits> variablesAtHead; diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeCache.h b/Source/JavaScriptCore/dfg/DFGByteCodeCache.h index fd3b5147f..f6a745c66 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeCache.h +++ b/Source/JavaScriptCore/dfg/DFGByteCodeCache.h @@ -138,7 +138,6 @@ public: delete iter->second.codeBlock; continue; } - iter->second.codeBlock->m_shouldDiscardBytecode = iter->second.oldValueOfShouldDiscardBytecode; } } @@ -155,7 +154,6 @@ public: value.codeBlock = key.executable()->codeBlockWithBytecodeFor(key.kind()); if (value.codeBlock) { value.owned = false; - value.oldValueOfShouldDiscardBytecode = value.codeBlock->m_shouldDiscardBytecode; } else { // Nope, so try to parse one. JSObject* exception; @@ -171,13 +169,6 @@ public: value.codeBlock = 0; } - // If we're about to return a code block, make sure that we're not going - // to be discarding its bytecode if a GC were to happen during DFG - // compilation. That's unlikely, but it's good to thoroughly enjoy this - // kind of paranoia. - if (!!value.codeBlock) - value.codeBlock->m_shouldDiscardBytecode = false; - m_map.add(key, value); return value.codeBlock; diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 0e575db4e..3a3678d12 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -66,6 +66,7 @@ public: , m_globalResolveNumber(0) , m_inlineStackTop(0) , m_haveBuiltOperandMaps(false) + , m_emptyJSValueIndex(UINT_MAX) { ASSERT(m_profiledBlock); @@ -185,16 +186,32 @@ private: // Two possibilities: either the block wants the local to be live // but has not loaded its value, or it has loaded its value, in // which case we're done. - Node& flushChild = m_graph[nodePtr->child1()]; + nodeIndex = nodePtr->child1().index(); + Node& flushChild = m_graph[nodeIndex]; if (flushChild.op == Phi) { VariableAccessData* variableAccessData = flushChild.variableAccessData(); - nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodePtr->child1().index())); + nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex)); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; return nodeIndex; } nodePtr = &flushChild; } + + ASSERT(&m_graph[nodeIndex] == nodePtr); ASSERT(nodePtr->op != Flush); + + if (m_graph.localIsCaptured(operand)) { + // We wish to use the same variable access data as the previous access, + // but for all other purposes we want to issue a load since for all we + // know, at this stage of compilation, the local has been clobbered. + + // Make sure we link to the Phi node, not to the GetLocal. + if (nodePtr->op == GetLocal) + nodeIndex = nodePtr->child1().index(); + + return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex)); + } + if (nodePtr->op == GetLocal) return nodeIndex; ASSERT(nodePtr->op == SetLocal); @@ -218,7 +235,11 @@ private: } void setLocal(unsigned operand, NodeIndex value) { - m_currentBlock->variablesAtTail.local(operand) = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value); + VariableAccessData* variableAccessData = newVariableAccessData(operand); + NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value); + m_currentBlock->variablesAtTail.local(operand) = nodeIndex; + if (m_graph.localIsCaptured(operand)) + addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); } // Used in implementing get/set, above, where the operand is an argument. @@ -226,7 +247,7 @@ private: { unsigned argument = operandToArgument(operand); ASSERT(argument < m_numArguments); - + NodeIndex nodeIndex = m_currentBlock->variablesAtTail.argument(argument); if (nodeIndex != NoNode) { @@ -235,16 +256,18 @@ private: // Two possibilities: either the block wants the local to be live // but has not loaded its value, or it has loaded its value, in // which case we're done. - Node& flushChild = m_graph[nodePtr->child1()]; + nodeIndex = nodePtr->child1().index(); + Node& flushChild = m_graph[nodeIndex]; if (flushChild.op == Phi) { VariableAccessData* variableAccessData = flushChild.variableAccessData(); - nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodePtr->child1().index())); + nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex)); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; return nodeIndex; } nodePtr = &flushChild; } + ASSERT(&m_graph[nodeIndex] == nodePtr); ASSERT(nodePtr->op != Flush); if (nodePtr->op == SetArgument) { @@ -256,6 +279,12 @@ private: return nodeIndex; } + if (m_graph.argumentIsCaptured(argument)) { + if (nodePtr->op == GetLocal) + nodeIndex = nodePtr->child1().index(); + return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex)); + } + if (nodePtr->op == GetLocal) return nodeIndex; @@ -278,11 +307,15 @@ private: { unsigned argument = operandToArgument(operand); ASSERT(argument < m_numArguments); - - m_currentBlock->variablesAtTail.argument(argument) = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value); + + VariableAccessData* variableAccessData = newVariableAccessData(operand); + NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value); + m_currentBlock->variablesAtTail.argument(argument) = nodeIndex; + if (m_graph.argumentIsCaptured(argument)) + addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); } - void flush(int operand) + void flushArgument(int operand) { // FIXME: This should check if the same operand had already been flushed to // some other local variable. @@ -308,7 +341,10 @@ private: nodeIndex = node.child1().index(); ASSERT(m_graph[nodeIndex].op != Flush); - + + // Emit a Flush regardless of whether we already flushed it. + // This gives us guidance to see that the variable also needs to be flushed + // for arguments, even if it already had to be flushed for other reasons. addToGraph(Flush, OpInfo(node.variableAccessData()), nodeIndex); return; } @@ -533,8 +569,10 @@ private: { NodeIndex resultIndex = (NodeIndex)m_graph.size(); m_graph.append(Node(op, currentCodeOrigin(), child1, child2, child3)); + ASSERT(op != Phi); + m_currentBlock->append(resultIndex); - if (op & NodeMustGenerate) + if (defaultFlags(op) & NodeMustGenerate) m_graph.ref(resultIndex); return resultIndex; } @@ -542,8 +580,12 @@ private: { NodeIndex resultIndex = (NodeIndex)m_graph.size(); m_graph.append(Node(op, currentCodeOrigin(), info, child1, child2, child3)); + if (op == Phi) + m_currentBlock->phis.append(resultIndex); + else + m_currentBlock->append(resultIndex); - if (op & NodeMustGenerate) + if (defaultFlags(op) & NodeMustGenerate) m_graph.ref(resultIndex); return resultIndex; } @@ -551,8 +593,10 @@ private: { NodeIndex resultIndex = (NodeIndex)m_graph.size(); m_graph.append(Node(op, currentCodeOrigin(), info1, info2, child1, child2, child3)); + ASSERT(op != Phi); + m_currentBlock->append(resultIndex); - if (op & NodeMustGenerate) + if (defaultFlags(op) & NodeMustGenerate) m_graph.ref(resultIndex); return resultIndex; } @@ -561,13 +605,25 @@ private: { NodeIndex resultIndex = (NodeIndex)m_graph.size(); m_graph.append(Node(Node::VarArg, op, currentCodeOrigin(), info1, info2, m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs)); + ASSERT(op != Phi); + m_currentBlock->append(resultIndex); m_numPassedVarArgs = 0; - if (op & NodeMustGenerate) + if (defaultFlags(op) & NodeMustGenerate) m_graph.ref(resultIndex); return resultIndex; } + + NodeIndex insertPhiNode(OpInfo info, BasicBlock* block) + { + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + m_graph.append(Node(Phi, currentCodeOrigin(), info)); + block->phis.append(resultIndex); + + return resultIndex; + } + void addVarArgChild(NodeIndex child) { m_graph.m_varArgChildren.append(NodeUse(child)); @@ -643,13 +699,14 @@ private: return nodeIndex; #if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("Making %s @%u safe at bc#%u because slow-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)); + dataLog("Making %s @%u safe at bc#%u because slow-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(static_cast<NodeType>(m_graph[nodeIndex].op)), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)); #endif switch (m_graph[nodeIndex].op) { case UInt32ToNumber: case ArithAdd: case ArithSub: + case ArithNegate: case ValueAdd: case ArithMod: // for ArithMode "MayOverflow" means we tried to divide by zero, or we saw double. m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow); @@ -695,7 +752,7 @@ private: return nodeIndex; #if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("Making %s @%u safe at bc#%u because special fast-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->specialFastCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)); + dataLog("Making %s @%u safe at bc#%u because special fast-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(static_cast<NodeType>(m_graph[nodeIndex].op)), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->specialFastCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)); #endif // FIXME: It might be possible to make this more granular. The DFG certainly can @@ -912,6 +969,9 @@ private: IdentifierMap m_identifierMap; // Mapping between values and constant numbers. JSValueMap m_jsValueMap; + // Index of the empty value, or UINT_MAX if there is no mapping. This is a horrible + // work-around for the fact that JSValueMap can't handle "empty" values. + unsigned m_emptyJSValueIndex; // Cache of code blocks that we've generated bytecode for. ByteCodeCache<canInlineFunctionFor> m_codeBlockCache; @@ -1066,7 +1126,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c // FIXME: Don't flush constants! for (int i = 1; i < argumentCountIncludingThis; ++i) - flush(registerOffset + argumentToOperand(i)); + flushArgument(registerOffset + argumentToOperand(i)); int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize; @@ -1129,7 +1189,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c // the caller to continue in whatever basic block we're in right now. if (!inlineStackEntry.m_didEarlyReturn && inlineStackEntry.m_didReturn) { BasicBlock* lastBlock = m_graph.m_blocks.last().get(); - ASSERT(lastBlock->begin == lastBlock->end || !m_graph.last().isTerminal()); + ASSERT(lastBlock->isEmpty() || !m_graph.last().isTerminal()); // If we created new blocks then the last block needs linking, but in the // caller. It doesn't need to be linked to, but it needs outgoing links. @@ -1161,7 +1221,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c continue; BasicBlock* block = m_graph.m_blocks[inlineStackEntry.m_unlinkedBlocks[i].m_blockIndex].get(); ASSERT(!block->isLinked); - Node& node = m_graph[block->end - 1]; + Node& node = m_graph[block->last()]; ASSERT(node.op == Jump); ASSERT(node.takenBlockIndex() == NoBlock); node.setTakenBlockIndex(m_graph.m_blocks.size()); @@ -1172,7 +1232,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c } // Need to create a new basic block for the continuation at the caller. - OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(nextOffset, m_graph.size(), m_numArguments, m_numLocals)); + OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(nextOffset, m_numArguments, m_numLocals)); #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("Creating inline epilogue basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame)); #endif @@ -1207,7 +1267,7 @@ bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType o } if (argumentCountIncludingThis == 3) { // Math.min(x, y) - set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), get(registerOffset + argumentToOperand(1)), get(registerOffset + argumentToOperand(2)))); + set(resultOperand, addToGraph(op, get(registerOffset + argumentToOperand(1)), get(registerOffset + argumentToOperand(2)))); return true; } @@ -1235,7 +1295,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins if (!MacroAssembler::supportsFloatingPointAbs()) return false; - NodeIndex nodeIndex = addToGraph(ArithAbs, OpInfo(NodeUseBottom), get(registerOffset + argumentToOperand(1))); + NodeIndex nodeIndex = addToGraph(ArithAbs, get(registerOffset + argumentToOperand(1))); if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow); set(resultOperand, nodeIndex); @@ -1364,7 +1424,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) // logic relies on every bytecode resulting in one or more nodes, which would // be true anyway except for op_loop_hint, which emits a Phantom to force this // to be true. - if (m_currentBlock->begin != m_graph.size()) + if (!m_currentBlock->isEmpty()) addToGraph(Jump, OpInfo(m_currentIndex)); else { #if DFG_ENABLE(DEBUG_VERBOSE) @@ -1502,11 +1562,11 @@ bool ByteCodeParser::parseBlock(unsigned limit) if (valueOfInt32Constant(op2) & 0x1f) result = addToGraph(BitURShift, op1, op2); else - result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), op1)); + result = makeSafe(addToGraph(UInt32ToNumber, op1)); } else { // Cannot optimize at this stage; shift & potentially rebox as a double. result = addToGraph(BitURShift, op1, op2); - result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), result)); + result = makeSafe(addToGraph(UInt32ToNumber, result)); } set(currentInstruction[1].u.operand, result); NEXT_OPCODE(op_urshift); @@ -1517,7 +1577,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_pre_inc: { unsigned srcDst = currentInstruction[1].u.operand; NodeIndex op = get(srcDst); - set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one()))); + set(srcDst, makeSafe(addToGraph(ArithAdd, op, one()))); NEXT_OPCODE(op_pre_inc); } @@ -1527,14 +1587,14 @@ bool ByteCodeParser::parseBlock(unsigned limit) ASSERT(result != srcDst); // Required for assumptions we make during OSR. NodeIndex op = get(srcDst); set(result, op); - set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one()))); + set(srcDst, makeSafe(addToGraph(ArithAdd, op, one()))); NEXT_OPCODE(op_post_inc); } case op_pre_dec: { unsigned srcDst = currentInstruction[1].u.operand; NodeIndex op = get(srcDst); - set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one()))); + set(srcDst, makeSafe(addToGraph(ArithSub, op, one()))); NEXT_OPCODE(op_pre_dec); } @@ -1543,7 +1603,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) unsigned srcDst = currentInstruction[2].u.operand; NodeIndex op = get(srcDst); set(result, op); - set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one()))); + set(srcDst, makeSafe(addToGraph(ArithSub, op, one()))); NEXT_OPCODE(op_post_dec); } @@ -1553,38 +1613,44 @@ bool ByteCodeParser::parseBlock(unsigned limit) NodeIndex op1 = get(currentInstruction[2].u.operand); NodeIndex op2 = get(currentInstruction[3].u.operand); if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult()) - set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op1, op2))); + set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, op1, op2))); else - set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, OpInfo(NodeUseBottom), op1, op2))); + set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, op1, op2))); NEXT_OPCODE(op_add); } case op_sub: { NodeIndex op1 = get(currentInstruction[2].u.operand); NodeIndex op2 = get(currentInstruction[3].u.operand); - set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2))); + set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, op1, op2))); NEXT_OPCODE(op_sub); } + case op_negate: { + NodeIndex op1 = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithNegate, op1))); + NEXT_OPCODE(op_negate); + } + case op_mul: { // Multiply requires that the inputs are not truncated, unfortunately. NodeIndex op1 = get(currentInstruction[2].u.operand); NodeIndex op2 = get(currentInstruction[3].u.operand); - set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, OpInfo(NodeUseBottom), op1, op2))); + set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, op1, op2))); NEXT_OPCODE(op_mul); } case op_mod: { NodeIndex op1 = get(currentInstruction[2].u.operand); NodeIndex op2 = get(currentInstruction[3].u.operand); - set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMod, OpInfo(NodeUseBottom), op1, op2))); + set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMod, op1, op2))); NEXT_OPCODE(op_mod); } case op_div: { NodeIndex op1 = get(currentInstruction[2].u.operand); NodeIndex op2 = get(currentInstruction[3].u.operand); - set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, OpInfo(NodeUseBottom), op1, op2))); + set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, op1, op2))); NEXT_OPCODE(op_div); } @@ -2187,6 +2253,42 @@ bool ByteCodeParser::parseBlock(unsigned limit) NEXT_OPCODE(op_loop_hint); } + + case op_init_lazy_reg: { + set(currentInstruction[1].u.operand, getJSConstantForValue(JSValue())); + NEXT_OPCODE(op_init_lazy_reg); + } + + case op_create_activation: { + set(currentInstruction[1].u.operand, addToGraph(CreateActivation, get(currentInstruction[1].u.operand))); + NEXT_OPCODE(op_create_activation); + } + + case op_tear_off_activation: { + // This currently ignores arguments because we don't support them yet. + addToGraph(TearOffActivation, get(currentInstruction[1].u.operand)); + NEXT_OPCODE(op_tear_off_activation); + } + + case op_new_func: { + if (!currentInstruction[3].u.operand) { + set(currentInstruction[1].u.operand, + addToGraph(NewFunctionNoCheck, OpInfo(currentInstruction[2].u.operand))); + } else { + set(currentInstruction[1].u.operand, + addToGraph( + NewFunction, + OpInfo(currentInstruction[2].u.operand), + get(currentInstruction[1].u.operand))); + } + NEXT_OPCODE(op_new_func); + } + + case op_new_func_exp: { + set(currentInstruction[1].u.operand, + addToGraph(NewFunctionExpression, OpInfo(currentInstruction[2].u.operand))); + NEXT_OPCODE(op_new_func_exp); + } default: // Parse failed! This should not happen because the capabilities checker @@ -2231,7 +2333,7 @@ void ByteCodeParser::processPhiStack() dataLog(" Did not find node, adding phi.\n"); #endif - valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? argumentToOperand(varNo) : static_cast<int>(varNo)))); + valueInPredecessor = insertPhiNode(OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? argumentToOperand(varNo) : static_cast<int>(varNo))), predecessorBlock); var = valueInPredecessor; if (stackType == ArgumentPhiStack) predecessorBlock->variablesAtHead.setArgumentFirstTime(varNo, valueInPredecessor); @@ -2255,7 +2357,11 @@ void ByteCodeParser::processPhiStack() dataLog(" Found @%u.\n", valueInPredecessor); #endif } - ASSERT(m_graph[valueInPredecessor].op == SetLocal || m_graph[valueInPredecessor].op == Phi || m_graph[valueInPredecessor].op == Flush || (m_graph[valueInPredecessor].op == SetArgument && stackType == ArgumentPhiStack)); + ASSERT(m_graph[valueInPredecessor].op == SetLocal + || m_graph[valueInPredecessor].op == Phi + || m_graph[valueInPredecessor].op == Flush + || (m_graph[valueInPredecessor].op == SetArgument + && stackType == ArgumentPhiStack)); VariableAccessData* dataForPredecessor = m_graph[valueInPredecessor].variableAccessData(); @@ -2309,7 +2415,7 @@ void ByteCodeParser::processPhiStack() continue; } - NodeIndex newPhi = addToGraph(Phi, OpInfo(dataForPhi)); + NodeIndex newPhi = insertPhiNode(OpInfo(dataForPhi), entry.m_block); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Splitting @%u, created @%u.\n", entry.m_phi, newPhi); @@ -2349,10 +2455,9 @@ void ByteCodeParser::fixVariableAccessPredictions() void ByteCodeParser::linkBlock(BasicBlock* block, Vector<BlockIndex>& possibleTargets) { - ASSERT(block->end != NoNode); ASSERT(!block->isLinked); - ASSERT(block->end > block->begin); - Node& node = m_graph[block->end - 1]; + ASSERT(!block->isEmpty()); + Node& node = m_graph[block->last()]; ASSERT(node.isTerminal()); switch (node.op) { @@ -2416,7 +2521,7 @@ void ByteCodeParser::determineReachability() BasicBlock* block = m_graph.m_blocks[index].get(); ASSERT(block->isLinked); - Node& node = m_graph[block->end - 1]; + Node& node = m_graph[block->last()]; ASSERT(node.isTerminal()); if (node.isJump()) @@ -2435,8 +2540,13 @@ void ByteCodeParser::buildOperandMapsIfNecessary() for (size_t i = 0; i < m_codeBlock->numberOfIdentifiers(); ++i) m_identifierMap.add(m_codeBlock->identifier(i).impl(), i); - for (size_t i = 0; i < m_codeBlock->numberOfConstantRegisters(); ++i) - m_jsValueMap.add(JSValue::encode(m_codeBlock->getConstant(i + FirstConstantRegisterIndex)), i + FirstConstantRegisterIndex); + for (size_t i = 0; i < m_codeBlock->numberOfConstantRegisters(); ++i) { + JSValue value = m_codeBlock->getConstant(i + FirstConstantRegisterIndex); + if (!value) + m_emptyJSValueIndex = i + FirstConstantRegisterIndex; + else + m_jsValueMap.add(JSValue::encode(value), i + FirstConstantRegisterIndex); + } m_haveBuiltOperandMaps = true; } @@ -2486,6 +2596,15 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(ByteCodeParser* byteCodeParse } for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) { JSValue value = codeBlock->getConstant(i + FirstConstantRegisterIndex); + if (!value) { + if (byteCodeParser->m_emptyJSValueIndex == UINT_MAX) { + byteCodeParser->m_emptyJSValueIndex = byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex; + byteCodeParser->m_codeBlock->addConstant(JSValue()); + byteCodeParser->m_constants.append(ConstantRecord()); + } + m_constantRemap[i] = byteCodeParser->m_emptyJSValueIndex; + continue; + } pair<JSValueMap::iterator, bool> result = byteCodeParser->m_jsValueMap.add(JSValue::encode(value), byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex); if (result.second) { byteCodeParser->m_codeBlock->addConstant(value); @@ -2527,6 +2646,16 @@ void ByteCodeParser::parseCodeBlock() { CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock; +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("Parsing code block %p. codeType = %s, numCapturedVars = %u, needsFullScopeChain = %s, needsActivation = %s, isStrictMode = %s\n", + codeBlock, + codeTypeToString(codeBlock->codeType()), + codeBlock->m_numCapturedVars, + codeBlock->needsFullScopeChain()?"true":"false", + codeBlock->ownerExecutable()->needsActivation()?"true":"false", + codeBlock->ownerExecutable()->isStrictMode()?"true":"false"); +#endif + for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= codeBlock->numberOfJumpTargets(); ++jumpTargetIndex) { // The maximum bytecode offset to go into the current basicblock is either the next jump target, or the end of the instructions. unsigned limit = jumpTargetIndex < codeBlock->numberOfJumpTargets() ? codeBlock->jumpTarget(jumpTargetIndex) : codeBlock->instructions().size(); @@ -2539,7 +2668,7 @@ void ByteCodeParser::parseCodeBlock() do { if (!m_currentBlock) { // Check if we can use the last block. - if (!m_graph.m_blocks.isEmpty() && m_graph.m_blocks.last()->begin == m_graph.m_blocks.last()->end) { + if (!m_graph.m_blocks.isEmpty() && m_graph.m_blocks.last()->isEmpty()) { // This must be a block belonging to us. ASSERT(m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex == m_graph.m_blocks.size() - 1); // Either the block is linkable or it isn't. If it's linkable then it's the last @@ -2557,7 +2686,7 @@ void ByteCodeParser::parseCodeBlock() #endif m_currentBlock->bytecodeBegin = m_currentIndex; } else { - OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_graph.size(), m_numArguments, m_numLocals)); + OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_numArguments, m_numLocals)); #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("Creating basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame)); #endif @@ -2580,10 +2709,8 @@ void ByteCodeParser::parseCodeBlock() // are at the end of an inline function, or we realized that we // should stop parsing because there was a return in the first // basic block. - ASSERT(m_currentBlock->begin == m_graph.size() || m_graph.last().isTerminal() || (m_currentIndex == codeBlock->instructions().size() && m_inlineStackTop->m_inlineCallFrame) || !shouldContinueParsing); + ASSERT(m_currentBlock->isEmpty() || m_graph.last().isTerminal() || (m_currentIndex == codeBlock->instructions().size() && m_inlineStackTop->m_inlineCallFrame) || !shouldContinueParsing); - m_currentBlock->end = m_graph.size(); - if (!shouldContinueParsing) return; @@ -2600,6 +2727,11 @@ bool ByteCodeParser::parse() // Set during construction. ASSERT(!m_currentIndex); +#if DFG_ENABLE(ALL_VARIABLES_CAPTURED) + // We should be pretending that the code has an activation. + ASSERT(m_graph.needsActivation()); +#endif + InlineStackEntry inlineStackEntry(this, m_codeBlock, m_profiledBlock, NoBlock, InvalidVirtualRegister, 0, InvalidVirtualRegister, InvalidVirtualRegister, CodeForCall); parseCodeBlock(); diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h index 3481f99e8..16793bb46 100644 --- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h +++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h @@ -420,6 +420,13 @@ public: move(arg2, GPRInfo::argumentGPR2); move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, ImmPtr arg2) + { + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2) { @@ -427,6 +434,13 @@ public: move(arg1, GPRInfo::argumentGPR1); move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); } + + ALWAYS_INLINE void setupArgumentsWithExecState(ImmPtr arg1, GPRReg arg2) + { + move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample! + move(arg1, GPRInfo::argumentGPR1); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2) { diff --git a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp index ac1e26c19..b4e75f808 100644 --- a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp @@ -82,15 +82,16 @@ private: dumpOperands(block->valuesAtHead, WTF::dataFile()); dataLog("\n"); #endif - for (NodeIndex nodeIndex = block->begin; nodeIndex < block->end; ++nodeIndex) { + for (unsigned i = 0; i < block->size(); ++i) { + NodeIndex nodeIndex = block->at(i); if (!m_graph[nodeIndex].shouldGenerate()) continue; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" %s @%u: ", Graph::opName(m_graph[nodeIndex].op), nodeIndex); + dataLog(" %s @%u: ", Graph::opName(static_cast<NodeType>(m_graph[nodeIndex].op)), nodeIndex); m_state.dump(WTF::dataFile()); dataLog("\n"); #endif - if (!m_state.execute(nodeIndex)) + if (!m_state.execute(i)) break; } #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) @@ -120,6 +121,9 @@ private: AbstractState m_state; bool m_changed; +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + unsigned m_count; +#endif }; void performCFA(Graph& graph) diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp index a3c27ebc1..82e1b4609 100644 --- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp @@ -43,9 +43,6 @@ public: for (unsigned i = 0; i < m_graph.size(); ++i) m_replacements[i] = NoNode; - - for (unsigned i = 0; i < LastNodeId; ++i) - m_lastSeen[i] = NoNode; } void run() @@ -71,68 +68,14 @@ private: return canonicalize(nodeUse.indexUnchecked()); } - // Computes where the search for a candidate for CSE should start. Don't call - // this directly; call startIndex() instead as it does logging in debug mode. - NodeIndex computeStartIndexForChildren(NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) + unsigned endIndexForPureCSE() { - const unsigned limit = 300; - - NodeIndex start = m_start; - if (m_compileIndex - start > limit) - start = m_compileIndex - limit; - - ASSERT(start >= m_start); - - NodeIndex child = canonicalize(child1); - if (child == NoNode) - return start; - - if (start < child) - start = child; - - child = canonicalize(child2); - if (child == NoNode) - return start; - - if (start < child) - start = child; - - child = canonicalize(child3); - if (child == NoNode) - return start; - - if (start < child) - start = child; - - return start; - } - - NodeIndex startIndexForChildren(NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) - { - NodeIndex result = computeStartIndexForChildren(child1, child2, child3); -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" lookback %u: ", result); -#endif - return result; - } - - NodeIndex startIndex() - { - Node& node = m_graph[m_compileIndex]; - return startIndexForChildren( - node.child1().indexUnchecked(), - node.child2().indexUnchecked(), - node.child3().indexUnchecked()); - } - - NodeIndex endIndexForPureCSE() - { - NodeIndex result = m_lastSeen[m_graph[m_compileIndex].op & NodeIdMask]; - if (result == NoNode) + unsigned result = m_lastSeen[m_graph[m_compileIndex].op]; + if (result == UINT_MAX) result = 0; else result++; - ASSERT(result <= m_compileIndex); + ASSERT(result <= m_indexInBlock); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" limit %u: ", result); #endif @@ -145,13 +88,16 @@ private: NodeIndex child2 = canonicalize(node.child2()); NodeIndex child3 = canonicalize(node.child3()); - NodeIndex start = startIndex(); - for (NodeIndex index = endIndexForPureCSE(); index-- > start;) { + for (unsigned i = endIndexForPureCSE(); i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1 || index == child2 || index == child3) + break; + Node& otherNode = m_graph[index]; if (node.op != otherNode.op) continue; - if (node.arithNodeFlagsForCompare() != otherNode.arithNodeFlagsForCompare()) + if (node.arithNodeFlags() != otherNode.arithNodeFlags()) continue; NodeIndex otherChild = canonicalize(otherNode.child1()); @@ -201,9 +147,9 @@ private: bool clobbersWorld(NodeIndex nodeIndex) { Node& node = m_graph[nodeIndex]; - if (node.op & NodeClobbersWorld) + if (node.flags & NodeClobbersWorld) return true; - if (!(node.op & NodeMightClobber)) + if (!(node.flags & NodeMightClobber)) return false; switch (node.op) { case ValueAdd: @@ -229,11 +175,14 @@ private: NodeIndex child2 = canonicalize(node.child2()); NodeIndex child3 = canonicalize(node.child3()); - NodeIndex start = startIndex(); - for (NodeIndex index = m_compileIndex; index-- > start;) { + for (unsigned i = m_indexInBlock; i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1 || index == child2 || index == child3) + break; + Node& otherNode = m_graph[index]; if (node.op == otherNode.op - && node.arithNodeFlagsForCompare() == otherNode.arithNodeFlagsForCompare()) { + && node.arithNodeFlags() == otherNode.arithNodeFlags()) { NodeIndex otherChild = canonicalize(otherNode.child1()); if (otherChild == NoNode) return index; @@ -258,8 +207,8 @@ private: NodeIndex globalVarLoadElimination(unsigned varNumber, JSGlobalObject* globalObject) { - NodeIndex start = startIndexForChildren(); - for (NodeIndex index = m_compileIndex; index-- > start;) { + for (unsigned i = m_indexInBlock; i--;) { + NodeIndex index = m_currentBlock->at(i); Node& node = m_graph[index]; switch (node.op) { case GetGlobalVar: @@ -281,8 +230,11 @@ private: NodeIndex getByValLoadElimination(NodeIndex child1, NodeIndex child2) { - NodeIndex start = startIndexForChildren(child1, child2); - for (NodeIndex index = m_compileIndex; index-- > start;) { + for (unsigned i = m_indexInBlock; i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1 || index == canonicalize(child2)) + break; + Node& node = m_graph[index]; switch (node.op) { case GetByVal: @@ -322,8 +274,11 @@ private: bool checkFunctionElimination(JSFunction* function, NodeIndex child1) { - NodeIndex start = startIndexForChildren(child1); - for (NodeIndex index = endIndexForPureCSE(); index-- > start;) { + for (unsigned i = endIndexForPureCSE(); i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1) + break; + Node& node = m_graph[index]; if (node.op == CheckFunction && node.child1() == child1 && node.function() == function) return true; @@ -333,8 +288,11 @@ private: bool checkStructureLoadElimination(const StructureSet& structureSet, NodeIndex child1) { - NodeIndex start = startIndexForChildren(child1); - for (NodeIndex index = m_compileIndex; index-- > start;) { + for (unsigned i = m_indexInBlock; i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1) + break; + Node& node = m_graph[index]; switch (node.op) { case CheckStructure: @@ -376,8 +334,11 @@ private: NodeIndex getByOffsetLoadElimination(unsigned identifierNumber, NodeIndex child1) { - NodeIndex start = startIndexForChildren(child1); - for (NodeIndex index = m_compileIndex; index-- > start;) { + for (unsigned i = m_indexInBlock; i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1) + break; + Node& node = m_graph[index]; switch (node.op) { case GetByOffset: @@ -419,8 +380,11 @@ private: NodeIndex getPropertyStorageLoadElimination(NodeIndex child1) { - NodeIndex start = startIndexForChildren(child1); - for (NodeIndex index = m_compileIndex; index-- > start;) { + for (unsigned i = m_indexInBlock; i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1) + break; + Node& node = m_graph[index]; switch (node.op) { case GetPropertyStorage: @@ -455,8 +419,11 @@ private: NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1, bool hasIntegerIndexPrediction) { - NodeIndex start = startIndexForChildren(child1); - for (NodeIndex index = m_compileIndex; index-- > start;) { + for (unsigned i = m_indexInBlock; i--;) { + NodeIndex index = m_currentBlock->at(i); + if (index == child1) + break; + Node& node = m_graph[index]; switch (node.op) { case GetIndexedPropertyStorage: { @@ -493,8 +460,8 @@ private: NodeIndex getScopeChainLoadElimination(unsigned depth) { - NodeIndex start = startIndexForChildren(); - for (NodeIndex index = endIndexForPureCSE(); index-- > start;) { + for (unsigned i = endIndexForPureCSE(); i--;) { + NodeIndex index = m_currentBlock->at(i); Node& node = m_graph[index]; if (node.op == GetScopeChain && node.scopeChainDepth() == depth) @@ -539,7 +506,7 @@ private: #endif Node& node = m_graph[m_compileIndex]; - node.op = Phantom; + node.setOpAndDefaultFlags(Phantom); node.setRefCount(1); // At this point we will eliminate all references to this node. @@ -555,14 +522,14 @@ private: Node& node = m_graph[m_compileIndex]; ASSERT(node.refCount() == 1); ASSERT(node.mustGenerate()); - node.op = Phantom; + node.setOpAndDefaultFlags(Phantom); } void performNodeCSE(Node& node) { bool shouldGenerate = node.shouldGenerate(); - if (node.op & NodeHasVarArgs) { + if (node.flags & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) performSubstitution(m_graph.m_varArgChildren[childIdx], shouldGenerate); } else { @@ -575,7 +542,7 @@ private: return; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" %s @%u: ", Graph::opName(m_graph[m_compileIndex].op), m_compileIndex); + dataLog(" %s @%u: ", Graph::opName(static_cast<NodeType>(m_graph[m_compileIndex].op)), m_compileIndex); #endif // NOTE: there are some nodes that we deliberately don't CSE even though we @@ -598,6 +565,7 @@ private: case BitURShift: case ArithAdd: case ArithSub: + case ArithNegate: case ArithMul: case ArithMod: case ArithDiv: @@ -701,7 +669,7 @@ private: break; } - m_lastSeen[node.op & NodeIdMask] = m_compileIndex; + m_lastSeen[node.op] = m_indexInBlock; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog("\n"); #endif @@ -709,16 +677,21 @@ private: void performBlockCSE(BasicBlock& block) { - m_start = block.begin; - NodeIndex end = block.end; - for (m_compileIndex = m_start; m_compileIndex < end; ++m_compileIndex) + m_currentBlock = █ + for (unsigned i = 0; i < LastNodeType; ++i) + m_lastSeen[i] = UINT_MAX; + + for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) { + m_compileIndex = block[m_indexInBlock]; performNodeCSE(m_graph[m_compileIndex]); + } } - NodeIndex m_start; + BasicBlock* m_currentBlock; NodeIndex m_compileIndex; + unsigned m_indexInBlock; Vector<NodeIndex, 16> m_replacements; - FixedArray<NodeIndex, LastNodeId> m_lastSeen; + FixedArray<unsigned, LastNodeType> m_lastSeen; }; void performCSE(Graph& graph) diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h index e339714e9..6509dbc3d 100644 --- a/Source/JavaScriptCore/dfg/DFGCapabilities.h +++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h @@ -57,11 +57,13 @@ inline bool mightCompileFunctionForConstruct(CodeBlock* codeBlock) inline bool mightInlineFunctionForCall(CodeBlock* codeBlock) { - return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount; + return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount + && !codeBlock->ownerExecutable()->needsActivation(); } inline bool mightInlineFunctionForConstruct(CodeBlock* codeBlock) { - return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount; + return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount + && !codeBlock->ownerExecutable()->needsActivation(); } // Opcode checking. @@ -84,6 +86,7 @@ inline bool canCompileOpcode(OpcodeID opcodeID) case op_post_dec: case op_add: case op_sub: + case op_negate: case op_mul: case op_mod: case op_div: @@ -151,21 +154,14 @@ inline bool canCompileOpcode(OpcodeID opcodeID) case op_throw_reference_error: case op_call: case op_construct: - return true; - - // Opcodes we support conditionally. Enabling these opcodes currently results in - // performance regressions. Each node that we disable under restrictions has a - // comment describing what we know about the regression so far. - - // Regresses string-validate-input, probably because it uses comparisons (< and >) - // on strings, which currently will cause speculation failures in some cases. case op_new_regexp: -#if DFG_ENABLE(RESTRICTIONS) - return false; -#else + case op_init_lazy_reg: + case op_create_activation: + case op_tear_off_activation: + case op_new_func: + case op_new_func_exp: return true; -#endif - + default: return false; } @@ -191,6 +187,14 @@ inline bool canInlineOpcode(OpcodeID opcodeID) case op_new_regexp: return false; + // We don't support inlining code that creates activations or has nested functions. + case op_init_lazy_reg: + case op_create_activation: + case op_tear_off_activation: + case op_new_func: + case op_new_func_exp: + return false; + default: return canCompileOpcode(opcodeID); } diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h index 330504c3e..8ff1e5cdd 100644 --- a/Source/JavaScriptCore/dfg/DFGCommon.h +++ b/Source/JavaScriptCore/dfg/DFGCommon.h @@ -53,7 +53,7 @@ #define DFG_ENABLE_CONSISTENCY_CHECK 0 // Emit a breakpoint into the head of every generated function, to aid debugging in GDB. #define DFG_ENABLE_JIT_BREAK_ON_EVERY_FUNCTION 0 -// Emit a breakpoint into the head of every generated node, to aid debugging in GDB. +// Emit a breakpoint into the head of every generated block, to aid debugging in GDB. #define DFG_ENABLE_JIT_BREAK_ON_EVERY_BLOCK 0 // Emit a breakpoint into the head of every generated node, to aid debugging in GDB. #define DFG_ENABLE_JIT_BREAK_ON_EVERY_NODE 0 @@ -69,10 +69,11 @@ #define DFG_ENABLE_OSR_ENTRY ENABLE(DFG_JIT) // Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path. #define DFG_ENABLE_SUCCESS_STATS 0 -// Used to enable conditionally supported opcodes that currently result in performance regressions. -#define DFG_ENABLE_RESTRICTIONS 1 // Enable verification that the DFG is able to insert code for control flow edges. #define DFG_ENABLE_EDGE_CODE_VERIFICATION 0 +// Pretend that all variables in the top-level code block got captured. Great +// for testing code gen for activations. +#define DFG_ENABLE_ALL_VARIABLES_CAPTURED 0 namespace JSC { namespace DFG { diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp index 124d7e637..a0af3e6ad 100644 --- a/Source/JavaScriptCore/dfg/DFGDriver.cpp +++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp @@ -34,6 +34,7 @@ #include "DFGCSEPhase.h" #include "DFGJITCompiler.h" #include "DFGPredictionPropagationPhase.h" +#include "DFGRedundantPhiEliminationPhase.h" #include "DFGVirtualRegisterAllocationPhase.h" namespace JSC { namespace DFG { @@ -58,6 +59,7 @@ inline bool compile(CompileMode compileMode, JSGlobalData& globalData, CodeBlock if (compileMode == CompileFunction) dfg.predictArgumentTypes(); + performRedundantPhiElimination(dfg); performArithNodeFlagsInference(dfg); performPredictionPropagation(dfg); performCSE(dfg); @@ -70,18 +72,19 @@ inline bool compile(CompileMode compileMode, JSGlobalData& globalData, CodeBlock #endif JITCompiler dataFlowJIT(dfg); + bool result; if (compileMode == CompileFunction) { ASSERT(jitCodeWithArityCheck); - dataFlowJIT.compileFunction(jitCode, *jitCodeWithArityCheck); + result = dataFlowJIT.compileFunction(jitCode, *jitCodeWithArityCheck); } else { ASSERT(compileMode == CompileOther); ASSERT(!jitCodeWithArityCheck); - dataFlowJIT.compile(jitCode); + result = dataFlowJIT.compile(jitCode); } - return true; + return result; } bool tryCompile(JSGlobalData& globalData, CodeBlock* codeBlock, JITCode& jitCode) diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp index b8eec93c7..900251e10 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.cpp +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -41,7 +41,7 @@ static const char* dfgOpNames[] = { const char *Graph::opName(NodeType op) { - return dfgOpNames[op & NodeIdMask]; + return dfgOpNames[op]; } const char* Graph::nameOfVariableAccessData(VariableAccessData* variableAccessData) @@ -120,7 +120,7 @@ void Graph::dumpCodeOrigin(NodeIndex nodeIndex) void Graph::dump(NodeIndex nodeIndex) { Node& node = at(nodeIndex); - NodeType op = node.op; + NodeType op = static_cast<NodeType>(node.op); unsigned refCount = node.refCount(); bool skipped = !refCount; @@ -157,7 +157,7 @@ void Graph::dump(NodeIndex nodeIndex) dataLog("-"); dataLog(">\t%s(", opName(op)); bool hasPrinted = false; - if (op & NodeHasVarArgs) { + if (node.flags & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) { if (hasPrinted) dataLog(", "); @@ -175,8 +175,8 @@ void Graph::dump(NodeIndex nodeIndex) hasPrinted = !!node.child1(); } - if (node.hasArithNodeFlags()) { - dataLog("%s%s", hasPrinted ? ", " : "", arithNodeFlagsAsString(node.rawArithNodeFlags())); + if (node.arithNodeFlags()) { + dataLog("%s%s", hasPrinted ? ", " : "", arithNodeFlagsAsString(node.arithNodeFlags())); hasPrinted = true; } if (node.hasVarNumber()) { @@ -265,6 +265,12 @@ void Graph::dump() for (size_t b = 0; b < m_blocks.size(); ++b) { BasicBlock* block = m_blocks[b].get(); dataLog("Block #%u (bc#%u): %s%s\n", (int)b, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : ""); + dataLog(" Phi Nodes:\n"); + for (size_t i = 0; i < block->phis.size(); ++i) { + // Dumping the dead Phi nodes is just annoying! + if (at(block->phis[i]).refCount()) + dump(block->phis[i]); + } dataLog(" vars before: "); if (block->cfaHasVisited) dumpOperands(block->valuesAtHead, WTF::dataFile()); @@ -274,8 +280,8 @@ void Graph::dump() dataLog(" var links: "); dumpOperands(block->variablesAtHead, WTF::dataFile()); dataLog("\n"); - for (size_t i = block->begin; i < block->end; ++i) - dump(i); + for (size_t i = 0; i < block->size(); ++i) + dump(block->at(i)); dataLog(" vars after: "); if (block->cfaHasVisited) dumpOperands(block->valuesAtTail, WTF::dataFile()); @@ -283,15 +289,12 @@ void Graph::dump() dataLog("<empty>"); dataLog("\n"); } - dataLog("Phi Nodes:\n"); - for (size_t i = m_blocks.last()->end; i < size(); ++i) - dump(i); } // FIXME: Convert this to be iterative, not recursive. #define DO_TO_CHILDREN(node, thingToDo) do { \ Node& _node = (node); \ - if (_node.op & NodeHasVarArgs) { \ + if (_node.flags & NodeHasVarArgs) { \ for (unsigned _childIdx = _node.firstChild(); \ _childIdx < _node.firstChild() + _node.numChildren(); \ _childIdx++) \ diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index 88d6a4eec..bacbac827 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -177,6 +177,12 @@ public: return Node::shouldSpeculateInteger(left, right) && add.canSpeculateInteger(); } + bool negateShouldSpeculateInteger(Node& negate) + { + ASSERT(negate.op == ArithNegate); + return at(negate.child1()).shouldSpeculateInteger() && negate.canSpeculateInteger(); + } + bool addShouldSpeculateInteger(NodeIndex nodeIndex) { return addShouldSpeculateInteger(at(nodeIndex)); @@ -305,6 +311,41 @@ public: return MethodOfGettingAValueProfile(valueProfileFor(nodeIndex)); } + bool needsActivation() const + { +#if DFG_ENABLE(ALL_VARIABLES_CAPTURED) + return true; +#else + return m_codeBlock->needsFullScopeChain() && m_codeBlock->codeType() != GlobalCode; +#endif + } + + // Pass an argument index. Currently it's ignored, but that's somewhat + // of a bug. + bool argumentIsCaptured(int) const + { + return needsActivation(); + } + bool localIsCaptured(int operand) const + { +#if DFG_ENABLE(ALL_VARIABLES_CAPTURED) + return operand < m_codeBlock->m_numVars; +#else + return operand < m_codeBlock->m_numCapturedVars; +#endif + } + + bool isCaptured(int operand) const + { + if (operandIsArgument(operand)) + return argumentIsCaptured(operandToArgument(operand)); + return localIsCaptured(operand); + } + bool isCaptured(VirtualRegister virtualRegister) const + { + return isCaptured(static_cast<int>(virtualRegister)); + } + JSGlobalData& m_globalData; CodeBlock* m_codeBlock; CodeBlock* m_profiledBlock; diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp index 7b2bbc788..af98f8d7a 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp @@ -44,7 +44,7 @@ void JITCompiler::linkOSRExits() for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) { OSRExit& exit = codeBlock()->osrExit(i); exit.m_check.initialJump().link(this); - store32(Imm32(i), &globalData()->osrExitIndex); + store32(TrustedImm32(i), &globalData()->osrExitIndex); beginUninterruptedSequence(); exit.m_check.switchToLateJump(jump()); endUninterruptedSequence(); @@ -75,7 +75,7 @@ void JITCompiler::compileBody(SpeculativeJIT& speculative) breakpoint(); #endif - addPtr(Imm32(1), AbsoluteAddress(codeBlock()->addressOfSpeculativeSuccessCounter())); + addPtr(TrustedImm32(1), AbsoluteAddress(codeBlock()->addressOfSpeculativeSuccessCounter())); bool compiledSpeculative = speculative.compile(); ASSERT_UNUSED(compiledSpeculative, compiledSpeculative); @@ -195,7 +195,7 @@ void JITCompiler::link(LinkBuffer& linkBuffer) codeBlock()->shrinkWeakReferenceTransitionsToFit(); } -void JITCompiler::compile(JITCode& entry) +bool JITCompiler::compile(JITCode& entry) { compileEntry(); SpeculativeJIT speculative(*this); @@ -204,14 +204,17 @@ void JITCompiler::compile(JITCode& entry) // Create OSR entry trampolines if necessary. speculative.createOSREntries(); - LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock); + LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock, JITCompilationCanFail); + if (linkBuffer.didFailToAllocate()) + return false; link(linkBuffer); speculative.linkOSREntries(linkBuffer); entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT); + return true; } -void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck) +bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck) { compileEntry(); @@ -222,7 +225,7 @@ void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi Label fromArityCheck(this); // Plant a check that sufficient space is available in the RegisterFile. // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291 - addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1); + addPtr(TrustedImm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1); Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), GPRInfo::regT1); // Return here after register file check. Label fromRegisterFileCheck = label(); @@ -258,7 +261,7 @@ void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi compileEntry(); load32(AssemblyHelpers::payloadFor((VirtualRegister)RegisterFile::ArgumentCount), GPRInfo::regT1); - branch32(AboveOrEqual, GPRInfo::regT1, Imm32(m_codeBlock->numParameters())).linkTo(fromArityCheck, this); + branch32(AboveOrEqual, GPRInfo::regT1, TrustedImm32(m_codeBlock->numParameters())).linkTo(fromArityCheck, this); move(stackPointerRegister, GPRInfo::argumentGPR0); poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); token = beginCall(); @@ -272,7 +275,9 @@ void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi // === Link === - LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock); + LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock, JITCompilationCanFail); + if (linkBuffer.didFailToAllocate()) + return false; link(linkBuffer); speculative.linkOSREntries(linkBuffer); @@ -282,6 +287,7 @@ void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi entryWithArityCheck = linkBuffer.locationOf(arityCheck); entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT); + return true; } } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h index a0c68fe4b..2df2703b0 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h @@ -194,8 +194,8 @@ public: { } - void compile(JITCode& entry); - void compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck); + bool compile(JITCode& entry); + bool compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck); // Accessors for properties. Graph& graph() { return m_graph; } @@ -297,12 +297,13 @@ public: // value of (None, []). But the old JIT may stash some values there. So we really // need (Top, TOP). for (size_t argument = 0; argument < basicBlock.variablesAtHead.numberOfArguments(); ++argument) { - if (basicBlock.variablesAtHead.argument(argument) == NoNode) + NodeIndex nodeIndex = basicBlock.variablesAtHead.argument(argument); + if (nodeIndex == NoNode || !m_graph[nodeIndex].shouldGenerate()) entry->m_expectedValues.argument(argument).makeTop(); } for (size_t local = 0; local < basicBlock.variablesAtHead.numberOfLocals(); ++local) { NodeIndex nodeIndex = basicBlock.variablesAtHead.local(local); - if (nodeIndex == NoNode) + if (nodeIndex == NoNode || !m_graph[nodeIndex].shouldGenerate()) entry->m_expectedValues.local(local).makeTop(); else if (m_graph[nodeIndex].variableAccessData()->shouldUseDoubleFormat()) entry->m_localsForcedDouble.set(local); diff --git a/Source/JavaScriptCore/dfg/DFGNode.cpp b/Source/JavaScriptCore/dfg/DFGNode.cpp new file mode 100644 index 000000000..c53817ba9 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNode.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGNode.h" + +#if ENABLE(DFG_JIT) + +namespace JSC { namespace DFG { + +const char* arithNodeFlagsAsString(NodeFlags flags) +{ + flags &= NodeArithMask; + + if (!flags) + return "<empty>"; + + static const int size = 64; + static char description[size]; + BoundsCheckedPointer<char> ptr(description, size); + + bool hasPrinted = false; + + if (flags & NodeUsedAsNumber) { + ptr.strcat("UsedAsNum"); + hasPrinted = true; + } + + if (flags & NodeNeedsNegZero) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("NeedsNegZero"); + hasPrinted = true; + } + + if (flags & NodeMayOverflow) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("MayOverflow"); + hasPrinted = true; + } + + if (flags & NodeMayNegZero) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("MayNegZero"); + hasPrinted = true; + } + + *ptr++ = 0; + + return description; +} + + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index 87dae7786..b672b67c5 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,36 +57,50 @@ struct StructureTransitionData { } }; -typedef unsigned ArithNodeFlags; -#define NodeUseBottom 0x00 -#define NodeUsedAsNumber 0x01 -#define NodeNeedsNegZero 0x02 -#define NodeUsedAsMask 0x03 -#define NodeMayOverflow 0x04 -#define NodeMayNegZero 0x08 -#define NodeBehaviorMask 0x0c +// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none) +// and some additional informative flags (must generate, is constant, etc). +#define NodeResultMask 0xF +#define NodeResultJS 0x1 +#define NodeResultNumber 0x2 +#define NodeResultInt32 0x3 +#define NodeResultBoolean 0x4 +#define NodeResultStorage 0x5 +#define NodeMustGenerate 0x10 // set on nodes that have side effects, and may not trivially be removed by DCE. +#define NodeHasVarArgs 0x20 +#define NodeClobbersWorld 0x40 +#define NodeMightClobber 0x80 +#define NodeArithMask 0xF00 +#define NodeUseBottom 0x000 +#define NodeUsedAsNumber 0x100 +#define NodeNeedsNegZero 0x200 +#define NodeUsedAsMask 0x300 +#define NodeMayOverflow 0x400 +#define NodeMayNegZero 0x800 +#define NodeBehaviorMask 0xc00 -static inline bool nodeUsedAsNumber(ArithNodeFlags flags) +typedef uint16_t NodeFlags; + +static inline bool nodeUsedAsNumber(NodeFlags flags) { return !!(flags & NodeUsedAsNumber); } -static inline bool nodeCanTruncateInteger(ArithNodeFlags flags) +static inline bool nodeCanTruncateInteger(NodeFlags flags) { return !nodeUsedAsNumber(flags); } -static inline bool nodeCanIgnoreNegativeZero(ArithNodeFlags flags) +static inline bool nodeCanIgnoreNegativeZero(NodeFlags flags) { return !(flags & NodeNeedsNegZero); } -static inline bool nodeMayOverflow(ArithNodeFlags flags) +static inline bool nodeMayOverflow(NodeFlags flags) { return !!(flags & NodeMayOverflow); } -static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags) +static inline bool nodeCanSpeculateInteger(NodeFlags flags) { if (flags & NodeMayOverflow) return !nodeUsedAsNumber(flags); @@ -97,67 +111,7 @@ static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags) return true; } -static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) -{ - if (!flags) - return "<empty>"; - - static const int size = 64; - static char description[size]; - BoundsCheckedPointer<char> ptr(description, size); - - bool hasPrinted = false; - - if (flags & NodeUsedAsNumber) { - ptr.strcat("UsedAsNum"); - hasPrinted = true; - } - - if (flags & NodeNeedsNegZero) { - if (hasPrinted) - ptr.strcat("|"); - ptr.strcat("NeedsNegZero"); - hasPrinted = true; - } - - if (flags & NodeMayOverflow) { - if (hasPrinted) - ptr.strcat("|"); - ptr.strcat("MayOverflow"); - hasPrinted = true; - } - - if (flags & NodeMayNegZero) { - if (hasPrinted) - ptr.strcat("|"); - ptr.strcat("MayNegZero"); - hasPrinted = true; - } - - *ptr++ = 0; - - return description; -} - -// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none) -// and some additional informative flags (must generate, is constant, etc). -#define NodeIdMask 0xFFF -#define NodeResultMask 0xF000 -#define NodeMustGenerate 0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE. -#define NodeIsConstant 0x20000 -#define NodeIsJump 0x40000 -#define NodeIsBranch 0x80000 -#define NodeIsTerminal 0x100000 -#define NodeHasVarArgs 0x200000 -#define NodeClobbersWorld 0x400000 -#define NodeMightClobber 0x800000 - -// These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result. -#define NodeResultJS 0x1000 -#define NodeResultNumber 0x2000 -#define NodeResultInt32 0x3000 -#define NodeResultBoolean 0x4000 -#define NodeResultStorage 0x5000 +const char* arithNodeFlagsAsString(NodeFlags); // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below. #define FOR_EACH_DFG_OP(macro) \ @@ -204,6 +158,7 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) /* Nodes for arithmetic operations. */\ macro(ArithAdd, NodeResultNumber) \ macro(ArithSub, NodeResultNumber) \ + macro(ArithNegate, NodeResultNumber) \ macro(ArithMul, NodeResultNumber) \ macro(ArithDiv, NodeResultNumber) \ macro(ArithMod, NodeResultNumber) \ @@ -291,12 +246,23 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \ \ + /* Nodes used for activations. Activation support works by having it anchored at */\ + /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\ + /* being threaded with each other. */\ + macro(CreateActivation, NodeResultJS) \ + macro(TearOffActivation, NodeMustGenerate) \ + \ + /* Nodes for creating functions. */\ + macro(NewFunctionNoCheck, NodeResultJS) \ + macro(NewFunction, NodeResultJS) \ + macro(NewFunctionExpression, NodeResultJS) \ + \ /* Block terminals. */\ - macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \ - macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \ - macro(Return, NodeMustGenerate | NodeIsTerminal) \ - macro(Throw, NodeMustGenerate | NodeIsTerminal) \ - macro(ThrowReferenceError, NodeMustGenerate | NodeIsTerminal) \ + macro(Jump, NodeMustGenerate) \ + macro(Branch, NodeMustGenerate) \ + macro(Return, NodeMustGenerate) \ + macro(Throw, NodeMustGenerate) \ + macro(ThrowReferenceError, NodeMustGenerate) \ \ /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\ /* this point, but execution does continue in the basic block - just in a */\ @@ -305,20 +271,25 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) // This enum generates a monotonically increasing id for all Node types, // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask). -enum NodeId { -#define DFG_OP_ENUM(opcode, flags) opcode##_id, +enum NodeType { +#define DFG_OP_ENUM(opcode, flags) opcode, FOR_EACH_DFG_OP(DFG_OP_ENUM) #undef DFG_OP_ENUM - LastNodeId + LastNodeType }; -// Entries in this enum describe all Node types. -// The enum value contains a monotonically increasing id, a result type, and additional flags. -enum NodeType { -#define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags), +// Specifies the default flags for each node. +inline NodeFlags defaultFlags(NodeType op) +{ + switch (op) { +#define DFG_OP_ENUM(opcode, flags) case opcode: return flags; FOR_EACH_DFG_OP(DFG_OP_ENUM) #undef DFG_OP_ENUM -}; + default: + ASSERT_NOT_REACHED(); + return 0; + } +} // This type used in passing an immediate argument to Node constructor; // distinguishes an immediate value (typically an index into a CodeBlock data structure - @@ -341,34 +312,32 @@ struct Node { // Construct a node with up to 3 children, no immediate value. Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) - : op(op) - , codeOrigin(codeOrigin) + : codeOrigin(codeOrigin) , children(NodeReferenceBlob::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_prediction(PredictNone) { - ASSERT(!(op & NodeHasVarArgs)); - ASSERT(!hasArithNodeFlags()); + setOpAndDefaultFlags(op); + ASSERT(!(flags & NodeHasVarArgs)); } // Construct a node with up to 3 children and an immediate value. Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) - : op(op) - , codeOrigin(codeOrigin) + : codeOrigin(codeOrigin) , children(NodeReferenceBlob::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_opInfo(imm.m_value) , m_prediction(PredictNone) { - ASSERT(!(op & NodeHasVarArgs)); + setOpAndDefaultFlags(op); + ASSERT(!(flags & NodeHasVarArgs)); } // Construct a node with up to 3 children and two immediate values. Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) - : op(op) - , codeOrigin(codeOrigin) + : codeOrigin(codeOrigin) , children(NodeReferenceBlob::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) @@ -376,13 +345,13 @@ struct Node { , m_opInfo2(safeCast<unsigned>(imm2.m_value)) , m_prediction(PredictNone) { - ASSERT(!(op & NodeHasVarArgs)); + setOpAndDefaultFlags(op); + ASSERT(!(flags & NodeHasVarArgs)); } // Construct a node with a variable number of children and two immediate values. Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren) - : op(op) - , codeOrigin(codeOrigin) + : codeOrigin(codeOrigin) , children(NodeReferenceBlob::Variable, firstChild, numChildren) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) @@ -390,12 +359,19 @@ struct Node { , m_opInfo2(safeCast<unsigned>(imm2.m_value)) , m_prediction(PredictNone) { - ASSERT(op & NodeHasVarArgs); + setOpAndDefaultFlags(op); + ASSERT(flags & NodeHasVarArgs); + } + + void setOpAndDefaultFlags(NodeType op) + { + this->op = op; + flags = defaultFlags(op); } bool mustGenerate() { - return op & NodeMustGenerate; + return flags & NodeMustGenerate; } bool isConstant() @@ -520,6 +496,7 @@ struct Node { case UInt32ToNumber: case ArithAdd: case ArithSub: + case ArithNegate: case ArithMul: case ArithAbs: case ArithMin: @@ -533,44 +510,32 @@ struct Node { } } - ArithNodeFlags rawArithNodeFlags() - { - ASSERT(hasArithNodeFlags()); - return m_opInfo; - } - // This corrects the arithmetic node flags, so that irrelevant bits are // ignored. In particular, anything other than ArithMul does not need // to know if it can speculate on negative zero. - ArithNodeFlags arithNodeFlags() + NodeFlags arithNodeFlags() { - ArithNodeFlags result = rawArithNodeFlags(); + NodeFlags result = flags & NodeArithMask; if (op == ArithMul) return result; return result & ~NodeNeedsNegZero; } - ArithNodeFlags arithNodeFlagsForCompare() - { - if (hasArithNodeFlags()) - return arithNodeFlags(); - return 0; - } - - void setArithNodeFlag(ArithNodeFlags flags) + void setArithNodeFlag(NodeFlags newFlags) { - ASSERT(hasArithNodeFlags()); - m_opInfo = flags; + ASSERT(!(newFlags & ~NodeArithMask)); + + flags &= ~NodeArithMask; + flags |= newFlags; } - bool mergeArithNodeFlags(ArithNodeFlags flags) + bool mergeArithNodeFlags(NodeFlags newFlags) { - if (!hasArithNodeFlags()) + ASSERT(!(newFlags & ~NodeArithMask)); + newFlags = flags | newFlags; + if (newFlags == flags) return false; - ArithNodeFlags newFlags = m_opInfo | flags; - if (newFlags == m_opInfo) - return false; - m_opInfo = newFlags; + flags = newFlags; return true; } @@ -626,42 +591,51 @@ struct Node { bool hasResult() { - return op & NodeResultMask; + return flags & NodeResultMask; } bool hasInt32Result() { - return (op & NodeResultMask) == NodeResultInt32; + return (flags & NodeResultMask) == NodeResultInt32; } bool hasNumberResult() { - return (op & NodeResultMask) == NodeResultNumber; + return (flags & NodeResultMask) == NodeResultNumber; } bool hasJSResult() { - return (op & NodeResultMask) == NodeResultJS; + return (flags & NodeResultMask) == NodeResultJS; } bool hasBooleanResult() { - return (op & NodeResultMask) == NodeResultBoolean; + return (flags & NodeResultMask) == NodeResultBoolean; } bool isJump() { - return op & NodeIsJump; + return op == Jump; } bool isBranch() { - return op & NodeIsBranch; + return op == Branch; } bool isTerminal() { - return op & NodeIsTerminal; + switch (op) { + case Jump: + case Branch: + case Return: + case Throw: + case ThrowReferenceError: + return true; + default: + return false; + } } unsigned takenBytecodeOffsetDuringParsing() @@ -775,6 +749,30 @@ struct Node { unsigned storageAccessDataIndex() { + ASSERT(hasStorageAccessData()); + return m_opInfo; + } + + bool hasFunctionDeclIndex() + { + return op == NewFunction + || op == NewFunctionNoCheck; + } + + unsigned functionDeclIndex() + { + ASSERT(hasFunctionDeclIndex()); + return m_opInfo; + } + + bool hasFunctionExprIndex() + { + return op == NewFunctionExpression; + } + + unsigned functionExprIndex() + { + ASSERT(hasFunctionExprIndex()); return m_opInfo; } @@ -799,7 +797,7 @@ struct Node { bool shouldGenerate() { - return m_refCount && op != Phi && op != Flush; + return m_refCount; } unsigned refCount() @@ -834,7 +832,7 @@ struct Node { NodeUse child1() { - ASSERT(!(op & NodeHasVarArgs)); + ASSERT(!(flags & NodeHasVarArgs)); return children.child1(); } @@ -848,25 +846,25 @@ struct Node { NodeUse child2() { - ASSERT(!(op & NodeHasVarArgs)); + ASSERT(!(flags & NodeHasVarArgs)); return children.child2(); } NodeUse child3() { - ASSERT(!(op & NodeHasVarArgs)); + ASSERT(!(flags & NodeHasVarArgs)); return children.child3(); } unsigned firstChild() { - ASSERT(op & NodeHasVarArgs); + ASSERT(flags & NodeHasVarArgs); return children.firstChild(); } unsigned numChildren() { - ASSERT(op & NodeHasVarArgs); + ASSERT(flags & NodeHasVarArgs); return children.numChildren(); } @@ -1032,8 +1030,8 @@ struct Node { fprintf(out, ", @%u", child3().index()); } - // This enum value describes the type of the node. - NodeType op; + uint16_t op; // real type is NodeType + NodeFlags flags; // Used to look up exception handling information (currently implemented as a bytecode index). CodeOrigin codeOrigin; // References to up to 3 children, or links to a variable length set of children. diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp index a672234a3..bd45020d1 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp @@ -98,7 +98,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload); m_jit.load32(scratchBuffer, scratch); } else if (exit.m_jsValueSource.hasKnownTag()) { - m_jit.store32(AssemblyHelpers::Imm32(exit.m_jsValueSource.tag()), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag); + m_jit.store32(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag); m_jit.store32(exit.m_jsValueSource.payloadGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload); } else { m_jit.store32(exit.m_jsValueSource.tagGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag); @@ -562,32 +562,40 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco // counter to 0; otherwise we set the counter to // counterValueForOptimizeAfterWarmUp(). - m_jit.add32(AssemblyHelpers::Imm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); + m_jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.codeBlock()), GPRInfo::regT0); m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2); m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1); - m_jit.add32(AssemblyHelpers::Imm32(1), GPRInfo::regT2); - m_jit.add32(AssemblyHelpers::Imm32(-1), GPRInfo::regT1); + m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2); + m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1); m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter())); m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0); - AssemblyHelpers::Jump fewFails = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::Imm32(m_jit.codeBlock()->largeFailCountThreshold())); - m_jit.mul32(AssemblyHelpers::Imm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2); + AssemblyHelpers::Jump fewFails = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->largeFailCountThreshold())); + m_jit.mul32(AssemblyHelpers::TrustedImm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2); AssemblyHelpers::Jump lowFailRate = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1); // Reoptimize as soon as possible. - m_jit.store32(AssemblyHelpers::Imm32(Options::executionCounterValueForOptimizeNextInvocation), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); AssemblyHelpers::Jump doneAdjusting = m_jit.jump(); fewFails.link(&m_jit); lowFailRate.link(&m_jit); - m_jit.store32(AssemblyHelpers::Imm32(m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp()), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + // Adjust the execution counter such that the target is to only optimize after a while. + int32_t targetValue = + ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt( + m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp(), + m_jit.baselineCodeBlock()); + m_jit.store32(AssemblyHelpers::TrustedImm32(-targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); + m_jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(targetValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount())); doneAdjusting.link(&m_jit); @@ -618,24 +626,24 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco GPRReg callerFrameGPR; if (inlineCallFrame->caller.inlineCallFrame) { - m_jit.add32(AssemblyHelpers::Imm32(inlineCallFrame->caller.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT3); + m_jit.add32(AssemblyHelpers::TrustedImm32(inlineCallFrame->caller.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT3); callerFrameGPR = GPRInfo::regT3; } else callerFrameGPR = GPRInfo::callFrameRegister; m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CodeBlock))); - m_jit.store32(AssemblyHelpers::Imm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain))); + m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain))); m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee->scope()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain))); - m_jit.store32(AssemblyHelpers::Imm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame))); + m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame))); m_jit.storePtr(callerFrameGPR, AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame))); m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ReturnPC))); - m_jit.store32(AssemblyHelpers::Imm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ArgumentCount))); - m_jit.store32(AssemblyHelpers::Imm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee))); + m_jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ArgumentCount))); + m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee))); m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee))); } if (exit.m_codeOrigin.inlineCallFrame) - m_jit.addPtr(AssemblyHelpers::Imm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister); + m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister); // 14) Jump into the corresponding baseline JIT code. diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp index f5e03973c..91a515c48 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp @@ -227,7 +227,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco break; case AlreadyInRegisterFileAsUnboxedInt32: - m_jit.store32(AssemblyHelpers::Imm32(static_cast<uint32_t>(TagTypeNumber >> 32)), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(exit.operandForIndex(index)))); + m_jit.store32(AssemblyHelpers::TrustedImm32(static_cast<uint32_t>(TagTypeNumber >> 32)), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(exit.operandForIndex(index)))); break; case UInt32InGPR: { @@ -541,32 +541,40 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco // counter to 0; otherwise we set the counter to // counterValueForOptimizeAfterWarmUp(). - m_jit.add32(AssemblyHelpers::Imm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); + m_jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.codeBlock()), GPRInfo::regT0); m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2); m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1); - m_jit.add32(AssemblyHelpers::Imm32(1), GPRInfo::regT2); - m_jit.add32(AssemblyHelpers::Imm32(-1), GPRInfo::regT1); + m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2); + m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1); m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter())); m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0); - AssemblyHelpers::Jump fewFails = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::Imm32(m_jit.codeBlock()->largeFailCountThreshold())); - m_jit.mul32(AssemblyHelpers::Imm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2); + AssemblyHelpers::Jump fewFails = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->largeFailCountThreshold())); + m_jit.mul32(AssemblyHelpers::TrustedImm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2); AssemblyHelpers::Jump lowFailRate = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1); // Reoptimize as soon as possible. - m_jit.store32(AssemblyHelpers::Imm32(Options::executionCounterValueForOptimizeNextInvocation), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); AssemblyHelpers::Jump doneAdjusting = m_jit.jump(); fewFails.link(&m_jit); lowFailRate.link(&m_jit); - m_jit.store32(AssemblyHelpers::Imm32(m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp()), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + // Adjust the execution counter such that the target is to only optimize after a while. + int32_t targetValue = + ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt( + m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp(), + m_jit.baselineCodeBlock()); + m_jit.store32(AssemblyHelpers::TrustedImm32(-targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); + m_jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(targetValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount())); doneAdjusting.link(&m_jit); @@ -595,7 +603,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco GPRReg callerFrameGPR; if (inlineCallFrame->caller.inlineCallFrame) { - m_jit.addPtr(AssemblyHelpers::Imm32(inlineCallFrame->caller.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT3); + m_jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->caller.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT3); callerFrameGPR = GPRInfo::regT3; } else callerFrameGPR = GPRInfo::callFrameRegister; @@ -609,7 +617,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco } if (exit.m_codeOrigin.inlineCallFrame) - m_jit.addPtr(AssemblyHelpers::Imm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister); + m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister); // 16) Jump into the corresponding baseline JIT code. diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 165a21416..304c54d95 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -31,10 +31,12 @@ #include "DFGRepatch.h" #include "HostCallReturnValue.h" #include "GetterSetter.h" -#include "InlineASM.h" +#include <wtf/InlineASM.h> #include "Interpreter.h" +#include "JSActivation.h" #include "JSByteArray.h" #include "JSGlobalData.h" +#include "JSStaticScopeObject.h" #include "Operations.h" #if ENABLE(DFG_JIT) @@ -144,6 +146,7 @@ FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) namespace JSC { namespace DFG { +template<bool strict> static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value) { JSGlobalData* globalData = &exec->globalData(); @@ -155,7 +158,7 @@ static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, return; } - JSArray::putByIndex(array, exec, index, value); + JSArray::putByIndex(array, exec, index, value, strict); return; } @@ -173,7 +176,7 @@ static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, } } - baseValue.put(exec, index, value); + baseValue.putByIndex(exec, index, value, strict); } template<bool strict> @@ -187,7 +190,7 @@ ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exe JSValue value = JSValue::decode(encodedValue); if (LIKELY(property.isUInt32())) { - putByVal(exec, baseValue, property.asUInt32(), value); + putByVal<strict>(exec, baseValue, property.asUInt32(), value); return; } @@ -195,7 +198,7 @@ ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exe double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsDouble == propertyAsUInt32) { - putByVal(exec, baseValue, propertyAsUInt32, value); + putByVal<strict>(exec, baseValue, propertyAsUInt32, value); return; } } @@ -471,14 +474,24 @@ void DFG_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, operationPutByValInternal<false>(exec, JSValue::encode(cell), encodedProperty, encodedValue); } -void DFG_OPERATION operationPutByValBeyondArrayBounds(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue) +void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue) +{ + JSGlobalData* globalData = &exec->globalData(); + NativeCallFrameTracer tracer(globalData, exec); + + // We should only get here if index is outside the existing vector. + ASSERT(!array->canSetIndex(index)); + JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), true); +} + +void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue) { JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); // We should only get here if index is outside the existing vector. ASSERT(!array->canSetIndex(index)); - JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue)); + JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), false); } EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array) @@ -734,8 +747,11 @@ size_t DFG_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue en { JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); + + JSValue src1 = JSValue::decode(encodedOp1); + JSValue src2 = JSValue::decode(encodedOp2); - return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)); + return JSValue::strictEqual(exec, src1, src2); } static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind) @@ -974,6 +990,43 @@ EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr return JSValue::encode(RegExpObject::create(exec->globalData(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regexp)); } +JSCell* DFG_OPERATION operationCreateActivation(ExecState* exec) +{ + JSGlobalData& globalData = exec->globalData(); + JSActivation* activation = JSActivation::create( + globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable())); + exec->setScopeChain(exec->scopeChain()->push(activation)); + return activation; +} + +void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activation) +{ + ASSERT(activation); + ASSERT(activation->inherits(&JSActivation::s_info)); + static_cast<JSActivation*>(activation)->tearOff(exec->globalData()); +} + +JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable) +{ + ASSERT(functionExecutable->inherits(&FunctionExecutable::s_info)); + return static_cast<FunctionExecutable*>(functionExecutable)->make(exec, exec->scopeChain()); +} + +JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* functionExecutableAsCell) +{ + ASSERT(functionExecutableAsCell->inherits(&FunctionExecutable::s_info)); + FunctionExecutable* functionExecutable = + static_cast<FunctionExecutable*>(functionExecutableAsCell); + JSFunction *function = functionExecutable->make(exec, exec->scopeChain()); + if (!functionExecutable->name().isNull()) { + JSStaticScopeObject* functionScopeObject = + JSStaticScopeObject::create( + exec, functionExecutable->name(), function, ReadOnly | DontDelete); + function->setScope(exec->globalData(), function->scope()->push(functionScopeObject)); + } + return function; +} + DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t callIndex) { JSGlobalData* globalData = &exec->globalData(); diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index cdb88de27..4ca58d621 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -89,6 +89,7 @@ typedef void DFG_OPERATION (*V_DFGOperation_EAZJ)(ExecState*, JSArray*, int32_t, typedef double DFG_OPERATION (*D_DFGOperation_DD)(double, double); typedef double DFG_OPERATION (*D_DFGOperation_EJ)(ExecState*, EncodedJSValue); typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*); +typedef void DFG_OPERATION (V_DFGOperation_EC)(ExecState*, JSCell*); // These routines are provide callbacks out to C++ implementations of operations too complex to JIT. JSCell* DFG_OPERATION operationNewObject(ExecState*); @@ -118,7 +119,8 @@ void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBas void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue); void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue); void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue); -void DFG_OPERATION operationPutByValBeyondArrayBounds(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue); +void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue); +void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue); EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*); EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*); void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*); @@ -145,6 +147,10 @@ void* DFG_OPERATION operationVirtualCall(ExecState*); void* DFG_OPERATION operationLinkCall(ExecState*); void* DFG_OPERATION operationVirtualConstruct(ExecState*); void* DFG_OPERATION operationLinkConstruct(ExecState*); +JSCell* DFG_OPERATION operationCreateActivation(ExecState*); +void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*); +JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*); +JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*); // This method is used to lookup an exception hander, keyed by faultLocation, which is // the return location from one of the calls out to one of the helper operations above. diff --git a/Source/JavaScriptCore/dfg/DFGPhase.cpp b/Source/JavaScriptCore/dfg/DFGPhase.cpp index bc1eabff4..bae12b1cc 100644 --- a/Source/JavaScriptCore/dfg/DFGPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPhase.cpp @@ -35,7 +35,7 @@ void Phase::beginPhase() { dataLog("Beginning DFG phase %s.\n", m_name); dataLog("Graph before %s:\n", m_name); - m_graph.dump(m_codeBlock); + m_graph.dump(); } void Phase::endPhase() diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp index b4c9e075a..98bdaac06 100644 --- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp @@ -105,7 +105,7 @@ private: if (!node.shouldGenerate()) return; - NodeType op = node.op; + NodeType op = static_cast<NodeType>(node.op); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex); @@ -209,6 +209,15 @@ private: break; } + case ArithNegate: + if (m_graph[node.child1()].prediction()) { + if (m_graph.negateShouldSpeculateInteger(node)) + changed |= mergePrediction(PredictInt32); + else + changed |= mergePrediction(PredictDouble); + } + break; + case ArithMul: case ArithMin: case ArithMax: @@ -397,6 +406,18 @@ private: break; } + case CreateActivation: { + changed |= setPrediction(PredictObjectOther); + break; + } + + case NewFunction: + case NewFunctionNoCheck: + case NewFunctionExpression: { + changed |= setPrediction(PredictFunction); + break; + } + case GetArrayLength: case GetByteArrayLength: case GetInt8ArrayLength: @@ -415,6 +436,9 @@ private: break; } + case Flush: + break; + #ifndef NDEBUG // These get ignored because they don't return anything. case PutScopedVar: @@ -424,7 +448,6 @@ private: case Return: case CheckHasInstance: case Phi: - case Flush: case Throw: case ThrowReferenceError: case ForceOSRExit: @@ -437,6 +460,7 @@ private: case CheckFunction: case PutStructure: case PutByOffset: + case TearOffActivation: break; // These gets ignored because it doesn't do anything. @@ -444,6 +468,10 @@ private: case InlineStart: case Nop: break; + + case LastNodeType: + ASSERT_NOT_REACHED(); + break; #else default: break; @@ -492,7 +520,7 @@ private: void vote(Node& node, VariableAccessData::Ballot ballot) { - if (node.op & NodeHasVarArgs) { + if (node.flags & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) vote(m_graph.m_varArgChildren[childIdx], ballot); return; @@ -586,8 +614,13 @@ private: break; } } - for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) - m_changed |= m_graph.m_variableAccessData[i].find()->tallyVotesForShouldUseDoubleFormat(); + for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) { + VariableAccessData* variableAccessData = m_graph.m_variableAccessData[i].find(); + if (operandIsArgument(variableAccessData->local()) + || m_graph.isCaptured(variableAccessData->local())) + continue; + m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat(); + } } void fixupNode(Node& node) @@ -595,7 +628,7 @@ private: if (!node.shouldGenerate()) return; - NodeType op = node.op; + NodeType op = static_cast<NodeType>(node.op); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex); @@ -651,13 +684,16 @@ private: node.op = GetFloat64ArrayLength; else ASSERT_NOT_REACHED(); - m_graph.deref(m_compileIndex); // No longer MustGenerate + // No longer MustGenerate + ASSERT(node.flags & NodeMustGenerate); + node.flags &= ~NodeMustGenerate; + m_graph.deref(m_compileIndex); break; } case GetIndexedPropertyStorage: { PredictedType basePrediction = m_graph[node.child2()].prediction(); if (!(basePrediction & PredictInt32) && basePrediction) { - node.op = Nop; + node.setOpAndDefaultFlags(Nop); m_graph.clearAndDerefChild1(node); m_graph.clearAndDerefChild2(node); m_graph.clearAndDerefChild3(node); diff --git a/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp b/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp new file mode 100644 index 000000000..fb30de742 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGRedundantPhiEliminationPhase.h" + +#if ENABLE(DFG_JIT) + +#include "DFGGraph.h" + +namespace JSC { namespace DFG { + +class RedundantPhiEliminationPhase : public Phase { +public: + RedundantPhiEliminationPhase(Graph& graph) + : Phase(graph, "redundant phi elimination") + { + } + + void run() + { + bool changed = false; + do { + changed = fixupPhis(); + } while (changed); + + updateBlockVariableInformation(); + + // Update the Phi references from non-Phi nodes, e.g., the GetLocals. + for (NodeIndex index = 0; index < m_graph.size(); ++index) { + Node& node = m_graph[index]; + + if (!node.shouldGenerate()) + continue; + + switch (node.op) { + case GetLocal: + replacePhiChild(node, 0); + break; + default: + break; + } + } + + } + +private: + NodeIndex getRedundantReplacement(NodeIndex phi) + { + NodeIndex child1 = m_graph[phi].child1().indexUnchecked(); + NodeIndex candidate = child1 == phi ? NoNode : child1; + + NodeIndex child2 = m_graph[phi].child2().indexUnchecked(); + if (candidate != NoNode) { + if (child2 != NoNode && child2 != candidate && child2 != phi) + return NoNode; + } else if (child2 != phi) + candidate = child2; + + NodeIndex child3 = m_graph[phi].child3().indexUnchecked(); + if (candidate != NoNode) { + if (child3 != NoNode && child3 != candidate && child3 != phi) + return NoNode; + } else if (child3 != phi) + candidate = child3; + + return candidate; + } + + bool replacePhiChild(Node& node, unsigned childIndex) + { + ASSERT(childIndex < 3); + + bool replaced = false; + NodeIndex child = node.children.child(childIndex).indexUnchecked(); + if (child != NoNode && m_graph[child].op == Phi) { + NodeIndex childReplacement = getRedundantReplacement(child); + if (childReplacement != NoNode) { + node.children.child(childIndex).setIndex(childReplacement); + replaced = true; + if (node.refCount()) { + m_graph[childReplacement].ref(); + m_graph.deref(child); + } + } + } + return replaced; + } + + bool fixupPhis() + { + bool changed = false; + + for (BlockIndex block = 0; block < m_graph.m_blocks.size(); ++block) { + Vector<NodeIndex>& phis = m_graph.m_blocks[block]->phis; + + for (size_t i = 0; i < phis.size(); ++i) { + NodeIndex phi = phis[i]; + Node& phiNode = m_graph[phi]; + + changed |= (replacePhiChild(phiNode, 0) && phiNode.refCount()); + changed |= (replacePhiChild(phiNode, 1) && phiNode.refCount()); + changed |= (replacePhiChild(phiNode, 2) && phiNode.refCount()); + } + } + + return changed; + } + + void updateBlockVariableInformation() + { + // Redundant Phi nodes are eliminated, we need to update + // the variable information if it references them. + for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { + BasicBlock* basicBlock = m_graph.m_blocks[blockIndex].get(); + + for (size_t arg = 0; arg < basicBlock->variablesAtHead.numberOfArguments(); ++arg) { + NodeIndex nodeIndex = basicBlock->variablesAtHead.argument(arg); + if (nodeIndex != NoNode && m_graph[nodeIndex].op == Phi && !m_graph[nodeIndex].refCount()) { + NodeIndex replacement = getRedundantReplacement(nodeIndex); + if (replacement != NoNode) { + // This argument must be unused in this block. + ASSERT(basicBlock->variablesAtTail.argument(arg) == nodeIndex); + basicBlock->variablesAtHead.argument(arg) = replacement; + basicBlock->variablesAtTail.argument(arg) = replacement; + } + } + } + + for (size_t local = 0; local < basicBlock->variablesAtHead.numberOfLocals(); ++local) { + NodeIndex nodeIndex = basicBlock->variablesAtHead.local(local); + if (nodeIndex != NoNode && m_graph[nodeIndex].op == Phi && !m_graph[nodeIndex].refCount()) { + NodeIndex replacement = getRedundantReplacement(nodeIndex); + if (replacement != NoNode) { + // This local variable must be unused in this block. + ASSERT(basicBlock->variablesAtTail.local(local) == nodeIndex); + basicBlock->variablesAtHead.local(local) = replacement; + basicBlock->variablesAtTail.local(local) = replacement; + } + } + } + } + } + +}; + +void performRedundantPhiElimination(Graph& graph) +{ + runPhase<RedundantPhiEliminationPhase>(graph); +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) diff --git a/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.h b/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.h new file mode 100644 index 000000000..202ab4441 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGRedundantPhiEliminationPhase_h +#define DFGRedundantPhiEliminationPhase_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +#include "DFGPhase.h" + +namespace JSC { namespace DFG { + +class Graph; + +// We inserted many can-be-redundant Phi nodes when building the graph. +// This phase will just remove them. + +void performRedundantPhiElimination(Graph&); + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGRedundantPhiEliminationPhase_h + diff --git a/Source/JavaScriptCore/dfg/DFGScoreBoard.h b/Source/JavaScriptCore/dfg/DFGScoreBoard.h index 912b3e8fd..140de185b 100644 --- a/Source/JavaScriptCore/dfg/DFGScoreBoard.h +++ b/Source/JavaScriptCore/dfg/DFGScoreBoard.h @@ -58,14 +58,27 @@ public: } } -#if DFG_ENABLE(CONSISTENCY_CHECK) ~ScoreBoard() { - // For every entry in the used list the use count of the virtual register should be zero. - for (size_t i = 0; i < m_free.size(); ++i) - ASSERT(!m_used[i] || m_used[i] == max()); + assertClear(); } + + void assertClear() + { +#if !ASSERT_DISABLED + // For every entry in the used list the use count of the virtual register should be zero, or max, due to it being a preserved local. + for (size_t i = 0; i < m_used.size(); ++i) + ASSERT(!m_used[i] || m_used[i] == max()); + // For every entry in the free list, the use count should be zero. + for (size_t i = 0; i < m_free.size(); ++i) + ASSERT(!m_used[m_free[i]]); + // There must not be duplicates in the free list. + for (size_t i = 0; i < m_free.size(); ++i) { + for (size_t j = i + 1; j < m_free.size(); ++j) + ASSERT(m_free[i] != m_free[j]); + } #endif + } VirtualRegister allocate() { @@ -99,6 +112,9 @@ public: uint32_t index = node.virtualRegister(); ASSERT(m_used[index] != max()); if (node.refCount() == ++m_used[index]) { +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + dataLog(" Freeing virtual register %u.", index); +#endif // If the use count in the scoreboard reaches the use count for the node, // then this was its last use; the virtual register is now free. // Clear the use count & add to the free list. diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index 8578337f5..7bcb44576 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -83,7 +83,7 @@ GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex) void SpeculativeJIT::useChildren(Node& node) { - if (node.op & NodeHasVarArgs) { + if (node.flags & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) use(m_jit.graph().m_varArgChildren[childIdx]); } else { @@ -365,12 +365,15 @@ void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeUse valueU bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction) { - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); + ASSERT(node.adjustedRefCount() == 1); nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; @@ -383,15 +386,15 @@ bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::Relationa bool SpeculativeJIT::nonSpeculativeStrictEq(Node& node, bool invert) { - if (!invert && (isKnownNumeric(node.child1().index()) || isKnownNumeric(node.child2().index()))) - return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq); - - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); + ASSERT(node.adjustedRefCount() == 1); nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; @@ -765,7 +768,6 @@ FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1) } #endif -#ifndef NDEBUG void ValueSource::dump(FILE* out) const { switch (kind()) { @@ -792,7 +794,6 @@ void ValueSource::dump(FILE* out) const break; } } -#endif void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition) { @@ -873,8 +874,10 @@ void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNo bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation) { // Fused compare & branch. - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); + // detectPeepHoleBranch currently only permits the branch to be the very next node, // so can be no intervening nodes to also reference the compare. ASSERT(node.adjustedRefCount() == 1); @@ -898,6 +901,7 @@ bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::Relationa } else nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; } @@ -915,12 +919,9 @@ void SpeculativeJIT::compileMovHint(Node& node) void SpeculativeJIT::compile(BasicBlock& block) { ASSERT(m_compileOkay); - ASSERT(m_compileIndex == block.begin); - if (!block.isReachable) { - m_compileIndex = block.end; + if (!block.isReachable) return; - } m_blockHeads[m_block] = m_jit.label(); #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK) @@ -930,7 +931,7 @@ void SpeculativeJIT::compile(BasicBlock& block) ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments()); for (size_t i = 0; i < m_arguments.size(); ++i) { NodeIndex nodeIndex = block.variablesAtHead.argument(i); - if (nodeIndex == NoNode) + if (nodeIndex == NoNode || m_jit.graph().argumentIsCaptured(i)) m_arguments[i] = ValueSource(ValueInRegisterFile); else m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction()); @@ -942,7 +943,7 @@ void SpeculativeJIT::compile(BasicBlock& block) ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals()); for (size_t i = 0; i < m_variables.size(); ++i) { NodeIndex nodeIndex = block.variablesAtHead.local(i); - if (nodeIndex == NoNode) + if (nodeIndex == NoNode || m_jit.graph().localIsCaptured(i)) m_variables[i] = ValueSource(ValueInRegisterFile); else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat()) m_variables[i] = ValueSource(DoubleInRegisterFile); @@ -955,12 +956,13 @@ void SpeculativeJIT::compile(BasicBlock& block) if (DFG_ENABLE_EDGE_CODE_VERIFICATION) { JITCompiler::Jump verificationSucceeded = - m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, Imm32(m_block)); + m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, TrustedImm32(m_block)); m_jit.breakpoint(); verificationSucceeded.link(&m_jit); } - for (; m_compileIndex < block.end; ++m_compileIndex) { + for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) { + m_compileIndex = block[m_indexInBlock]; Node& node = at(m_compileIndex); m_codeOriginForOSR = node.codeOrigin; if (!node.shouldGenerate()) { @@ -1005,7 +1007,6 @@ void SpeculativeJIT::compile(BasicBlock& block) compile(node); if (!m_compileOkay) { m_compileOkay = true; - m_compileIndex = block.end; clearGenerationInfo(); return; } @@ -1045,7 +1046,7 @@ void SpeculativeJIT::compile(BasicBlock& block) #endif // Make sure that the abstract state is rematerialized for the next node. - m_state.execute(m_compileIndex); + m_state.execute(m_indexInBlock); if (node.shouldGenerate()) checkConsistency(); @@ -1232,7 +1233,7 @@ bool SpeculativeJIT::compile() checkArgumentTypes(); if (DFG_ENABLE_EDGE_CODE_VERIFICATION) - m_jit.move(Imm32(0), GPRInfo::regT0); + m_jit.move(TrustedImm32(0), GPRInfo::regT0); ASSERT(!m_compileIndex); for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) @@ -1258,7 +1259,7 @@ void SpeculativeJIT::createOSREntries() } m_osrEntryHeads.append(m_jit.label()); - m_jit.move(Imm32(blockIndex), GPRInfo::regT0); + m_jit.move(TrustedImm32(blockIndex), GPRInfo::regT0); m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit); } } @@ -2318,8 +2319,14 @@ void SpeculativeJIT::compileArithSub(Node& node) if (nodeCanTruncateInteger(node.arithNodeFlags())) { m_jit.move(op1.gpr(), result.gpr()); m_jit.sub32(Imm32(imm2), result.gpr()); - } else + } else { +#if ENABLE(JIT_CONSTANT_BLINDING) + GPRTemporary scratch(this); + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr(), scratch.gpr())); +#else speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr())); +#endif + } integerResult(result.gpr(), m_compileIndex); return; @@ -2365,6 +2372,34 @@ void SpeculativeJIT::compileArithSub(Node& node) doubleResult(result.fpr(), m_compileIndex); } +void SpeculativeJIT::compileArithNegate(Node& node) +{ + if (m_jit.graph().negateShouldSpeculateInteger(node)) { + SpeculateIntegerOperand op1(this, node.child1()); + GPRTemporary result(this); + + m_jit.move(op1.gpr(), result.gpr()); + + if (nodeCanTruncateInteger(node.arithNodeFlags())) + m_jit.neg32(result.gpr()); + else { + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr())); + if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, result.gpr())); + } + + integerResult(result.gpr(), m_compileIndex); + return; + } + + SpeculateDoubleOperand op1(this, node.child1()); + FPRTemporary result(this); + + m_jit.negateDouble(op1.fpr(), result.fpr()); + + doubleResult(result.fpr(), m_compileIndex); +} + void SpeculativeJIT::compileArithMul(Node& node) { if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { @@ -2456,8 +2491,9 @@ bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeUse value, JSVal { JSValueOperand op1(this, value); - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); Node& branchNode = at(branchNodeIndex); BlockIndex taken = branchNode.takenBlockIndex(); BlockIndex notTaken = branchNode.notTakenBlockIndex(); @@ -2493,6 +2529,7 @@ bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeUse value, JSVal use(node.child1()); use(node.child2()); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; } @@ -2504,18 +2541,18 @@ bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeUse value, JSVal GPRReg resultGPR = result.gpr(); m_jit.move(MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(ValueFalse)), resultGPR); MacroAssembler::Jump notEqual = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant)))); - m_jit.or32(MacroAssembler::Imm32(1), resultGPR); + m_jit.or32(MacroAssembler::TrustedImm32(1), resultGPR); notEqual.link(&m_jit); jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); #else GPRReg op1PayloadGPR = op1.payloadGPR(); GPRReg op1TagGPR = op1.tagGPR(); GPRReg resultGPR = result.gpr(); - m_jit.move(Imm32(0), resultGPR); + m_jit.move(TrustedImm32(0), resultGPR); MacroAssembler::JumpList notEqual; notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, MacroAssembler::Imm32(constant.tag()))); notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1PayloadGPR, MacroAssembler::Imm32(constant.payload()))); - m_jit.move(Imm32(1), resultGPR); + m_jit.move(TrustedImm32(1), resultGPR); notEqual.link(&m_jit); booleanResult(resultGPR, m_compileIndex); #endif @@ -2543,11 +2580,13 @@ bool SpeculativeJIT::compileStrictEq(Node& node) // 2) If the operands are predicted integer, do an integer comparison. if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) { - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); compilePeepHoleIntegerBranch(node, branchNodeIndex, MacroAssembler::Equal); use(node.child1()); use(node.child2()); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; } @@ -2558,11 +2597,13 @@ bool SpeculativeJIT::compileStrictEq(Node& node) // 3) If the operands are predicted double, do a double comparison. if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) { - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); compilePeepHoleDoubleBranch(node, branchNodeIndex, MacroAssembler::DoubleEqual); use(node.child1()); use(node.child2()); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; } @@ -2574,11 +2615,13 @@ bool SpeculativeJIT::compileStrictEq(Node& node) // or array comparison. if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) { - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction); use(node.child1()); use(node.child2()); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; } @@ -2587,11 +2630,13 @@ bool SpeculativeJIT::compileStrictEq(Node& node) } if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) { - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction); use(node.child1()); use(node.child2()); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; } @@ -2691,6 +2736,28 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node) storageResult(storageReg, m_compileIndex); } +void SpeculativeJIT::compileNewFunctionNoCheck(Node& node) +{ + GPRResult result(this); + GPRReg resultGPR = result.gpr(); + flushRegisters(); + callOperation( + operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex())); + cellResult(resultGPR, m_compileIndex); +} + +void SpeculativeJIT::compileNewFunctionExpression(Node& node) +{ + GPRResult result(this); + GPRReg resultGPR = result.gpr(); + flushRegisters(); + callOperation( + operationNewFunctionExpression, + resultGPR, + m_jit.codeBlock()->functionExpr(node.functionExprIndex())); + cellResult(resultGPR, m_compileIndex); +} + } } // namespace JSC::DFG #endif diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index 5d95b064f..1744a03f3 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -104,9 +104,7 @@ public: return m_nodeIndex; } -#ifndef NDEBUG void dump(FILE* out) const; -#endif private: static NodeIndex nodeIndexFromKind(ValueSourceKind kind) @@ -454,7 +452,7 @@ private: ASSERT(info.gpr() == target); if (node.hasConstant()) { ASSERT(isBooleanConstant(nodeIndex)); - m_jit.move(Imm32(valueOfBooleanConstant(nodeIndex)), target); + m_jit.move(TrustedImm32(valueOfBooleanConstant(nodeIndex)), target); } else m_jit.load32(JITCompiler::payloadFor(spillMe), target); #endif @@ -466,7 +464,7 @@ private: if (node.hasConstant()) { JSValue value = valueOfJSConstant(nodeIndex); ASSERT(value.isCell()); - m_jit.move(ImmPtr(value.asCell()), target); + m_jit.move(TrustedImmPtr(value.asCell()), target); } else m_jit.loadPtr(JITCompiler::payloadFor(spillMe), target); return; @@ -481,9 +479,12 @@ private: ASSERT(registerFormat & DataFormatJS); #if USE(JSVALUE64) ASSERT(info.gpr() == target); - if (node.hasConstant()) - m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), target); - else if (info.spillFormat() == DataFormatInteger) { + if (node.hasConstant()) { + if (valueOfJSConstant(nodeIndex).isCell()) + m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex).asTrustedImmPtr(), target); + else + m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), target); + } else if (info.spillFormat() == DataFormatInteger) { ASSERT(registerFormat == DataFormatJSInteger); m_jit.load32(JITCompiler::payloadFor(spillMe), target); m_jit.orPtr(GPRInfo::tagTypeNumberRegister, target); @@ -875,20 +876,21 @@ private: } } - // Returns the node index of the branch node if peephole is okay, NoNode otherwise. - NodeIndex detectPeepHoleBranch() + // Returns the index of the branch node if peephole is okay, UINT_MAX otherwise. + unsigned detectPeepHoleBranch() { - NodeIndex lastNodeIndex = m_jit.graph().m_blocks[m_block]->end - 1; + BasicBlock* block = m_jit.graph().m_blocks[m_block].get(); // Check that no intervening nodes will be generated. - for (NodeIndex index = m_compileIndex + 1; index < lastNodeIndex; ++index) { - if (at(index).shouldGenerate()) - return NoNode; + for (unsigned index = m_indexInBlock + 1; index < block->size() - 1; ++index) { + NodeIndex nodeIndex = block->at(index); + if (at(nodeIndex).shouldGenerate()) + return UINT_MAX; } // Check if the lastNode is a branch on this node. - Node& lastNode = at(lastNodeIndex); - return lastNode.op == Branch && lastNode.child1().index() == m_compileIndex ? lastNodeIndex : NoNode; + Node& lastNode = at(block->last()); + return lastNode.op == Branch && lastNode.child1().index() == m_compileIndex ? block->size() - 1 : UINT_MAX; } void nonSpeculativeValueToNumber(Node&); @@ -1124,7 +1126,7 @@ private: } JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg result, int startConstant, int numConstants) { - m_jit.setupArgumentsWithExecState(Imm32(startConstant), Imm32(numConstants)); + m_jit.setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants)); return appendCallWithExceptionCheckSetResult(operation, result); } JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, void* pointer) @@ -1162,6 +1164,11 @@ private: m_jit.setupArgumentsWithExecState(arg1); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, JSCell* cell) + { + m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell)); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell) { m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell)); @@ -1182,14 +1189,14 @@ private: m_jit.setupArgumentsWithExecState(arg1, arg2); return appendCallWithExceptionCheckSetResult(operation, result); } - JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, MacroAssembler::Imm32 imm) + JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, MacroAssembler::TrustedImm32 imm) { - m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value))))); + m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::TrustedImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value))))); return appendCallWithExceptionCheckSetResult(operation, result); } - JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, MacroAssembler::Imm32 imm, GPRReg arg2) + JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, MacroAssembler::TrustedImm32 imm, GPRReg arg2) { - m_jit.setupArgumentsWithExecState(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))), arg2); + m_jit.setupArgumentsWithExecState(MacroAssembler::TrustedImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))), arg2); return appendCallWithExceptionCheckSetResult(operation, result); } JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg result, GPRReg arg1, GPRReg arg2) @@ -1197,6 +1204,11 @@ private: m_jit.setupArgumentsWithExecState(arg1, arg2); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1) + { + m_jit.setupArgumentsWithExecState(arg1); + return appendCallWithExceptionCheck(operation); + } JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1, GPRReg arg2, void* pointer) { m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(pointer)); @@ -1287,7 +1299,7 @@ private: } JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, void* pointer) { - m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, ImmPtr(pointer)); + m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(pointer)); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2) @@ -1330,6 +1342,11 @@ private: m_jit.setupArgumentsWithExecState(arg1); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, JSCell* cell) + { + m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell)); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell) { m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell)); @@ -1350,12 +1367,12 @@ private: m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } - JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, MacroAssembler::Imm32 imm) + JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, MacroAssembler::TrustedImm32 imm) { m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, imm, TrustedImm32(JSValue::Int32Tag)); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } - JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, MacroAssembler::Imm32 imm, GPRReg arg2Tag, GPRReg arg2Payload) + JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, MacroAssembler::TrustedImm32 imm, GPRReg arg2Tag, GPRReg arg2Payload) { m_jit.setupArgumentsWithExecState(imm, TrustedImm32(JSValue::Int32Tag), arg2Payload, arg2Tag); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); @@ -1365,6 +1382,11 @@ private: m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } + JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1) + { + m_jit.setupArgumentsWithExecState(arg1); + return appendCallWithExceptionCheck(operation); + } JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, void* pointer) { m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(pointer)); @@ -1620,7 +1642,7 @@ private: { if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) return; - m_jit.move(Imm32(destination), GPRInfo::regT0); + m_jit.move(TrustedImm32(destination), GPRInfo::regT0); } void addBranch(const MacroAssembler::Jump& jump, BlockIndex destination) @@ -1693,6 +1715,7 @@ private: void compilePutByValForByteArray(GPRReg base, GPRReg property, Node&); void compileAdd(Node&); void compileArithSub(Node&); + void compileArithNegate(Node&); void compileArithMul(Node&); void compileArithMod(Node&); void compileSoftModulo(Node&); @@ -1715,14 +1738,18 @@ private: void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness, TypedArrayRounding = TruncateRounding); void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements); void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements); + void compileNewFunctionNoCheck(Node& node); + void compileNewFunctionExpression(Node& node); - // It is acceptable to have structure be equal to scratch, so long as you're fine - // with the structure GPR being clobbered. - template<typename T> - void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath) + template <typename ClassType, bool destructor, typename StructureType> + void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath) { - MarkedAllocator* allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject)); - + MarkedAllocator* allocator = 0; + if (destructor) + allocator = &m_jit.globalData()->heap.allocatorForObjectWithDestructor(sizeof(ClassType)); + else + allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType)); + m_jit.loadPtr(&allocator->m_firstFreeCell, resultGPR); slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR)); @@ -1738,14 +1765,22 @@ private: m_jit.storePtr(scratchGPR, &allocator->m_firstFreeCell); // Initialize the object's classInfo pointer - m_jit.storePtr(MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset())); + m_jit.storePtr(MacroAssembler::TrustedImmPtr(&ClassType::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset())); // Initialize the object's inheritorID. m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID())); // Initialize the object's property storage pointer. m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR); - m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage())); + m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, ClassType::offsetOfPropertyStorage())); + } + + // It is acceptable to have structure be equal to scratch, so long as you're fine + // with the structure GPR being clobbered. + template<typename T> + void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath) + { + return emitAllocateBasicJSObject<JSFinalObject, false>(structure, resultGPR, scratchGPR, slowPath); } #if USE(JSVALUE64) @@ -1849,6 +1884,7 @@ private: // The current node being generated. BlockIndex m_block; NodeIndex m_compileIndex; + unsigned m_indexInBlock; // Virtual and physical register maps. Vector<GenerationInfo, 32> m_generationInfo; RegisterBank<GPRInfo> m_gprs; @@ -2482,6 +2518,7 @@ inline SpeculativeJIT::SpeculativeJIT(JITCompiler& jit) : m_compileOkay(true) , m_jit(jit) , m_compileIndex(0) + , m_indexInBlock(0) , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters) , m_blockHeads(jit.graph().m_blocks.size()) , m_arguments(jit.codeBlock()->numParameters()) diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 8c4d8c030..b6814229c 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -652,14 +652,17 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeUse operand, bool invert) { - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); + ASSERT(node.adjustedRefCount() == 1); nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert); use(node.child1()); use(node.child2()); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; @@ -947,7 +950,7 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.storePtr(resultPayloadGPR, callFramePayloadSlot(RegisterFile::ScopeChain)); m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), callFrameTagSlot(RegisterFile::ScopeChain)); - m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); + m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin; CallBeginToken token = m_jit.beginJSCall(); @@ -958,12 +961,12 @@ void SpeculativeJIT::emitCall(Node& node) slowPath.link(&m_jit); - m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); m_jit.poke(GPRInfo::argumentGPR0); token = m_jit.beginCall(); JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction); m_jit.addFastExceptionCheck(slowCall, codeOrigin, token); - m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); + m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); token = m_jit.beginJSCall(); JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR); m_jit.notifyCall(theCall, codeOrigin, token); @@ -1387,10 +1390,10 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf GPRReg resultPayloadGPR = resultPayload.gpr(); MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); - m_jit.move(Imm32(1), resultPayloadGPR); + m_jit.move(TrustedImm32(1), resultPayloadGPR); MacroAssembler::Jump done = m_jit.jump(); falseCase.link(&m_jit); - m_jit.move(Imm32(0), resultPayloadGPR); + m_jit.move(TrustedImm32(0), resultPayloadGPR); done.link(&m_jit); booleanResult(resultPayloadGPR, m_compileIndex); @@ -1414,9 +1417,9 @@ void SpeculativeJIT::compileDoubleCompare(Node& node, MacroAssembler::DoubleCond SpeculateDoubleOperand op2(this, node.child2()); GPRTemporary resultPayload(this); - m_jit.move(Imm32(1), resultPayload.gpr()); + m_jit.move(TrustedImm32(1), resultPayload.gpr()); MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr()); - m_jit.move(Imm32(0), resultPayload.gpr()); + m_jit.move(TrustedImm32(0), resultPayload.gpr()); trueCase.link(&m_jit); booleanResult(resultPayload.gpr(), m_compileIndex); @@ -1637,7 +1640,7 @@ void SpeculativeJIT::emitBranch(Node& node) void SpeculativeJIT::compile(Node& node) { - NodeType op = node.op; + NodeType op = static_cast<NodeType>(node.op); switch (op) { case JSConstant: @@ -1654,54 +1657,59 @@ void SpeculativeJIT::compile(Node& node) AbstractValue& value = block()->valuesAtHead.operand(node.local()); // If we have no prediction for this local, then don't attempt to compile. - if (prediction == PredictNone) { + if (prediction == PredictNone || value.isClear()) { terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); break; } - if (node.variableAccessData()->shouldUseDoubleFormat()) { - FPRTemporary result(this); - m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr()); - VirtualRegister virtualRegister = node.virtualRegister(); - m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble); - m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr()); - break; - } + if (!m_jit.graph().isCaptured(node.local())) { + if (node.variableAccessData()->shouldUseDoubleFormat()) { + FPRTemporary result(this); + m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr()); + VirtualRegister virtualRegister = node.virtualRegister(); + m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble); + m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr()); + break; + } - GPRTemporary result(this); - if (isInt32Prediction(prediction)) { - m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); - - // Like integerResult, but don't useChildren - our children are phi nodes, - // and don't represent values within this dataflow with virtual registers. - VirtualRegister virtualRegister = node.virtualRegister(); - m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger); - m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr()); - break; - } + if (isInt32Prediction(prediction)) { + GPRTemporary result(this); + m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); - if (isArrayPrediction(prediction) || isByteArrayPrediction(prediction)) { - m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); + // Like integerResult, but don't useChildren - our children are phi nodes, + // and don't represent values within this dataflow with virtual registers. + VirtualRegister virtualRegister = node.virtualRegister(); + m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger); + m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr()); + break; + } - // Like cellResult, but don't useChildren - our children are phi nodes, - // and don't represent values within this dataflow with virtual registers. - VirtualRegister virtualRegister = node.virtualRegister(); - m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell); - m_generationInfo[virtualRegister].initCell(m_compileIndex, node.refCount(), result.gpr()); - break; - } + if (isArrayPrediction(prediction) || isByteArrayPrediction(prediction)) { + GPRTemporary result(this); + m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); + + // Like cellResult, but don't useChildren - our children are phi nodes, + // and don't represent values within this dataflow with virtual registers. + VirtualRegister virtualRegister = node.virtualRegister(); + m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell); + m_generationInfo[virtualRegister].initCell(m_compileIndex, node.refCount(), result.gpr()); + break; + } - if (isBooleanPrediction(prediction)) { - m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); + if (isBooleanPrediction(prediction)) { + GPRTemporary result(this); + m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); - // Like booleanResult, but don't useChildren - our children are phi nodes, - // and don't represent values within this dataflow with virtual registers. - VirtualRegister virtualRegister = node.virtualRegister(); - m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean); - m_generationInfo[virtualRegister].initBoolean(m_compileIndex, node.refCount(), result.gpr()); - break; + // Like booleanResult, but don't useChildren - our children are phi nodes, + // and don't represent values within this dataflow with virtual registers. + VirtualRegister virtualRegister = node.virtualRegister(); + m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean); + m_generationInfo[virtualRegister].initBoolean(m_compileIndex, node.refCount(), result.gpr()); + break; + } } + GPRTemporary result(this); GPRTemporary tag(this); m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); m_jit.load32(JITCompiler::tagFor(node.local()), tag.gpr()); @@ -1712,7 +1720,12 @@ void SpeculativeJIT::compile(Node& node) m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS); m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS); - DataFormat format = isCellPrediction(value.m_type) ? DataFormatJSCell : DataFormatJS; + DataFormat format; + if (isCellPrediction(value.m_type) + && !m_jit.graph().isCaptured(node.local())) + format = DataFormatJSCell; + else + format = DataFormatJS; m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), tag.gpr(), result.gpr(), format); break; } @@ -1733,53 +1746,65 @@ void SpeculativeJIT::compile(Node& node) m_codeOriginForOSR = nextNode.codeOrigin; - if (node.variableAccessData()->shouldUseDoubleFormat()) { - SpeculateDoubleOperand value(this, node.child1()); - m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); - noResult(m_compileIndex); - // Indicate that it's no longer necessary to retrieve the value of - // this bytecode variable from registers or other locations in the register file, - // but that it is stored as a double. - valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile); - } else { + if (!m_jit.graph().isCaptured(node.local())) { + if (node.variableAccessData()->shouldUseDoubleFormat()) { + SpeculateDoubleOperand value(this, node.child1()); + m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); + noResult(m_compileIndex); + // Indicate that it's no longer necessary to retrieve the value of + // this bytecode variable from registers or other locations in the register file, + // but that it is stored as a double. + valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile); + break; + } PredictedType predictedType = node.variableAccessData()->prediction(); if (m_generationInfo[at(node.child1()).virtualRegister()].registerFormat() == DataFormatDouble) { DoubleOperand value(this, node.child1()); m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); noResult(m_compileIndex); - } else if (isInt32Prediction(predictedType)) { + valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile); + break; + } + if (isInt32Prediction(predictedType)) { SpeculateIntegerOperand value(this, node.child1()); m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local())); noResult(m_compileIndex); - } else if (isArrayPrediction(predictedType)) { + valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile); + break; + } + if (isArrayPrediction(predictedType)) { SpeculateCellOperand cell(this, node.child1()); GPRReg cellGPR = cell.gpr(); if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local())); noResult(m_compileIndex); - } else if (isByteArrayPrediction(predictedType)) { + valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); + break; + } + if (isByteArrayPrediction(predictedType)) { SpeculateCellOperand cell(this, node.child1()); GPRReg cellGPR = cell.gpr(); if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local())); noResult(m_compileIndex); - } else if (isBooleanPrediction(predictedType)) { + valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); + break; + } + if (isBooleanPrediction(predictedType)) { SpeculateBooleanOperand value(this, node.child1()); m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local())); noResult(m_compileIndex); - } else { - JSValueOperand value(this, node.child1()); - m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node.local())); - m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node.local())); - noResult(m_compileIndex); + valueSourceReferenceForOperand(node.local()) = ValueSource(BooleanInRegisterFile); + break; } - - // Indicate that it's no longer necessary to retrieve the value of - // this bytecode variable from registers or other locations in the register file. - valueSourceReferenceForOperand(node.local()) = ValueSource::forPrediction(predictedType); } + JSValueOperand value(this, node.child1()); + m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node.local())); + m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node.local())); + noResult(m_compileIndex); + valueSourceReferenceForOperand(node.local()) = ValueSource(ValueInRegisterFile); break; } @@ -1863,6 +1888,10 @@ void SpeculativeJIT::compile(Node& node) compileArithSub(node); break; + case ArithNegate: + compileArithNegate(node); + break; + case ArithMul: compileArithMul(node); break; @@ -1951,7 +1980,7 @@ void SpeculativeJIT::compile(Node& node) case ArithAbs: { if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) { SpeculateIntegerOperand op1(this, node.child1()); - GPRTemporary result(this); + GPRTemporary result(this, op1); GPRTemporary scratch(this); m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr()); @@ -2350,7 +2379,7 @@ void SpeculativeJIT::compile(Node& node) // Code to handle put beyond array bounds. silentSpillAllRegisters(scratchReg); - callOperation(operationPutByValBeyondArrayBounds, baseReg, propertyReg, valueTagReg, valuePayloadReg); + callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, baseReg, propertyReg, valueTagReg, valuePayloadReg); silentFillAllRegisters(scratchReg); JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump(); @@ -2514,10 +2543,10 @@ void SpeculativeJIT::compile(Node& node) m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - m_jit.add32(Imm32(1), storageLengthGPR); + m_jit.add32(TrustedImm32(1), storageLengthGPR); m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length))); - m_jit.add32(Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); - m_jit.move(Imm32(JSValue::Int32Tag), storageGPR); + m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); MacroAssembler::Jump done = m_jit.jump(); @@ -2554,7 +2583,7 @@ void SpeculativeJIT::compile(Node& node) MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR); - m_jit.sub32(Imm32(1), storageLengthGPR); + m_jit.sub32(TrustedImm32(1), storageLengthGPR); MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset())); @@ -2563,11 +2592,11 @@ void SpeculativeJIT::compile(Node& node) m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length))); - MacroAssembler::Jump holeCase = m_jit.branch32(MacroAssembler::Equal, Imm32(JSValue::EmptyValueTag), valueTagGPR); + MacroAssembler::Jump holeCase = m_jit.branch32(MacroAssembler::Equal, TrustedImm32(JSValue::EmptyValueTag), valueTagGPR); m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.sub32(MacroAssembler::Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); MacroAssembler::JumpList done; @@ -2575,8 +2604,8 @@ void SpeculativeJIT::compile(Node& node) holeCase.link(&m_jit); emptyArrayCase.link(&m_jit); - m_jit.move(MacroAssembler::Imm32(jsUndefined().tag()), valueTagGPR); - m_jit.move(MacroAssembler::Imm32(jsUndefined().payload()), valuePayloadGPR); + m_jit.move(MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR); + m_jit.move(MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR); done.append(m_jit.jump()); slowCase.link(&m_jit); @@ -3384,7 +3413,7 @@ void SpeculativeJIT::compile(Node& node) case Phi: case Flush: - ASSERT_NOT_REACHED(); + break; case Breakpoint: #if ENABLE(DEBUG_WITH_BREAKPOINT) @@ -3466,6 +3495,77 @@ void SpeculativeJIT::compile(Node& node) break; } + case CreateActivation: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value, false); + + GPRReg valueTagGPR = value.tagGPR(); + GPRReg valuePayloadGPR = value.payloadGPR(); + GPRReg resultGPR = result.gpr(); + + m_jit.move(valuePayloadGPR, resultGPR); + + JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); + + silentSpillAllRegisters(resultGPR); + callOperation(operationCreateActivation, resultGPR); + silentFillAllRegisters(resultGPR); + + alreadyCreated.link(&m_jit); + + cellResult(resultGPR, m_compileIndex); + break; + } + + case TearOffActivation: { + JSValueOperand value(this, node.child1()); + + GPRReg valueTagGPR = value.tagGPR(); + GPRReg valuePayloadGPR = value.payloadGPR(); + + JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); + + silentSpillAllRegisters(InvalidGPRReg); + callOperation(operationTearOffActivation, valuePayloadGPR); + silentFillAllRegisters(InvalidGPRReg); + + notCreated.link(&m_jit); + + noResult(m_compileIndex); + break; + } + + case NewFunctionNoCheck: + compileNewFunctionNoCheck(node); + break; + + case NewFunction: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value, false); + + GPRReg valueTagGPR = value.tagGPR(); + GPRReg valuePayloadGPR = value.payloadGPR(); + GPRReg resultGPR = result.gpr(); + + m_jit.move(valuePayloadGPR, resultGPR); + + JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); + + silentSpillAllRegisters(resultGPR); + callOperation( + operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex())); + silentFillAllRegisters(resultGPR); + + alreadyCreated.link(&m_jit); + + cellResult(resultGPR, m_compileIndex); + break; + } + + case NewFunctionExpression: + compileNewFunctionExpression(node); + break; + case ForceOSRExit: { terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); break; @@ -3478,10 +3578,11 @@ void SpeculativeJIT::compile(Node& node) case InlineStart: case Nop: + case LastNodeType: ASSERT_NOT_REACHED(); break; } - + if (!m_compileOkay) return; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 6d375f81f..1597b1674 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -57,7 +57,7 @@ GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat } else { ASSERT(isJSConstant(nodeIndex)); JSValue jsValue = valueOfJSConstant(nodeIndex); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); + m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr); } } else if (info.spillFormat() == DataFormatInteger) { m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); @@ -141,7 +141,7 @@ FPRReg SpeculativeJIT::fillDouble(NodeIndex nodeIndex) // FIXME: should not be reachable? ASSERT(isJSConstant(nodeIndex)); JSValue jsValue = valueOfJSConstant(nodeIndex); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); + m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr); m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); info.fillJSValue(gpr, DataFormatJS); unlock(gpr); @@ -283,7 +283,7 @@ GPRReg SpeculativeJIT::fillJSValue(NodeIndex nodeIndex) } else { ASSERT(isJSConstant(nodeIndex)); JSValue jsValue = valueOfJSConstant(nodeIndex); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); + m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr); info.fillJSValue(gpr, DataFormatJS); } @@ -628,14 +628,17 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeUse operand, bool invert) { - NodeIndex branchNodeIndex = detectPeepHoleBranch(); - if (branchNodeIndex != NoNode) { + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock != UINT_MAX) { + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); + ASSERT(node.adjustedRefCount() == 1); nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert); use(node.child1()); use(node.child2()); + m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; @@ -808,15 +811,21 @@ void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branch JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister); - JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister); + JITCompiler::Jump leftOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister); + JITCompiler::Jump leftDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister); + leftOK.link(&m_jit); + JITCompiler::Jump rightOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister); + JITCompiler::Jump rightDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister); + rightOK.link(&m_jit); - branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken); + branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken); jump(notTaken, ForceJump); twoCellsCase.link(&m_jit); branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken); - numberCase.link(&m_jit); + leftDouble.link(&m_jit); + rightDouble.link(&m_jit); silentSpillAllRegisters(resultGPR); callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR); @@ -865,9 +874,14 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert) JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister); - JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister); + JITCompiler::Jump leftOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister); + JITCompiler::Jump leftDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister); + leftOK.link(&m_jit); + JITCompiler::Jump rightOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister); + JITCompiler::Jump rightDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister); + rightOK.link(&m_jit); - m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR); + m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR); JITCompiler::Jump done1 = m_jit.jump(); @@ -878,7 +892,8 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert) JITCompiler::Jump done2 = m_jit.jump(); - numberCase.link(&m_jit); + leftDouble.link(&m_jit); + rightDouble.link(&m_jit); notEqualCase.link(&m_jit); silentSpillAllRegisters(resultGPR); @@ -948,7 +963,7 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR); m_jit.storePtr(resultGPR, callFrameSlot(RegisterFile::ScopeChain)); - m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); + m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin; CallBeginToken token = m_jit.beginJSCall(); @@ -959,11 +974,11 @@ void SpeculativeJIT::emitCall(Node& node) slowPath.link(&m_jit); - m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); token = m_jit.beginCall(); JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction); m_jit.addFastExceptionCheck(slowCall, codeOrigin, token); - m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); + m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); token = m_jit.beginJSCall(); JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR); m_jit.notifyCall(theCall, codeOrigin, token); @@ -1461,10 +1476,10 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); - m_jit.move(Imm32(ValueTrue), resultGPR); + m_jit.move(TrustedImm32(ValueTrue), resultGPR); MacroAssembler::Jump done = m_jit.jump(); falseCase.link(&m_jit); - m_jit.move(Imm32(ValueFalse), resultGPR); + m_jit.move(TrustedImm32(ValueFalse), resultGPR); done.link(&m_jit); jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); @@ -1491,7 +1506,7 @@ void SpeculativeJIT::compileDoubleCompare(Node& node, MacroAssembler::DoubleCond m_jit.move(TrustedImm32(ValueTrue), result.gpr()); MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr()); - m_jit.xorPtr(Imm32(true), result.gpr()); + m_jit.xorPtr(TrustedImm32(true), result.gpr()); trueCase.link(&m_jit); jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); @@ -1577,7 +1592,7 @@ void SpeculativeJIT::compileLogicalNot(Node& node) GPRTemporary result(this); m_jit.move(TrustedImm32(ValueFalse), result.gpr()); MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr()); - m_jit.xor32(Imm32(true), result.gpr()); + m_jit.xor32(TrustedImm32(true), result.gpr()); nonZero.link(&m_jit); jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); return; @@ -1699,18 +1714,18 @@ void SpeculativeJIT::emitBranch(Node& node) bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1())); if (predictBoolean) { - branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false))), notTaken); - branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true))), taken); + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), notTaken); + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), taken); speculationCheck(BadType, JSValueRegs(valueGPR), node.child1(), m_jit.jump()); value.use(); } else { - branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0))), notTaken); + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(0))), notTaken); branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken); if (!predictBoolean) { - branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false))), notTaken); - branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true))), taken); + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), notTaken); + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), taken); } value.use(); @@ -1729,7 +1744,7 @@ void SpeculativeJIT::emitBranch(Node& node) void SpeculativeJIT::compile(Node& node) { - NodeType op = node.op; + NodeType op = static_cast<NodeType>(node.op); switch (op) { case JSConstant: @@ -1751,27 +1766,30 @@ void SpeculativeJIT::compile(Node& node) break; } - if (node.variableAccessData()->shouldUseDoubleFormat()) { - FPRTemporary result(this); - m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr()); - VirtualRegister virtualRegister = node.virtualRegister(); - m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble); - m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr()); - break; - } - - GPRTemporary result(this); - if (isInt32Prediction(value.m_type)) { - m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); - - // Like integerResult, but don't useChildren - our children are phi nodes, - // and don't represent values within this dataflow with virtual registers. - VirtualRegister virtualRegister = node.virtualRegister(); - m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger); - m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr()); - break; + if (!m_jit.graph().isCaptured(node.local())) { + if (node.variableAccessData()->shouldUseDoubleFormat()) { + FPRTemporary result(this); + m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr()); + VirtualRegister virtualRegister = node.virtualRegister(); + m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble); + m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr()); + break; + } + + if (isInt32Prediction(value.m_type)) { + GPRTemporary result(this); + m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); + + // Like integerResult, but don't useChildren - our children are phi nodes, + // and don't represent values within this dataflow with virtual registers. + VirtualRegister virtualRegister = node.virtualRegister(); + m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger); + m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr()); + break; + } } + GPRTemporary result(this); m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr()); // Like jsValueResult, but don't useChildren - our children are phi nodes, @@ -1780,7 +1798,9 @@ void SpeculativeJIT::compile(Node& node) m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS); DataFormat format; - if (isCellPrediction(value.m_type)) + if (m_jit.graph().isCaptured(node.local())) + format = DataFormatJS; + else if (isCellPrediction(value.m_type)) format = DataFormatJSCell; else if (isBooleanPrediction(value.m_type)) format = DataFormatJSBoolean; @@ -1817,48 +1837,60 @@ void SpeculativeJIT::compile(Node& node) // OSR exit, would not be visible to the old JIT in any way. m_codeOriginForOSR = nextNode.codeOrigin; - if (node.variableAccessData()->shouldUseDoubleFormat()) { - SpeculateDoubleOperand value(this, node.child1()); - m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); - noResult(m_compileIndex); - // Indicate that it's no longer necessary to retrieve the value of - // this bytecode variable from registers or other locations in the register file, - // but that it is stored as a double. - valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile); - } else { + if (!m_jit.graph().isCaptured(node.local())) { + if (node.variableAccessData()->shouldUseDoubleFormat()) { + SpeculateDoubleOperand value(this, node.child1()); + m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); + noResult(m_compileIndex); + // Indicate that it's no longer necessary to retrieve the value of + // this bytecode variable from registers or other locations in the register file, + // but that it is stored as a double. + valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile); + break; + } + PredictedType predictedType = node.variableAccessData()->prediction(); if (isInt32Prediction(predictedType)) { SpeculateIntegerOperand value(this, node.child1()); m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local())); noResult(m_compileIndex); - } else if (isArrayPrediction(predictedType)) { + valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile); + break; + } + if (isArrayPrediction(predictedType)) { SpeculateCellOperand cell(this, node.child1()); GPRReg cellGPR = cell.gpr(); if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local())); noResult(m_compileIndex); - } else if (isByteArrayPrediction(predictedType)) { + valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); + break; + } + if (isByteArrayPrediction(predictedType)) { SpeculateCellOperand cell(this, node.child1()); GPRReg cellGPR = cell.gpr(); if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local())); noResult(m_compileIndex); - } else if (isBooleanPrediction(predictedType)) { + valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); + break; + } + if (isBooleanPrediction(predictedType)) { SpeculateBooleanOperand boolean(this, node.child1()); m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local())); noResult(m_compileIndex); - } else { - JSValueOperand value(this, node.child1()); - m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local())); - noResult(m_compileIndex); + valueSourceReferenceForOperand(node.local()) = ValueSource(BooleanInRegisterFile); + break; } - - // Indicate that it's no longer necessary to retrieve the value of - // this bytecode variable from registers or other locations in the register file. - valueSourceReferenceForOperand(node.local()) = ValueSource::forPrediction(predictedType); } + + JSValueOperand value(this, node.child1()); + m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local())); + noResult(m_compileIndex); + + valueSourceReferenceForOperand(node.local()) = ValueSource(ValueInRegisterFile); break; } @@ -1942,6 +1974,10 @@ void SpeculativeJIT::compile(Node& node) compileArithSub(node); break; + case ArithNegate: + compileArithNegate(node); + break; + case ArithMul: compileArithMul(node); break; @@ -2007,7 +2043,7 @@ void SpeculativeJIT::compile(Node& node) case ArithAbs: { if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) { SpeculateIntegerOperand op1(this, node.child1()); - GPRTemporary result(this, op1); + GPRTemporary result(this); GPRTemporary scratch(this); m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr()); @@ -2389,7 +2425,7 @@ void SpeculativeJIT::compile(Node& node) // Code to handle put beyond array bounds. silentSpillAllRegisters(scratchReg); - callOperation(operationPutByValBeyondArrayBounds, baseReg, propertyReg, valueReg); + callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, baseReg, propertyReg, valueReg); silentFillAllRegisters(scratchReg); JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump(); @@ -2549,9 +2585,9 @@ void SpeculativeJIT::compile(Node& node) m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); - m_jit.add32(Imm32(1), storageLengthGPR); + m_jit.add32(TrustedImm32(1), storageLengthGPR); m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length))); - m_jit.add32(Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR); MacroAssembler::Jump done = m_jit.jump(); @@ -2587,7 +2623,7 @@ void SpeculativeJIT::compile(Node& node) MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR); - m_jit.sub32(Imm32(1), storageLengthGPR); + m_jit.sub32(TrustedImm32(1), storageLengthGPR); MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset())); @@ -2598,7 +2634,7 @@ void SpeculativeJIT::compile(Node& node) MacroAssembler::Jump holeCase = m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR); m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); - m_jit.sub32(MacroAssembler::Imm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); MacroAssembler::JumpList done; @@ -3358,9 +3394,9 @@ void SpeculativeJIT::compile(Node& node) break; } - case Phi: case Flush: - ASSERT_NOT_REACHED(); + case Phi: + break; case Breakpoint: #if ENABLE(DEBUG_WITH_BREAKPOINT) @@ -3434,6 +3470,73 @@ void SpeculativeJIT::compile(Node& node) jsValueResult(resultGPR, m_compileIndex); break; } + + case CreateActivation: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + GPRReg valueGPR = value.gpr(); + GPRReg resultGPR = result.gpr(); + + m_jit.move(valueGPR, resultGPR); + + JITCompiler::Jump alreadyCreated = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR); + + silentSpillAllRegisters(resultGPR); + callOperation(operationCreateActivation, resultGPR); + silentFillAllRegisters(resultGPR); + + alreadyCreated.link(&m_jit); + + cellResult(resultGPR, m_compileIndex); + break; + } + + case TearOffActivation: { + JSValueOperand value(this, node.child1()); + GPRReg valueGPR = value.gpr(); + + JITCompiler::Jump notCreated = m_jit.branchTestPtr(JITCompiler::Zero, valueGPR); + + silentSpillAllRegisters(InvalidGPRReg); + callOperation(operationTearOffActivation, valueGPR); + silentFillAllRegisters(InvalidGPRReg); + + notCreated.link(&m_jit); + + noResult(m_compileIndex); + break; + } + + case NewFunctionNoCheck: + compileNewFunctionNoCheck(node); + break; + + case NewFunction: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + GPRReg valueGPR = value.gpr(); + GPRReg resultGPR = result.gpr(); + + m_jit.move(valueGPR, resultGPR); + + JITCompiler::Jump alreadyCreated = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR); + + silentSpillAllRegisters(resultGPR); + callOperation( + operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex())); + silentFillAllRegisters(resultGPR); + + alreadyCreated.link(&m_jit); + + cellResult(resultGPR, m_compileIndex); + break; + } + + case NewFunctionExpression: + compileNewFunctionExpression(node); + break; case ForceOSRExit: { terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); @@ -3449,6 +3552,10 @@ void SpeculativeJIT::compile(Node& node) case Nop: ASSERT_NOT_REACHED(); break; + + case LastNodeType: + ASSERT_NOT_REACHED(); + break; } if (!m_compileOkay) diff --git a/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp b/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp index c0b9fae65..255003612 100644 --- a/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp @@ -48,39 +48,62 @@ public: dataLog("\n"); #endif ScoreBoard scoreBoard(m_graph, m_graph.m_preservedVars); - unsigned sizeExcludingPhiNodes = m_graph.m_blocks.last()->end; - for (size_t i = 0; i < sizeExcludingPhiNodes; ++i) { - Node& node = m_graph[i]; - - if (!node.shouldGenerate()) - continue; + scoreBoard.assertClear(); +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + bool needsNewLine = false; +#endif + for (size_t blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { + BasicBlock* block = m_graph.m_blocks[blockIndex].get(); + for (size_t indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { + NodeIndex nodeIndex = block->at(indexInBlock); +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + if (needsNewLine) + dataLog("\n"); + dataLog(" @%u:", nodeIndex); + needsNewLine = true; +#endif + Node& node = m_graph[nodeIndex]; - // GetLocal nodes are effectively phi nodes in the graph, referencing - // results from prior blocks. - if (node.op != GetLocal) { - // First, call use on all of the current node's children, then - // allocate a VirtualRegister for this node. We do so in this - // order so that if a child is on its last use, and a - // VirtualRegister is freed, then it may be reused for node. - if (node.op & NodeHasVarArgs) { - for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) - scoreBoard.use(m_graph.m_varArgChildren[childIdx]); - } else { - scoreBoard.use(node.child1()); - scoreBoard.use(node.child2()); - scoreBoard.use(node.child3()); + if (!node.shouldGenerate() || node.op == Phi || node.op == Flush) + continue; + + // GetLocal nodes are effectively phi nodes in the graph, referencing + // results from prior blocks. + if (node.op != GetLocal) { + // First, call use on all of the current node's children, then + // allocate a VirtualRegister for this node. We do so in this + // order so that if a child is on its last use, and a + // VirtualRegister is freed, then it may be reused for node. + if (node.flags & NodeHasVarArgs) { + for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) + scoreBoard.use(m_graph.m_varArgChildren[childIdx]); + } else { + scoreBoard.use(node.child1()); + scoreBoard.use(node.child2()); + scoreBoard.use(node.child3()); + } } - } - if (!node.hasResult()) - continue; + if (!node.hasResult()) + continue; - node.setVirtualRegister(scoreBoard.allocate()); - // 'mustGenerate' nodes have their useCount artificially elevated, - // call use now to account for this. - if (node.mustGenerate()) - scoreBoard.use(i); + VirtualRegister virtualRegister = scoreBoard.allocate(); +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + dataLog(" Assigning virtual register %u to node %u.", + virtualRegister, nodeIndex); +#endif + node.setVirtualRegister(virtualRegister); + // 'mustGenerate' nodes have their useCount artificially elevated, + // call use now to account for this. + if (node.mustGenerate()) + scoreBoard.use(nodeIndex); + } + scoreBoard.assertClear(); } +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + if (needsNewLine) + dataLog("\n"); +#endif // 'm_numCalleeRegisters' is the number of locals and temporaries allocated // for the function (and checked for on entry). Since we perform a new and diff --git a/Source/JavaScriptCore/heap/CopiedAllocator.h b/Source/JavaScriptCore/heap/CopiedAllocator.h index c5ba50d78..dc3c5dfed 100644 --- a/Source/JavaScriptCore/heap/CopiedAllocator.h +++ b/Source/JavaScriptCore/heap/CopiedAllocator.h @@ -31,6 +31,7 @@ namespace JSC { class CopiedAllocator { + friend class JIT; public: CopiedAllocator(); void* allocate(size_t); @@ -93,7 +94,7 @@ inline void CopiedAllocator::resetCurrentBlock(CopiedBlock* newBlock) inline size_t CopiedAllocator::currentUtilization() { - return static_cast<size_t>(m_currentOffset - m_currentBlock->m_payload); + return static_cast<size_t>(m_currentOffset - m_currentBlock->payload()); } inline void CopiedAllocator::resetLastAllocation(void* ptr) diff --git a/Source/JavaScriptCore/heap/CopiedBlock.h b/Source/JavaScriptCore/heap/CopiedBlock.h index a57c1150c..387b2ddab 100644 --- a/Source/JavaScriptCore/heap/CopiedBlock.h +++ b/Source/JavaScriptCore/heap/CopiedBlock.h @@ -40,26 +40,29 @@ class CopiedBlock : public HeapBlock { public: CopiedBlock(PageAllocationAligned& allocation) : HeapBlock(allocation) - , m_offset(m_payload) + , m_offset(payload()) , m_isPinned(false) { - ASSERT(is8ByteAligned(static_cast<void*>(m_payload))); + ASSERT(is8ByteAligned(static_cast<void*>(m_offset))); #if USE(JSVALUE64) - memset(static_cast<void*>(m_payload), 0, static_cast<size_t>((reinterpret_cast<char*>(this) + allocation.size()) - m_payload)); + char* offset = static_cast<char*>(m_offset); + memset(static_cast<void*>(offset), 0, static_cast<size_t>((reinterpret_cast<char*>(this) + allocation.size()) - offset)); #else JSValue emptyValue; - JSValue* limit = reinterpret_cast<JSValue*>(reinterpret_cast<char*>(this) + allocation.size()); - for (JSValue* currentValue = reinterpret_cast<JSValue*>(m_payload); currentValue < limit; currentValue++) + JSValue* limit = reinterpret_cast_ptr<JSValue*>(reinterpret_cast<char*>(this) + allocation.size()); + for (JSValue* currentValue = reinterpret_cast<JSValue*>(m_offset); currentValue < limit; currentValue++) *currentValue = emptyValue; #endif } + char* payload() + { + return reinterpret_cast<char*>(this) + ((sizeof(CopiedBlock) + 7) & ~7); + } + private: void* m_offset; uintptr_t m_isPinned; - uintptr_t m_padding; - uintptr_t m_dummy; - char m_payload[1]; }; } // namespace JSC diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp index 3310d2c58..c8470120f 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.cpp +++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp @@ -153,7 +153,7 @@ void CopiedSpace::doneFillingBlock(CopiedBlock* block) ASSERT(block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); ASSERT(m_inCopyingPhase); - if (block->m_offset == block->m_payload) { + if (block->m_offset == block->payload()) { recycleBlock(block); return; } @@ -167,7 +167,7 @@ void CopiedSpace::doneFillingBlock(CopiedBlock* block) { MutexLocker locker(m_memoryStatsLock); - m_totalMemoryUtilized += static_cast<size_t>(static_cast<char*>(block->m_offset) - block->m_payload); + m_totalMemoryUtilized += static_cast<size_t>(static_cast<char*>(block->m_offset) - block->payload()); } { diff --git a/Source/JavaScriptCore/heap/CopiedSpace.h b/Source/JavaScriptCore/heap/CopiedSpace.h index 285e2b9a2..e8fa80055 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.h +++ b/Source/JavaScriptCore/heap/CopiedSpace.h @@ -46,6 +46,7 @@ class HeapBlock; class CopiedSpace { friend class SlotVisitor; + friend class JIT; public: CopiedSpace(Heap*); void init(); @@ -53,6 +54,8 @@ public: CheckedBoolean tryAllocate(size_t, void**); CheckedBoolean tryReallocate(void**, size_t, size_t); + CopiedAllocator& allocator() { return m_allocator; } + void startedCopying(); void doneCopying(); bool isInCopyPhase() { return m_inCopyingPhase; } diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h index 9a1f63cec..0b1b38d32 100644 --- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h +++ b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h @@ -92,7 +92,7 @@ inline CheckedBoolean CopiedSpace::borrowBlock(CopiedBlock** outBlock) MutexLocker locker(m_loanedBlocksLock); m_numberOfLoanedBlocks++; - ASSERT(block->m_offset == block->m_payload); + ASSERT(block->m_offset == block->payload()); *outBlock = block; return true; } @@ -151,9 +151,9 @@ inline void* CopiedSpace::allocateFromBlock(CopiedBlock* block, size_t bytes) ASSERT(is8ByteAligned(block->m_offset)); void* ptr = block->m_offset; - ASSERT(block->m_offset >= block->m_payload && block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); + ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); block->m_offset = static_cast<void*>((static_cast<char*>(ptr) + bytes)); - ASSERT(block->m_offset >= block->m_payload && block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); + ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); ASSERT(is8ByteAligned(ptr)); return ptr; diff --git a/Source/JavaScriptCore/heap/DFGCodeBlocks.cpp b/Source/JavaScriptCore/heap/DFGCodeBlocks.cpp index 03c8df2ff..f0d7c0c89 100644 --- a/Source/JavaScriptCore/heap/DFGCodeBlocks.cpp +++ b/Source/JavaScriptCore/heap/DFGCodeBlocks.cpp @@ -67,8 +67,10 @@ void DFGCodeBlocks::jettison(PassOwnPtr<CodeBlock> codeBlockPtr) void DFGCodeBlocks::clearMarks() { - for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) + for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) { (*iter)->m_dfgData->mayBeExecuting = false; + (*iter)->m_dfgData->visitAggregateHasBeenCalled = false; + } } void DFGCodeBlocks::deleteUnmarkedJettisonedCodeBlocks() diff --git a/Source/JavaScriptCore/heap/GCAssertions.h b/Source/JavaScriptCore/heap/GCAssertions.h index f044df6f0..9feefe1d1 100644 --- a/Source/JavaScriptCore/heap/GCAssertions.h +++ b/Source/JavaScriptCore/heap/GCAssertions.h @@ -26,7 +26,7 @@ #ifndef GCAssertions_h #define GCAssertions_h -#include "Assertions.h" +#include <wtf/Assertions.h> #if ENABLE(GC_VALIDATION) #define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { \ diff --git a/Source/JavaScriptCore/heap/HandleHeap.h b/Source/JavaScriptCore/heap/HandleHeap.h index 3b9db37a2..c9ee11b2f 100644 --- a/Source/JavaScriptCore/heap/HandleHeap.h +++ b/Source/JavaScriptCore/heap/HandleHeap.h @@ -26,11 +26,11 @@ #ifndef HandleHeap_h #define HandleHeap_h -#include "BlockStack.h" +#include <wtf/BlockStack.h> #include "Handle.h" -#include "HashCountedSet.h" -#include "SentinelLinkedList.h" -#include "SinglyLinkedList.h" +#include <wtf/HashCountedSet.h> +#include <wtf/SentinelLinkedList.h> +#include <wtf/SinglyLinkedList.h> namespace JSC { diff --git a/Source/JavaScriptCore/heap/HandleStack.h b/Source/JavaScriptCore/heap/HandleStack.h index a1e8a0b2a..858ebf23f 100644 --- a/Source/JavaScriptCore/heap/HandleStack.h +++ b/Source/JavaScriptCore/heap/HandleStack.h @@ -26,8 +26,8 @@ #ifndef HandleStack_h #define HandleStack_h -#include "Assertions.h" -#include "BlockStack.h" +#include <wtf/Assertions.h> +#include <wtf/BlockStack.h> #include "Handle.h" #include <wtf/UnusedParam.h> diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp index 1333c7b2c..a5d4a063f 100644 --- a/Source/JavaScriptCore/heap/Heap.cpp +++ b/Source/JavaScriptCore/heap/Heap.cpp @@ -328,6 +328,7 @@ Heap::Heap(JSGlobalData* globalData, HeapSize heapSize) , m_handleHeap(globalData) , m_isSafeToCollect(false) , m_globalData(globalData) + , m_lastGCLength(0) { (*m_activityCallback)(); m_numberOfFreeBlocks = 0; @@ -781,6 +782,7 @@ void Heap::collect(SweepToggle sweepToggle) ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); + double lastGCStartTime = WTF::currentTime(); #if ENABLE(GGC) bool fullGC = sweepToggle == DoSweep; if (!fullGC) @@ -835,6 +837,8 @@ void Heap::collect(SweepToggle sweepToggle) m_lastFullGCSize = newSize; setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle)); } + double lastGCEndTime = WTF::currentTime(); + m_lastGCLength = lastGCEndTime - lastGCStartTime; JAVASCRIPTCORE_GC_END(); (*m_activityCallback)(); diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index bcacee6d5..09a95882b 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -99,6 +99,7 @@ namespace JSC { MarkedAllocator& firstAllocatorWithoutDestructors() { return m_objectSpace.firstAllocator(); } MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); } MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); } + CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); } CheckedBoolean tryAllocateStorage(size_t, void**); CheckedBoolean tryReallocateStorage(void**, size_t, size_t); @@ -137,6 +138,8 @@ namespace JSC { void getConservativeRegisterRoots(HashSet<JSCell*>& roots); + double lastGCLength() { return m_lastGCLength; } + private: friend class CodeBlock; friend class LLIntOffsetsExtractor; @@ -235,6 +238,7 @@ namespace JSC { bool m_isSafeToCollect; JSGlobalData* m_globalData; + double m_lastGCLength; }; bool Heap::isBusy() diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h index 5f70b69d4..3d0182eb8 100644 --- a/Source/JavaScriptCore/heap/MarkedBlock.h +++ b/Source/JavaScriptCore/heap/MarkedBlock.h @@ -321,6 +321,8 @@ namespace JSC { return false; if ((atomNumber - firstAtom) % m_atomsPerCell) // Filters pointers into cell middles. return false; + if (atomNumber >= m_endAtom) // Filters pointers into invalid cells out of the range. + return false; return isLive(static_cast<const JSCell*>(p)); } diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h index cfcf3f8dc..b553eb1b1 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.h +++ b/Source/JavaScriptCore/heap/MarkedSpace.h @@ -26,7 +26,7 @@ #include "MarkedAllocator.h" #include "MarkedBlock.h" #include "MarkedBlockSet.h" -#include "PageAllocationAligned.h" +#include <wtf/PageAllocationAligned.h> #include <wtf/Bitmap.h> #include <wtf/DoublyLinkedList.h> #include <wtf/FixedArray.h> diff --git a/Source/JavaScriptCore/heap/PassWeak.h b/Source/JavaScriptCore/heap/PassWeak.h index b7aa7b10d..0d86e6c65 100644 --- a/Source/JavaScriptCore/heap/PassWeak.h +++ b/Source/JavaScriptCore/heap/PassWeak.h @@ -26,10 +26,10 @@ #ifndef PassWeak_h #define PassWeak_h -#include "Assertions.h" +#include <wtf/Assertions.h> #include "Handle.h" -#include "NullPtr.h" -#include "TypeTraits.h" +#include <wtf/NullPtr.h> +#include <wtf/TypeTraits.h> namespace JSC { diff --git a/Source/JavaScriptCore/heap/Strong.h b/Source/JavaScriptCore/heap/Strong.h index a9389fa53..d2f2a2278 100644 --- a/Source/JavaScriptCore/heap/Strong.h +++ b/Source/JavaScriptCore/heap/Strong.h @@ -26,7 +26,7 @@ #ifndef Strong_h #define Strong_h -#include "Assertions.h" +#include <wtf/Assertions.h> #include "Handle.h" #include "HandleHeap.h" diff --git a/Source/JavaScriptCore/heap/Weak.h b/Source/JavaScriptCore/heap/Weak.h index 96fe1b58c..8291e4440 100644 --- a/Source/JavaScriptCore/heap/Weak.h +++ b/Source/JavaScriptCore/heap/Weak.h @@ -26,7 +26,7 @@ #ifndef Weak_h #define Weak_h -#include "Assertions.h" +#include <wtf/Assertions.h> #include "Handle.h" #include "HandleHeap.h" #include "JSGlobalData.h" diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 336f109c0..a74d3de89 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -44,6 +44,7 @@ #include "GetterSetter.h" #include "JSActivation.h" #include "JSArray.h" +#include "JSBoundFunction.h" #include "JSByteArray.h" #include "JSNotAnObject.h" #include "JSPropertyNameIterator.h" @@ -559,31 +560,27 @@ void Interpreter::initialize(LLInt::Data* llintData, bool canUseJIT) { UNUSED_PARAM(llintData); UNUSED_PARAM(canUseJIT); -#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT) -#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - // Having LLInt enabled, but not being able to use the JIT, and not having - // a computed goto interpreter, is not supported. Not because we cannot - // support it, but because I decided to draw the line at the number of - // permutations of execution engines that I wanted this code to grok. - ASSERT(canUseJIT); + + // If we have LLInt, then we shouldn't be building any kind of classic interpreter. +#if ENABLE(LLINT) && ENABLE(CLASSIC_INTERPRETER) +#error "Building both LLInt and the Classic Interpreter is not supported because it doesn't make sense." #endif - if (canUseJIT) { + #if ENABLE(LLINT) - m_opcodeTable = llintData->opcodeMap(); - for (int i = 0; i < numOpcodeIDs; ++i) - m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i)); -#else + m_opcodeTable = llintData->opcodeMap(); + for (int i = 0; i < numOpcodeIDs; ++i) + m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i)); + m_classicEnabled = false; +#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) + if (canUseJIT) { // If the JIT is present, don't use jump destinations for opcodes. for (int i = 0; i < numOpcodeIDs; ++i) { Opcode opcode = bitwise_cast<void*>(static_cast<uintptr_t>(i)); m_opcodeTable[i] = opcode; } -#endif + m_classicEnabled = false; } else { -#if ENABLE(LLINT) - m_opcodeTable = new Opcode[numOpcodeIDs]; -#endif privateExecute(InitializeAndReturn, 0, 0); for (int i = 0; i < numOpcodeIDs; ++i) @@ -817,13 +814,14 @@ static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message)); } -static int getLineNumberForCallFrame(CallFrame* callFrame) +static int getLineNumberForCallFrame(JSGlobalData* globalData, CallFrame* callFrame) { + UNUSED_PARAM(globalData); callFrame = callFrame->removeHostCallFrameFlag(); CodeBlock* codeBlock = callFrame->codeBlock(); if (!codeBlock) return -1; -#if ENABLE(INTERPRETER) +#if ENABLE(CLASSIC_INTERPRETER) if (!globalData->canUseJIT()) return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode() - 1); #endif @@ -833,6 +831,8 @@ static int getLineNumberForCallFrame(CallFrame* callFrame) return codeBlock->lineNumberForBytecodeOffset(codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex); #endif return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode()); +#else + return -1; #endif } @@ -842,19 +842,28 @@ static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, unsigned bytecodeOffset = 0; lineNumber = -1; ASSERT(!callFrame->hasHostCallFrameFlag()); - CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : 0; + CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag(); bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame(); ASSERT(!callerFrame->hasHostCallFrameFlag()); if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock()) return callerFrame; - + CodeBlock* callerCodeBlock = callerFrame->codeBlock(); + +#if ENABLE(JIT) + if (!callFrame->hasReturnPC()) + callframeIsHost = true; +#endif +#if ENABLE(DFG_JIT) + if (callFrame->isInlineCallFrame()) + callframeIsHost = false; +#endif if (callframeIsHost) { // Don't need to deal with inline callframes here as by definition we haven't // inlined a call with an intervening native call frame. -#if ENABLE(INTERPRETER) +#if ENABLE(CLASSIC_INTERPRETER) if (!globalData->canUseJIT()) { bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode(); lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1); @@ -863,14 +872,15 @@ static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, #endif #if ENABLE(JIT) #if ENABLE(DFG_JIT) - if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) - bytecodeOffset = callerCodeBlock->codeOrigin(callerFrame->codeOriginIndexForDFG()).bytecodeIndex; - else + if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) { + unsigned codeOriginIndex = callerFrame->codeOriginIndexForDFG(); + bytecodeOffset = callerCodeBlock->codeOrigin(codeOriginIndex).bytecodeIndex; + } else #endif bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode(); #endif } else { -#if ENABLE(INTERPRETER) +#if ENABLE(CLASSIC_INTERPRETER) if (!globalData->canUseJIT()) { bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC()); lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1); @@ -914,7 +924,7 @@ static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, static ALWAYS_INLINE const UString getSourceURLFromCallFrame(CallFrame* callFrame) { ASSERT(!callFrame->hasHostCallFrameFlag()); -#if ENABLE(INTERPRETER) +#if ENABLE(CLASSIC_INTERPRETER) #if ENABLE(JIT) if (callFrame->globalData().canUseJIT()) return callFrame->codeBlock()->ownerExecutable()->sourceURL(); @@ -949,8 +959,8 @@ void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<Stack return; if (line == -1) - line = getLineNumberForCallFrame(callFrame); - + line = getLineNumberForCallFrame(globalData, callFrame); + while (callFrame && callFrame != CallFrame::noCaller()) { UString sourceURL; if (callFrame->codeBlock()) { @@ -1144,7 +1154,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S break; } case JSONPPathEntryTypeLookup: { - baseObject.put(callFrame, JSONPPath.last().m_pathIndex, JSONPValue); + baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode()); if (callFrame->hadException()) return jsUndefined(); break; @@ -1184,7 +1194,7 @@ failedJSONP: m_reentryDepth++; #if ENABLE(JIT) - if (callFrame->globalData().canUseJIT()) + if (!classicEnabled()) result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData); else #endif @@ -1256,7 +1266,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT m_reentryDepth++; #if ENABLE(JIT) - if (callFrame->globalData().canUseJIT()) + if (!classicEnabled()) result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData); else #endif @@ -1352,7 +1362,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc m_reentryDepth++; #if ENABLE(JIT) - if (callFrame->globalData().canUseJIT()) + if (!classicEnabled()) result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData); else #endif @@ -2567,24 +2577,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += OPCODE_LENGTH(op_bitor); NEXT_INSTRUCTION(); } - DEFINE_OPCODE(op_bitnot) { - /* bitnot dst(r) src(r) - - Computes bitwise NOT of register src1 (converted to int32), - and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); - if (src.isInt32()) - callFrame->uncheckedR(dst) = jsNumber(~src.asInt32()); - else { - JSValue result = jsNumber(~src.toInt32(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - vPC += OPCODE_LENGTH(op_bitnot); - NEXT_INSTRUCTION(); - } DEFINE_OPCODE(op_not) { /* not dst(r) src(r) @@ -3785,7 +3777,7 @@ skip_id_custom_self: if (jsArray->canSetIndex(i)) jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue()); else - jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue()); + jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode()); } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { JSByteArray* jsByteArray = asByteArray(baseValue); JSValue jsValue = callFrame->r(value).jsValue(); @@ -3794,9 +3786,9 @@ skip_id_custom_self: else if (jsValue.isDouble()) jsByteArray->setIndex(i, jsValue.asDouble()); else - baseValue.put(callFrame, i, jsValue); + baseValue.putByIndex(callFrame, i, jsValue, codeBlock->isStrictMode()); } else - baseValue.put(callFrame, i, callFrame->r(value).jsValue()); + baseValue.putByIndex(callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode()); } else { Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); if (!globalData->exception) { // Don't put to an object if toString threw an exception. @@ -3859,7 +3851,9 @@ skip_id_custom_self: unsigned property = vPC[2].u.operand; int value = vPC[3].u.operand; - callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue()); + JSValue arrayValue = callFrame->r(base).jsValue(); + ASSERT(isJSArray(arrayValue)); + asArray(arrayValue)->putDirectIndex(callFrame, property, callFrame->r(value).jsValue(), false); vPC += OPCODE_LENGTH(op_put_by_index); NEXT_INSTRUCTION(); @@ -5316,18 +5310,29 @@ JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunctio JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const { CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function); + if (!functionCallFrame) return jsNull(); - if (functionCallFrame->callerFrame()->hasHostCallFrameFlag()) + int lineNumber; + CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber); + if (!callerFrame) return jsNull(); - - CallFrame* callerFrame = functionCallFrame->trueCallerFrame(); - JSValue caller = callerFrame->callee(); if (!caller) return jsNull(); + // Skip over function bindings. + ASSERT(caller.isObject()); + while (asObject(caller)->inherits(&JSBoundFunction::s_info)) { + callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber); + if (!callerFrame) + return jsNull(); + caller = callerFrame->callee(); + if (!caller) + return jsNull(); + } + return caller; } diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.cpp b/Source/JavaScriptCore/jit/ExecutableAllocator.cpp index 75137279e..5912f8652 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocator.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocator.cpp @@ -29,11 +29,22 @@ #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) #include "CodeProfiling.h" +#include <wtf/DataLog.h> +#include <wtf/HashSet.h> #include <wtf/MetaAllocator.h> #include <wtf/PageReservation.h> +#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) +#include <wtf/PassOwnPtr.h> +#endif +#include <wtf/ThreadingPrimitives.h> #include <wtf/VMTags.h> #endif +// Uncomment to create an artificial executable memory usage limit. This limit +// is imperfect and is primarily useful for testing the VM's ability to handle +// out-of-executable-memory situations. +// #define EXECUTABLE_MEMORY_LIMIT 1000000 + #if ENABLE(ASSEMBLER) using namespace WTF; @@ -47,15 +58,48 @@ public: DemandExecutableAllocator() : MetaAllocator(32) // round up all allocations to 32 bytes { + MutexLocker lock(allocatorsMutex()); + allocators().add(this); // Don't preallocate any memory here. } virtual ~DemandExecutableAllocator() { + { + MutexLocker lock(allocatorsMutex()); + allocators().remove(this); + } for (unsigned i = 0; i < reservations.size(); ++i) reservations.at(i).deallocate(); } + static size_t bytesAllocatedByAllAllocators() + { + size_t total = 0; + MutexLocker lock(allocatorsMutex()); + for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator) + total += (*allocator)->bytesAllocated(); + return total; + } + + static size_t bytesCommittedByAllocactors() + { + size_t total = 0; + MutexLocker lock(allocatorsMutex()); + for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator) + total += (*allocator)->bytesCommitted(); + return total; + } + +#if ENABLE(META_ALLOCATOR_PROFILE) + static void dumpProfileFromAllAllocators() + { + MutexLocker lock(allocatorsMutex()); + for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator) + (*allocator)->dumpProfile(); + } +#endif + protected: virtual void* allocateNewSpace(size_t& numPages) { @@ -65,6 +109,11 @@ protected: numPages = newNumPages; +#ifdef EXECUTABLE_MEMORY_LIMIT + if (bytesAllocatedByAllAllocators() >= EXECUTABLE_MEMORY_LIMIT) + return 0; +#endif + PageReservation reservation = PageReservation::reserve(numPages * pageSize(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true); if (!reservation) CRASH(); @@ -86,20 +135,50 @@ protected: private: Vector<PageReservation, 16> reservations; + static HashSet<DemandExecutableAllocator*>& allocators() + { + DEFINE_STATIC_LOCAL(HashSet<DemandExecutableAllocator*>, sAllocators, ()); + return sAllocators; + } + static Mutex& allocatorsMutex() + { + DEFINE_STATIC_LOCAL(Mutex, mutex, ()); + return mutex; + } }; -static DemandExecutableAllocator* allocator; +#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) +void ExecutableAllocator::initializeAllocator() +{ +} +#else +static DemandExecutableAllocator* gAllocator; + +namespace { +static inline DemandExecutableAllocator* allocator() +{ + return gAllocator; +} +} void ExecutableAllocator::initializeAllocator() { - ASSERT(!allocator); - allocator = new DemandExecutableAllocator(); - CodeProfiling::notifyAllocator(allocator); + ASSERT(!gAllocator); + gAllocator = new DemandExecutableAllocator(); + CodeProfiling::notifyAllocator(gAllocator); } +#endif ExecutableAllocator::ExecutableAllocator(JSGlobalData&) +#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) + : m_allocator(adoptPtr(new DemandExecutableAllocator())) +#endif +{ + ASSERT(allocator()); +} + +ExecutableAllocator::~ExecutableAllocator() { - ASSERT(allocator); } bool ExecutableAllocator::isValid() const @@ -109,26 +188,44 @@ bool ExecutableAllocator::isValid() const bool ExecutableAllocator::underMemoryPressure() { +#ifdef EXECUTABLE_MEMORY_LIMIT + return DemandExecutableAllocator::bytesAllocatedByAllAllocators() > EXECUTABLE_MEMORY_LIMIT / 2; +#else return false; +#endif +} + +double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage) +{ +#ifdef EXECUTABLE_MEMORY_LIMIT + size_t bytesAllocated = DemandExecutableAllocator::bytesAllocatedByAllAllocators() + addedMemoryUsage; + if (bytesAllocated >= EXECUTABLE_MEMORY_LIMIT) + bytesAllocated = EXECUTABLE_MEMORY_LIMIT; + return static_cast<double>(EXECUTABLE_MEMORY_LIMIT) / + (EXECUTABLE_MEMORY_LIMIT - bytesAllocated); +#else + UNUSED_PARAM(addedMemoryUsage); + return 1.0; +#endif } -PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID) +PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort) { - RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID); - if (!result) + RefPtr<ExecutableMemoryHandle> result = allocator()->allocate(sizeInBytes, ownerUID); + if (!result && effort == JITCompilationMustSucceed) CRASH(); return result.release(); } size_t ExecutableAllocator::committedByteCount() { - return allocator->bytesCommitted(); + return DemandExecutableAllocator::bytesCommittedByAllocactors(); } #if ENABLE(META_ALLOCATOR_PROFILE) void ExecutableAllocator::dumpProfile() { - allocator->dumpProfile(); + DemandExecutableAllocator::dumpProfileFromAllAllocators(); } #endif diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.h b/Source/JavaScriptCore/jit/ExecutableAllocator.h index 7520913d0..8a14ac67e 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocator.h +++ b/Source/JavaScriptCore/jit/ExecutableAllocator.h @@ -25,6 +25,7 @@ #ifndef ExecutableAllocator_h #define ExecutableAllocator_h +#include "JITCompilationEffort.h" #include <stddef.h> // for ptrdiff_t #include <limits> #include <wtf/Assertions.h> @@ -95,11 +96,16 @@ typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle; #if ENABLE(JIT) && ENABLE(ASSEMBLER) +#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) +class DemandExecutableAllocator; +#endif + class ExecutableAllocator { enum ProtectionSetting { Writable, Executable }; public: ExecutableAllocator(JSGlobalData&); + ~ExecutableAllocator(); static void initializeAllocator(); @@ -107,13 +113,15 @@ public: static bool underMemoryPressure(); + static double memoryPressureMultiplier(size_t addedMemoryUsage); + #if ENABLE(META_ALLOCATOR_PROFILE) static void dumpProfile(); #else static void dumpProfile() { } #endif - PassRefPtr<ExecutableMemoryHandle> allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID); + PassRefPtr<ExecutableMemoryHandle> allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort); #if ENABLE(ASSEMBLER_WX_EXCLUSIVE) static void makeWritable(void* start, size_t size) @@ -232,7 +240,13 @@ private: #if ENABLE(ASSEMBLER_WX_EXCLUSIVE) static void reprotectRegion(void*, size_t, ProtectionSetting); +#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) + // We create a MetaAllocator for each JS global object. + OwnPtr<DemandExecutableAllocator> m_allocator; + DemandExecutableAllocator* allocator() { return m_allocator.get(); } #endif +#endif + }; #endif // ENABLE(JIT) && ENABLE(ASSEMBLER) diff --git a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index 37a57e8b7..959ea744b 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -104,6 +104,10 @@ ExecutableAllocator::ExecutableAllocator(JSGlobalData&) ASSERT(allocator); } +ExecutableAllocator::~ExecutableAllocator() +{ +} + bool ExecutableAllocator::isValid() const { return !!allocator->bytesReserved(); @@ -115,10 +119,23 @@ bool ExecutableAllocator::underMemoryPressure() return statistics.bytesAllocated > statistics.bytesReserved / 2; } -PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData& globalData, size_t sizeInBytes, void* ownerUID) +double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage) +{ + MetaAllocator::Statistics statistics = allocator->currentStatistics(); + ASSERT(statistics.bytesAllocated <= statistics.bytesReserved); + size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage; + if (bytesAllocated >= statistics.bytesReserved) + bytesAllocated = statistics.bytesReserved; + return static_cast<double>(statistics.bytesReserved) / + (statistics.bytesReserved - bytesAllocated); +} + +PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData& globalData, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort) { RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID); if (!result) { + if (effort == JITCompilationCanFail) + return result; releaseExecutableMemory(globalData); result = allocator->allocate(sizeInBytes, ownerUID); if (!result) diff --git a/Source/JavaScriptCore/jit/HostCallReturnValue.cpp b/Source/JavaScriptCore/jit/HostCallReturnValue.cpp index 924bc7671..9d449c374 100644 --- a/Source/JavaScriptCore/jit/HostCallReturnValue.cpp +++ b/Source/JavaScriptCore/jit/HostCallReturnValue.cpp @@ -27,7 +27,7 @@ #include "HostCallReturnValue.h" #include "CallFrame.h" -#include "InlineASM.h" +#include <wtf/InlineASM.h> #include "JSObject.h" #include "JSValueInlineMethods.h" #include "ScopeChain.h" diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp index 2adc596ce..541cc896a 100644 --- a/Source/JavaScriptCore/jit/JIT.cpp +++ b/Source/JavaScriptCore/jit/JIT.cpp @@ -35,7 +35,7 @@ JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse #endif #include "CodeBlock.h" -#include "CryptographicallyRandomNumber.h" +#include <wtf/CryptographicallyRandomNumber.h> #include "DFGNode.h" // for DFG_SUCCESS_STATS #include "Interpreter.h" #include "JITInlineMethods.h" @@ -102,7 +102,7 @@ void JIT::emitOptimizationCheck(OptimizationCheckKind kind) Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? Options::executionCounterIncrementForLoop : Options::executionCounterIncrementForReturn), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter())); JITStubCall stubCall(this, kind == LoopOptimizationCheck ? cti_optimize_from_loop : cti_optimize_from_ret); if (kind == LoopOptimizationCheck) - stubCall.addArgument(Imm32(m_bytecodeOffset)); + stubCall.addArgument(TrustedImm32(m_bytecodeOffset)); stubCall.call(); skipOptimize.link(this); } @@ -235,14 +235,10 @@ void JIT::privateCompileMainPass() DEFINE_UNARY_OP(op_is_object) DEFINE_UNARY_OP(op_is_string) DEFINE_UNARY_OP(op_is_undefined) -#if USE(JSVALUE64) - DEFINE_UNARY_OP(op_negate) -#endif DEFINE_UNARY_OP(op_typeof) DEFINE_OP(op_add) DEFINE_OP(op_bitand) - DEFINE_OP(op_bitnot) DEFINE_OP(op_bitor) DEFINE_OP(op_bitxor) DEFINE_OP(op_call) @@ -302,9 +298,7 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_mod) DEFINE_OP(op_mov) DEFINE_OP(op_mul) -#if USE(JSVALUE32_64) DEFINE_OP(op_negate) -#endif DEFINE_OP(op_neq) DEFINE_OP(op_neq_null) DEFINE_OP(op_new_array) @@ -437,7 +431,6 @@ void JIT::privateCompileSlowCases() switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) { DEFINE_SLOWCASE_OP(op_add) DEFINE_SLOWCASE_OP(op_bitand) - DEFINE_SLOWCASE_OP(op_bitnot) DEFINE_SLOWCASE_OP(op_bitor) DEFINE_SLOWCASE_OP(op_bitxor) DEFINE_SLOWCASE_OP(op_call) @@ -475,10 +468,9 @@ void JIT::privateCompileSlowCases() DEFINE_SLOWCASE_OP(op_method_check) DEFINE_SLOWCASE_OP(op_mod) DEFINE_SLOWCASE_OP(op_mul) -#if USE(JSVALUE32_64) DEFINE_SLOWCASE_OP(op_negate) -#endif DEFINE_SLOWCASE_OP(op_neq) + DEFINE_SLOWCASE_OP(op_new_array) DEFINE_SLOWCASE_OP(op_new_object) DEFINE_SLOWCASE_OP(op_new_func) DEFINE_SLOWCASE_OP(op_new_func_exp) @@ -509,7 +501,7 @@ void JIT::privateCompileSlowCases() #if ENABLE(VALUE_PROFILER) if (m_canBeOptimized) - add32(Imm32(1), AbsoluteAddress(&rareCaseProfile->m_counter)); + add32(TrustedImm32(1), AbsoluteAddress(&rareCaseProfile->m_counter)); #endif emitJumpSlowToHot(jump(), 0); @@ -527,7 +519,7 @@ void JIT::privateCompileSlowCases() #endif } -JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) +JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort effort) { #if ENABLE(JIT_VERBOSE_OSR) printf("Compiling JIT code!\n"); @@ -581,7 +573,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) } #endif - addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1); + addPtr(TrustedImm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1); registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1); } @@ -589,7 +581,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) #if ENABLE(VALUE_PROFILER) if (m_canBeOptimized) - add32(Imm32(1), AbsoluteAddress(&m_codeBlock->m_executionEntryCount)); + add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->m_executionEntryCount)); #endif privateCompileMainPass(); @@ -625,7 +617,9 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) ASSERT(m_jmpTable.isEmpty()); - LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock); + LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock, effort); + if (patchBuffer.didFailToAllocate()) + return JITCode(); // Translate vPC offsets into addresses in JIT generated code, for switch tables. for (unsigned i = 0; i < m_switches.size(); ++i) { @@ -702,7 +696,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) } #if ENABLE(DFG_JIT) || ENABLE(LLINT) - if (m_canBeOptimized + if (canBeOptimized() #if ENABLE(LLINT) || true #endif @@ -721,6 +715,10 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) CodeRef result = patchBuffer.finalizeCode(); + m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.add( + static_cast<double>(result.size()) / + static_cast<double>(m_codeBlock->instructions().size())); + #if ENABLE(JIT_VERBOSE) dataLog("JIT generated code for %p at [%p, %p).\n", m_codeBlock, result.executableMemory()->start(), result.executableMemory()->end()); #endif diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h index a2bc4272a..2d2841baf 100644 --- a/Source/JavaScriptCore/jit/JIT.h +++ b/Source/JavaScriptCore/jit/JIT.h @@ -199,9 +199,9 @@ namespace JSC { static const int patchPutByIdDefaultOffset = 256; public: - static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, CodePtr* functionEntryArityCheck = 0) + static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCompilationEffort effort, CodePtr* functionEntryArityCheck = 0) { - return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck); + return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck, effort); } static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress) @@ -254,8 +254,13 @@ namespace JSC { static CodeRef compileCTINativeCall(JSGlobalData* globalData, NativeFunction func) { - if (!globalData->canUseJIT()) + if (!globalData->canUseJIT()) { +#if ENABLE(LLINT) + return CodeRef::createLLIntCodeRef(llint_native_call_trampoline); +#else return CodeRef(); +#endif + } JIT jit(globalData, 0); return jit.privateCompileCTINativeCall(globalData, func); } @@ -291,7 +296,7 @@ namespace JSC { void privateCompileMainPass(); void privateCompileLinkPass(); void privateCompileSlowCases(); - JITCode privateCompile(CodePtr* functionEntryArityCheck); + JITCode privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort); void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame); void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, const Identifier&, const PropertySlot&, size_t cachedOffset); void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame); @@ -336,8 +341,10 @@ namespace JSC { void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind); template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr); + void emitAllocateBasicStorage(size_t, RegisterID result, RegisterID storagePtr); template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr); void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr); + void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr); #if ENABLE(VALUE_PROFILER) // This assumes that the value to profile is in regT0 and that regT3 is available for @@ -464,7 +471,7 @@ namespace JSC { #if ENABLE(OPCODE_SAMPLING) #error "OPCODE_SAMPLING is not yet supported" #else - static const int patchOffsetGetByIdSlowCaseCall = 48; + static const int patchOffsetGetByIdSlowCaseCall = 52; #endif static const int patchOffsetOpCallCompareToJump = 16; @@ -500,7 +507,7 @@ namespace JSC { #if ENABLE(OPCODE_SAMPLING) #error "OPCODE_SAMPLING is not yet supported" #else - static const int patchOffsetGetByIdSlowCaseCall = 64; + static const int patchOffsetGetByIdSlowCaseCall = 68; #endif static const int patchOffsetOpCallCompareToJump = 32; static const int patchOffsetMethodCheckProtoObj = 32; @@ -518,7 +525,7 @@ namespace JSC { #if ENABLE(OPCODE_SAMPLING) #error "OPCODE_SAMPLING is not yet supported" #else - static const int patchOffsetGetByIdSlowCaseCall = 64; + static const int patchOffsetGetByIdSlowCaseCall = 68; #endif static const int patchOffsetOpCallCompareToJump = 32; static const int patchOffsetMethodCheckProtoObj = 32; @@ -778,7 +785,6 @@ namespace JSC { void emit_op_add(Instruction*); void emit_op_bitand(Instruction*); - void emit_op_bitnot(Instruction*); void emit_op_bitor(Instruction*); void emit_op_bitxor(Instruction*); void emit_op_call(Instruction*); @@ -898,7 +904,6 @@ namespace JSC { void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&); - void emitSlow_op_bitnot(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_bitor(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&); @@ -957,7 +962,7 @@ namespace JSC { void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_new_func(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_new_func_exp(Instruction*, Vector<SlowCaseEntry>::iterator&); - + void emitSlow_op_new_array(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitRightShift(Instruction*, bool isUnsigned); void emitRightShiftSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator&, bool isUnsigned); diff --git a/Source/JavaScriptCore/jit/JITArithmetic.cpp b/Source/JavaScriptCore/jit/JITArithmetic.cpp index 362cc6241..1b32e3bcf 100644 --- a/Source/JavaScriptCore/jit/JITArithmetic.cpp +++ b/Source/JavaScriptCore/jit/JITArithmetic.cpp @@ -192,6 +192,42 @@ void JIT::emitSlow_op_jngreatereq(Instruction* currentInstruction, Vector<SlowCa #if USE(JSVALUE64) +void JIT::emit_op_negate(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned src = currentInstruction[2].u.operand; + + emitGetVirtualRegister(src, regT0); + + Jump srcNotInt = emitJumpIfNotImmediateInteger(regT0); + addSlowCase(branchTest32(Zero, regT0, TrustedImm32(0x7fffffff))); + neg32(regT0); + emitFastArithReTagImmediate(regT0, regT0); + + Jump end = jump(); + + srcNotInt.link(this); + emitJumpSlowCaseIfNotImmediateNumber(regT0); + + move(TrustedImmPtr(reinterpret_cast<void*>(0x8000000000000000ull)), regT1); + xorPtr(regT1, regT0); + + end.link(this); + emitPutVirtualRegister(dst); +} + +void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + + linkSlowCase(iter); // 0x7fffffff check + linkSlowCase(iter); // double check + + JITStubCall stubCall(this, cti_op_negate); + stubCall.addArgument(regT1, regT0); + stubCall.call(dst); +} + void JIT::emit_op_lshift(Instruction* currentInstruction) { unsigned result = currentInstruction[1].u.operand; @@ -797,13 +833,13 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsign addSlowCase(branchMul32(Overflow, regT1, regT2)); JumpList done; done.append(branchTest32(NonZero, regT2)); - Jump negativeZero = branch32(LessThan, regT0, Imm32(0)); - done.append(branch32(GreaterThanOrEqual, regT1, Imm32(0))); + Jump negativeZero = branch32(LessThan, regT0, TrustedImm32(0)); + done.append(branch32(GreaterThanOrEqual, regT1, TrustedImm32(0))); negativeZero.link(this); // We only get here if we have a genuine negative zero. Record this, // so that the speculative JIT knows that we failed speculation // because of a negative zero. - add32(Imm32(1), AbsoluteAddress(&profile->m_counter)); + add32(TrustedImm32(1), AbsoluteAddress(&profile->m_counter)); addSlowCase(jump()); done.link(this); move(regT2, regT0); @@ -927,13 +963,13 @@ void JIT::emit_op_add(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0)); - emitFastArithIntToImmNoCheck(regT0, regT0); + addSlowCase(branchAdd32(Overflow, regT0, Imm32(getConstantOperandImmediateInt(op1)), regT1)); + emitFastArithIntToImmNoCheck(regT1, regT0); } else if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0)); - emitFastArithIntToImmNoCheck(regT0, regT0); + addSlowCase(branchAdd32(Overflow, regT0, Imm32(getConstantOperandImmediateInt(op2)), regT1)); + emitFastArithIntToImmNoCheck(regT1, regT0); } else compileBinaryArithOp(op_add, result, op1, op2, types); @@ -973,8 +1009,8 @@ void JIT::emit_op_mul(Instruction* currentInstruction) #endif emitGetVirtualRegister(op2, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0)); - emitFastArithReTagImmediate(regT0, regT0); + addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT1)); + emitFastArithReTagImmediate(regT1, regT0); } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) { #if ENABLE(VALUE_PROFILER) // Add a special fast case profile because the DFG JIT will expect one. @@ -982,8 +1018,8 @@ void JIT::emit_op_mul(Instruction* currentInstruction) #endif emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0)); - emitFastArithReTagImmediate(regT0, regT0); + addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT1)); + emitFastArithReTagImmediate(regT1, regT0); } else compileBinaryArithOp(op_mul, result, op1, op2, types); @@ -1069,7 +1105,7 @@ void JIT::emit_op_div(Instruction* currentInstruction) emitFastArithReTagImmediate(regT0, regT0); Jump isInteger = jump(); notInteger.link(this); - add32(Imm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter)); + add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter)); moveDoubleToPtr(fpRegT0, regT0); subPtr(tagTypeNumberRegister, regT0); isInteger.link(this); diff --git a/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp b/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp index 4916261fe..11a758103 100644 --- a/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp +++ b/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp @@ -448,31 +448,6 @@ void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEnt stubCall.call(dst); } -// BitNot (~) - -void JIT::emit_op_bitnot(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned src = currentInstruction[2].u.operand; - - emitLoad(src, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); - - not32(regT0); - emitStoreAndMapInt32(dst, regT1, regT0, dst == src, OPCODE_LENGTH(op_bitnot)); -} - -void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_bitnot); - stubCall.addArgument(regT1, regT0); - stubCall.call(dst); -} - // PostInc (i++) void JIT::emit_op_post_inc(Instruction* currentInstruction) @@ -504,7 +479,7 @@ void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseE JITStubCall stubCall(this, cti_op_post_inc); stubCall.addArgument(srcDst); - stubCall.addArgument(Imm32(srcDst)); + stubCall.addArgument(TrustedImm32(srcDst)); stubCall.call(dst); } @@ -644,9 +619,9 @@ void JIT::emit_op_add(Instruction* currentInstruction) void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType) { // Int32 case. - emitLoad(op, regT1, regT0); + emitLoad(op, regT1, regT2); Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); - addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0)); + addSlowCase(branchAdd32(Overflow, regT2, Imm32(constant), regT0)); emitStoreInt32(dst, regT0, (op == dst)); // Double case. @@ -757,8 +732,13 @@ void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultT // Int32 case. emitLoad(op, regT1, regT0); Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); - addSlowCase(branchSub32(Overflow, Imm32(constant), regT0)); - emitStoreInt32(dst, regT0, (op == dst)); +#if ENABLE(JIT_CONSTANT_BLINDING) + addSlowCase(branchSub32(Overflow, regT0, Imm32(constant), regT2, regT3)); +#else + addSlowCase(branchSub32(Overflow, regT0, Imm32(constant), regT2)); +#endif + + emitStoreInt32(dst, regT2, (op == dst)); // Double case. if (!supportsFloatingPoint()) { @@ -886,7 +866,7 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi emitStoreInt32(dst, regT2); Jump isInteger = jump(); notInteger.link(this); - add32(Imm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); + add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); emitStoreDouble(dst, fpRegT1); isInteger.link(this); #else @@ -990,7 +970,7 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi emitStoreInt32(dst, regT2); Jump isInteger = jump(); notInteger.link(this); - add32(Imm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); + add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); emitStoreDouble(dst, fpRegT0); isInteger.link(this); #else @@ -1096,7 +1076,7 @@ void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry> // We only get here if we have a genuine negative zero. Record this, // so that the speculative JIT knows that we failed speculation // because of a negative zero. - add32(Imm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); + add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); #endif overflow.link(this); @@ -1175,7 +1155,7 @@ void JIT::emit_op_div(Instruction* currentInstruction) emitStoreInt32(dst, regT2); end.append(jump()); notInteger.link(this); - add32(Imm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); + add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter)); emitStoreDouble(dst, fpRegT0); #else emitStoreDouble(dst, fpRegT0); diff --git a/Source/JavaScriptCore/jit/JITCall.cpp b/Source/JavaScriptCore/jit/JITCall.cpp index 69dc9540e..73d017d05 100644 --- a/Source/JavaScriptCore/jit/JITCall.cpp +++ b/Source/JavaScriptCore/jit/JITCall.cpp @@ -83,8 +83,7 @@ void JIT::compileLoadVarargs(Instruction* instruction) slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1)); // Initialize ArgumentCount. - emitFastArithReTagImmediate(regT0, regT2); - storePtr(regT2, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); + store32(regT0, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); // Initialize 'this'. emitGetVirtualRegister(thisValue, regT2); @@ -93,13 +92,13 @@ void JIT::compileLoadVarargs(Instruction* instruction) // Copy arguments. neg32(regT0); signExtend32ToPtr(regT0, regT0); - end.append(branchAddPtr(Zero, Imm32(1), regT0)); + end.append(branchAddPtr(Zero, TrustedImm32(1), regT0)); // regT0: -argumentCount Label copyLoop = label(); loadPtr(BaseIndex(callFrameRegister, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT2); storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))); - branchAddPtr(NonZero, Imm32(1), regT0).linkTo(copyLoop, this); + branchAddPtr(NonZero, TrustedImm32(1), regT0).linkTo(copyLoop, this); end.append(jump()); } diff --git a/Source/JavaScriptCore/jit/JITCall32_64.cpp b/Source/JavaScriptCore/jit/JITCall32_64.cpp index b84ad1a49..7fb6c78b9 100644 --- a/Source/JavaScriptCore/jit/JITCall32_64.cpp +++ b/Source/JavaScriptCore/jit/JITCall32_64.cpp @@ -171,7 +171,7 @@ void JIT::compileLoadVarargs(Instruction* instruction) // Copy arguments. neg32(regT2); - end.append(branchAdd32(Zero, Imm32(1), regT2)); + end.append(branchAdd32(Zero, TrustedImm32(1), regT2)); // regT2: -argumentCount; Label copyLoop = label(); @@ -179,7 +179,7 @@ void JIT::compileLoadVarargs(Instruction* instruction) load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))), regT1); store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))))); store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))))); - branchAdd32(NonZero, Imm32(1), regT2).linkTo(copyLoop, this); + branchAdd32(NonZero, TrustedImm32(1), regT2).linkTo(copyLoop, this); end.append(jump()); } diff --git a/Source/JavaScriptCore/jit/JITCompilationEffort.h b/Source/JavaScriptCore/jit/JITCompilationEffort.h new file mode 100644 index 000000000..5eb680178 --- /dev/null +++ b/Source/JavaScriptCore/jit/JITCompilationEffort.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JITCompilationEffort_h +#define JITCompilationEffort_h + +namespace JSC { + +enum JITCompilationEffort { + JITCompilationCanFail, + JITCompilationMustSucceed +}; + +} // namespace JSC + +#endif // JITCompilationEffort_h + diff --git a/Source/JavaScriptCore/jit/JITDriver.h b/Source/JavaScriptCore/jit/JITDriver.h index b204c7737..66cf51925 100644 --- a/Source/JavaScriptCore/jit/JITDriver.h +++ b/Source/JavaScriptCore/jit/JITDriver.h @@ -38,7 +38,7 @@ namespace JSC { template<typename CodeBlockType> -inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType) +inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType, JITCompilationEffort effort) { if (jitType == codeBlock->getJITType()) return true; @@ -48,6 +48,8 @@ inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockTy codeBlock->unlinkIncomingCalls(); + JITCode oldJITCode = jitCode; + bool dfgCompiled = false; if (jitType == JITCode::DFGJIT) dfgCompiled = DFG::tryCompile(globalData, codeBlock.get(), jitCode); @@ -57,16 +59,21 @@ inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockTy } else { if (codeBlock->alternative()) { codeBlock = static_pointer_cast<CodeBlockType>(codeBlock->releaseAlternative()); + jitCode = oldJITCode; + return false; + } + jitCode = JIT::compile(&globalData, codeBlock.get(), effort); + if (!jitCode) { + jitCode = oldJITCode; return false; } - jitCode = JIT::compile(&globalData, codeBlock.get()); } codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr()); return true; } -inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType) +inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, JITCompilationEffort effort) { if (jitType == codeBlock->getJITType()) return true; @@ -76,6 +83,9 @@ inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<Fun codeBlock->unlinkIncomingCalls(); + JITCode oldJITCode = jitCode; + MacroAssemblerCodePtr oldJITCodeWithArityCheck = jitCodeWithArityCheck; + bool dfgCompiled = false; if (jitType == JITCode::DFGJIT) dfgCompiled = DFG::tryCompileFunction(globalData, codeBlock.get(), jitCode, jitCodeWithArityCheck); @@ -86,9 +96,16 @@ inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<Fun if (codeBlock->alternative()) { codeBlock = static_pointer_cast<FunctionCodeBlock>(codeBlock->releaseAlternative()); symbolTable = codeBlock->sharedSymbolTable(); + jitCode = oldJITCode; + jitCodeWithArityCheck = oldJITCodeWithArityCheck; + return false; + } + jitCode = JIT::compile(&globalData, codeBlock.get(), effort, &jitCodeWithArityCheck); + if (!jitCode) { + jitCode = oldJITCode; + jitCodeWithArityCheck = oldJITCodeWithArityCheck; return false; } - jitCode = JIT::compile(&globalData, codeBlock.get(), &jitCodeWithArityCheck); } codeBlock->setJITCode(jitCode, jitCodeWithArityCheck); diff --git a/Source/JavaScriptCore/jit/JITExceptions.cpp b/Source/JavaScriptCore/jit/JITExceptions.cpp index 2edd3408f..ab1180716 100644 --- a/Source/JavaScriptCore/jit/JITExceptions.cpp +++ b/Source/JavaScriptCore/jit/JITExceptions.cpp @@ -48,8 +48,7 @@ ExceptionHandler genericThrow(JSGlobalData* globalData, ExecState* callFrame, JS Instruction* catchPCForInterpreter = 0; if (handler) { catchRoutine = handler->nativeCode.executableAddress(); - if (callFrame->codeBlock()->hasInstructions()) - catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target]; + catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target]; } else catchRoutine = FunctionPtr(ctiOpThrowNotCaught).value(); diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h index e0310569d..998d5ac18 100644 --- a/Source/JavaScriptCore/jit/JITInlineMethods.h +++ b/Source/JavaScriptCore/jit/JITInlineMethods.h @@ -269,7 +269,7 @@ ALWAYS_INLINE void JIT::updateTopCallFrame() #if USE(JSVALUE32_64) storePtr(TrustedImmPtr(m_codeBlock->instructions().begin() + m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount)); #else - store32(Imm32(m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount)); + store32(TrustedImm32(m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount)); #endif } storePtr(callFrameRegister, &m_globalData->topCallFrame); @@ -459,6 +459,78 @@ inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, Register #endif } +inline void JIT::emitAllocateBasicStorage(size_t size, RegisterID result, RegisterID storagePtr) +{ + CopiedAllocator* allocator = &m_globalData->heap.storageAllocator(); + + // FIXME: We need to check for wrap-around. + // Check to make sure that the allocation will fit in the current block. + loadPtr(&allocator->m_currentOffset, result); + addPtr(TrustedImm32(size), result); + loadPtr(&allocator->m_currentBlock, storagePtr); + addPtr(TrustedImm32(HeapBlock::s_blockSize), storagePtr); + addSlowCase(branchPtr(AboveOrEqual, result, storagePtr)); + + // Load the original offset. + loadPtr(&allocator->m_currentOffset, result); + + // Bump the pointer forward. + move(result, storagePtr); + addPtr(TrustedImm32(size), storagePtr); + storePtr(storagePtr, &allocator->m_currentOffset); +} + +inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr) +{ + unsigned initialLength = std::max(length, 4U); + size_t initialStorage = JSArray::storageSize(initialLength); + + // Allocate the cell for the array. + emitAllocateBasicJSObject<JSArray, false>(TrustedImmPtr(m_codeBlock->globalObject()->arrayStructure()), cellResult, storagePtr); + + // Allocate the backing store for the array. + emitAllocateBasicStorage(initialStorage, storageResult, storagePtr); + + // Store all the necessary info in the ArrayStorage. + storePtr(storageResult, Address(storageResult, ArrayStorage::allocBaseOffset())); + store32(Imm32(length), Address(storageResult, ArrayStorage::lengthOffset())); + store32(Imm32(length), Address(storageResult, ArrayStorage::numValuesInVectorOffset())); + + // Store the newly allocated ArrayStorage. + storePtr(storageResult, Address(cellResult, JSArray::storageOffset())); + + // Store the vector length and index bias. + store32(Imm32(initialLength), Address(cellResult, JSArray::vectorLengthOffset())); + store32(TrustedImm32(0), Address(cellResult, JSArray::indexBiasOffset())); + + // Initialize the subclass data and the sparse value map. + storePtr(TrustedImmPtr(0), Address(cellResult, JSArray::subclassDataOffset())); + storePtr(TrustedImmPtr(0), Address(cellResult, JSArray::sparseValueMapOffset())); + + // Store the values we have. + for (unsigned i = 0; i < length; i++) { +#if USE(JSVALUE64) + loadPtr(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register)), storagePtr); + storePtr(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i)); +#else + load32(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register)), storagePtr); + store32(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i)); + load32(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register) + sizeof(uint32_t)), storagePtr); + store32(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i + sizeof(uint32_t))); +#endif + } + + // Zero out the remaining slots. + for (unsigned i = length; i < initialLength; i++) { +#if USE(JSVALUE64) + storePtr(TrustedImmPtr(0), Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i)); +#else + store32(TrustedImm32(static_cast<int>(JSValue::EmptyValueTag)), Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); + store32(TrustedImm32(0), Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); +#endif + } +} + #if ENABLE(VALUE_PROFILER) inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile) { @@ -485,11 +557,11 @@ inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile) } if (m_randomGenerator.getUint32() & 1) - add32(Imm32(1), bucketCounterRegister); + add32(TrustedImm32(1), bucketCounterRegister); else - add32(Imm32(3), bucketCounterRegister); - and32(Imm32(ValueProfile::bucketIndexMask), bucketCounterRegister); - move(ImmPtr(valueProfile->m_buckets), scratch); + add32(TrustedImm32(3), bucketCounterRegister); + and32(TrustedImm32(ValueProfile::bucketIndexMask), bucketCounterRegister); + move(TrustedImmPtr(valueProfile->m_buckets), scratch); #if USE(JSVALUE64) storePtr(value, BaseIndex(scratch, bucketCounterRegister, TimesEight)); #elif USE(JSVALUE32_64) @@ -796,7 +868,10 @@ ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst) // TODO: we want to reuse values that are already in registers if we can - add a register allocator! if (m_codeBlock->isConstantRegisterIndex(src)) { JSValue value = m_codeBlock->getConstant(src); - move(ImmPtr(JSValue::encode(value)), dst); + if (!value.isNumber()) + move(TrustedImmPtr(JSValue::encode(value)), dst); + else + move(ImmPtr(JSValue::encode(value)), dst); killLastResultRegister(); return; } diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index bc53d2cd8..2db82bf4a 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -29,6 +29,7 @@ #include "JIT.h" #include "Arguments.h" +#include "CopiedSpaceInlineMethods.h" #include "Heap.h" #include "JITInlineMethods.h" #include "JITStubCall.h" @@ -357,7 +358,10 @@ void JIT::emit_op_mov(Instruction* currentInstruction) emitPutVirtualRegister(dst); } else { if (m_codeBlock->isConstantRegisterIndex(src)) { - storePtr(ImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register))); + if (!getConstantOperand(src).isNumber()) + storePtr(TrustedImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register))); + else + storePtr(ImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register))); if (dst == m_lastResultBytecodeRegister) killLastResultRegister(); } else if ((src == m_lastResultBytecodeRegister) || (dst == m_lastResultBytecodeRegister)) { @@ -389,7 +393,7 @@ void JIT::emit_op_jmp(Instruction* currentInstruction) void JIT::emit_op_new_object(Instruction* currentInstruction) { - emitAllocateJSFinalObject(ImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1); + emitAllocateJSFinalObject(TrustedImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1); emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -594,8 +598,8 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction) void JIT::emit_op_strcat(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_strcat); - stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); stubCall.call(currentInstruction[1].u.operand); } @@ -609,7 +613,7 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction) void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_ensure_property_exists); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -618,7 +622,7 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_skip); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); - stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); stubCall.callWithValueProfiling(currentInstruction[1].u.operand); } @@ -654,7 +658,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo linkSlowCase(iter); JITStubCall stubCall(this, cti_op_resolve_global); stubCall.addArgument(TrustedImmPtr(ident)); - stubCall.addArgument(Imm32(currentIndex)); + stubCall.addArgument(TrustedImm32(currentIndex)); stubCall.addArgument(regT0); stubCall.callWithValueProfiling(dst); } @@ -763,20 +767,11 @@ void JIT::emit_op_eq(Instruction* currentInstruction) emitPutVirtualRegister(currentInstruction[1].u.operand); } -void JIT::emit_op_bitnot(Instruction* currentInstruction) -{ - emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT0); - not32(regT0); - emitFastArithIntToImmNoCheck(regT0, regT0); - emitPutVirtualRegister(currentInstruction[1].u.operand); -} - void JIT::emit_op_resolve_with_base(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_with_base); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.callWithValueProfiling(currentInstruction[2].u.operand); } @@ -784,7 +779,7 @@ void JIT::emit_op_resolve_with_this(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_with_this); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.callWithValueProfiling(currentInstruction[2].u.operand); } @@ -971,17 +966,25 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy unsigned src2 = currentInstruction[3].u.operand; emitGetVirtualRegisters(src1, regT0, src2, regT1); - - // Jump to a slow case if either operand is a number, or if both are JSCell*s. + + // Jump slow if both are cells (to cover strings). move(regT0, regT2); orPtr(regT1, regT2); addSlowCase(emitJumpIfJSCell(regT2)); - addSlowCase(emitJumpIfImmediateNumber(regT2)); + + // Jump slow if either is a double. First test if it's an integer, which is fine, and then test + // if it's a double. + Jump leftOK = emitJumpIfImmediateInteger(regT0); + addSlowCase(emitJumpIfImmediateNumber(regT0)); + leftOK.link(this); + Jump rightOK = emitJumpIfImmediateInteger(regT1); + addSlowCase(emitJumpIfImmediateNumber(regT1)); + rightOK.link(this); if (type == OpStrictEq) - compare32(Equal, regT1, regT0, regT0); + comparePtr(Equal, regT1, regT0, regT0); else - compare32(NotEqual, regT1, regT0, regT0); + comparePtr(NotEqual, regT1, regT0, regT0); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(dst); @@ -1034,7 +1037,7 @@ void JIT::emit_op_catch(Instruction* currentInstruction) void JIT::emit_op_jmp_scopes(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_jmp_scopes); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.call(); addJump(jump(), currentInstruction[2].u.operand); } @@ -1052,7 +1055,7 @@ void JIT::emit_op_switch_imm(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_switch_imm); stubCall.addArgument(scrutinee, regT2); - stubCall.addArgument(Imm32(tableIndex)); + stubCall.addArgument(TrustedImm32(tableIndex)); stubCall.call(); jump(regT0); } @@ -1070,7 +1073,7 @@ void JIT::emit_op_switch_char(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_switch_char); stubCall.addArgument(scrutinee, regT2); - stubCall.addArgument(Imm32(tableIndex)); + stubCall.addArgument(TrustedImm32(tableIndex)); stubCall.call(); jump(regT0); } @@ -1087,7 +1090,7 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_switch_string); stubCall.addArgument(scrutinee, regT2); - stubCall.addArgument(Imm32(tableIndex)); + stubCall.addArgument(TrustedImm32(tableIndex)); stubCall.call(); jump(regT0); } @@ -1095,7 +1098,10 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction) void JIT::emit_op_throw_reference_error(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_throw_reference_error); - stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand)))); + if (!m_codeBlock->getConstant(currentInstruction[1].u.operand).isNumber()) + stubCall.addArgument(TrustedImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand)))); + else + stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand)))); stubCall.call(); } @@ -1106,9 +1112,9 @@ void JIT::emit_op_debug(Instruction* currentInstruction) breakpoint(); #else JITStubCall stubCall(this, cti_op_debug); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); stubCall.call(); #endif } @@ -1318,14 +1324,6 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand); // inverted! } -void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - linkSlowCase(iter); - JITStubCall stubCall(this, cti_op_bitnot); - stubCall.addArgument(regT0); - stubCall.call(currentInstruction[1].u.operand); -} - void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { linkSlowCase(iter); @@ -1380,6 +1378,7 @@ void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseE { linkSlowCase(iter); linkSlowCase(iter); + linkSlowCase(iter); JITStubCall stubCall(this, cti_op_stricteq); stubCall.addArgument(regT0); stubCall.addArgument(regT1); @@ -1390,6 +1389,7 @@ void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCase { linkSlowCase(iter); linkSlowCase(iter); + linkSlowCase(iter); JITStubCall stubCall(this, cti_op_nstricteq); stubCall.addArgument(regT0); stubCall.addArgument(regT1); @@ -1565,7 +1565,7 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve linkSlowCase(iter); // We managed to skip all the nodes in the scope chain, but the cache missed. JITStubCall stubCall(this, cti_op_resolve_global); stubCall.addArgument(TrustedImmPtr(ident)); - stubCall.addArgument(Imm32(currentIndex)); + stubCall.addArgument(TrustedImm32(currentIndex)); stubCall.addArgument(regT0); stubCall.callWithValueProfiling(dst); } @@ -1645,17 +1645,39 @@ void JIT::emitSlow_op_new_func_exp(Instruction* currentInstruction, Vector<SlowC void JIT::emit_op_new_array(Instruction* currentInstruction) { + int length = currentInstruction[3].u.operand; + if (CopiedSpace::isOversize(JSArray::storageSize(length))) { + JITStubCall stubCall(this, cti_op_new_array); + stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); + stubCall.call(currentInstruction[1].u.operand); + return; + } + int dst = currentInstruction[1].u.operand; + int values = currentInstruction[2].u.operand; + + emitAllocateJSArray(values, length, regT0, regT1, regT2); + emitStoreCell(dst, regT0); +} + +void JIT::emitSlow_op_new_array(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + int length = currentInstruction[3].u.operand; + if (CopiedSpace::isOversize(JSArray::storageSize(length))) + return; + linkSlowCase(iter); // Not enough space in MarkedSpace for cell. + linkSlowCase(iter); // Not enough space in CopiedSpace for storage. JITStubCall stubCall(this, cti_op_new_array); - stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); stubCall.call(currentInstruction[1].u.operand); } void JIT::emit_op_new_array_buffer(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_new_array_buffer); - stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); stubCall.call(currentInstruction[1].u.operand); } diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index 1a09302cf..b67696f35 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -536,7 +536,7 @@ void JIT::emit_op_jmp(Instruction* currentInstruction) void JIT::emit_op_new_object(Instruction* currentInstruction) { - emitAllocateJSFinalObject(ImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1); + emitAllocateJSFinalObject(TrustedImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1); emitStoreCell(currentInstruction[1].u.operand, regT0); } @@ -701,8 +701,8 @@ void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowC void JIT::emit_op_strcat(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_strcat); - stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); stubCall.call(currentInstruction[1].u.operand); } @@ -716,7 +716,7 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction) void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_ensure_property_exists); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -725,7 +725,7 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_skip); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); - stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); stubCall.callWithValueProfiling(currentInstruction[1].u.operand); } @@ -766,7 +766,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo linkSlowCase(iter); JITStubCall stubCall(this, cti_op_resolve_global); stubCall.addArgument(TrustedImmPtr(ident)); - stubCall.addArgument(Imm32(currentIndex)); + stubCall.addArgument(TrustedImm32(currentIndex)); stubCall.callWithValueProfiling(dst); } @@ -817,7 +817,7 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt if (supportsFloatingPoint()) { // regT1 contains the tag from the hot path. - Jump notNumber = branch32(Above, regT1, Imm32(JSValue::LowestTag)); + Jump notNumber = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)); emitLoadDouble(cond, fpRegT0); emitJumpSlowToHot(branchDoubleZeroOrNaN(fpRegT0, fpRegT1), target); @@ -853,7 +853,7 @@ void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntr if (supportsFloatingPoint()) { // regT1 contains the tag from the hot path. - Jump notNumber = branch32(Above, regT1, Imm32(JSValue::LowestTag)); + Jump notNumber = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)); emitLoadDouble(cond, fpRegT0); emitJumpSlowToHot(branchDoubleNonZero(fpRegT0, fpRegT1), target); @@ -1164,7 +1164,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_with_base); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.callWithValueProfiling(currentInstruction[2].u.operand); } @@ -1172,7 +1172,7 @@ void JIT::emit_op_resolve_with_this(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_with_this); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.callWithValueProfiling(currentInstruction[2].u.operand); } @@ -1364,7 +1364,7 @@ void JIT::emit_op_catch(Instruction* currentInstruction) void JIT::emit_op_jmp_scopes(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_jmp_scopes); - stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand)); stubCall.call(); addJump(jump(), currentInstruction[2].u.operand); } @@ -1382,7 +1382,7 @@ void JIT::emit_op_switch_imm(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_switch_imm); stubCall.addArgument(scrutinee); - stubCall.addArgument(Imm32(tableIndex)); + stubCall.addArgument(TrustedImm32(tableIndex)); stubCall.call(); jump(regT0); } @@ -1400,7 +1400,7 @@ void JIT::emit_op_switch_char(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_switch_char); stubCall.addArgument(scrutinee); - stubCall.addArgument(Imm32(tableIndex)); + stubCall.addArgument(TrustedImm32(tableIndex)); stubCall.call(); jump(regT0); } @@ -1417,7 +1417,7 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_switch_string); stubCall.addArgument(scrutinee); - stubCall.addArgument(Imm32(tableIndex)); + stubCall.addArgument(TrustedImm32(tableIndex)); stubCall.call(); jump(regT0); } diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index 1ee2915dc..19abdbd89 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -57,7 +57,7 @@ void JIT::emit_op_put_by_index(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_put_by_index); stubCall.addArgument(base); - stubCall.addArgument(Imm32(property)); + stubCall.addArgument(TrustedImm32(property)); stubCall.addArgument(value); stubCall.call(); } diff --git a/Source/JavaScriptCore/jit/JITStubCall.h b/Source/JavaScriptCore/jit/JITStubCall.h index 51401a77f..a525ff227 100644 --- a/Source/JavaScriptCore/jit/JITStubCall.h +++ b/Source/JavaScriptCore/jit/JITStubCall.h @@ -104,12 +104,24 @@ namespace JSC { m_jit->poke(argument, m_stackIndex); m_stackIndex += stackIndexStep; } + + void addArgument(JIT::Imm32 argument) + { + m_jit->poke(argument, m_stackIndex); + m_stackIndex += stackIndexStep; + } void addArgument(JIT::TrustedImmPtr argument) { m_jit->poke(argument, m_stackIndex); m_stackIndex += stackIndexStep; } + + void addArgument(JIT::ImmPtr argument) + { + m_jit->poke(argument, m_stackIndex); + m_stackIndex += stackIndexStep; + } void addArgument(JIT::RegisterID argument) { diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index a0a816505..eebe90427 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -43,7 +43,7 @@ #include "ExceptionHelpers.h" #include "GetterSetter.h" #include "Heap.h" -#include "InlineASM.h" +#include <wtf/InlineASM.h> #include "JIT.h" #include "JITExceptions.h" #include "JSActivation.h" @@ -1929,12 +1929,16 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) CallFrame* callFrame = stackFrame.callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned bytecodeIndex = stackFrame.args[0].int32(); + unsigned bytecodeIndex = stackFrame.args[0].int32(); + #if ENABLE(JIT_VERBOSE_OSR) dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter()); #endif + if (!codeBlock->checkIfOptimizationThresholdReached()) + return; + if (codeBlock->hasOptimizedReplacement()) { #if ENABLE(JIT_VERBOSE_OSR) dataLog("Considering loop OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); @@ -2033,6 +2037,9 @@ DEFINE_STUB_FUNCTION(void, optimize_from_ret) dataLog("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter()); #endif + if (!codeBlock->checkIfOptimizationThresholdReached()) + return; + if (codeBlock->hasOptimizedReplacement()) { #if ENABLE(JIT_VERBOSE_OSR) dataLog("Returning from old JIT call frame with optimized replacement %p(%p), with success/fail %u/%u", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); @@ -2546,7 +2553,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val) if (jsArray->canSetIndex(i)) jsArray->setIndex(*globalData, i, value); else - JSArray::putByIndex(jsArray, callFrame, i, value); + JSArray::putByIndex(jsArray, callFrame, i, value, callFrame->codeBlock()->isStrictMode()); } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { JSByteArray* jsByteArray = asByteArray(baseValue); ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array)); @@ -2561,9 +2568,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val) } } - baseValue.put(callFrame, i, value); + baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode()); } else - baseValue.put(callFrame, i, value); + baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode()); } else { Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. @@ -2604,7 +2611,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array) if (!isJSByteArray(baseValue)) ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val)); - baseValue.put(callFrame, i, value); + baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode()); } else { Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. @@ -3036,19 +3043,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift) return JSValue::encode(result); } -DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - JSValue src = stackFrame.args[0].jsValue(); - - ASSERT(!src.isInt32()); - CallFrame* callFrame = stackFrame.callFrame; - JSValue result = jsNumber(~src.toInt32(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValue::encode(result); -} - DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base) { STUB_INIT_STACK_FRAME(stackFrame); @@ -3307,7 +3301,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq) JSValue src1 = stackFrame.args[0].jsValue(); JSValue src2 = stackFrame.args[1].jsValue(); - + bool result = JSValue::strictEqual(stackFrame.callFrame, src1, src2); CHECK_FOR_EXCEPTION_AT_END(); return JSValue::encode(jsBoolean(result)); @@ -3408,7 +3402,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_index) CallFrame* callFrame = stackFrame.callFrame; unsigned property = stackFrame.args[1].int32(); - stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue()); + JSValue arrayValue = stackFrame.args[0].jsValue(); + ASSERT(isJSArray(arrayValue)); + asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue(), false); } DEFINE_STUB_FUNCTION(void*, op_switch_imm) diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h index 890d99747..49f666465 100644 --- a/Source/JavaScriptCore/jit/JITStubs.h +++ b/Source/JavaScriptCore/jit/JITStubs.h @@ -32,6 +32,7 @@ #include "CallData.h" #include "Intrinsic.h" +#include "LowLevelInterpreter.h" #include "MacroAssemblerCodeRef.h" #include "Register.h" #include "ThunkGenerators.h" @@ -39,6 +40,8 @@ namespace JSC { +#if ENABLE(JIT) + struct StructureStubInfo; class CodeBlock; @@ -261,8 +264,6 @@ namespace JSC { #define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*)) -#if ENABLE(JIT) - #define STUB_ARGS_DECLARATION void** args #define STUB_ARGS (args) @@ -306,8 +307,22 @@ namespace JSC { MacroAssemblerCodePtr ctiVirtualConstructLink() { return m_trampolineStructure.ctiVirtualConstructLink; } MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; } MacroAssemblerCodePtr ctiVirtualConstruct() { return m_trampolineStructure.ctiVirtualConstruct; } - MacroAssemblerCodePtr ctiNativeCall() { return m_trampolineStructure.ctiNativeCall; } - MacroAssemblerCodePtr ctiNativeConstruct() { return m_trampolineStructure.ctiNativeConstruct; } + MacroAssemblerCodePtr ctiNativeCall() + { +#if ENABLE(LLINT) + if (!m_executableMemory) + return MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_call_trampoline); +#endif + return m_trampolineStructure.ctiNativeCall; + } + MacroAssemblerCodePtr ctiNativeConstruct() + { +#if ENABLE(LLINT) + if (!m_executableMemory) + return MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_construct_trampoline); +#endif + return m_trampolineStructure.ctiNativeConstruct; + } MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; } MacroAssemblerCodeRef ctiStub(JSGlobalData*, ThunkGenerator); @@ -330,7 +345,6 @@ namespace JSC { extern "C" { EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION); - EncodedJSValue JIT_STUB cti_op_bitnot(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION); diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp index 099796986..371aff2f9 100644 --- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp +++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp @@ -27,7 +27,7 @@ #include "ThunkGenerators.h" #include "CodeBlock.h" -#include "InlineASM.h" +#include <wtf/InlineASM.h> #include "SpecializedThunkJIT.h" #include <wtf/text/StringImpl.h> diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp index 9f207c510..3d9d1d33e 100644 --- a/Source/JavaScriptCore/jsc.cpp +++ b/Source/JavaScriptCore/jsc.cpp @@ -206,9 +206,9 @@ protected: addConstructableFunction(globalData, "Float64Array", constructJSFloat64Array, 1); #endif - JSObject* array = constructEmptyArray(globalExec()); + JSArray* array = constructEmptyArray(globalExec()); for (size_t i = 0; i < arguments.size(); ++i) - array->methodTable()->putByIndex(array, globalExec(), i, jsString(globalExec(), arguments[i])); + array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]), false); putDirect(globalData, Identifier(globalExec(), "arguments"), array); } diff --git a/Source/JavaScriptCore/llint/LLIntData.cpp b/Source/JavaScriptCore/llint/LLIntData.cpp index c0fe78142..983a7d706 100644 --- a/Source/JavaScriptCore/llint/LLIntData.cpp +++ b/Source/JavaScriptCore/llint/LLIntData.cpp @@ -72,6 +72,7 @@ void Data::performAssertions(JSGlobalData& globalData) ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 4); ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 0); #endif +#if USE(JSVALUE32_64) ASSERT(JSValue::Int32Tag == -1); ASSERT(JSValue::BooleanTag == -2); ASSERT(JSValue::NullTag == -3); @@ -80,12 +81,26 @@ void Data::performAssertions(JSGlobalData& globalData) ASSERT(JSValue::EmptyValueTag == -6); ASSERT(JSValue::DeletedValueTag == -7); ASSERT(JSValue::LowestTag == -7); +#else + ASSERT(TagBitTypeOther == 0x2); + ASSERT(TagBitBool == 0x4); + ASSERT(TagBitUndefined == 0x8); + ASSERT(ValueEmpty == 0x0); + ASSERT(ValueFalse == (TagBitTypeOther | TagBitBool)); + ASSERT(ValueTrue == (TagBitTypeOther | TagBitBool | 1)); + ASSERT(ValueUndefined == (TagBitTypeOther | TagBitUndefined)); + ASSERT(ValueNull == TagBitTypeOther); +#endif ASSERT(StringType == 5); ASSERT(ObjectType == 13); ASSERT(MasqueradesAsUndefined == 1); ASSERT(ImplementsHasInstance == 2); ASSERT(ImplementsDefaultHasInstance == 8); +#if USE(JSVALUE64) + ASSERT(&globalData.heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject)) - &globalData.heap.firstAllocatorWithoutDestructors() == 1); +#else ASSERT(&globalData.heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject)) - &globalData.heap.firstAllocatorWithoutDestructors() == 3); +#endif ASSERT(FirstConstantRegisterIndex == 0x40000000); ASSERT(GlobalCode == 0); ASSERT(EvalCode == 1); diff --git a/Source/JavaScriptCore/llint/LLIntEntrypoints.cpp b/Source/JavaScriptCore/llint/LLIntEntrypoints.cpp index f610f4b4c..dd7d9433d 100644 --- a/Source/JavaScriptCore/llint/LLIntEntrypoints.cpp +++ b/Source/JavaScriptCore/llint/LLIntEntrypoints.cpp @@ -30,8 +30,10 @@ #include "JITCode.h" #include "JSGlobalData.h" +#include "JSObject.h" #include "LLIntThunks.h" #include "LowLevelInterpreter.h" +#include "ScopeChain.h" namespace JSC { namespace LLInt { @@ -39,14 +41,14 @@ void getFunctionEntrypoint(JSGlobalData& globalData, CodeSpecializationKind kind { if (!globalData.canUseJIT()) { if (kind == CodeForCall) { - jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_prologue)))); - arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_call_arity_check)); + jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), JITCode::InterpreterThunk); + arityCheck = MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check); return; } ASSERT(kind == CodeForConstruct); - jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_prologue)))); - arityCheck = MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_function_for_construct_arity_check)); + jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), JITCode::InterpreterThunk); + arityCheck = MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check); return; } @@ -64,7 +66,7 @@ void getFunctionEntrypoint(JSGlobalData& globalData, CodeSpecializationKind kind void getEvalEntrypoint(JSGlobalData& globalData, JITCode& jitCode) { if (!globalData.canUseJIT()) { - jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_eval_prologue)))); + jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), JITCode::InterpreterThunk); return; } @@ -74,7 +76,7 @@ void getEvalEntrypoint(JSGlobalData& globalData, JITCode& jitCode) void getProgramEntrypoint(JSGlobalData& globalData, JITCode& jitCode) { if (!globalData.canUseJIT()) { - jitCode = JITCode::HostFunction(MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr(bitwise_cast<void*>(&llint_program_prologue)))); + jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), JITCode::InterpreterThunk); return; } diff --git a/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h b/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h index 9fe86fac4..2539ee9b3 100644 --- a/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h +++ b/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h @@ -43,6 +43,18 @@ #define OFFLINE_ASM_ARMv7 0 #endif +#if CPU(X86_64) +#define OFFLINE_ASM_X86_64 1 +#else +#define OFFLINE_ASM_X86_64 0 +#endif + +#if USE(JSVALUE64) +#define OFFLINE_ASM_JSVALUE64 1 +#else +#define OFFLINE_ASM_JSVALUE64 0 +#endif + #if !ASSERT_DISABLED #define OFFLINE_ASM_ASSERT_ENABLED 1 #else @@ -73,6 +85,12 @@ #define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 0 #endif +#if ENABLE(VALUE_PROFILER) +#define OFFLINE_ASM_VALUE_PROFILER 1 +#else +#define OFFLINE_ASM_VALUE_PROFILER 0 +#endif + #if CPU(ARM_THUMB2) #define OFFLINE_ASM_GLOBAL_LABEL(label) \ ".globl " SYMBOL_STRING(label) "\n" \ diff --git a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp index 5b76cd521..f863cb218 100644 --- a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp +++ b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp @@ -61,6 +61,7 @@ public: const unsigned* LLIntOffsetsExtractor::dummy() { +#if ENABLE(JIT) // This is a file generated by offlineasm/generate_offsets_extractor.rb, and contains code // to create a table of offsets, sizes, and a header identifying what combination of // Platform.h macros we have set. We include it inside of a method on LLIntOffsetsExtractor @@ -69,6 +70,9 @@ const unsigned* LLIntOffsetsExtractor::dummy() // compiler to kindly step aside and yield to our best intentions. #include "LLIntDesiredOffsets.h" return extractorTable; +#else + return 0; +#endif } } // namespace JSC diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index 3203d25d2..b6bb664bc 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -65,16 +65,7 @@ namespace JSC { namespace LLInt { #define LLINT_OP_C(index) (exec->r(pc[index].u.operand)) #define LLINT_RETURN_TWO(first, second) do { \ - union { \ - struct { \ - void* a; \ - void* b; \ - } pair; \ - int64_t i; \ - } __rt_u; \ - __rt_u.pair.a = first; \ - __rt_u.pair.b = second; \ - return __rt_u.i; \ + return encodeResult(first, second); \ } while (false) #define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec) @@ -114,6 +105,7 @@ namespace JSC { namespace LLInt { LLINT_END_IMPL(); \ } while (false) +#if ENABLE(VALUE_PROFILER) #define LLINT_RETURN_PROFILED(opcode, value) do { \ JSValue __rp_returnValue = (value); \ LLINT_CHECK_EXCEPTION(); \ @@ -122,6 +114,9 @@ namespace JSC { namespace LLInt { JSValue::encode(__rp_returnValue); \ LLINT_END_IMPL(); \ } while (false) +#else // ENABLE(VALUE_PROFILER) +#define LLINT_RETURN_PROFILED(opcode, value) LLINT_RETURN(value) +#endif // ENABLE(VALUE_PROFILER) #define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec)) @@ -163,7 +158,6 @@ extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand) { - LLINT_BEGIN(); JSValue value = LLINT_OP_C(operand).jsValue(); union { struct { @@ -184,14 +178,13 @@ extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc u.bits.tag, u.bits.payload, value.description()); - LLINT_END(); + LLINT_END_IMPL(); } LLINT_SLOW_PATH_DECL(trace_prologue) { - LLINT_BEGIN(); dataLog("%p / %p: in prologue.\n", exec->codeBlock(), exec); - LLINT_END(); + LLINT_END_IMPL(); } static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind) @@ -207,54 +200,52 @@ static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpec LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call) { - LLINT_BEGIN(); traceFunctionPrologue(exec, "call prologue", CodeForCall); - LLINT_END(); + LLINT_END_IMPL(); } LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct) { - LLINT_BEGIN(); traceFunctionPrologue(exec, "construct prologue", CodeForConstruct); - LLINT_END(); + LLINT_END_IMPL(); } LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call) { - LLINT_BEGIN(); traceFunctionPrologue(exec, "call arity check", CodeForCall); - LLINT_END(); + LLINT_END_IMPL(); } LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct) { - LLINT_BEGIN(); traceFunctionPrologue(exec, "construct arity check", CodeForConstruct); - LLINT_END(); + LLINT_END_IMPL(); } LLINT_SLOW_PATH_DECL(trace) { - LLINT_BEGIN(); dataLog("%p / %p: executing bc#%zu, %s, scope %p\n", exec->codeBlock(), exec, static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), opcodeNames[exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode)], exec->scopeChain()); - LLINT_END(); + if (exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode) == op_ret) { + dataLog("Will be returning to %p\n", exec->returnPC().value()); + dataLog("The new cfr will be %p\n", exec->callerFrame()); + } + LLINT_END_IMPL(); } LLINT_SLOW_PATH_DECL(special_trace) { - LLINT_BEGIN(); dataLog("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n", exec->codeBlock(), exec, static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode), exec->returnPC().value()); - LLINT_END(); + LLINT_END_IMPL(); } inline bool shouldJIT(ExecState* exec) @@ -263,6 +254,41 @@ inline bool shouldJIT(ExecState* exec) return exec->globalData().canUseJIT(); } +// Returns true if we should try to OSR. +inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec) +{ + if (!codeBlock->checkIfJITThresholdReached()) { +#if ENABLE(JIT_VERBOSE_OSR) + dataLog(" JIT threshold should be lifted.\n"); +#endif + return false; + } + + CodeBlock::JITCompilationResult result = codeBlock->jitCompile(exec->globalData()); + switch (result) { + case CodeBlock::AlreadyCompiled: +#if ENABLE(JIT_VERBOSE_OSR) + dataLog(" Code was already compiled.\n"); +#endif + codeBlock->jitSoon(); + return true; + case CodeBlock::CouldNotCompile: +#if ENABLE(JIT_VERBOSE_OSR) + dataLog(" JIT compilation failed.\n"); +#endif + codeBlock->dontJITAnytimeSoon(); + return false; + case CodeBlock::CompiledSuccessfully: +#if ENABLE(JIT_VERBOSE_OSR) + dataLog(" JIT compilation successful.\n"); +#endif + codeBlock->jitSoon(); + return true; + } + ASSERT_NOT_REACHED(); + return false; +} + enum EntryKind { Prologue, ArityCheck }; static SlowPathReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind) { @@ -274,12 +300,9 @@ static SlowPathReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock->dontJITAnytimeSoon(); LLINT_RETURN_TWO(0, exec); } - if (!codeBlock->jitCompile(exec->globalData())) { -#if ENABLE(JIT_VERBOSE_OSR) - dataLog(" Code was already compiled.\n"); -#endif - } - codeBlock->jitSoon(); + if (!jitCompileAndSetHeuristics(codeBlock, exec)) + LLINT_RETURN_TWO(0, exec); + if (kind == Prologue) LLINT_RETURN_TWO(codeBlock->getJITCode().executableAddressAtOffset(0), exec); ASSERT(kind == ArityCheck); @@ -324,12 +347,8 @@ LLINT_SLOW_PATH_DECL(loop_osr) LLINT_RETURN_TWO(0, exec); } - if (!codeBlock->jitCompile(exec->globalData())) { -#if ENABLE(JIT_VERBOSE_OSR) - dataLog(" Code was already compiled.\n"); -#endif - } - codeBlock->jitSoon(); + if (!jitCompileAndSetHeuristics(codeBlock, exec)) + LLINT_RETURN_TWO(0, exec); ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT); @@ -353,14 +372,9 @@ LLINT_SLOW_PATH_DECL(replace) dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter()); #endif - if (shouldJIT(exec)) { - if (!codeBlock->jitCompile(exec->globalData())) { -#if ENABLE(JIT_VERBOSE_OSR) - dataLog(" Code was already compiled.\n"); -#endif - } - codeBlock->jitSoon(); - } else + if (shouldJIT(exec)) + jitCompileAndSetHeuristics(codeBlock, exec); + else codeBlock->dontJITAnytimeSoon(); LLINT_END_IMPL(); } @@ -664,12 +678,6 @@ LLINT_SLOW_PATH_DECL(slow_path_bitxor) LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec))); } -LLINT_SLOW_PATH_DECL(slow_path_bitnot) -{ - LLINT_BEGIN(); - LLINT_RETURN(jsNumber(~LLINT_OP_C(2).jsValue().toInt32(exec))); -} - LLINT_SLOW_PATH_DECL(slow_path_check_has_instance) { LLINT_BEGIN(); @@ -873,8 +881,10 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue); } } - + +#if ENABLE(VALUE_PROFILER) pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result); +#endif LLINT_END(); } @@ -1023,7 +1033,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_val) if (jsArray->canSetIndex(i)) jsArray->setIndex(globalData, i, value); else - JSArray::putByIndex(jsArray, exec, i, value); + JSArray::putByIndex(jsArray, exec, i, value, exec->codeBlock()->isStrictMode()); LLINT_END(); } if (isJSByteArray(baseValue) @@ -1038,7 +1048,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_val) LLINT_END(); } } - baseValue.put(exec, i, value); + baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode()); LLINT_END(); } @@ -1078,7 +1088,9 @@ LLINT_SLOW_PATH_DECL(slow_path_del_by_val) LLINT_SLOW_PATH_DECL(slow_path_put_by_index) { LLINT_BEGIN(); - LLINT_OP_C(1).jsValue().put(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue()); + JSValue arrayValue = LLINT_OP_C(1).jsValue(); + ASSERT(isJSArray(arrayValue)); + asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue(), false); LLINT_END(); } @@ -1384,7 +1396,7 @@ LLINT_SLOW_PATH_DECL(slow_path_call_varargs) execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue; execCallee->setCallerFrame(exec); - exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_varargs)); + exec->setCurrentVPC(pc + OPCODE_LENGTH(op_call_varargs)); return setUpCall(execCallee, pc, CodeForCall, calleeAsValue); } @@ -1402,7 +1414,7 @@ LLINT_SLOW_PATH_DECL(slow_path_call_eval) execCallee->setScopeChain(exec->scopeChain()); execCallee->setReturnPC(bitwise_cast<Instruction*>(&llint_generic_return_point)); execCallee->setCodeBlock(0); - exec->uncheckedR(RegisterFile::ArgumentCount).tag() = bitwise_cast<int32_t>(pc + OPCODE_LENGTH(op_call_eval)); + exec->setCurrentVPC(pc + OPCODE_LENGTH(op_call_eval)); if (!isHostFunction(calleeAsValue, globalFuncEval)) return setUpCall(execCallee, pc, CodeForCall, calleeAsValue); @@ -1553,6 +1565,13 @@ LLINT_SLOW_PATH_DECL(slow_path_profile_did_call) LLINT_END(); } +LLINT_SLOW_PATH_DECL(throw_from_native_call) +{ + LLINT_BEGIN(); + ASSERT(globalData.exception); + LLINT_END(); +} + } } // namespace JSC::LLInt #endif // ENABLE(LLINT) diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.h b/Source/JavaScriptCore/llint/LLIntSlowPaths.h index fe684d306..334070a07 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.h +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.h @@ -38,8 +38,40 @@ struct Instruction; namespace LLInt { +#if USE(JSVALUE64) +struct SlowPathReturnType { + void* a; + void* b; + + SlowPathReturnType(void* a, void* b) + : a(a) + , b(b) + { + } +}; + +inline SlowPathReturnType encodeResult(void* a, void* b) +{ + return SlowPathReturnType(a, b); +} +#else typedef int64_t SlowPathReturnType; +inline SlowPathReturnType encodeResult(void* a, void* b) +{ + union { + struct { + void* a; + void* b; + } pair; + int64_t i; + } u; + u.pair.a = a; + u.pair.b = b; + return u.i; +} +#endif + extern "C" SlowPathReturnType llint_trace_operand(ExecState*, Instruction*, int fromWhere, int operand); extern "C" SlowPathReturnType llint_trace_value(ExecState*, Instruction*, int fromWhere, int operand); @@ -97,7 +129,6 @@ LLINT_SLOW_PATH_DECL(slow_path_urshift); LLINT_SLOW_PATH_DECL(slow_path_bitand); LLINT_SLOW_PATH_DECL(slow_path_bitor); LLINT_SLOW_PATH_DECL(slow_path_bitxor); -LLINT_SLOW_PATH_DECL(slow_path_bitnot); LLINT_SLOW_PATH_DECL(slow_path_check_has_instance); LLINT_SLOW_PATH_DECL(slow_path_instanceof); LLINT_SLOW_PATH_DECL(slow_path_typeof); @@ -162,6 +193,7 @@ LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error); LLINT_SLOW_PATH_DECL(slow_path_debug); LLINT_SLOW_PATH_DECL(slow_path_profile_will_call); LLINT_SLOW_PATH_DECL(slow_path_profile_did_call); +LLINT_SLOW_PATH_DECL(throw_from_native_call); } } // namespace JSC::LLInt diff --git a/Source/JavaScriptCore/llint/LLIntThunks.cpp b/Source/JavaScriptCore/llint/LLIntThunks.cpp index ddb0c46c2..b4d026423 100644 --- a/Source/JavaScriptCore/llint/LLIntThunks.cpp +++ b/Source/JavaScriptCore/llint/LLIntThunks.cpp @@ -29,8 +29,10 @@ #if ENABLE(LLINT) #include "JSInterfaceJIT.h" +#include "JSObject.h" #include "LinkBuffer.h" #include "LowLevelInterpreter.h" +#include "ScopeChain.h" namespace JSC { namespace LLInt { diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm index a9f83f680..9af91bef2 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm @@ -21,54 +21,8 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. - -# Crash course on the language that this is written in (which I just call -# "assembly" even though it's more than that): -# -# - Mostly gas-style operand ordering. The last operand tends to be the -# destination. So "a := b" is written as "mov b, a". But unlike gas, -# comparisons are in-order, so "if (a < b)" is written as -# "bilt a, b, ...". -# -# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer. -# Currently this is just 32-bit so "i" and "p" are interchangeable -# except when an op supports one but not the other. -# -# - In general, valid operands for macro invocations and instructions are -# registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses -# (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels -# (eg "_foo" or ".foo"). Macro invocations can also take anonymous -# macros as operands. Instructions cannot take anonymous macros. -# -# - Labels must have names that begin with either "_" or ".". A "." label -# is local and gets renamed before code gen to minimize namespace -# pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_" -# may or may not be removed during code gen depending on whether the asm -# conventions for C name mangling on the target platform mandate a "_" -# prefix. -# -# - A "macro" is a lambda expression, which may be either anonymous or -# named. But this has caveats. "macro" can take zero or more arguments, -# which may be macros or any valid operands, but it can only return -# code. But you can do Turing-complete things via continuation passing -# style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do -# that, since you'll just crash the assembler. -# -# - An "if" is a conditional on settings. Any identifier supplied in the -# predicate of an "if" is assumed to be a #define that is available -# during code gen. So you can't use "if" for computation in a macro, but -# you can use it to select different pieces of code for different -# platforms. -# -# - Arguments to macros follow lexical scoping rather than dynamic scoping. -# Const's also follow lexical scoping and may override (hide) arguments -# or other consts. All variables (arguments and constants) can be bound -# to operands. Additionally, arguments (but not constants) can be bound -# to macros. - - -# Below we have a bunch of constant declarations. Each constant must have -# a corresponding ASSERT() in LLIntData.cpp. +# First come the common protocols that both interpreters use. Note that each +# of these must have an ASSERT() in LLIntData.cpp # These declarations must match interpreter/RegisterFile.h. const CallFrameHeaderSize = 48 @@ -81,10 +35,24 @@ const CodeBlock = -8 const ThisArgumentOffset = -CallFrameHeaderSize - 8 -# Declare some aliases for the registers we will use. -const PC = t4 +# Some register conventions. +if JSVALUE64 + # - Use a pair of registers to represent the PC: one register for the + # base of the register file, and one register for the index. + # - The PC base (or PB for short) should be stored in the csr. It will + # get clobbered on calls to other JS code, but will get saved on calls + # to C functions. + # - C calls are still given the Instruction* rather than the PC index. + # This requires an add before the call, and a sub after. + const PC = t4 + const PB = t6 + const tagTypeNumber = csr1 + const tagMask = csr2 +else + const PC = t4 +end -# Offsets needed for reasoning about value representation. +# Constants for reasoning about value representation. if BIG_ENDIAN const TagOffset = 0 const PayloadOffset = 4 @@ -93,16 +61,6 @@ else const PayloadOffset = 0 end -# Value representation constants. -const Int32Tag = -1 -const BooleanTag = -2 -const NullTag = -3 -const UndefinedTag = -4 -const CellTag = -5 -const EmptyValueTag = -6 -const DeletedValueTag = -7 -const LowestTag = DeletedValueTag - # Type constants. const StringType = 5 const ObjectType = 13 @@ -112,9 +70,6 @@ const MasqueradesAsUndefined = 1 const ImplementsHasInstance = 2 const ImplementsDefaultHasInstance = 8 -# Heap allocation constants. -const JSFinalObjectSizeClassIndex = 3 - # Bytecode operand constants. const FirstConstantRegisterIndex = 0x40000000 @@ -126,14 +81,27 @@ const FunctionCode = 2 # The interpreter steals the tag word of the argument count. const LLIntReturnPC = ArgumentCount + TagOffset -# This must match wtf/Vector.h. -const VectorSizeOffset = 0 -const VectorBufferOffset = 4 - # String flags. const HashFlags8BitBuffer = 64 -# Utilities +# Allocation constants +if JSVALUE64 + const JSFinalObjectSizeClassIndex = 1 +else + const JSFinalObjectSizeClassIndex = 3 +end + +# This must match wtf/Vector.h +if JSVALUE64 + const VectorSizeOffset = 0 + const VectorBufferOffset = 8 +else + const VectorSizeOffset = 0 + const VectorBufferOffset = 4 +end + + +# Some common utilities. macro crash() storei 0, 0xbbadbeef[] move 0, t0 @@ -151,7 +119,7 @@ end macro preserveReturnAddressAfterCall(destinationRegister) if ARMv7 move lr, destinationRegister - elsif X86 + elsif X86 or X86_64 pop destinationRegister else error @@ -161,109 +129,23 @@ end macro restoreReturnAddressBeforeReturn(sourceRegister) if ARMv7 move sourceRegister, lr - elsif X86 + elsif X86 or X86_64 push sourceRegister else error end end -macro dispatch(advance) - addp advance * 4, PC - jmp [PC] -end - -macro dispatchBranchWithOffset(pcOffset) - lshifti 2, pcOffset - addp pcOffset, PC - jmp [PC] -end - -macro dispatchBranch(pcOffset) - loadi pcOffset, t0 - dispatchBranchWithOffset(t0) -end - -macro dispatchAfterCall() - loadi ArgumentCount + TagOffset[cfr], PC - jmp [PC] -end - -macro cCall2(function, arg1, arg2) - if ARMv7 - move arg1, t0 - move arg2, t1 - elsif X86 - poke arg1, 0 - poke arg2, 1 - else - error - end - call function -end - -# This barely works. arg3 and arg4 should probably be immediates. -macro cCall4(function, arg1, arg2, arg3, arg4) - if ARMv7 - move arg1, t0 - move arg2, t1 - move arg3, t2 - move arg4, t3 - elsif X86 - poke arg1, 0 - poke arg2, 1 - poke arg3, 2 - poke arg4, 3 - else - error - end - call function -end - -macro callSlowPath(slow_path) - cCall2(slow_path, cfr, PC) - move t0, PC - move t1, cfr -end - -# Debugging operation if you'd like to print an operand in the instruction stream. fromWhere -# should be an immediate integer - any integer you like; use it to identify the place you're -# debugging from. operand should likewise be an immediate, and should identify the operand -# in the instruction stream you'd like to print out. -macro traceOperand(fromWhere, operand) - cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand) - move t0, PC - move t1, cfr -end - -# Debugging operation if you'd like to print the value of an operand in the instruction -# stream. Same as traceOperand(), but assumes that the operand is a register, and prints its -# value. -macro traceValue(fromWhere, operand) - cCall4(_llint_trace_value, cfr, PC, fromWhere, operand) - move t0, PC - move t1, cfr -end - macro traceExecution() if EXECUTION_TRACING callSlowPath(_llint_trace) end end -# Call a slow_path for call opcodes. -macro callCallSlowPath(advance, slow_path, action) - addp advance * 4, PC, t0 - storep t0, ArgumentCount + TagOffset[cfr] - cCall2(slow_path, cfr, PC) - move t1, cfr - action(t0) -end - -macro slowPathForCall(advance, slow_path) +macro slowPathForCall(advance, slowPath) callCallSlowPath( advance, - slow_path, + slowPath, macro (callee) call callee dispatchAfterCall() @@ -273,26 +155,12 @@ end macro checkSwitchToJIT(increment, action) if JIT_ENABLED loadp CodeBlock[cfr], t0 - baddis increment, CodeBlock::m_llintExecuteCounter[t0], .continue + baddis increment, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t0], .continue action() .continue: end end -macro checkSwitchToJITForLoop() - checkSwitchToJIT( - 1, - macro () - storei PC, ArgumentCount + TagOffset[cfr] - cCall2(_llint_loop_osr, cfr, PC) - move t1, cfr - btpz t0, .recover - jmp t0 - .recover: - loadi ArgumentCount + TagOffset[cfr], PC - end) -end - macro checkSwitchToJITForEpilogue() checkSwitchToJIT( 10, @@ -305,94 +173,6 @@ macro assertNotConstant(index) assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end) end -# Index, tag, and payload must be different registers. Index is not -# changed. -macro loadConstantOrVariable(index, tag, payload) - bigteq index, FirstConstantRegisterIndex, .constant - loadi TagOffset[cfr, index, 8], tag - loadi PayloadOffset[cfr, index, 8], payload - jmp .done -.constant: - loadp CodeBlock[cfr], payload - loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload - # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex, - # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3. - loadp TagOffset[payload, index, 8], tag - loadp PayloadOffset[payload, index, 8], payload -.done: -end - -# Index and payload may be the same register. Index may be clobbered. -macro loadConstantOrVariable2Reg(index, tag, payload) - bigteq index, FirstConstantRegisterIndex, .constant - loadi TagOffset[cfr, index, 8], tag - loadi PayloadOffset[cfr, index, 8], payload - jmp .done -.constant: - loadp CodeBlock[cfr], tag - loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag - # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex, - # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3. - lshifti 3, index - addp index, tag - loadp PayloadOffset[tag], payload - loadp TagOffset[tag], tag -.done: -end - -macro loadConstantOrVariablePayloadTagCustom(index, tagCheck, payload) - bigteq index, FirstConstantRegisterIndex, .constant - tagCheck(TagOffset[cfr, index, 8]) - loadi PayloadOffset[cfr, index, 8], payload - jmp .done -.constant: - loadp CodeBlock[cfr], payload - loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload - # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex, - # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3. - tagCheck(TagOffset[payload, index, 8]) - loadp PayloadOffset[payload, index, 8], payload -.done: -end - -# Index and payload must be different registers. Index is not mutated. Use -# this if you know what the tag of the variable should be. Doing the tag -# test as part of loading the variable reduces register use, but may not -# be faster than doing loadConstantOrVariable followed by a branch on the -# tag. -macro loadConstantOrVariablePayload(index, expectedTag, payload, slow) - loadConstantOrVariablePayloadTagCustom( - index, - macro (actualTag) bineq actualTag, expectedTag, slow end, - payload) -end - -macro loadConstantOrVariablePayloadUnchecked(index, payload) - loadConstantOrVariablePayloadTagCustom( - index, - macro (actualTag) end, - payload) -end - -macro writeBarrier(tag, payload) - # Nothing to do, since we don't have a generational or incremental collector. -end - -macro valueProfile(tag, payload, profile) - if JIT_ENABLED - storei tag, ValueProfile::m_buckets + TagOffset[profile] - storei payload, ValueProfile::m_buckets + PayloadOffset[profile] - end -end - - -# Indicate the beginning of LLInt. -_llint_begin: - crash() - - -# Entrypoints into the interpreter - macro functionForCallCodeBlockGetter(targetRegister) loadp Callee[cfr], targetRegister loadp JSFunction::m_executable[targetRegister], targetRegister @@ -429,7 +209,7 @@ macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath) end codeBlockGetter(t1) if JIT_ENABLED - baddis 5, CodeBlock::m_llintExecuteCounter[t1], .continue + baddis 5, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t1], .continue cCall2(osrSlowPath, cfr, PC) move t1, cfr btpz t0, .recover @@ -443,14 +223,18 @@ macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath) codeBlockSetter(t1) # Set up the PC. - loadp CodeBlock::m_instructions[t1], t0 - loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC + if JSVALUE64 + loadp CodeBlock::m_instructions[t1], PB + move 0, PC + else + loadp CodeBlock::m_instructions[t1], PC + end end # Expects that CodeBlock is in t1, which is what prologue() leaves behind. # Must call dispatch(0) after calling this. macro functionInitialization(profileArgSkip) - if JIT_ENABLED + if VALUE_PROFILER # Profile the arguments. Unfortunately, we have no choice but to do this. This # code is pretty horrendous because of the difference in ordering between # arguments and value profiles, the desire to have a simple loop-down-to-zero @@ -459,21 +243,27 @@ macro functionInitialization(profileArgSkip) # optimal way for architectures that have more than five registers available # for arbitrary use in the interpreter. loadi CodeBlock::m_numParameters[t1], t0 - addi -profileArgSkip, t0 # Use addi because that's what has the peephole - assert(macro (ok) bigteq t0, 0, ok end) - btiz t0, .argumentProfileDone + addp -profileArgSkip, t0 # Use addi because that's what has the peephole + assert(macro (ok) bpgteq t0, 0, ok end) + btpz t0, .argumentProfileDone loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3 - muli sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction! - negi t0 - lshifti 3, t0 + mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction! + negp t0 + lshiftp 3, t0 addp t2, t3 .argumentProfileLoop: - loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2 - subp sizeof ValueProfile, t3 - storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3] - loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2 - storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3] - baddinz 8, t0, .argumentProfileLoop + if JSVALUE64 + loadp ThisArgumentOffset + 8 - profileArgSkip * 8[cfr, t0], t2 + subp sizeof ValueProfile, t3 + storep t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3] + else + loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2 + subp sizeof ValueProfile, t3 + storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3] + loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2 + storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3] + end + baddpnz 8, t0, .argumentProfileLoop .argumentProfileDone: end @@ -490,101 +280,6 @@ macro functionInitialization(profileArgSkip) .stackHeightOK: end -# Expects that CodeBlock is in t1, which is what prologue() leaves behind. -macro functionArityCheck(doneLabel, slow_path) - loadi PayloadOffset + ArgumentCount[cfr], t0 - biaeq t0, CodeBlock::m_numParameters[t1], doneLabel - cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error - move t1, cfr - btiz t0, .continue - loadp JITStackFrame::globalData[sp], t1 - loadp JSGlobalData::callFrameForThrow[t1], t0 - jmp JSGlobalData::targetMachinePCForThrow[t1] -.continue: - # Reload CodeBlock and PC, since the slow_path clobbered it. - loadp CodeBlock[cfr], t1 - loadp CodeBlock::m_instructions[t1], t0 - loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC - jmp doneLabel -end - -_llint_program_prologue: - prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) - dispatch(0) - - -_llint_eval_prologue: - prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) - dispatch(0) - - -_llint_function_for_call_prologue: - prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call) -.functionForCallBegin: - functionInitialization(0) - dispatch(0) - - -_llint_function_for_construct_prologue: - prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct) -.functionForConstructBegin: - functionInitialization(1) - dispatch(0) - - -_llint_function_for_call_arity_check: - prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call) - functionArityCheck(.functionForCallBegin, _llint_slow_path_call_arityCheck) - - -_llint_function_for_construct_arity_check: - prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct) - functionArityCheck(.functionForConstructBegin, _llint_slow_path_construct_arityCheck) - -# Instruction implementations - -_llint_op_enter: - traceExecution() - loadp CodeBlock[cfr], t2 - loadi CodeBlock::m_numVars[t2], t2 - btiz t2, .opEnterDone - move UndefinedTag, t0 - move 0, t1 -.opEnterLoop: - subi 1, t2 - storei t0, TagOffset[cfr, t2, 8] - storei t1, PayloadOffset[cfr, t2, 8] - btinz t2, .opEnterLoop -.opEnterDone: - dispatch(1) - - -_llint_op_create_activation: - traceExecution() - loadi 4[PC], t0 - bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateActivationDone - callSlowPath(_llint_slow_path_create_activation) -.opCreateActivationDone: - dispatch(2) - - -_llint_op_init_lazy_reg: - traceExecution() - loadi 4[PC], t0 - storei EmptyValueTag, TagOffset[cfr, t0, 8] - storei 0, PayloadOffset[cfr, t0, 8] - dispatch(2) - - -_llint_op_create_arguments: - traceExecution() - loadi 4[PC], t0 - bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateArgumentsDone - callSlowPath(_llint_slow_path_create_arguments) -.opCreateArgumentsDone: - dispatch(2) - - macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result, scratch1, scratch2, slowCase) if ALWAYS_ALLOCATE_SLOW jmp slowCase @@ -618,66 +313,62 @@ macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result, end end -_llint_op_create_this: - traceExecution() - loadi 8[PC], t0 - assertNotConstant(t0) - bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow - loadi PayloadOffset[cfr, t0, 8], t0 - loadp JSCell::m_structure[t0], t1 - bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow - loadp JSObject::m_inheritorID[t0], t2 - btpz t2, .opCreateThisSlow - allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow) - loadi 4[PC], t1 - storei CellTag, TagOffset[cfr, t1, 8] - storei t0, PayloadOffset[cfr, t1, 8] - dispatch(3) +macro doReturn() + loadp ReturnPC[cfr], t2 + loadp CallerFrame[cfr], cfr + restoreReturnAddressBeforeReturn(t2) + ret +end -.opCreateThisSlow: - callSlowPath(_llint_slow_path_create_this) - dispatch(3) +# Indicate the beginning of LLInt. +_llint_begin: + crash() -_llint_op_get_callee: - traceExecution() - loadi 4[PC], t0 - loadp PayloadOffset + Callee[cfr], t1 - storei CellTag, TagOffset[cfr, t0, 8] - storei t1, PayloadOffset[cfr, t0, 8] - dispatch(2) +_llint_program_prologue: + prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) + dispatch(0) -_llint_op_convert_this: - traceExecution() - loadi 4[PC], t0 - bineq TagOffset[cfr, t0, 8], CellTag, .opConvertThisSlow - loadi PayloadOffset[cfr, t0, 8], t0 - loadp JSCell::m_structure[t0], t0 - bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow - dispatch(2) -.opConvertThisSlow: - callSlowPath(_llint_slow_path_convert_this) - dispatch(2) +_llint_eval_prologue: + prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue) + dispatch(0) -_llint_op_new_object: - traceExecution() - loadp CodeBlock[cfr], t0 - loadp CodeBlock::m_globalObject[t0], t0 - loadp JSGlobalObject::m_emptyObjectStructure[t0], t1 - allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow) - loadi 4[PC], t1 - storei CellTag, TagOffset[cfr, t1, 8] - storei t0, PayloadOffset[cfr, t1, 8] - dispatch(2) +_llint_function_for_call_prologue: + prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call) +.functionForCallBegin: + functionInitialization(0) + dispatch(0) + -.opNewObjectSlow: - callSlowPath(_llint_slow_path_new_object) - dispatch(2) +_llint_function_for_construct_prologue: + prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct) +.functionForConstructBegin: + functionInitialization(1) + dispatch(0) + + +_llint_function_for_call_arity_check: + prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call) + functionArityCheck(.functionForCallBegin, _llint_slow_path_call_arityCheck) + + +_llint_function_for_construct_arity_check: + prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct) + functionArityCheck(.functionForConstructBegin, _llint_slow_path_construct_arityCheck) + + +# Value-representation-specific code. +if JSVALUE64 + include LowLevelInterpreter64 +else + include LowLevelInterpreter32_64 +end +# Value-representation-agnostic code. _llint_op_new_array: traceExecution() callSlowPath(_llint_slow_path_new_array) @@ -696,148 +387,6 @@ _llint_op_new_regexp: dispatch(3) -_llint_op_mov: - traceExecution() - loadi 8[PC], t1 - loadi 4[PC], t0 - loadConstantOrVariable(t1, t2, t3) - storei t2, TagOffset[cfr, t0, 8] - storei t3, PayloadOffset[cfr, t0, 8] - dispatch(3) - - -_llint_op_not: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t1 - loadConstantOrVariable(t0, t2, t3) - bineq t2, BooleanTag, .opNotSlow - xori 1, t3 - storei t2, TagOffset[cfr, t1, 8] - storei t3, PayloadOffset[cfr, t1, 8] - dispatch(3) - -.opNotSlow: - callSlowPath(_llint_slow_path_not) - dispatch(3) - - -_llint_op_eq: - traceExecution() - loadi 12[PC], t2 - loadi 8[PC], t0 - loadConstantOrVariable(t2, t3, t1) - loadConstantOrVariable2Reg(t0, t2, t0) - bineq t2, t3, .opEqSlow - bieq t2, CellTag, .opEqSlow - bib t2, LowestTag, .opEqSlow - loadi 4[PC], t2 - cieq t0, t1, t0 - storei BooleanTag, TagOffset[cfr, t2, 8] - storei t0, PayloadOffset[cfr, t2, 8] - dispatch(4) - -.opEqSlow: - callSlowPath(_llint_slow_path_eq) - dispatch(4) - - -_llint_op_eq_null: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t3 - assertNotConstant(t0) - loadi TagOffset[cfr, t0, 8], t1 - loadi PayloadOffset[cfr, t0, 8], t0 - bineq t1, CellTag, .opEqNullImmediate - loadp JSCell::m_structure[t0], t1 - tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 - jmp .opEqNullNotImmediate -.opEqNullImmediate: - cieq t1, NullTag, t2 - cieq t1, UndefinedTag, t1 - ori t2, t1 -.opEqNullNotImmediate: - storei BooleanTag, TagOffset[cfr, t3, 8] - storei t1, PayloadOffset[cfr, t3, 8] - dispatch(3) - - -_llint_op_neq: - traceExecution() - loadi 12[PC], t2 - loadi 8[PC], t0 - loadConstantOrVariable(t2, t3, t1) - loadConstantOrVariable2Reg(t0, t2, t0) - bineq t2, t3, .opNeqSlow - bieq t2, CellTag, .opNeqSlow - bib t2, LowestTag, .opNeqSlow - loadi 4[PC], t2 - cineq t0, t1, t0 - storei BooleanTag, TagOffset[cfr, t2, 8] - storei t0, PayloadOffset[cfr, t2, 8] - dispatch(4) - -.opNeqSlow: - callSlowPath(_llint_slow_path_neq) - dispatch(4) - - -_llint_op_neq_null: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t3 - assertNotConstant(t0) - loadi TagOffset[cfr, t0, 8], t1 - loadi PayloadOffset[cfr, t0, 8], t0 - bineq t1, CellTag, .opNeqNullImmediate - loadp JSCell::m_structure[t0], t1 - tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 - jmp .opNeqNullNotImmediate -.opNeqNullImmediate: - cineq t1, NullTag, t2 - cineq t1, UndefinedTag, t1 - andi t2, t1 -.opNeqNullNotImmediate: - storei BooleanTag, TagOffset[cfr, t3, 8] - storei t1, PayloadOffset[cfr, t3, 8] - dispatch(3) - - -macro strictEq(equalityOperation, slow_path) - loadi 12[PC], t2 - loadi 8[PC], t0 - loadConstantOrVariable(t2, t3, t1) - loadConstantOrVariable2Reg(t0, t2, t0) - bineq t2, t3, .slow - bib t2, LowestTag, .slow - bineq t2, CellTag, .notString - loadp JSCell::m_structure[t0], t2 - loadp JSCell::m_structure[t1], t3 - bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .notString - bbeq Structure::m_typeInfo + TypeInfo::m_type[t3], StringType, .slow -.notString: - loadi 4[PC], t2 - equalityOperation(t0, t1, t0) - storei BooleanTag, TagOffset[cfr, t2, 8] - storei t0, PayloadOffset[cfr, t2, 8] - dispatch(4) - -.slow: - callSlowPath(slow_path) - dispatch(4) -end - -_llint_op_stricteq: - traceExecution() - strictEq(macro (left, right, result) cieq left, right, result end, _llint_slow_path_stricteq) - - -_llint_op_nstricteq: - traceExecution() - strictEq(macro (left, right, result) cineq left, right, result end, _llint_slow_path_nstricteq) - - _llint_op_less: traceExecution() callSlowPath(_llint_slow_path_less) @@ -862,360 +411,12 @@ _llint_op_greatereq: dispatch(4) -_llint_op_pre_inc: - traceExecution() - loadi 4[PC], t0 - bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreIncSlow - loadi PayloadOffset[cfr, t0, 8], t1 - baddio 1, t1, .opPreIncSlow - storei t1, PayloadOffset[cfr, t0, 8] - dispatch(2) - -.opPreIncSlow: - callSlowPath(_llint_slow_path_pre_inc) - dispatch(2) - - -_llint_op_pre_dec: - traceExecution() - loadi 4[PC], t0 - bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreDecSlow - loadi PayloadOffset[cfr, t0, 8], t1 - bsubio 1, t1, .opPreDecSlow - storei t1, PayloadOffset[cfr, t0, 8] - dispatch(2) - -.opPreDecSlow: - callSlowPath(_llint_slow_path_pre_dec) - dispatch(2) - - -_llint_op_post_inc: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t1 - bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostIncSlow - bieq t0, t1, .opPostIncDone - loadi PayloadOffset[cfr, t0, 8], t2 - move t2, t3 - baddio 1, t3, .opPostIncSlow - storei Int32Tag, TagOffset[cfr, t1, 8] - storei t2, PayloadOffset[cfr, t1, 8] - storei t3, PayloadOffset[cfr, t0, 8] -.opPostIncDone: - dispatch(3) - -.opPostIncSlow: - callSlowPath(_llint_slow_path_post_inc) - dispatch(3) - - -_llint_op_post_dec: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t1 - bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostDecSlow - bieq t0, t1, .opPostDecDone - loadi PayloadOffset[cfr, t0, 8], t2 - move t2, t3 - bsubio 1, t3, .opPostDecSlow - storei Int32Tag, TagOffset[cfr, t1, 8] - storei t2, PayloadOffset[cfr, t1, 8] - storei t3, PayloadOffset[cfr, t0, 8] -.opPostDecDone: - dispatch(3) - -.opPostDecSlow: - callSlowPath(_llint_slow_path_post_dec) - dispatch(3) - - -_llint_op_to_jsnumber: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t1 - loadConstantOrVariable(t0, t2, t3) - bieq t2, Int32Tag, .opToJsnumberIsInt - biaeq t2, EmptyValueTag, .opToJsnumberSlow -.opToJsnumberIsInt: - storei t2, TagOffset[cfr, t1, 8] - storei t3, PayloadOffset[cfr, t1, 8] - dispatch(3) - -.opToJsnumberSlow: - callSlowPath(_llint_slow_path_to_jsnumber) - dispatch(3) - - -_llint_op_negate: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t3 - loadConstantOrVariable(t0, t1, t2) - bineq t1, Int32Tag, .opNegateSrcNotInt - btiz t2, 0x7fffffff, .opNegateSlow - negi t2 - storei Int32Tag, TagOffset[cfr, t3, 8] - storei t2, PayloadOffset[cfr, t3, 8] - dispatch(3) -.opNegateSrcNotInt: - bia t1, LowestTag, .opNegateSlow - xori 0x80000000, t1 - storei t1, TagOffset[cfr, t3, 8] - storei t2, PayloadOffset[cfr, t3, 8] - dispatch(3) - -.opNegateSlow: - callSlowPath(_llint_slow_path_negate) - dispatch(3) - - -macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slow_path) - loadi 12[PC], t2 - loadi 8[PC], t0 - loadConstantOrVariable(t2, t3, t1) - loadConstantOrVariable2Reg(t0, t2, t0) - bineq t2, Int32Tag, .op1NotInt - bineq t3, Int32Tag, .op2NotInt - loadi 4[PC], t2 - integerOperationAndStore(t3, t1, t0, .slow, t2) - dispatch(5) - -.op1NotInt: - # First operand is definitely not an int, the second operand could be anything. - bia t2, LowestTag, .slow - bib t3, LowestTag, .op1NotIntOp2Double - bineq t3, Int32Tag, .slow - ci2d t1, ft1 - jmp .op1NotIntReady -.op1NotIntOp2Double: - fii2d t1, t3, ft1 -.op1NotIntReady: - loadi 4[PC], t1 - fii2d t0, t2, ft0 - doubleOperation(ft1, ft0) - stored ft0, [cfr, t1, 8] - dispatch(5) - -.op2NotInt: - # First operand is definitely an int, the second operand is definitely not. - loadi 4[PC], t2 - bia t3, LowestTag, .slow - ci2d t0, ft0 - fii2d t1, t3, ft1 - doubleOperation(ft1, ft0) - stored ft0, [cfr, t2, 8] - dispatch(5) - -.slow: - callSlowPath(slow_path) - dispatch(5) -end - -macro binaryOp(integerOperation, doubleOperation, slow_path) - binaryOpCustomStore( - macro (int32Tag, left, right, slow, index) - integerOperation(left, right, slow) - storei int32Tag, TagOffset[cfr, index, 8] - storei right, PayloadOffset[cfr, index, 8] - end, - doubleOperation, slow_path) -end - -_llint_op_add: - traceExecution() - binaryOp( - macro (left, right, slow) baddio left, right, slow end, - macro (left, right) addd left, right end, - _llint_slow_path_add) - - -_llint_op_mul: - traceExecution() - binaryOpCustomStore( - macro (int32Tag, left, right, slow, index) - const scratch = int32Tag # We know that we can reuse the int32Tag register since it has a constant. - move right, scratch - bmulio left, scratch, slow - btinz scratch, .done - bilt left, 0, slow - bilt right, 0, slow - .done: - storei Int32Tag, TagOffset[cfr, index, 8] - storei scratch, PayloadOffset[cfr, index, 8] - end, - macro (left, right) muld left, right end, - _llint_slow_path_mul) - - -_llint_op_sub: - traceExecution() - binaryOp( - macro (left, right, slow) bsubio left, right, slow end, - macro (left, right) subd left, right end, - _llint_slow_path_sub) - - -_llint_op_div: - traceExecution() - binaryOpCustomStore( - macro (int32Tag, left, right, slow, index) - ci2d left, ft0 - ci2d right, ft1 - divd ft0, ft1 - bcd2i ft1, right, .notInt - storei int32Tag, TagOffset[cfr, index, 8] - storei right, PayloadOffset[cfr, index, 8] - jmp .done - .notInt: - stored ft1, [cfr, index, 8] - .done: - end, - macro (left, right) divd left, right end, - _llint_slow_path_div) - - _llint_op_mod: traceExecution() callSlowPath(_llint_slow_path_mod) dispatch(4) -macro bitOp(operation, slow_path, advance) - loadi 12[PC], t2 - loadi 8[PC], t0 - loadConstantOrVariable(t2, t3, t1) - loadConstantOrVariable2Reg(t0, t2, t0) - bineq t3, Int32Tag, .slow - bineq t2, Int32Tag, .slow - loadi 4[PC], t2 - operation(t1, t0, .slow) - storei t3, TagOffset[cfr, t2, 8] - storei t0, PayloadOffset[cfr, t2, 8] - dispatch(advance) - -.slow: - callSlowPath(slow_path) - dispatch(advance) -end - -_llint_op_lshift: - traceExecution() - bitOp( - macro (left, right, slow) lshifti left, right end, - _llint_slow_path_lshift, - 4) - - -_llint_op_rshift: - traceExecution() - bitOp( - macro (left, right, slow) rshifti left, right end, - _llint_slow_path_rshift, - 4) - - -_llint_op_urshift: - traceExecution() - bitOp( - macro (left, right, slow) - urshifti left, right - bilt right, 0, slow - end, - _llint_slow_path_urshift, - 4) - - -_llint_op_bitand: - traceExecution() - bitOp( - macro (left, right, slow) andi left, right end, - _llint_slow_path_bitand, - 5) - - -_llint_op_bitxor: - traceExecution() - bitOp( - macro (left, right, slow) xori left, right end, - _llint_slow_path_bitxor, - 5) - - -_llint_op_bitor: - traceExecution() - bitOp( - macro (left, right, slow) ori left, right end, - _llint_slow_path_bitor, - 5) - - -_llint_op_bitnot: - traceExecution() - loadi 8[PC], t1 - loadi 4[PC], t0 - loadConstantOrVariable(t1, t2, t3) - bineq t2, Int32Tag, .opBitnotSlow - noti t3 - storei t2, TagOffset[cfr, t0, 8] - storei t3, PayloadOffset[cfr, t0, 8] - dispatch(3) - -.opBitnotSlow: - callSlowPath(_llint_slow_path_bitnot) - dispatch(3) - - -_llint_op_check_has_instance: - traceExecution() - loadi 4[PC], t1 - loadConstantOrVariablePayload(t1, CellTag, t0, .opCheckHasInstanceSlow) - loadp JSCell::m_structure[t0], t0 - btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow - dispatch(2) - -.opCheckHasInstanceSlow: - callSlowPath(_llint_slow_path_check_has_instance) - dispatch(2) - - -_llint_op_instanceof: - traceExecution() - # Check that baseVal implements the default HasInstance behavior. - # FIXME: This should be deprecated. - loadi 12[PC], t1 - loadConstantOrVariablePayloadUnchecked(t1, t0) - loadp JSCell::m_structure[t0], t0 - btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow - - # Actually do the work. - loadi 16[PC], t0 - loadi 4[PC], t3 - loadConstantOrVariablePayload(t0, CellTag, t1, .opInstanceofSlow) - loadp JSCell::m_structure[t1], t2 - bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow - loadi 8[PC], t0 - loadConstantOrVariablePayload(t0, CellTag, t2, .opInstanceofSlow) - - # Register state: t1 = prototype, t2 = value - move 1, t0 -.opInstanceofLoop: - loadp JSCell::m_structure[t2], t2 - loadi Structure::m_prototype + PayloadOffset[t2], t2 - bpeq t2, t1, .opInstanceofDone - btinz t2, .opInstanceofLoop - - move 0, t0 -.opInstanceofDone: - storei BooleanTag, TagOffset[cfr, t3, 8] - storei t0, PayloadOffset[cfr, t3, 8] - dispatch(5) - -.opInstanceofSlow: - callSlowPath(_llint_slow_path_instanceof) - dispatch(5) - - _llint_op_typeof: traceExecution() callSlowPath(_llint_slow_path_typeof) @@ -1276,156 +477,6 @@ _llint_op_resolve_skip: dispatch(5) -macro resolveGlobal(size, slow) - # Operands are as follows: - # 4[PC] Destination for the load. - # 8[PC] Property identifier index in the code block. - # 12[PC] Structure pointer, initialized to 0 by bytecode generator. - # 16[PC] Offset in global object, initialized to 0 by bytecode generator. - loadp CodeBlock[cfr], t0 - loadp CodeBlock::m_globalObject[t0], t0 - loadp JSCell::m_structure[t0], t1 - bpneq t1, 12[PC], slow - loadi 16[PC], t1 - loadp JSObject::m_propertyStorage[t0], t0 - loadi TagOffset[t0, t1, 8], t2 - loadi PayloadOffset[t0, t1, 8], t3 - loadi 4[PC], t0 - storei t2, TagOffset[cfr, t0, 8] - storei t3, PayloadOffset[cfr, t0, 8] - loadi (size - 1) * 4[PC], t0 - valueProfile(t2, t3, t0) -end - -_llint_op_resolve_global: - traceExecution() - resolveGlobal(6, .opResolveGlobalSlow) - dispatch(6) - -.opResolveGlobalSlow: - callSlowPath(_llint_slow_path_resolve_global) - dispatch(6) - - -# Gives you the scope in t0, while allowing you to optionally perform additional checks on the -# scopes as they are traversed. scopeCheck() is called with two arguments: the register -# holding the scope, and a register that can be used for scratch. Note that this does not -# use t3, so you can hold stuff in t3 if need be. -macro getScope(deBruijinIndexOperand, scopeCheck) - loadp ScopeChain + PayloadOffset[cfr], t0 - loadi deBruijinIndexOperand, t2 - - btiz t2, .done - - loadp CodeBlock[cfr], t1 - bineq CodeBlock::m_codeType[t1], FunctionCode, .loop - btbz CodeBlock::m_needsFullScopeChain[t1], .loop - - loadi CodeBlock::m_activationRegister[t1], t1 - - # Need to conditionally skip over one scope. - bieq TagOffset[cfr, t1, 8], EmptyValueTag, .noActivation - scopeCheck(t0, t1) - loadp ScopeChainNode::next[t0], t0 -.noActivation: - subi 1, t2 - - btiz t2, .done -.loop: - scopeCheck(t0, t1) - loadp ScopeChainNode::next[t0], t0 - subi 1, t2 - btinz t2, .loop - -.done: -end - -_llint_op_resolve_global_dynamic: - traceExecution() - loadp JITStackFrame::globalData[sp], t3 - loadp JSGlobalData::activationStructure[t3], t3 - getScope( - 20[PC], - macro (scope, scratch) - loadp ScopeChainNode::object[scope], scratch - bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow - end) - resolveGlobal(7, .opResolveGlobalDynamicSlow) - dispatch(7) - -.opResolveGlobalDynamicSuperSlow: - callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic) - dispatch(7) - -.opResolveGlobalDynamicSlow: - callSlowPath(_llint_slow_path_resolve_global_dynamic) - dispatch(7) - - -_llint_op_get_scoped_var: - traceExecution() - # Operands are as follows: - # 4[PC] Destination for the load. - # 8[PC] Index of register in the scope. - # 12[PC] De Bruijin index. - getScope(12[PC], macro (scope, scratch) end) - loadi 4[PC], t1 - loadi 8[PC], t2 - loadp ScopeChainNode::object[t0], t0 - loadp JSVariableObject::m_registers[t0], t0 - loadi TagOffset[t0, t2, 8], t3 - loadi PayloadOffset[t0, t2, 8], t0 - storei t3, TagOffset[cfr, t1, 8] - storei t0, PayloadOffset[cfr, t1, 8] - loadi 16[PC], t1 - valueProfile(t3, t0, t1) - dispatch(5) - - -_llint_op_put_scoped_var: - traceExecution() - getScope(8[PC], macro (scope, scratch) end) - loadi 12[PC], t1 - loadConstantOrVariable(t1, t3, t2) - loadi 4[PC], t1 - writeBarrier(t3, t2) - loadp ScopeChainNode::object[t0], t0 - loadp JSVariableObject::m_registers[t0], t0 - storei t3, TagOffset[t0, t1, 8] - storei t2, PayloadOffset[t0, t1, 8] - dispatch(4) - - -_llint_op_get_global_var: - traceExecution() - loadi 8[PC], t1 - loadi 4[PC], t3 - loadp CodeBlock[cfr], t0 - loadp CodeBlock::m_globalObject[t0], t0 - loadp JSGlobalObject::m_registers[t0], t0 - loadi TagOffset[t0, t1, 8], t2 - loadi PayloadOffset[t0, t1, 8], t1 - storei t2, TagOffset[cfr, t3, 8] - storei t1, PayloadOffset[cfr, t3, 8] - loadi 12[PC], t3 - valueProfile(t2, t1, t3) - dispatch(4) - - -_llint_op_put_global_var: - traceExecution() - loadi 8[PC], t1 - loadp CodeBlock[cfr], t0 - loadp CodeBlock::m_globalObject[t0], t0 - loadp JSGlobalObject::m_registers[t0], t0 - loadConstantOrVariable(t1, t2, t3) - loadi 4[PC], t1 - writeBarrier(t2, t3) - storei t2, TagOffset[t0, t1, 8] - storei t3, PayloadOffset[t0, t1, 8] - dispatch(3) - - _llint_op_resolve_base: traceExecution() callSlowPath(_llint_slow_path_resolve_base) @@ -1450,230 +501,12 @@ _llint_op_resolve_with_this: dispatch(5) -_llint_op_get_by_id: - traceExecution() - # We only do monomorphic get_by_id caching for now, and we do not modify the - # opcode. We do, however, allow for the cache to change anytime if fails, since - # ping-ponging is free. At best we get lucky and the get_by_id will continue - # to take fast path on the new cache. At worst we take slow path, which is what - # we would have been doing anyway. - loadi 8[PC], t0 - loadi 16[PC], t1 - loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow) - loadi 20[PC], t2 - loadp JSObject::m_propertyStorage[t3], t0 - bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow - loadi 4[PC], t1 - loadi TagOffset[t0, t2], t3 - loadi PayloadOffset[t0, t2], t2 - storei t3, TagOffset[cfr, t1, 8] - storei t2, PayloadOffset[cfr, t1, 8] - loadi 32[PC], t1 - valueProfile(t3, t2, t1) - dispatch(9) - -.opGetByIdSlow: - callSlowPath(_llint_slow_path_get_by_id) - dispatch(9) - - -_llint_op_get_arguments_length: - traceExecution() - loadi 8[PC], t0 - loadi 4[PC], t1 - bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentsLengthSlow - loadi ArgumentCount + PayloadOffset[cfr], t2 - subi 1, t2 - storei Int32Tag, TagOffset[cfr, t1, 8] - storei t2, PayloadOffset[cfr, t1, 8] - dispatch(4) - -.opGetArgumentsLengthSlow: - callSlowPath(_llint_slow_path_get_arguments_length) - dispatch(4) - - -_llint_op_put_by_id: - traceExecution() - loadi 4[PC], t3 - loadi 16[PC], t1 - loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow) - loadi 12[PC], t2 - loadp JSObject::m_propertyStorage[t0], t3 - bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow - loadi 20[PC], t1 - loadConstantOrVariable2Reg(t2, t0, t2) - writeBarrier(t0, t2) - storei t0, TagOffset[t3, t1] - storei t2, PayloadOffset[t3, t1] - dispatch(9) - -.opPutByIdSlow: - callSlowPath(_llint_slow_path_put_by_id) - dispatch(9) - - -macro putByIdTransition(additionalChecks) - traceExecution() - loadi 4[PC], t3 - loadi 16[PC], t1 - loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow) - loadi 12[PC], t2 - bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow - additionalChecks(t1, t3, .opPutByIdSlow) - loadi 20[PC], t1 - loadp JSObject::m_propertyStorage[t0], t3 - addp t1, t3 - loadConstantOrVariable2Reg(t2, t1, t2) - writeBarrier(t1, t2) - storei t1, TagOffset[t3] - loadi 24[PC], t1 - storei t2, PayloadOffset[t3] - storep t1, JSCell::m_structure[t0] - dispatch(9) -end - -_llint_op_put_by_id_transition_direct: - putByIdTransition(macro (oldStructure, scratch, slow) end) - - -_llint_op_put_by_id_transition_normal: - putByIdTransition( - macro (oldStructure, scratch, slow) - const protoCell = oldStructure # Reusing the oldStructure register for the proto - - loadp 28[PC], scratch - assert(macro (ok) btpnz scratch, ok end) - loadp StructureChain::m_vector[scratch], scratch - assert(macro (ok) btpnz scratch, ok end) - bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done - .loop: - loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell - loadp JSCell::m_structure[protoCell], oldStructure - bpneq oldStructure, [scratch], slow - addp 4, scratch - bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop - .done: - end) - - _llint_op_del_by_id: traceExecution() callSlowPath(_llint_slow_path_del_by_id) dispatch(4) -_llint_op_get_by_val: - traceExecution() - loadp CodeBlock[cfr], t1 - loadi 8[PC], t2 - loadi 12[PC], t3 - loadp CodeBlock::m_globalData[t1], t1 - loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow) - loadp JSGlobalData::jsArrayClassInfo[t1], t2 - loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow) - bpneq [t0], t2, .opGetByValSlow - loadp JSArray::m_storage[t0], t3 - biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow - loadi 4[PC], t0 - loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2 - loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1 - bieq t2, EmptyValueTag, .opGetByValSlow - storei t2, TagOffset[cfr, t0, 8] - storei t1, PayloadOffset[cfr, t0, 8] - loadi 16[PC], t0 - valueProfile(t2, t1, t0) - dispatch(5) - -.opGetByValSlow: - callSlowPath(_llint_slow_path_get_by_val) - dispatch(5) - - -_llint_op_get_argument_by_val: - traceExecution() - loadi 8[PC], t0 - loadi 12[PC], t1 - bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentByValSlow - loadConstantOrVariablePayload(t1, Int32Tag, t2, .opGetArgumentByValSlow) - addi 1, t2 - loadi ArgumentCount + PayloadOffset[cfr], t1 - biaeq t2, t1, .opGetArgumentByValSlow - negi t2 - loadi 4[PC], t3 - loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0 - loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1 - storei t0, TagOffset[cfr, t3, 8] - storei t1, PayloadOffset[cfr, t3, 8] - dispatch(5) - -.opGetArgumentByValSlow: - callSlowPath(_llint_slow_path_get_argument_by_val) - dispatch(5) - - -_llint_op_get_by_pname: - traceExecution() - loadi 12[PC], t0 - loadConstantOrVariablePayload(t0, CellTag, t1, .opGetByPnameSlow) - loadi 16[PC], t0 - bpneq t1, PayloadOffset[cfr, t0, 8], .opGetByPnameSlow - loadi 8[PC], t0 - loadConstantOrVariablePayload(t0, CellTag, t2, .opGetByPnameSlow) - loadi 20[PC], t0 - loadi PayloadOffset[cfr, t0, 8], t3 - loadp JSCell::m_structure[t2], t0 - bpneq t0, JSPropertyNameIterator::m_cachedStructure[t3], .opGetByPnameSlow - loadi 24[PC], t0 - loadi [cfr, t0, 8], t0 - subi 1, t0 - biaeq t0, JSPropertyNameIterator::m_numCacheableSlots[t3], .opGetByPnameSlow - loadp JSObject::m_propertyStorage[t2], t2 - loadi TagOffset[t2, t0, 8], t1 - loadi PayloadOffset[t2, t0, 8], t3 - loadi 4[PC], t0 - storei t1, TagOffset[cfr, t0, 8] - storei t3, PayloadOffset[cfr, t0, 8] - dispatch(7) - -.opGetByPnameSlow: - callSlowPath(_llint_slow_path_get_by_pname) - dispatch(7) - - -_llint_op_put_by_val: - traceExecution() - loadi 4[PC], t0 - loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow) - loadi 8[PC], t0 - loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow) - loadp CodeBlock[cfr], t0 - loadp CodeBlock::m_globalData[t0], t0 - loadp JSGlobalData::jsArrayClassInfo[t0], t0 - bpneq [t1], t0, .opPutByValSlow - biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow - loadp JSArray::m_storage[t1], t0 - bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty -.opPutByValStoreResult: - loadi 12[PC], t3 - loadConstantOrVariable2Reg(t3, t1, t3) - writeBarrier(t1, t3) - storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8] - storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8] - dispatch(4) - -.opPutByValEmpty: - addi 1, ArrayStorage::m_numValuesInVector[t0] - bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult - addi 1, t2, t1 - storei t1, ArrayStorage::m_length[t0] - jmp .opPutByValStoreResult - -.opPutByValSlow: - callSlowPath(_llint_slow_path_put_by_val) - dispatch(4) - - _llint_op_del_by_val: traceExecution() callSlowPath(_llint_slow_path_del_by_val) @@ -1692,33 +525,12 @@ _llint_op_put_getter_setter: dispatch(5) -_llint_op_loop: - nop -_llint_op_jmp: - traceExecution() - dispatchBranch(4[PC]) - - _llint_op_jmp_scopes: traceExecution() callSlowPath(_llint_slow_path_jmp_scopes) dispatch(0) -macro jumpTrueOrFalse(conditionOp, slow) - loadi 4[PC], t1 - loadConstantOrVariablePayload(t1, BooleanTag, t0, .slow) - conditionOp(t0, .target) - dispatch(3) - -.target: - dispatchBranch(8[PC]) - -.slow: - callSlowPath(slow) - dispatch(0) -end - _llint_op_loop_if_true: nop _llint_op_jtrue: @@ -1737,88 +549,6 @@ _llint_op_jfalse: _llint_slow_path_jfalse) -macro equalNull(cellHandler, immediateHandler) - loadi 4[PC], t0 - loadi TagOffset[cfr, t0, 8], t1 - loadi PayloadOffset[cfr, t0, 8], t0 - bineq t1, CellTag, .immediate - loadp JSCell::m_structure[t0], t2 - cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target) - dispatch(3) - -.target: - dispatchBranch(8[PC]) - -.immediate: - ori 1, t1 - immediateHandler(t1, .target) - dispatch(3) -end - -_llint_op_jeq_null: - traceExecution() - equalNull( - macro (value, target) btbnz value, MasqueradesAsUndefined, target end, - macro (value, target) bieq value, NullTag, target end) - - -_llint_op_jneq_null: - traceExecution() - equalNull( - macro (value, target) btbz value, MasqueradesAsUndefined, target end, - macro (value, target) bineq value, NullTag, target end) - - -_llint_op_jneq_ptr: - traceExecution() - loadi 4[PC], t0 - loadi 8[PC], t1 - bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch - bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough -.opJneqPtrBranch: - dispatchBranch(12[PC]) -.opJneqPtrFallThrough: - dispatch(4) - - -macro compare(integerCompare, doubleCompare, slow_path) - loadi 4[PC], t2 - loadi 8[PC], t3 - loadConstantOrVariable(t2, t0, t1) - loadConstantOrVariable2Reg(t3, t2, t3) - bineq t0, Int32Tag, .op1NotInt - bineq t2, Int32Tag, .op2NotInt - integerCompare(t1, t3, .jumpTarget) - dispatch(4) - -.op1NotInt: - bia t0, LowestTag, .slow - bib t2, LowestTag, .op1NotIntOp2Double - bineq t2, Int32Tag, .slow - ci2d t3, ft1 - jmp .op1NotIntReady -.op1NotIntOp2Double: - fii2d t3, t2, ft1 -.op1NotIntReady: - fii2d t1, t0, ft0 - doubleCompare(ft0, ft1, .jumpTarget) - dispatch(4) - -.op2NotInt: - ci2d t1, ft0 - bia t2, LowestTag, .slow - fii2d t3, t2, ft1 - doubleCompare(ft0, ft1, .jumpTarget) - dispatch(4) - -.jumpTarget: - dispatchBranch(12[PC]) - -.slow: - callSlowPath(slow_path) - dispatch(0) -end - _llint_op_loop_if_less: nop _llint_op_jless: @@ -1897,117 +627,18 @@ _llint_op_loop_hint: dispatch(1) -_llint_op_switch_imm: - traceExecution() - loadi 12[PC], t2 - loadi 4[PC], t3 - loadConstantOrVariable(t2, t1, t0) - loadp CodeBlock[cfr], t2 - loadp CodeBlock::m_rareData[t2], t2 - muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this! - loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2 - addp t3, t2 - bineq t1, Int32Tag, .opSwitchImmNotInt - subi SimpleJumpTable::min[t2], t0 - biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough - loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3 - loadi [t3, t0, 4], t1 - btiz t1, .opSwitchImmFallThrough - dispatchBranchWithOffset(t1) - -.opSwitchImmNotInt: - bib t1, LowestTag, .opSwitchImmSlow # Go to slow path if it's a double. -.opSwitchImmFallThrough: - dispatchBranch(8[PC]) - -.opSwitchImmSlow: - callSlowPath(_llint_slow_path_switch_imm) - dispatch(0) - - -_llint_op_switch_char: - traceExecution() - loadi 12[PC], t2 - loadi 4[PC], t3 - loadConstantOrVariable(t2, t1, t0) - loadp CodeBlock[cfr], t2 - loadp CodeBlock::m_rareData[t2], t2 - muli sizeof SimpleJumpTable, t3 - loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2 - addp t3, t2 - bineq t1, CellTag, .opSwitchCharFallThrough - loadp JSCell::m_structure[t0], t1 - bbneq Structure::m_typeInfo + TypeInfo::m_type[t1], StringType, .opSwitchCharFallThrough - loadp JSString::m_value[t0], t0 - bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough - loadp StringImpl::m_data8[t0], t1 - btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit - loadh [t1], t0 - jmp .opSwitchCharReady -.opSwitchChar8Bit: - loadb [t1], t0 -.opSwitchCharReady: - subi SimpleJumpTable::min[t2], t0 - biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough - loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2 - loadi [t2, t0, 4], t1 - btiz t1, .opSwitchImmFallThrough - dispatchBranchWithOffset(t1) - -.opSwitchCharFallThrough: - dispatchBranch(8[PC]) - - _llint_op_switch_string: traceExecution() callSlowPath(_llint_slow_path_switch_string) dispatch(0) -_llint_op_new_func: - traceExecution() - btiz 12[PC], .opNewFuncUnchecked - loadi 4[PC], t1 - bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewFuncDone -.opNewFuncUnchecked: - callSlowPath(_llint_slow_path_new_func) -.opNewFuncDone: - dispatch(4) - - _llint_op_new_func_exp: traceExecution() callSlowPath(_llint_slow_path_new_func_exp) dispatch(3) -macro doCall(slow_path) - loadi 4[PC], t0 - loadi 16[PC], t1 - loadp LLIntCallLinkInfo::callee[t1], t2 - loadConstantOrVariablePayload(t0, CellTag, t3, .opCallSlow) - bineq t3, t2, .opCallSlow - loadi 12[PC], t3 - addp 24, PC - lshifti 3, t3 - addp cfr, t3 # t3 contains the new value of cfr - loadp JSFunction::m_scopeChain[t2], t0 - storei t2, Callee + PayloadOffset[t3] - storei t0, ScopeChain + PayloadOffset[t3] - loadi 8 - 24[PC], t2 - storei PC, ArgumentCount + TagOffset[cfr] - storep cfr, CallerFrame[t3] - storei t2, ArgumentCount + PayloadOffset[t3] - storei CellTag, Callee + TagOffset[t3] - storei CellTag, ScopeChain + TagOffset[t3] - move t3, cfr - call LLIntCallLinkInfo::machineCodeTarget[t1] - dispatchAfterCall() - -.opCallSlow: - slowPathForCall(6, slow_path) -end - _llint_op_call: traceExecution() doCall(_llint_slow_path_call) @@ -2066,97 +697,16 @@ _llint_generic_return_point: dispatchAfterCall() -_llint_op_tear_off_activation: - traceExecution() - loadi 4[PC], t0 - loadi 8[PC], t1 - bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated - bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated -.opTearOffActivationCreated: - callSlowPath(_llint_slow_path_tear_off_activation) -.opTearOffActivationNotCreated: - dispatch(3) - - -_llint_op_tear_off_arguments: - traceExecution() - loadi 4[PC], t0 - subi 1, t0 # Get the unmodifiedArgumentsRegister - bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffArgumentsNotCreated - callSlowPath(_llint_slow_path_tear_off_arguments) -.opTearOffArgumentsNotCreated: - dispatch(2) - - -macro doReturn() - loadp ReturnPC[cfr], t2 - loadp CallerFrame[cfr], cfr - restoreReturnAddressBeforeReturn(t2) - ret -end - -_llint_op_ret: - traceExecution() - checkSwitchToJITForEpilogue() - loadi 4[PC], t2 - loadConstantOrVariable(t2, t1, t0) - doReturn() - - -_llint_op_call_put_result: - loadi 4[PC], t2 - loadi 8[PC], t3 - storei t1, TagOffset[cfr, t2, 8] - storei t0, PayloadOffset[cfr, t2, 8] - valueProfile(t1, t0, t3) - traceExecution() # Needs to be here because it would clobber t1, t0 - dispatch(3) - - -_llint_op_ret_object_or_this: - traceExecution() - checkSwitchToJITForEpilogue() - loadi 4[PC], t2 - loadConstantOrVariable(t2, t1, t0) - bineq t1, CellTag, .opRetObjectOrThisNotObject - loadp JSCell::m_structure[t0], t2 - bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject - doReturn() - -.opRetObjectOrThisNotObject: - loadi 8[PC], t2 - loadConstantOrVariable(t2, t1, t0) - doReturn() - - -_llint_op_method_check: - traceExecution() - # We ignore method checks and use normal get_by_id optimizations. - dispatch(1) - - _llint_op_strcat: traceExecution() callSlowPath(_llint_slow_path_strcat) dispatch(4) -_llint_op_to_primitive: +_llint_op_method_check: traceExecution() - loadi 8[PC], t2 - loadi 4[PC], t3 - loadConstantOrVariable(t2, t1, t0) - bineq t1, CellTag, .opToPrimitiveIsImm - loadp JSCell::m_structure[t0], t2 - bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase -.opToPrimitiveIsImm: - storei t1, TagOffset[cfr, t3, 8] - storei t0, PayloadOffset[cfr, t3, 8] - dispatch(3) - -.opToPrimitiveSlowCase: - callSlowPath(_llint_slow_path_to_primitive) - dispatch(3) + # We ignore method checks and use normal get_by_id optimizations. + dispatch(1) _llint_op_get_pnames: @@ -2165,46 +715,6 @@ _llint_op_get_pnames: dispatch(0) # The slow_path either advances the PC or jumps us to somewhere else. -_llint_op_next_pname: - traceExecution() - loadi 12[PC], t1 - loadi 16[PC], t2 - loadi PayloadOffset[cfr, t1, 8], t0 - bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd - loadi 20[PC], t2 - loadi PayloadOffset[cfr, t2, 8], t2 - loadp JSPropertyNameIterator::m_jsStrings[t2], t3 - loadi [t3, t0, 8], t3 - addi 1, t0 - storei t0, PayloadOffset[cfr, t1, 8] - loadi 4[PC], t1 - storei CellTag, TagOffset[cfr, t1, 8] - storei t3, PayloadOffset[cfr, t1, 8] - loadi 8[PC], t3 - loadi PayloadOffset[cfr, t3, 8], t3 - loadp JSCell::m_structure[t3], t1 - bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow - loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0 - loadp StructureChain::m_vector[t0], t0 - btpz [t0], .opNextPnameTarget -.opNextPnameCheckPrototypeLoop: - bieq Structure::m_prototype + TagOffset[t1], NullTag, .opNextPnameSlow - loadp Structure::m_prototype + PayloadOffset[t1], t2 - loadp JSCell::m_structure[t2], t1 - bpneq t1, [t0], .opNextPnameSlow - addp 4, t0 - btpnz [t0], .opNextPnameCheckPrototypeLoop -.opNextPnameTarget: - dispatchBranch(24[PC]) - -.opNextPnameEnd: - dispatch(7) - -.opNextPnameSlow: - callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target. - dispatch(0) - - _llint_op_push_scope: traceExecution() callSlowPath(_llint_slow_path_push_scope) @@ -2223,27 +733,6 @@ _llint_op_push_new_scope: dispatch(4) -_llint_op_catch: - # This is where we end up from the JIT's throw trampoline (because the - # machine code return address will be set to _llint_op_catch), and from - # the interpreter's throw trampoline (see _llint_throw_trampoline). - # The JIT throwing protocol calls for the cfr to be in t0. The throwing - # code must have known that we were throwing to the interpreter, and have - # set JSGlobalData::targetInterpreterPCForThrow. - move t0, cfr - loadp JITStackFrame::globalData[sp], t3 - loadi JSGlobalData::targetInterpreterPCForThrow[t3], PC - loadi JSGlobalData::exception + PayloadOffset[t3], t0 - loadi JSGlobalData::exception + TagOffset[t3], t1 - storei 0, JSGlobalData::exception + PayloadOffset[t3] - storei EmptyValueTag, JSGlobalData::exception + TagOffset[t3] - loadi 4[PC], t2 - storei t0, PayloadOffset[cfr, t2, 8] - storei t1, TagOffset[cfr, t2, 8] - traceExecution() # This needs to be here because we don't want to clobber t0, t1, t2, t3 above. - dispatch(2) - - _llint_op_throw: traceExecution() callSlowPath(_llint_slow_path_throw) @@ -2256,27 +745,6 @@ _llint_op_throw_reference_error: dispatch(2) -_llint_op_jsr: - traceExecution() - loadi 4[PC], t0 - addi 3 * 4, PC, t1 - storei t1, [cfr, t0, 8] - dispatchBranch(8[PC]) - - -_llint_op_sret: - traceExecution() - loadi 4[PC], t0 - loadp [cfr, t0, 8], PC - dispatch(0) - - -_llint_op_debug: - traceExecution() - callSlowPath(_llint_slow_path_debug) - dispatch(4) - - _llint_op_profile_will_call: traceExecution() loadp JITStackFrame::enabledProfilerReference[sp], t0 @@ -2295,29 +763,18 @@ _llint_op_profile_did_call: dispatch(2) -_llint_op_end: +_llint_op_debug: traceExecution() - checkSwitchToJITForEpilogue() - loadi 4[PC], t0 - loadi TagOffset[cfr, t0, 8], t1 - loadi PayloadOffset[cfr, t0, 8], t0 - doReturn() + callSlowPath(_llint_slow_path_debug) + dispatch(4) -_llint_throw_from_slow_path_trampoline: - # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so - # the throw target is not necessarily interpreted code, we come to here. - # This essentially emulates the JIT's throwing protocol. - loadp JITStackFrame::globalData[sp], t1 - loadp JSGlobalData::callFrameForThrow[t1], t0 - jmp JSGlobalData::targetMachinePCForThrow[t1] +_llint_native_call_trampoline: + nativeCallTrampoline(NativeExecutable::m_function) -_llint_throw_during_call_trampoline: - preserveReturnAddressAfterCall(t2) - loadp JITStackFrame::globalData[sp], t1 - loadp JSGlobalData::callFrameForThrow[t1], t0 - jmp JSGlobalData::targetMachinePCForThrow[t1] +_llint_native_construct_trampoline: + nativeCallTrampoline(NativeExecutable::m_constructor) # Lastly, make sure that we can link even though we don't support all opcodes. diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.h b/Source/JavaScriptCore/llint/LowLevelInterpreter.h index e5a54a45d..6383757cf 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter.h +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.h @@ -48,6 +48,10 @@ extern "C" void llint_generic_return_point(); extern "C" void llint_throw_from_slow_path_trampoline(); extern "C" void llint_throw_during_call_trampoline(); +// Native call trampolines +extern "C" void llint_native_call_trampoline(); +extern "C" void llint_native_construct_trampoline(); + #endif // ENABLE(LLINT) #endif // LowLevelInterpreter_h diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm new file mode 100644 index 000000000..46c6226e5 --- /dev/null +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm @@ -0,0 +1,1653 @@ +# Copyright (C) 2011, 2012 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. + + +# Crash course on the language that this is written in (which I just call +# "assembly" even though it's more than that): +# +# - Mostly gas-style operand ordering. The last operand tends to be the +# destination. So "a := b" is written as "mov b, a". But unlike gas, +# comparisons are in-order, so "if (a < b)" is written as +# "bilt a, b, ...". +# +# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer. +# Currently this is just 32-bit so "i" and "p" are interchangeable +# except when an op supports one but not the other. +# +# - In general, valid operands for macro invocations and instructions are +# registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses +# (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels +# (eg "_foo" or ".foo"). Macro invocations can also take anonymous +# macros as operands. Instructions cannot take anonymous macros. +# +# - Labels must have names that begin with either "_" or ".". A "." label +# is local and gets renamed before code gen to minimize namespace +# pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_" +# may or may not be removed during code gen depending on whether the asm +# conventions for C name mangling on the target platform mandate a "_" +# prefix. +# +# - A "macro" is a lambda expression, which may be either anonymous or +# named. But this has caveats. "macro" can take zero or more arguments, +# which may be macros or any valid operands, but it can only return +# code. But you can do Turing-complete things via continuation passing +# style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do +# that, since you'll just crash the assembler. +# +# - An "if" is a conditional on settings. Any identifier supplied in the +# predicate of an "if" is assumed to be a #define that is available +# during code gen. So you can't use "if" for computation in a macro, but +# you can use it to select different pieces of code for different +# platforms. +# +# - Arguments to macros follow lexical scoping rather than dynamic scoping. +# Const's also follow lexical scoping and may override (hide) arguments +# or other consts. All variables (arguments and constants) can be bound +# to operands. Additionally, arguments (but not constants) can be bound +# to macros. + + +# Below we have a bunch of constant declarations. Each constant must have +# a corresponding ASSERT() in LLIntData.cpp. + + +# Value representation constants. +const Int32Tag = -1 +const BooleanTag = -2 +const NullTag = -3 +const UndefinedTag = -4 +const CellTag = -5 +const EmptyValueTag = -6 +const DeletedValueTag = -7 +const LowestTag = DeletedValueTag + + +# Utilities +macro dispatch(advance) + addp advance * 4, PC + jmp [PC] +end + +macro dispatchBranchWithOffset(pcOffset) + lshifti 2, pcOffset + addp pcOffset, PC + jmp [PC] +end + +macro dispatchBranch(pcOffset) + loadi pcOffset, t0 + dispatchBranchWithOffset(t0) +end + +macro dispatchAfterCall() + loadi ArgumentCount + TagOffset[cfr], PC + jmp [PC] +end + +macro cCall2(function, arg1, arg2) + if ARMv7 + move arg1, t0 + move arg2, t1 + elsif X86 + poke arg1, 0 + poke arg2, 1 + else + error + end + call function +end + +# This barely works. arg3 and arg4 should probably be immediates. +macro cCall4(function, arg1, arg2, arg3, arg4) + if ARMv7 + move arg1, t0 + move arg2, t1 + move arg3, t2 + move arg4, t3 + elsif X86 + poke arg1, 0 + poke arg2, 1 + poke arg3, 2 + poke arg4, 3 + else + error + end + call function +end + +macro callSlowPath(slowPath) + cCall2(slowPath, cfr, PC) + move t0, PC + move t1, cfr +end + +# Debugging operation if you'd like to print an operand in the instruction stream. fromWhere +# should be an immediate integer - any integer you like; use it to identify the place you're +# debugging from. operand should likewise be an immediate, and should identify the operand +# in the instruction stream you'd like to print out. +macro traceOperand(fromWhere, operand) + cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand) + move t0, PC + move t1, cfr +end + +# Debugging operation if you'd like to print the value of an operand in the instruction +# stream. Same as traceOperand(), but assumes that the operand is a register, and prints its +# value. +macro traceValue(fromWhere, operand) + cCall4(_llint_trace_value, cfr, PC, fromWhere, operand) + move t0, PC + move t1, cfr +end + +# Call a slowPath for call opcodes. +macro callCallSlowPath(advance, slowPath, action) + addp advance * 4, PC, t0 + storep t0, ArgumentCount + TagOffset[cfr] + cCall2(slowPath, cfr, PC) + move t1, cfr + action(t0) +end + +macro checkSwitchToJITForLoop() + checkSwitchToJIT( + 1, + macro () + storei PC, ArgumentCount + TagOffset[cfr] + cCall2(_llint_loop_osr, cfr, PC) + move t1, cfr + btpz t0, .recover + jmp t0 + .recover: + loadi ArgumentCount + TagOffset[cfr], PC + end) +end + +# Index, tag, and payload must be different registers. Index is not +# changed. +macro loadConstantOrVariable(index, tag, payload) + bigteq index, FirstConstantRegisterIndex, .constant + loadi TagOffset[cfr, index, 8], tag + loadi PayloadOffset[cfr, index, 8], payload + jmp .done +.constant: + loadp CodeBlock[cfr], payload + loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload + # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex, + # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3. + loadp TagOffset[payload, index, 8], tag + loadp PayloadOffset[payload, index, 8], payload +.done: +end + +# Index and payload may be the same register. Index may be clobbered. +macro loadConstantOrVariable2Reg(index, tag, payload) + bigteq index, FirstConstantRegisterIndex, .constant + loadi TagOffset[cfr, index, 8], tag + loadi PayloadOffset[cfr, index, 8], payload + jmp .done +.constant: + loadp CodeBlock[cfr], tag + loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag + # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex, + # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3. + lshifti 3, index + addp index, tag + loadp PayloadOffset[tag], payload + loadp TagOffset[tag], tag +.done: +end + +macro loadConstantOrVariablePayloadTagCustom(index, tagCheck, payload) + bigteq index, FirstConstantRegisterIndex, .constant + tagCheck(TagOffset[cfr, index, 8]) + loadi PayloadOffset[cfr, index, 8], payload + jmp .done +.constant: + loadp CodeBlock[cfr], payload + loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload + # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex, + # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3. + tagCheck(TagOffset[payload, index, 8]) + loadp PayloadOffset[payload, index, 8], payload +.done: +end + +# Index and payload must be different registers. Index is not mutated. Use +# this if you know what the tag of the variable should be. Doing the tag +# test as part of loading the variable reduces register use, but may not +# be faster than doing loadConstantOrVariable followed by a branch on the +# tag. +macro loadConstantOrVariablePayload(index, expectedTag, payload, slow) + loadConstantOrVariablePayloadTagCustom( + index, + macro (actualTag) bineq actualTag, expectedTag, slow end, + payload) +end + +macro loadConstantOrVariablePayloadUnchecked(index, payload) + loadConstantOrVariablePayloadTagCustom( + index, + macro (actualTag) end, + payload) +end + +macro writeBarrier(tag, payload) + # Nothing to do, since we don't have a generational or incremental collector. +end + +macro valueProfile(tag, payload, profile) + if VALUE_PROFILER + storei tag, ValueProfile::m_buckets + TagOffset[profile] + storei payload, ValueProfile::m_buckets + PayloadOffset[profile] + end +end + + +# Entrypoints into the interpreter + +# Expects that CodeBlock is in t1, which is what prologue() leaves behind. +macro functionArityCheck(doneLabel, slow_path) + loadi PayloadOffset + ArgumentCount[cfr], t0 + biaeq t0, CodeBlock::m_numParameters[t1], doneLabel + cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error + move t1, cfr + btiz t0, .continue + loadp JITStackFrame::globalData[sp], t1 + loadp JSGlobalData::callFrameForThrow[t1], t0 + jmp JSGlobalData::targetMachinePCForThrow[t1] +.continue: + # Reload CodeBlock and PC, since the slow_path clobbered it. + loadp CodeBlock[cfr], t1 + loadp CodeBlock::m_instructions[t1], PC + jmp doneLabel +end + + +# Instruction implementations + +_llint_op_enter: + traceExecution() + loadp CodeBlock[cfr], t2 + loadi CodeBlock::m_numVars[t2], t2 + btiz t2, .opEnterDone + move UndefinedTag, t0 + move 0, t1 +.opEnterLoop: + subi 1, t2 + storei t0, TagOffset[cfr, t2, 8] + storei t1, PayloadOffset[cfr, t2, 8] + btinz t2, .opEnterLoop +.opEnterDone: + dispatch(1) + + +_llint_op_create_activation: + traceExecution() + loadi 4[PC], t0 + bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateActivationDone + callSlowPath(_llint_slow_path_create_activation) +.opCreateActivationDone: + dispatch(2) + + +_llint_op_init_lazy_reg: + traceExecution() + loadi 4[PC], t0 + storei EmptyValueTag, TagOffset[cfr, t0, 8] + storei 0, PayloadOffset[cfr, t0, 8] + dispatch(2) + + +_llint_op_create_arguments: + traceExecution() + loadi 4[PC], t0 + bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateArgumentsDone + callSlowPath(_llint_slow_path_create_arguments) +.opCreateArgumentsDone: + dispatch(2) + + +_llint_op_create_this: + traceExecution() + loadi 8[PC], t0 + assertNotConstant(t0) + bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow + loadi PayloadOffset[cfr, t0, 8], t0 + loadp JSCell::m_structure[t0], t1 + bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow + loadp JSObject::m_inheritorID[t0], t2 + btpz t2, .opCreateThisSlow + allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow) + loadi 4[PC], t1 + storei CellTag, TagOffset[cfr, t1, 8] + storei t0, PayloadOffset[cfr, t1, 8] + dispatch(3) + +.opCreateThisSlow: + callSlowPath(_llint_slow_path_create_this) + dispatch(3) + + +_llint_op_get_callee: + traceExecution() + loadi 4[PC], t0 + loadp PayloadOffset + Callee[cfr], t1 + storei CellTag, TagOffset[cfr, t0, 8] + storei t1, PayloadOffset[cfr, t0, 8] + dispatch(2) + + +_llint_op_convert_this: + traceExecution() + loadi 4[PC], t0 + bineq TagOffset[cfr, t0, 8], CellTag, .opConvertThisSlow + loadi PayloadOffset[cfr, t0, 8], t0 + loadp JSCell::m_structure[t0], t0 + bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow + dispatch(2) + +.opConvertThisSlow: + callSlowPath(_llint_slow_path_convert_this) + dispatch(2) + + +_llint_op_new_object: + traceExecution() + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSGlobalObject::m_emptyObjectStructure[t0], t1 + allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow) + loadi 4[PC], t1 + storei CellTag, TagOffset[cfr, t1, 8] + storei t0, PayloadOffset[cfr, t1, 8] + dispatch(2) + +.opNewObjectSlow: + callSlowPath(_llint_slow_path_new_object) + dispatch(2) + + +_llint_op_mov: + traceExecution() + loadi 8[PC], t1 + loadi 4[PC], t0 + loadConstantOrVariable(t1, t2, t3) + storei t2, TagOffset[cfr, t0, 8] + storei t3, PayloadOffset[cfr, t0, 8] + dispatch(3) + + +_llint_op_not: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t1 + loadConstantOrVariable(t0, t2, t3) + bineq t2, BooleanTag, .opNotSlow + xori 1, t3 + storei t2, TagOffset[cfr, t1, 8] + storei t3, PayloadOffset[cfr, t1, 8] + dispatch(3) + +.opNotSlow: + callSlowPath(_llint_slow_path_not) + dispatch(3) + + +_llint_op_eq: + traceExecution() + loadi 12[PC], t2 + loadi 8[PC], t0 + loadConstantOrVariable(t2, t3, t1) + loadConstantOrVariable2Reg(t0, t2, t0) + bineq t2, t3, .opEqSlow + bieq t2, CellTag, .opEqSlow + bib t2, LowestTag, .opEqSlow + loadi 4[PC], t2 + cieq t0, t1, t0 + storei BooleanTag, TagOffset[cfr, t2, 8] + storei t0, PayloadOffset[cfr, t2, 8] + dispatch(4) + +.opEqSlow: + callSlowPath(_llint_slow_path_eq) + dispatch(4) + + +_llint_op_eq_null: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t3 + assertNotConstant(t0) + loadi TagOffset[cfr, t0, 8], t1 + loadi PayloadOffset[cfr, t0, 8], t0 + bineq t1, CellTag, .opEqNullImmediate + loadp JSCell::m_structure[t0], t1 + tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 + jmp .opEqNullNotImmediate +.opEqNullImmediate: + cieq t1, NullTag, t2 + cieq t1, UndefinedTag, t1 + ori t2, t1 +.opEqNullNotImmediate: + storei BooleanTag, TagOffset[cfr, t3, 8] + storei t1, PayloadOffset[cfr, t3, 8] + dispatch(3) + + +_llint_op_neq: + traceExecution() + loadi 12[PC], t2 + loadi 8[PC], t0 + loadConstantOrVariable(t2, t3, t1) + loadConstantOrVariable2Reg(t0, t2, t0) + bineq t2, t3, .opNeqSlow + bieq t2, CellTag, .opNeqSlow + bib t2, LowestTag, .opNeqSlow + loadi 4[PC], t2 + cineq t0, t1, t0 + storei BooleanTag, TagOffset[cfr, t2, 8] + storei t0, PayloadOffset[cfr, t2, 8] + dispatch(4) + +.opNeqSlow: + callSlowPath(_llint_slow_path_neq) + dispatch(4) + + +_llint_op_neq_null: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t3 + assertNotConstant(t0) + loadi TagOffset[cfr, t0, 8], t1 + loadi PayloadOffset[cfr, t0, 8], t0 + bineq t1, CellTag, .opNeqNullImmediate + loadp JSCell::m_structure[t0], t1 + tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 + jmp .opNeqNullNotImmediate +.opNeqNullImmediate: + cineq t1, NullTag, t2 + cineq t1, UndefinedTag, t1 + andi t2, t1 +.opNeqNullNotImmediate: + storei BooleanTag, TagOffset[cfr, t3, 8] + storei t1, PayloadOffset[cfr, t3, 8] + dispatch(3) + + +macro strictEq(equalityOperation, slowPath) + loadi 12[PC], t2 + loadi 8[PC], t0 + loadConstantOrVariable(t2, t3, t1) + loadConstantOrVariable2Reg(t0, t2, t0) + bineq t2, t3, .slow + bib t2, LowestTag, .slow + bineq t2, CellTag, .notString + loadp JSCell::m_structure[t0], t2 + loadp JSCell::m_structure[t1], t3 + bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .notString + bbeq Structure::m_typeInfo + TypeInfo::m_type[t3], StringType, .slow +.notString: + loadi 4[PC], t2 + equalityOperation(t0, t1, t0) + storei BooleanTag, TagOffset[cfr, t2, 8] + storei t0, PayloadOffset[cfr, t2, 8] + dispatch(4) + +.slow: + callSlowPath(slowPath) + dispatch(4) +end + +_llint_op_stricteq: + traceExecution() + strictEq(macro (left, right, result) cieq left, right, result end, _llint_slow_path_stricteq) + + +_llint_op_nstricteq: + traceExecution() + strictEq(macro (left, right, result) cineq left, right, result end, _llint_slow_path_nstricteq) + + +_llint_op_pre_inc: + traceExecution() + loadi 4[PC], t0 + bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreIncSlow + loadi PayloadOffset[cfr, t0, 8], t1 + baddio 1, t1, .opPreIncSlow + storei t1, PayloadOffset[cfr, t0, 8] + dispatch(2) + +.opPreIncSlow: + callSlowPath(_llint_slow_path_pre_inc) + dispatch(2) + + +_llint_op_pre_dec: + traceExecution() + loadi 4[PC], t0 + bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreDecSlow + loadi PayloadOffset[cfr, t0, 8], t1 + bsubio 1, t1, .opPreDecSlow + storei t1, PayloadOffset[cfr, t0, 8] + dispatch(2) + +.opPreDecSlow: + callSlowPath(_llint_slow_path_pre_dec) + dispatch(2) + + +_llint_op_post_inc: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t1 + bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostIncSlow + bieq t0, t1, .opPostIncDone + loadi PayloadOffset[cfr, t0, 8], t2 + move t2, t3 + baddio 1, t3, .opPostIncSlow + storei Int32Tag, TagOffset[cfr, t1, 8] + storei t2, PayloadOffset[cfr, t1, 8] + storei t3, PayloadOffset[cfr, t0, 8] +.opPostIncDone: + dispatch(3) + +.opPostIncSlow: + callSlowPath(_llint_slow_path_post_inc) + dispatch(3) + + +_llint_op_post_dec: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t1 + bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostDecSlow + bieq t0, t1, .opPostDecDone + loadi PayloadOffset[cfr, t0, 8], t2 + move t2, t3 + bsubio 1, t3, .opPostDecSlow + storei Int32Tag, TagOffset[cfr, t1, 8] + storei t2, PayloadOffset[cfr, t1, 8] + storei t3, PayloadOffset[cfr, t0, 8] +.opPostDecDone: + dispatch(3) + +.opPostDecSlow: + callSlowPath(_llint_slow_path_post_dec) + dispatch(3) + + +_llint_op_to_jsnumber: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t1 + loadConstantOrVariable(t0, t2, t3) + bieq t2, Int32Tag, .opToJsnumberIsInt + biaeq t2, EmptyValueTag, .opToJsnumberSlow +.opToJsnumberIsInt: + storei t2, TagOffset[cfr, t1, 8] + storei t3, PayloadOffset[cfr, t1, 8] + dispatch(3) + +.opToJsnumberSlow: + callSlowPath(_llint_slow_path_to_jsnumber) + dispatch(3) + + +_llint_op_negate: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t3 + loadConstantOrVariable(t0, t1, t2) + bineq t1, Int32Tag, .opNegateSrcNotInt + btiz t2, 0x7fffffff, .opNegateSlow + negi t2 + storei Int32Tag, TagOffset[cfr, t3, 8] + storei t2, PayloadOffset[cfr, t3, 8] + dispatch(3) +.opNegateSrcNotInt: + bia t1, LowestTag, .opNegateSlow + xori 0x80000000, t1 + storei t1, TagOffset[cfr, t3, 8] + storei t2, PayloadOffset[cfr, t3, 8] + dispatch(3) + +.opNegateSlow: + callSlowPath(_llint_slow_path_negate) + dispatch(3) + + +macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath) + loadi 12[PC], t2 + loadi 8[PC], t0 + loadConstantOrVariable(t2, t3, t1) + loadConstantOrVariable2Reg(t0, t2, t0) + bineq t2, Int32Tag, .op1NotInt + bineq t3, Int32Tag, .op2NotInt + loadi 4[PC], t2 + integerOperationAndStore(t3, t1, t0, .slow, t2) + dispatch(5) + +.op1NotInt: + # First operand is definitely not an int, the second operand could be anything. + bia t2, LowestTag, .slow + bib t3, LowestTag, .op1NotIntOp2Double + bineq t3, Int32Tag, .slow + ci2d t1, ft1 + jmp .op1NotIntReady +.op1NotIntOp2Double: + fii2d t1, t3, ft1 +.op1NotIntReady: + loadi 4[PC], t1 + fii2d t0, t2, ft0 + doubleOperation(ft1, ft0) + stored ft0, [cfr, t1, 8] + dispatch(5) + +.op2NotInt: + # First operand is definitely an int, the second operand is definitely not. + loadi 4[PC], t2 + bia t3, LowestTag, .slow + ci2d t0, ft0 + fii2d t1, t3, ft1 + doubleOperation(ft1, ft0) + stored ft0, [cfr, t2, 8] + dispatch(5) + +.slow: + callSlowPath(slowPath) + dispatch(5) +end + +macro binaryOp(integerOperation, doubleOperation, slowPath) + binaryOpCustomStore( + macro (int32Tag, left, right, slow, index) + integerOperation(left, right, slow) + storei int32Tag, TagOffset[cfr, index, 8] + storei right, PayloadOffset[cfr, index, 8] + end, + doubleOperation, slowPath) +end + +_llint_op_add: + traceExecution() + binaryOp( + macro (left, right, slow) baddio left, right, slow end, + macro (left, right) addd left, right end, + _llint_slow_path_add) + + +_llint_op_mul: + traceExecution() + binaryOpCustomStore( + macro (int32Tag, left, right, slow, index) + const scratch = int32Tag # We know that we can reuse the int32Tag register since it has a constant. + move right, scratch + bmulio left, scratch, slow + btinz scratch, .done + bilt left, 0, slow + bilt right, 0, slow + .done: + storei Int32Tag, TagOffset[cfr, index, 8] + storei scratch, PayloadOffset[cfr, index, 8] + end, + macro (left, right) muld left, right end, + _llint_slow_path_mul) + + +_llint_op_sub: + traceExecution() + binaryOp( + macro (left, right, slow) bsubio left, right, slow end, + macro (left, right) subd left, right end, + _llint_slow_path_sub) + + +_llint_op_div: + traceExecution() + binaryOpCustomStore( + macro (int32Tag, left, right, slow, index) + ci2d left, ft0 + ci2d right, ft1 + divd ft0, ft1 + bcd2i ft1, right, .notInt + storei int32Tag, TagOffset[cfr, index, 8] + storei right, PayloadOffset[cfr, index, 8] + jmp .done + .notInt: + stored ft1, [cfr, index, 8] + .done: + end, + macro (left, right) divd left, right end, + _llint_slow_path_div) + + +macro bitOp(operation, slowPath, advance) + loadi 12[PC], t2 + loadi 8[PC], t0 + loadConstantOrVariable(t2, t3, t1) + loadConstantOrVariable2Reg(t0, t2, t0) + bineq t3, Int32Tag, .slow + bineq t2, Int32Tag, .slow + loadi 4[PC], t2 + operation(t1, t0, .slow) + storei t3, TagOffset[cfr, t2, 8] + storei t0, PayloadOffset[cfr, t2, 8] + dispatch(advance) + +.slow: + callSlowPath(slowPath) + dispatch(advance) +end + +_llint_op_lshift: + traceExecution() + bitOp( + macro (left, right, slow) lshifti left, right end, + _llint_slow_path_lshift, + 4) + + +_llint_op_rshift: + traceExecution() + bitOp( + macro (left, right, slow) rshifti left, right end, + _llint_slow_path_rshift, + 4) + + +_llint_op_urshift: + traceExecution() + bitOp( + macro (left, right, slow) + urshifti left, right + bilt right, 0, slow + end, + _llint_slow_path_urshift, + 4) + + +_llint_op_bitand: + traceExecution() + bitOp( + macro (left, right, slow) andi left, right end, + _llint_slow_path_bitand, + 5) + + +_llint_op_bitxor: + traceExecution() + bitOp( + macro (left, right, slow) xori left, right end, + _llint_slow_path_bitxor, + 5) + + +_llint_op_bitor: + traceExecution() + bitOp( + macro (left, right, slow) ori left, right end, + _llint_slow_path_bitor, + 5) + + +_llint_op_check_has_instance: + traceExecution() + loadi 4[PC], t1 + loadConstantOrVariablePayload(t1, CellTag, t0, .opCheckHasInstanceSlow) + loadp JSCell::m_structure[t0], t0 + btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow + dispatch(2) + +.opCheckHasInstanceSlow: + callSlowPath(_llint_slow_path_check_has_instance) + dispatch(2) + + +_llint_op_instanceof: + traceExecution() + # Check that baseVal implements the default HasInstance behavior. + # FIXME: This should be deprecated. + loadi 12[PC], t1 + loadConstantOrVariablePayloadUnchecked(t1, t0) + loadp JSCell::m_structure[t0], t0 + btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow + + # Actually do the work. + loadi 16[PC], t0 + loadi 4[PC], t3 + loadConstantOrVariablePayload(t0, CellTag, t1, .opInstanceofSlow) + loadp JSCell::m_structure[t1], t2 + bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow + loadi 8[PC], t0 + loadConstantOrVariablePayload(t0, CellTag, t2, .opInstanceofSlow) + + # Register state: t1 = prototype, t2 = value + move 1, t0 +.opInstanceofLoop: + loadp JSCell::m_structure[t2], t2 + loadi Structure::m_prototype + PayloadOffset[t2], t2 + bpeq t2, t1, .opInstanceofDone + btinz t2, .opInstanceofLoop + + move 0, t0 +.opInstanceofDone: + storei BooleanTag, TagOffset[cfr, t3, 8] + storei t0, PayloadOffset[cfr, t3, 8] + dispatch(5) + +.opInstanceofSlow: + callSlowPath(_llint_slow_path_instanceof) + dispatch(5) + + +macro resolveGlobal(size, slow) + # Operands are as follows: + # 4[PC] Destination for the load. + # 8[PC] Property identifier index in the code block. + # 12[PC] Structure pointer, initialized to 0 by bytecode generator. + # 16[PC] Offset in global object, initialized to 0 by bytecode generator. + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSCell::m_structure[t0], t1 + bpneq t1, 12[PC], slow + loadi 16[PC], t1 + loadp JSObject::m_propertyStorage[t0], t0 + loadi TagOffset[t0, t1, 8], t2 + loadi PayloadOffset[t0, t1, 8], t3 + loadi 4[PC], t0 + storei t2, TagOffset[cfr, t0, 8] + storei t3, PayloadOffset[cfr, t0, 8] + loadi (size - 1) * 4[PC], t0 + valueProfile(t2, t3, t0) +end + +_llint_op_resolve_global: + traceExecution() + resolveGlobal(6, .opResolveGlobalSlow) + dispatch(6) + +.opResolveGlobalSlow: + callSlowPath(_llint_slow_path_resolve_global) + dispatch(6) + + +# Gives you the scope in t0, while allowing you to optionally perform additional checks on the +# scopes as they are traversed. scopeCheck() is called with two arguments: the register +# holding the scope, and a register that can be used for scratch. Note that this does not +# use t3, so you can hold stuff in t3 if need be. +macro getScope(deBruijinIndexOperand, scopeCheck) + loadp ScopeChain + PayloadOffset[cfr], t0 + loadi deBruijinIndexOperand, t2 + + btiz t2, .done + + loadp CodeBlock[cfr], t1 + bineq CodeBlock::m_codeType[t1], FunctionCode, .loop + btbz CodeBlock::m_needsFullScopeChain[t1], .loop + + loadi CodeBlock::m_activationRegister[t1], t1 + + # Need to conditionally skip over one scope. + bieq TagOffset[cfr, t1, 8], EmptyValueTag, .noActivation + scopeCheck(t0, t1) + loadp ScopeChainNode::next[t0], t0 +.noActivation: + subi 1, t2 + + btiz t2, .done +.loop: + scopeCheck(t0, t1) + loadp ScopeChainNode::next[t0], t0 + subi 1, t2 + btinz t2, .loop + +.done: +end + +_llint_op_resolve_global_dynamic: + traceExecution() + loadp JITStackFrame::globalData[sp], t3 + loadp JSGlobalData::activationStructure[t3], t3 + getScope( + 20[PC], + macro (scope, scratch) + loadp ScopeChainNode::object[scope], scratch + bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow + end) + resolveGlobal(7, .opResolveGlobalDynamicSlow) + dispatch(7) + +.opResolveGlobalDynamicSuperSlow: + callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic) + dispatch(7) + +.opResolveGlobalDynamicSlow: + callSlowPath(_llint_slow_path_resolve_global_dynamic) + dispatch(7) + + +_llint_op_get_scoped_var: + traceExecution() + # Operands are as follows: + # 4[PC] Destination for the load. + # 8[PC] Index of register in the scope. + # 12[PC] De Bruijin index. + getScope(12[PC], macro (scope, scratch) end) + loadi 4[PC], t1 + loadi 8[PC], t2 + loadp ScopeChainNode::object[t0], t0 + loadp JSVariableObject::m_registers[t0], t0 + loadi TagOffset[t0, t2, 8], t3 + loadi PayloadOffset[t0, t2, 8], t0 + storei t3, TagOffset[cfr, t1, 8] + storei t0, PayloadOffset[cfr, t1, 8] + loadi 16[PC], t1 + valueProfile(t3, t0, t1) + dispatch(5) + + +_llint_op_put_scoped_var: + traceExecution() + getScope(8[PC], macro (scope, scratch) end) + loadi 12[PC], t1 + loadConstantOrVariable(t1, t3, t2) + loadi 4[PC], t1 + writeBarrier(t3, t2) + loadp ScopeChainNode::object[t0], t0 + loadp JSVariableObject::m_registers[t0], t0 + storei t3, TagOffset[t0, t1, 8] + storei t2, PayloadOffset[t0, t1, 8] + dispatch(4) + + +_llint_op_get_global_var: + traceExecution() + loadi 8[PC], t1 + loadi 4[PC], t3 + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSGlobalObject::m_registers[t0], t0 + loadi TagOffset[t0, t1, 8], t2 + loadi PayloadOffset[t0, t1, 8], t1 + storei t2, TagOffset[cfr, t3, 8] + storei t1, PayloadOffset[cfr, t3, 8] + loadi 12[PC], t3 + valueProfile(t2, t1, t3) + dispatch(4) + + +_llint_op_put_global_var: + traceExecution() + loadi 8[PC], t1 + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSGlobalObject::m_registers[t0], t0 + loadConstantOrVariable(t1, t2, t3) + loadi 4[PC], t1 + writeBarrier(t2, t3) + storei t2, TagOffset[t0, t1, 8] + storei t3, PayloadOffset[t0, t1, 8] + dispatch(3) + + +_llint_op_get_by_id: + traceExecution() + # We only do monomorphic get_by_id caching for now, and we do not modify the + # opcode. We do, however, allow for the cache to change anytime if fails, since + # ping-ponging is free. At best we get lucky and the get_by_id will continue + # to take fast path on the new cache. At worst we take slow path, which is what + # we would have been doing anyway. + loadi 8[PC], t0 + loadi 16[PC], t1 + loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow) + loadi 20[PC], t2 + loadp JSObject::m_propertyStorage[t3], t0 + bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow + loadi 4[PC], t1 + loadi TagOffset[t0, t2], t3 + loadi PayloadOffset[t0, t2], t2 + storei t3, TagOffset[cfr, t1, 8] + storei t2, PayloadOffset[cfr, t1, 8] + loadi 32[PC], t1 + valueProfile(t3, t2, t1) + dispatch(9) + +.opGetByIdSlow: + callSlowPath(_llint_slow_path_get_by_id) + dispatch(9) + + +_llint_op_get_arguments_length: + traceExecution() + loadi 8[PC], t0 + loadi 4[PC], t1 + bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentsLengthSlow + loadi ArgumentCount + PayloadOffset[cfr], t2 + subi 1, t2 + storei Int32Tag, TagOffset[cfr, t1, 8] + storei t2, PayloadOffset[cfr, t1, 8] + dispatch(4) + +.opGetArgumentsLengthSlow: + callSlowPath(_llint_slow_path_get_arguments_length) + dispatch(4) + + +_llint_op_put_by_id: + traceExecution() + loadi 4[PC], t3 + loadi 16[PC], t1 + loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow) + loadi 12[PC], t2 + loadp JSObject::m_propertyStorage[t0], t3 + bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow + loadi 20[PC], t1 + loadConstantOrVariable2Reg(t2, t0, t2) + writeBarrier(t0, t2) + storei t0, TagOffset[t3, t1] + storei t2, PayloadOffset[t3, t1] + dispatch(9) + +.opPutByIdSlow: + callSlowPath(_llint_slow_path_put_by_id) + dispatch(9) + + +macro putByIdTransition(additionalChecks) + traceExecution() + loadi 4[PC], t3 + loadi 16[PC], t1 + loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow) + loadi 12[PC], t2 + bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow + additionalChecks(t1, t3, .opPutByIdSlow) + loadi 20[PC], t1 + loadp JSObject::m_propertyStorage[t0], t3 + addp t1, t3 + loadConstantOrVariable2Reg(t2, t1, t2) + writeBarrier(t1, t2) + storei t1, TagOffset[t3] + loadi 24[PC], t1 + storei t2, PayloadOffset[t3] + storep t1, JSCell::m_structure[t0] + dispatch(9) +end + +_llint_op_put_by_id_transition_direct: + putByIdTransition(macro (oldStructure, scratch, slow) end) + + +_llint_op_put_by_id_transition_normal: + putByIdTransition( + macro (oldStructure, scratch, slow) + const protoCell = oldStructure # Reusing the oldStructure register for the proto + + loadp 28[PC], scratch + assert(macro (ok) btpnz scratch, ok end) + loadp StructureChain::m_vector[scratch], scratch + assert(macro (ok) btpnz scratch, ok end) + bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done + .loop: + loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell + loadp JSCell::m_structure[protoCell], oldStructure + bpneq oldStructure, [scratch], slow + addp 4, scratch + bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop + .done: + end) + + +_llint_op_get_by_val: + traceExecution() + loadp CodeBlock[cfr], t1 + loadi 8[PC], t2 + loadi 12[PC], t3 + loadp CodeBlock::m_globalData[t1], t1 + loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow) + loadp JSGlobalData::jsArrayClassInfo[t1], t2 + loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow) + bpneq [t0], t2, .opGetByValSlow + loadp JSArray::m_storage[t0], t3 + biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow + loadi 4[PC], t0 + loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2 + loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1 + bieq t2, EmptyValueTag, .opGetByValSlow + storei t2, TagOffset[cfr, t0, 8] + storei t1, PayloadOffset[cfr, t0, 8] + loadi 16[PC], t0 + valueProfile(t2, t1, t0) + dispatch(5) + +.opGetByValSlow: + callSlowPath(_llint_slow_path_get_by_val) + dispatch(5) + + +_llint_op_get_argument_by_val: + traceExecution() + loadi 8[PC], t0 + loadi 12[PC], t1 + bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentByValSlow + loadConstantOrVariablePayload(t1, Int32Tag, t2, .opGetArgumentByValSlow) + addi 1, t2 + loadi ArgumentCount + PayloadOffset[cfr], t1 + biaeq t2, t1, .opGetArgumentByValSlow + negi t2 + loadi 4[PC], t3 + loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0 + loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1 + storei t0, TagOffset[cfr, t3, 8] + storei t1, PayloadOffset[cfr, t3, 8] + dispatch(5) + +.opGetArgumentByValSlow: + callSlowPath(_llint_slow_path_get_argument_by_val) + dispatch(5) + + +_llint_op_get_by_pname: + traceExecution() + loadi 12[PC], t0 + loadConstantOrVariablePayload(t0, CellTag, t1, .opGetByPnameSlow) + loadi 16[PC], t0 + bpneq t1, PayloadOffset[cfr, t0, 8], .opGetByPnameSlow + loadi 8[PC], t0 + loadConstantOrVariablePayload(t0, CellTag, t2, .opGetByPnameSlow) + loadi 20[PC], t0 + loadi PayloadOffset[cfr, t0, 8], t3 + loadp JSCell::m_structure[t2], t0 + bpneq t0, JSPropertyNameIterator::m_cachedStructure[t3], .opGetByPnameSlow + loadi 24[PC], t0 + loadi [cfr, t0, 8], t0 + subi 1, t0 + biaeq t0, JSPropertyNameIterator::m_numCacheableSlots[t3], .opGetByPnameSlow + loadp JSObject::m_propertyStorage[t2], t2 + loadi TagOffset[t2, t0, 8], t1 + loadi PayloadOffset[t2, t0, 8], t3 + loadi 4[PC], t0 + storei t1, TagOffset[cfr, t0, 8] + storei t3, PayloadOffset[cfr, t0, 8] + dispatch(7) + +.opGetByPnameSlow: + callSlowPath(_llint_slow_path_get_by_pname) + dispatch(7) + + +_llint_op_put_by_val: + traceExecution() + loadi 4[PC], t0 + loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow) + loadi 8[PC], t0 + loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow) + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalData[t0], t0 + loadp JSGlobalData::jsArrayClassInfo[t0], t0 + bpneq [t1], t0, .opPutByValSlow + biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow + loadp JSArray::m_storage[t1], t0 + bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty +.opPutByValStoreResult: + loadi 12[PC], t3 + loadConstantOrVariable2Reg(t3, t1, t3) + writeBarrier(t1, t3) + storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8] + storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8] + dispatch(4) + +.opPutByValEmpty: + addi 1, ArrayStorage::m_numValuesInVector[t0] + bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult + addi 1, t2, t1 + storei t1, ArrayStorage::m_length[t0] + jmp .opPutByValStoreResult + +.opPutByValSlow: + callSlowPath(_llint_slow_path_put_by_val) + dispatch(4) + + +_llint_op_loop: + nop +_llint_op_jmp: + traceExecution() + dispatchBranch(4[PC]) + + +macro jumpTrueOrFalse(conditionOp, slow) + loadi 4[PC], t1 + loadConstantOrVariablePayload(t1, BooleanTag, t0, .slow) + conditionOp(t0, .target) + dispatch(3) + +.target: + dispatchBranch(8[PC]) + +.slow: + callSlowPath(slow) + dispatch(0) +end + + +macro equalNull(cellHandler, immediateHandler) + loadi 4[PC], t0 + assertNotConstant(t0) + loadi TagOffset[cfr, t0, 8], t1 + loadi PayloadOffset[cfr, t0, 8], t0 + bineq t1, CellTag, .immediate + loadp JSCell::m_structure[t0], t2 + cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target) + dispatch(3) + +.target: + dispatchBranch(8[PC]) + +.immediate: + ori 1, t1 + immediateHandler(t1, .target) + dispatch(3) +end + +_llint_op_jeq_null: + traceExecution() + equalNull( + macro (value, target) btbnz value, MasqueradesAsUndefined, target end, + macro (value, target) bieq value, NullTag, target end) + + +_llint_op_jneq_null: + traceExecution() + equalNull( + macro (value, target) btbz value, MasqueradesAsUndefined, target end, + macro (value, target) bineq value, NullTag, target end) + + +_llint_op_jneq_ptr: + traceExecution() + loadi 4[PC], t0 + loadi 8[PC], t1 + bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch + bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough +.opJneqPtrBranch: + dispatchBranch(12[PC]) +.opJneqPtrFallThrough: + dispatch(4) + + +macro compare(integerCompare, doubleCompare, slowPath) + loadi 4[PC], t2 + loadi 8[PC], t3 + loadConstantOrVariable(t2, t0, t1) + loadConstantOrVariable2Reg(t3, t2, t3) + bineq t0, Int32Tag, .op1NotInt + bineq t2, Int32Tag, .op2NotInt + integerCompare(t1, t3, .jumpTarget) + dispatch(4) + +.op1NotInt: + bia t0, LowestTag, .slow + bib t2, LowestTag, .op1NotIntOp2Double + bineq t2, Int32Tag, .slow + ci2d t3, ft1 + jmp .op1NotIntReady +.op1NotIntOp2Double: + fii2d t3, t2, ft1 +.op1NotIntReady: + fii2d t1, t0, ft0 + doubleCompare(ft0, ft1, .jumpTarget) + dispatch(4) + +.op2NotInt: + ci2d t1, ft0 + bia t2, LowestTag, .slow + fii2d t3, t2, ft1 + doubleCompare(ft0, ft1, .jumpTarget) + dispatch(4) + +.jumpTarget: + dispatchBranch(12[PC]) + +.slow: + callSlowPath(slowPath) + dispatch(0) +end + + +_llint_op_switch_imm: + traceExecution() + loadi 12[PC], t2 + loadi 4[PC], t3 + loadConstantOrVariable(t2, t1, t0) + loadp CodeBlock[cfr], t2 + loadp CodeBlock::m_rareData[t2], t2 + muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this! + loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2 + addp t3, t2 + bineq t1, Int32Tag, .opSwitchImmNotInt + subi SimpleJumpTable::min[t2], t0 + biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough + loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3 + loadi [t3, t0, 4], t1 + btiz t1, .opSwitchImmFallThrough + dispatchBranchWithOffset(t1) + +.opSwitchImmNotInt: + bib t1, LowestTag, .opSwitchImmSlow # Go to slow path if it's a double. +.opSwitchImmFallThrough: + dispatchBranch(8[PC]) + +.opSwitchImmSlow: + callSlowPath(_llint_slow_path_switch_imm) + dispatch(0) + + +_llint_op_switch_char: + traceExecution() + loadi 12[PC], t2 + loadi 4[PC], t3 + loadConstantOrVariable(t2, t1, t0) + loadp CodeBlock[cfr], t2 + loadp CodeBlock::m_rareData[t2], t2 + muli sizeof SimpleJumpTable, t3 + loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2 + addp t3, t2 + bineq t1, CellTag, .opSwitchCharFallThrough + loadp JSCell::m_structure[t0], t1 + bbneq Structure::m_typeInfo + TypeInfo::m_type[t1], StringType, .opSwitchCharFallThrough + loadp JSString::m_value[t0], t0 + bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough + loadp StringImpl::m_data8[t0], t1 + btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit + loadh [t1], t0 + jmp .opSwitchCharReady +.opSwitchChar8Bit: + loadb [t1], t0 +.opSwitchCharReady: + subi SimpleJumpTable::min[t2], t0 + biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough + loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2 + loadi [t2, t0, 4], t1 + btiz t1, .opSwitchCharFallThrough + dispatchBranchWithOffset(t1) + +.opSwitchCharFallThrough: + dispatchBranch(8[PC]) + + +_llint_op_new_func: + traceExecution() + btiz 12[PC], .opNewFuncUnchecked + loadi 4[PC], t1 + bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewFuncDone +.opNewFuncUnchecked: + callSlowPath(_llint_slow_path_new_func) +.opNewFuncDone: + dispatch(4) + + +macro doCall(slowPath) + loadi 4[PC], t0 + loadi 16[PC], t1 + loadp LLIntCallLinkInfo::callee[t1], t2 + loadConstantOrVariablePayload(t0, CellTag, t3, .opCallSlow) + bineq t3, t2, .opCallSlow + loadi 12[PC], t3 + addp 24, PC + lshifti 3, t3 + addp cfr, t3 # t3 contains the new value of cfr + loadp JSFunction::m_scopeChain[t2], t0 + storei t2, Callee + PayloadOffset[t3] + storei t0, ScopeChain + PayloadOffset[t3] + loadi 8 - 24[PC], t2 + storei PC, ArgumentCount + TagOffset[cfr] + storep cfr, CallerFrame[t3] + storei t2, ArgumentCount + PayloadOffset[t3] + storei CellTag, Callee + TagOffset[t3] + storei CellTag, ScopeChain + TagOffset[t3] + move t3, cfr + call LLIntCallLinkInfo::machineCodeTarget[t1] + dispatchAfterCall() + +.opCallSlow: + slowPathForCall(6, slowPath) +end + + +_llint_op_tear_off_activation: + traceExecution() + loadi 4[PC], t0 + loadi 8[PC], t1 + bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated + bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated +.opTearOffActivationCreated: + callSlowPath(_llint_slow_path_tear_off_activation) +.opTearOffActivationNotCreated: + dispatch(3) + + +_llint_op_tear_off_arguments: + traceExecution() + loadi 4[PC], t0 + subi 1, t0 # Get the unmodifiedArgumentsRegister + bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffArgumentsNotCreated + callSlowPath(_llint_slow_path_tear_off_arguments) +.opTearOffArgumentsNotCreated: + dispatch(2) + + +_llint_op_ret: + traceExecution() + checkSwitchToJITForEpilogue() + loadi 4[PC], t2 + loadConstantOrVariable(t2, t1, t0) + doReturn() + + +_llint_op_call_put_result: + loadi 4[PC], t2 + loadi 8[PC], t3 + storei t1, TagOffset[cfr, t2, 8] + storei t0, PayloadOffset[cfr, t2, 8] + valueProfile(t1, t0, t3) + traceExecution() # Needs to be here because it would clobber t1, t0 + dispatch(3) + + +_llint_op_ret_object_or_this: + traceExecution() + checkSwitchToJITForEpilogue() + loadi 4[PC], t2 + loadConstantOrVariable(t2, t1, t0) + bineq t1, CellTag, .opRetObjectOrThisNotObject + loadp JSCell::m_structure[t0], t2 + bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject + doReturn() + +.opRetObjectOrThisNotObject: + loadi 8[PC], t2 + loadConstantOrVariable(t2, t1, t0) + doReturn() + + +_llint_op_to_primitive: + traceExecution() + loadi 8[PC], t2 + loadi 4[PC], t3 + loadConstantOrVariable(t2, t1, t0) + bineq t1, CellTag, .opToPrimitiveIsImm + loadp JSCell::m_structure[t0], t2 + bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase +.opToPrimitiveIsImm: + storei t1, TagOffset[cfr, t3, 8] + storei t0, PayloadOffset[cfr, t3, 8] + dispatch(3) + +.opToPrimitiveSlowCase: + callSlowPath(_llint_slow_path_to_primitive) + dispatch(3) + + +_llint_op_next_pname: + traceExecution() + loadi 12[PC], t1 + loadi 16[PC], t2 + loadi PayloadOffset[cfr, t1, 8], t0 + bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd + loadi 20[PC], t2 + loadi PayloadOffset[cfr, t2, 8], t2 + loadp JSPropertyNameIterator::m_jsStrings[t2], t3 + loadi [t3, t0, 8], t3 + addi 1, t0 + storei t0, PayloadOffset[cfr, t1, 8] + loadi 4[PC], t1 + storei CellTag, TagOffset[cfr, t1, 8] + storei t3, PayloadOffset[cfr, t1, 8] + loadi 8[PC], t3 + loadi PayloadOffset[cfr, t3, 8], t3 + loadp JSCell::m_structure[t3], t1 + bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow + loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0 + loadp StructureChain::m_vector[t0], t0 + btpz [t0], .opNextPnameTarget +.opNextPnameCheckPrototypeLoop: + bieq Structure::m_prototype + TagOffset[t1], NullTag, .opNextPnameSlow + loadp Structure::m_prototype + PayloadOffset[t1], t2 + loadp JSCell::m_structure[t2], t1 + bpneq t1, [t0], .opNextPnameSlow + addp 4, t0 + btpnz [t0], .opNextPnameCheckPrototypeLoop +.opNextPnameTarget: + dispatchBranch(24[PC]) + +.opNextPnameEnd: + dispatch(7) + +.opNextPnameSlow: + callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target. + dispatch(0) + + +_llint_op_catch: + # This is where we end up from the JIT's throw trampoline (because the + # machine code return address will be set to _llint_op_catch), and from + # the interpreter's throw trampoline (see _llint_throw_trampoline). + # The JIT throwing protocol calls for the cfr to be in t0. The throwing + # code must have known that we were throwing to the interpreter, and have + # set JSGlobalData::targetInterpreterPCForThrow. + move t0, cfr + loadp JITStackFrame::globalData[sp], t3 + loadi JSGlobalData::targetInterpreterPCForThrow[t3], PC + loadi JSGlobalData::exception + PayloadOffset[t3], t0 + loadi JSGlobalData::exception + TagOffset[t3], t1 + storei 0, JSGlobalData::exception + PayloadOffset[t3] + storei EmptyValueTag, JSGlobalData::exception + TagOffset[t3] + loadi 4[PC], t2 + storei t0, PayloadOffset[cfr, t2, 8] + storei t1, TagOffset[cfr, t2, 8] + traceExecution() # This needs to be here because we don't want to clobber t0, t1, t2, t3 above. + dispatch(2) + + +_llint_op_jsr: + traceExecution() + loadi 4[PC], t0 + addi 3 * 4, PC, t1 + storei t1, [cfr, t0, 8] + dispatchBranch(8[PC]) + + +_llint_op_sret: + traceExecution() + loadi 4[PC], t0 + loadp [cfr, t0, 8], PC + dispatch(0) + + +_llint_op_end: + traceExecution() + checkSwitchToJITForEpilogue() + loadi 4[PC], t0 + assertNotConstant(t0) + loadi TagOffset[cfr, t0, 8], t1 + loadi PayloadOffset[cfr, t0, 8], t0 + doReturn() + + +_llint_throw_from_slow_path_trampoline: + # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so + # the throw target is not necessarily interpreted code, we come to here. + # This essentially emulates the JIT's throwing protocol. + loadp JITStackFrame::globalData[sp], t1 + loadp JSGlobalData::callFrameForThrow[t1], t0 + jmp JSGlobalData::targetMachinePCForThrow[t1] + + +_llint_throw_during_call_trampoline: + preserveReturnAddressAfterCall(t2) + loadp JITStackFrame::globalData[sp], t1 + loadp JSGlobalData::callFrameForThrow[t1], t0 + jmp JSGlobalData::targetMachinePCForThrow[t1] + + +macro nativeCallTrampoline(executableOffsetToFunction) + storep 0, CodeBlock[cfr] + loadp CallerFrame[cfr], t0 + loadi ScopeChain + PayloadOffset[t0], t1 + storei CellTag, ScopeChain + TagOffset[cfr] + storei t1, ScopeChain + PayloadOffset[cfr] + if X86 + peek 0, t1 + storep t1, ReturnPC[cfr] + move cfr, t2 # t2 = ecx + subp 16 - 4, sp + loadi Callee + PayloadOffset[cfr], t1 + loadp JSFunction::m_executable[t1], t1 + move t0, cfr + call executableOffsetToFunction[t1] + addp 16 - 4, sp + loadp JITStackFrame::globalData + 4[sp], t3 + elsif ARMv7 + move t0, t2 + preserveReturnAddressAfterCall(t3) + storep t3, ReturnPC[cfr] + move cfr, t0 + loadi Callee + PayloadOffset[cfr], t1 + loadp JSFunction::m_executable[t1], t1 + move t2, cfr + call executableOffsetToFunction[t1] + restoreReturnAddressBeforeReturn(t3) + loadp JITStackFrame::globalData[sp], t3 + else + error + end + bineq JSGlobalData::exception + TagOffset[t3], EmptyValueTag, .exception + ret +.exception: + preserveReturnAddressAfterCall(t1) # This is really only needed on X86 + callSlowPath(_llint_throw_from_native_call) + jmp _llint_throw_from_slow_path_trampoline +end + diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm new file mode 100644 index 000000000..d8c931fa0 --- /dev/null +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm @@ -0,0 +1,1490 @@ +# Copyright (C) 2011, 2012 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. + + +# Some value representation constants. +const TagBitTypeOther = 0x2 +const TagBitBool = 0x4 +const TagBitUndefined = 0x8 +const ValueEmpty = 0x0 +const ValueFalse = TagBitTypeOther | TagBitBool +const ValueTrue = TagBitTypeOther | TagBitBool | 1 +const ValueUndefined = TagBitTypeOther | TagBitUndefined +const ValueNull = TagBitTypeOther + +# Utilities. +macro dispatch(advance) + addp advance, PC + jmp [PB, PC, 8] +end + +macro dispatchInt(advance) + addi advance, PC + jmp [PB, PC, 8] +end + +macro dispatchAfterCall() + loadi ArgumentCount + TagOffset[cfr], PC + loadp CodeBlock[cfr], PB + loadp CodeBlock::m_instructions[PB], PB + jmp [PB, PC, 8] +end + +macro cCall2(function, arg1, arg2) + move arg1, t5 + move arg2, t4 + call function +end + +# This barely works. arg3 and arg4 should probably be immediates. +macro cCall4(function, arg1, arg2, arg3, arg4) + move arg1, t5 + move arg2, t4 + move arg3, t1 + move arg4, t2 + call function +end + +macro prepareStateForCCall() + leap [PB, PC, 8], PC + move PB, t3 +end + +macro restoreStateAfterCCall() + move t0, PC + move t1, cfr + move t3, PB + subp PB, PC + urshiftp 3, PC +end + +macro callSlowPath(slowPath) + prepareStateForCCall() + cCall2(slowPath, cfr, PC) + restoreStateAfterCCall() +end + +macro traceOperand(fromWhere, operand) + prepareStateForCCall() + cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand) + restoreStateAfterCCall() +end + +macro traceValue(fromWhere, operand) + prepareStateForCCall() + cCall4(_llint_trace_value, cfr, PC, fromWhere, operand) + restoreStateAfterCCall() +end + +# Call a slow path for call call opcodes. +macro callCallSlowPath(advance, slowPath, action) + addi advance, PC, t0 + storei t0, ArgumentCount + TagOffset[cfr] + prepareStateForCCall() + cCall2(slowPath, cfr, PC) + move t1, cfr + action(t0) +end + +macro checkSwitchToJITForLoop() + checkSwitchToJIT( + 1, + macro() + storei PC, ArgumentCount + TagOffset[cfr] + prepareStateForCCall() + cCall2(_llint_loop_osr, cfr, PC) + move t1, cfr + btpz t0, .recover + jmp t0 + .recover: + loadp ArgumentCount + TagOffset[cfr], PC + end) +end + +# Index and value must be different registers. Index may be clobbered. +macro loadConstantOrVariable(index, value) + bpgteq index, FirstConstantRegisterIndex, .constant + loadp [cfr, index, 8], value + jmp .done +.constant: + loadp CodeBlock[cfr], value + loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value + subp FirstConstantRegisterIndex, index + loadp [value, index, 8], value +.done: +end + +macro loadConstantOrVariableInt32(index, value, slow) + loadConstantOrVariable(index, value) + bpb value, tagTypeNumber, slow +end + +macro loadConstantOrVariableCell(index, value, slow) + loadConstantOrVariable(index, value) + btpnz value, tagMask, slow +end + +macro writeBarrier(value) + # Nothing to do, since we don't have a generational or incremental collector. +end + +macro valueProfile(value, profile) + if VALUE_PROFILER + storep value, ValueProfile::m_buckets[profile] + end +end + + +# Entrypoints into the interpreter. + +# Expects that CodeBlock is in t1, which is what prologue() leaves behind. +macro functionArityCheck(doneLabel, slow_path) + loadi PayloadOffset + ArgumentCount[cfr], t0 + biaeq t0, CodeBlock::m_numParameters[t1], doneLabel + prepareStateForCCall() + cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error + move t1, cfr + btiz t0, .continue + loadp JITStackFrame::globalData[sp], t1 + loadp JSGlobalData::callFrameForThrow[t1], t0 + jmp JSGlobalData::targetMachinePCForThrow[t1] +.continue: + # Reload CodeBlock and reset PC, since the slow_path clobbered them. + loadp CodeBlock[cfr], t1 + loadp CodeBlock::m_instructions[t1], PB + move 0, PC + jmp doneLabel +end + + +# Instruction implementations + +_llint_op_enter: + traceExecution() + loadp CodeBlock[cfr], t2 + loadi CodeBlock::m_numVars[t2], t2 + btiz t2, .opEnterDone + move ValueUndefined, t0 +.opEnterLoop: + subi 1, t2 + storep t0, [cfr, t2, 8] + btinz t2, .opEnterLoop +.opEnterDone: + dispatch(1) + + +_llint_op_create_activation: + traceExecution() + loadis 8[PB, PC, 8], t0 + bpneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone + callSlowPath(_llint_slow_path_create_activation) +.opCreateActivationDone: + dispatch(2) + + +_llint_op_init_lazy_reg: + traceExecution() + loadis 8[PB, PC, 8], t0 + storep ValueEmpty, [cfr, t0, 8] + dispatch(2) + + +_llint_op_create_arguments: + traceExecution() + loadis 8[PB, PC, 8], t0 + bpneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone + callSlowPath(_llint_slow_path_create_arguments) +.opCreateArgumentsDone: + dispatch(2) + + +_llint_op_create_this: + traceExecution() + loadis 16[PB, PC, 8], t0 + assertNotConstant(t0) + loadp [cfr, t0, 8], t0 + btpnz t0, tagMask, .opCreateThisSlow + loadp JSCell::m_structure[t0], t1 + bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow + loadp JSObject::m_inheritorID[t0], t2 + btpz t2, .opCreateThisSlow + allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow) + loadis 8[PB, PC, 8], t1 + storep t0, [cfr, t1, 8] + dispatch(3) + +.opCreateThisSlow: + callSlowPath(_llint_slow_path_create_this) + dispatch(3) + + +_llint_op_get_callee: + traceExecution() + loadis 8[PB, PC, 8], t0 + loadp Callee[cfr], t1 + storep t1, [cfr, t0, 8] + dispatch(2) + + +_llint_op_convert_this: + traceExecution() + loadis 8[PB, PC, 8], t0 + loadp [cfr, t0, 8], t0 + btpnz t0, tagMask, .opConvertThisSlow + loadp JSCell::m_structure[t0], t0 + bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow + dispatch(2) + +.opConvertThisSlow: + callSlowPath(_llint_slow_path_convert_this) + dispatch(2) + + +_llint_op_new_object: + traceExecution() + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSGlobalObject::m_emptyObjectStructure[t0], t1 + allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow) + loadis 8[PB, PC, 8], t1 + storep t0, [cfr, t1, 8] + dispatch(2) + +.opNewObjectSlow: + callSlowPath(_llint_slow_path_new_object) + dispatch(2) + + +_llint_op_mov: + traceExecution() + loadis 16[PB, PC, 8], t1 + loadis 8[PB, PC, 8], t0 + loadConstantOrVariable(t1, t2) + storep t2, [cfr, t0, 8] + dispatch(3) + + +_llint_op_not: + traceExecution() + loadis 16[PB, PC, 8], t0 + loadis 8[PB, PC, 8], t1 + loadConstantOrVariable(t0, t2) + xorp ValueFalse, t2 + btpnz t2, ~1, .opNotSlow + xorp ValueTrue, t2 + storep t2, [cfr, t1, 8] + dispatch(3) + +.opNotSlow: + callSlowPath(_llint_slow_path_not) + dispatch(3) + + +macro equalityComparison(integerComparison, slowPath) + traceExecution() + loadis 24[PB, PC, 8], t0 + loadis 16[PB, PC, 8], t2 + loadis 8[PB, PC, 8], t3 + loadConstantOrVariableInt32(t0, t1, .slow) + loadConstantOrVariableInt32(t2, t0, .slow) + integerComparison(t0, t1, t0) + orp ValueFalse, t0 + storep t0, [cfr, t3, 8] + dispatch(4) + +.slow: + callSlowPath(slowPath) + dispatch(4) +end + +_llint_op_eq: + equalityComparison( + macro (left, right, result) cieq left, right, result end, + _llint_slow_path_eq) + + +_llint_op_neq: + equalityComparison( + macro (left, right, result) cineq left, right, result end, + _llint_slow_path_neq) + + +macro equalNullComparison() + loadis 16[PB, PC, 8], t0 + loadp [cfr, t0, 8], t0 + btpnz t0, tagMask, .immediate + loadp JSCell::m_structure[t0], t2 + tbnz Structure::m_typeInfo + TypeInfo::m_flags[t2], MasqueradesAsUndefined, t0 + jmp .done +.immediate: + andp ~TagBitUndefined, t0 + cpeq t0, ValueNull, t0 +.done: +end + +_llint_op_eq_null: + traceExecution() + equalNullComparison() + loadis 8[PB, PC, 8], t1 + orp ValueFalse, t0 + storep t0, [cfr, t1, 8] + dispatch(3) + + +_llint_op_neq_null: + traceExecution() + equalNullComparison() + loadis 8[PB, PC, 8], t1 + xorp ValueTrue, t0 + storep t0, [cfr, t1, 8] + dispatch(3) + + +macro strictEq(equalityOperation, slowPath) + traceExecution() + loadis 24[PB, PC, 8], t0 + loadis 16[PB, PC, 8], t2 + loadConstantOrVariable(t0, t1) + loadConstantOrVariable(t2, t0) + move t0, t2 + orp t1, t2 + btpz t2, tagMask, .slow + bpaeq t0, tagTypeNumber, .leftOK + btpnz t0, tagTypeNumber, .slow +.leftOK: + bpaeq t1, tagTypeNumber, .rightOK + btpnz t1, tagTypeNumber, .slow +.rightOK: + equalityOperation(t0, t1, t0) + loadis 8[PB, PC, 8], t1 + orp ValueFalse, t0 + storep t0, [cfr, t1, 8] + dispatch(4) + +.slow: + callSlowPath(slowPath) + dispatch(4) +end + +_llint_op_stricteq: + strictEq( + macro (left, right, result) cpeq left, right, result end, + _llint_slow_path_stricteq) + + +_llint_op_nstricteq: + strictEq( + macro (left, right, result) cpneq left, right, result end, + _llint_slow_path_nstricteq) + + +macro preOp(arithmeticOperation, slowPath) + traceExecution() + loadis 8[PB, PC, 8], t0 + loadp [cfr, t0, 8], t1 + bpb t1, tagTypeNumber, .slow + arithmeticOperation(t1, .slow) + orp tagTypeNumber, t1 + storep t1, [cfr, t0, 8] + dispatch(2) + +.slow: + callSlowPath(slowPath) + dispatch(2) +end + +_llint_op_pre_inc: + preOp( + macro (value, slow) baddio 1, value, slow end, + _llint_slow_path_pre_inc) + + +_llint_op_pre_dec: + preOp( + macro (value, slow) bsubio 1, value, slow end, + _llint_slow_path_pre_dec) + + +macro postOp(arithmeticOperation, slowPath) + traceExecution() + loadis 16[PB, PC, 8], t0 + loadis 8[PB, PC, 8], t1 + loadp [cfr, t0, 8], t2 + bieq t0, t1, .done + bpb t2, tagTypeNumber, .slow + move t2, t3 + arithmeticOperation(t3, .slow) + orp tagTypeNumber, t3 + storep t2, [cfr, t1, 8] + storep t3, [cfr, t0, 8] +.done: + dispatch(3) + +.slow: + callSlowPath(slowPath) + dispatch(3) +end + +_llint_op_post_inc: + postOp( + macro (value, slow) baddio 1, value, slow end, + _llint_slow_path_post_inc) + + +_llint_op_post_dec: + postOp( + macro (value, slow) bsubio 1, value, slow end, + _llint_slow_path_post_dec) + + +_llint_op_to_jsnumber: + traceExecution() + loadis 16[PB, PC, 8], t0 + loadis 8[PB, PC, 8], t1 + loadConstantOrVariable(t0, t2) + bpaeq t2, tagTypeNumber, .opToJsnumberIsImmediate + btpz t2, tagTypeNumber, .opToJsnumberSlow +.opToJsnumberIsImmediate: + storep t2, [cfr, t1, 8] + dispatch(3) + +.opToJsnumberSlow: + callSlowPath(_llint_slow_path_to_jsnumber) + dispatch(3) + + +_llint_op_negate: + traceExecution() + loadis 16[PB, PC, 8], t0 + loadis 8[PB, PC, 8], t1 + loadConstantOrVariable(t0, t2) + bpb t2, tagTypeNumber, .opNegateNotInt + btiz t2, 0x7fffffff, .opNegateSlow + negi t2 + orp tagTypeNumber, t2 + storep t2, [cfr, t1, 8] + dispatch(3) +.opNegateNotInt: + btpz t2, tagTypeNumber, .opNegateSlow + xorp 0x8000000000000000, t2 + storep t2, [cfr, t1, 8] + dispatch(3) + +.opNegateSlow: + callSlowPath(_llint_slow_path_negate) + dispatch(3) + + +macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath) + loadis 24[PB, PC, 8], t0 + loadis 16[PB, PC, 8], t2 + loadConstantOrVariable(t0, t1) + loadConstantOrVariable(t2, t0) + bpb t0, tagTypeNumber, .op1NotInt + bpb t1, tagTypeNumber, .op2NotInt + loadis 8[PB, PC, 8], t2 + integerOperationAndStore(t1, t0, .slow, t2) + dispatch(5) + +.op1NotInt: + # First operand is definitely not an int, the second operand could be anything. + btpz t0, tagTypeNumber, .slow + bpaeq t1, tagTypeNumber, .op1NotIntOp2Int + btpz t1, tagTypeNumber, .slow + addp tagTypeNumber, t1 + fp2d t1, ft1 + jmp .op1NotIntReady +.op1NotIntOp2Int: + ci2d t1, ft1 +.op1NotIntReady: + loadis 8[PB, PC, 8], t2 + addp tagTypeNumber, t0 + fp2d t0, ft0 + doubleOperation(ft1, ft0) + fd2p ft0, t0 + subp tagTypeNumber, t0 + storep t0, [cfr, t2, 8] + dispatch(5) + +.op2NotInt: + # First operand is definitely an int, the second is definitely not. + loadis 8[PB, PC, 8], t2 + btpz t1, tagTypeNumber, .slow + ci2d t0, ft0 + addp tagTypeNumber, t1 + fp2d t1, ft1 + doubleOperation(ft1, ft0) + fd2p ft0, t0 + subp tagTypeNumber, t0 + storep t0, [cfr, t2, 8] + dispatch(5) + +.slow: + callSlowPath(slowPath) + dispatch(5) +end + +macro binaryOp(integerOperation, doubleOperation, slowPath) + binaryOpCustomStore( + macro (left, right, slow, index) + integerOperation(left, right, slow) + orp tagTypeNumber, right + storep right, [cfr, index, 8] + end, + doubleOperation, slowPath) +end + +_llint_op_add: + traceExecution() + binaryOp( + macro (left, right, slow) baddio left, right, slow end, + macro (left, right) addd left, right end, + _llint_slow_path_add) + + +_llint_op_mul: + traceExecution() + binaryOpCustomStore( + macro (left, right, slow, index) + # Assume t3 is scratchable. + move right, t3 + bmulio left, t3, slow + btinz t3, .done + bilt left, 0, slow + bilt right, 0, slow + .done: + orp tagTypeNumber, t3 + storep t3, [cfr, index, 8] + end, + macro (left, right) muld left, right end, + _llint_slow_path_mul) + + +_llint_op_sub: + traceExecution() + binaryOp( + macro (left, right, slow) bsubio left, right, slow end, + macro (left, right) subd left, right end, + _llint_slow_path_sub) + + +_llint_op_div: + traceExecution() + binaryOpCustomStore( + macro (left, right, slow, index) + # Assume t3 is scratchable. + btiz left, slow + btinz right, .intOK + bilt left, 0, slow + .intOK: + move left, t3 + move right, t0 + cdqi + idivi t3 + btinz t1, slow + orp tagTypeNumber, t0 + storep t0, [cfr, index, 8] + end, + macro (left, right) divd left, right end, + _llint_slow_path_div) + + +macro bitOp(operation, slowPath, advance) + loadis 24[PB, PC, 8], t0 + loadis 16[PB, PC, 8], t2 + loadis 8[PB, PC, 8], t3 + loadConstantOrVariable(t0, t1) + loadConstantOrVariable(t2, t0) + bpb t0, tagTypeNumber, .slow + bpb t1, tagTypeNumber, .slow + operation(t1, t0, .slow) + orp tagTypeNumber, t0 + storep t0, [cfr, t3, 8] + dispatch(advance) + +.slow: + callSlowPath(slowPath) + dispatch(advance) +end + +_llint_op_lshift: + traceExecution() + bitOp( + macro (left, right, slow) lshifti left, right end, + _llint_slow_path_lshift, + 4) + + +_llint_op_rshift: + traceExecution() + bitOp( + macro (left, right, slow) rshifti left, right end, + _llint_slow_path_rshift, + 4) + + +_llint_op_urshift: + traceExecution() + bitOp( + macro (left, right, slow) + urshifti left, right + bilt right, 0, slow + end, + _llint_slow_path_urshift, + 4) + + +_llint_op_bitand: + traceExecution() + bitOp( + macro (left, right, slow) andi left, right end, + _llint_slow_path_bitand, + 5) + + +_llint_op_bitxor: + traceExecution() + bitOp( + macro (left, right, slow) xori left, right end, + _llint_slow_path_bitxor, + 5) + + +_llint_op_bitor: + traceExecution() + bitOp( + macro (left, right, slow) ori left, right end, + _llint_slow_path_bitor, + 5) + + +_llint_op_check_has_instance: + traceExecution() + loadis 8[PB, PC, 8], t1 + loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow) + loadp JSCell::m_structure[t0], t0 + btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow + dispatch(2) + +.opCheckHasInstanceSlow: + callSlowPath(_llint_slow_path_check_has_instance) + dispatch(2) + + +_llint_op_instanceof: + traceExecution() + # Check that baseVal implements the default HasInstance behavior. + # FIXME: This should be deprecated. + loadis 24[PB, PC, 8], t1 + loadConstantOrVariable(t1, t0) + loadp JSCell::m_structure[t0], t0 + btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow + + # Actually do the work. + loadis 32[PB, PC, 8], t0 + loadis 8[PB, PC, 8], t3 + loadConstantOrVariableCell(t0, t1, .opInstanceofSlow) + loadp JSCell::m_structure[t1], t2 + bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow + loadis 16[PB, PC, 8], t0 + loadConstantOrVariableCell(t0, t2, .opInstanceofSlow) + + # Register state: t1 = prototype, t2 = value + move 1, t0 +.opInstanceofLoop: + loadp JSCell::m_structure[t2], t2 + loadp Structure::m_prototype[t2], t2 + bpeq t2, t1, .opInstanceofDone + btpz t2, tagMask, .opInstanceofLoop + + move 0, t0 +.opInstanceofDone: + orp ValueFalse, t0 + storep t0, [cfr, t3, 8] + dispatch(5) + +.opInstanceofSlow: + callSlowPath(_llint_slow_path_instanceof) + dispatch(5) + + +macro resolveGlobal(size, slow) + # Operands are as follows: + # 8[PB, PC, 8] Destination for the load. + # 16[PB, PC, 8] Property identifier index in the code block. + # 24[PB, PC, 8] Structure pointer, initialized to 0 by bytecode generator. + # 32[PB, PC, 8] Offset in global object, initialized to 0 by bytecode generator. + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSCell::m_structure[t0], t1 + bpneq t1, 24[PB, PC, 8], slow + loadis 32[PB, PC, 8], t1 + loadp JSObject::m_propertyStorage[t0], t0 + loadp [t0, t1, 8], t2 + loadis 8[PB, PC, 8], t0 + storep t2, [cfr, t0, 8] + loadp (size - 1) * 8[PB, PC, 8], t0 + valueProfile(t2, t0) +end + +_llint_op_resolve_global: + traceExecution() + resolveGlobal(6, .opResolveGlobalSlow) + dispatch(6) + +.opResolveGlobalSlow: + callSlowPath(_llint_slow_path_resolve_global) + dispatch(6) + + +# Gives you the scope in t0, while allowing you to optionally perform additional checks on the +# scopes as they are traversed. scopeCheck() is called with two arguments: the register +# holding the scope, and a register that can be used for scratch. Note that this does not +# use t3, so you can hold stuff in t3 if need be. +macro getScope(deBruijinIndexOperand, scopeCheck) + loadp ScopeChain[cfr], t0 + loadis deBruijinIndexOperand, t2 + + btiz t2, .done + + loadp CodeBlock[cfr], t1 + bineq CodeBlock::m_codeType[t1], FunctionCode, .loop + btbz CodeBlock::m_needsFullScopeChain[t1], .loop + + loadis CodeBlock::m_activationRegister[t1], t1 + + # Need to conditionally skip over one scope. + btpz [cfr, t1, 8], .noActivation + scopeCheck(t0, t1) + loadp ScopeChainNode::next[t0], t0 +.noActivation: + subi 1, t2 + + btiz t2, .done +.loop: + scopeCheck(t0, t1) + loadp ScopeChainNode::next[t0], t0 + subi 1, t2 + btinz t2, .loop + +.done: +end + +_llint_op_resolve_global_dynamic: + traceExecution() + loadp JITStackFrame::globalData[sp], t3 + loadp JSGlobalData::activationStructure[t3], t3 + getScope( + 40[PB, PC, 8], + macro (scope, scratch) + loadp ScopeChainNode::object[scope], scratch + bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow + end) + resolveGlobal(7, .opResolveGlobalDynamicSlow) + dispatch(7) + +.opResolveGlobalDynamicSuperSlow: + callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic) + dispatch(7) + +.opResolveGlobalDynamicSlow: + callSlowPath(_llint_slow_path_resolve_global_dynamic) + dispatch(7) + + +_llint_op_get_scoped_var: + traceExecution() + # Operands are as follows: + # 8[PB, PC, 8] Destination for the load + # 16[PB, PC, 8] Index of register in the scope + # 24[PB, PC, 8] De Bruijin index. + getScope(24[PB, PC, 8], macro (scope, scratch) end) + loadis 8[PB, PC, 8], t1 + loadis 16[PB, PC, 8], t2 + loadp ScopeChainNode::object[t0], t0 + loadp JSVariableObject::m_registers[t0], t0 + loadp [t0, t2, 8], t3 + storep t3, [cfr, t1, 8] + loadp 32[PB, PC, 8], t1 + valueProfile(t3, t1) + dispatch(5) + + +_llint_op_put_scoped_var: + traceExecution() + getScope(16[PB, PC, 8], macro (scope, scratch) end) + loadis 24[PB, PC, 8], t1 + loadConstantOrVariable(t1, t3) + loadis 8[PB, PC, 8], t1 + writeBarrier(t3) + loadp ScopeChainNode::object[t0], t0 + loadp JSVariableObject::m_registers[t0], t0 + storep t3, [t0, t1, 8] + dispatch(4) + + +_llint_op_get_global_var: + traceExecution() + loadis 16[PB, PC, 8], t1 + loadis 8[PB, PC, 8], t3 + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSGlobalObject::m_registers[t0], t0 + loadp [t0, t1, 8], t2 + storep t2, [cfr, t3, 8] + loadp 24[PB, PC, 8], t3 + valueProfile(t2, t3) + dispatch(4) + + +_llint_op_put_global_var: + traceExecution() + loadis 16[PB, PC, 8], t1 + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + loadp JSGlobalObject::m_registers[t0], t0 + loadConstantOrVariable(t1, t2) + loadis 8[PB, PC, 8], t1 + writeBarrier(t2) + storep t2, [t0, t1, 8] + dispatch(3) + + +_llint_op_get_by_id: + traceExecution() + # We only do monomorphic get_by_id caching for now, and we do not modify the + # opcode. We do, however, allow for the cache to change anytime if fails, since + # ping-ponging is free. At best we get lucky and the get_by_id will continue + # to take fast path on the new cache. At worst we take slow path, which is what + # we would have been doing anyway. + loadis 16[PB, PC, 8], t0 + loadp 32[PB, PC, 8], t1 + loadConstantOrVariableCell(t0, t3, .opGetByIdSlow) + loadis 40[PB, PC, 8], t2 + loadp JSObject::m_propertyStorage[t3], t0 + bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow + loadis 8[PB, PC, 8], t1 + loadp [t0, t2], t3 + storep t3, [cfr, t1, 8] + loadp 64[PB, PC, 8], t1 + valueProfile(t3, t1) + dispatch(9) + +.opGetByIdSlow: + callSlowPath(_llint_slow_path_get_by_id) + dispatch(9) + + +_llint_op_get_arguments_length: + traceExecution() + loadis 16[PB, PC, 8], t0 + loadis 8[PB, PC, 8], t1 + btpnz [cfr, t0, 8], .opGetArgumentsLengthSlow + loadi ArgumentCount + PayloadOffset[cfr], t2 + subi 1, t2 + orp tagTypeNumber, t2 + storep t2, [cfr, t1, 8] + dispatch(4) + +.opGetArgumentsLengthSlow: + callSlowPath(_llint_slow_path_get_arguments_length) + dispatch(4) + + +_llint_op_put_by_id: + traceExecution() + loadis 8[PB, PC, 8], t3 + loadp 32[PB, PC, 8], t1 + loadConstantOrVariableCell(t3, t0, .opPutByIdSlow) + loadis 24[PB, PC, 8], t2 + loadp JSObject::m_propertyStorage[t0], t3 + bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow + loadis 40[PB, PC, 8], t1 + loadConstantOrVariable(t2, t0) + writeBarrier(t0) + storep t0, [t3, t1] + dispatch(9) + +.opPutByIdSlow: + callSlowPath(_llint_slow_path_put_by_id) + dispatch(9) + + +macro putByIdTransition(additionalChecks) + traceExecution() + loadis 8[PB, PC, 8], t3 + loadp 32[PB, PC, 8], t1 + loadConstantOrVariableCell(t3, t0, .opPutByIdSlow) + loadis 24[PB, PC, 8], t2 + bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow + additionalChecks(t1, t3, .opPutByIdSlow) + loadis 40[PB, PC, 8], t1 + loadp JSObject::m_propertyStorage[t0], t3 + addp t1, t3 + loadConstantOrVariable(t2, t1) + writeBarrier(t1) + storep t1, [t3] + loadp 48[PB, PC, 8], t1 + storep t1, JSCell::m_structure[t0] + dispatch(9) +end + +_llint_op_put_by_id_transition_direct: + putByIdTransition(macro (oldStructure, scratch, slow) end) + + +_llint_op_put_by_id_transition_normal: + putByIdTransition( + macro (oldStructure, scratch, slow) + const protoCell = oldStructure # Reusing the oldStructure register for the proto + loadp 56[PB, PC, 8], scratch + assert(macro (ok) btpnz scratch, ok end) + loadp StructureChain::m_vector[scratch], scratch + assert(macro (ok) btpnz scratch, ok end) + bpeq Structure::m_prototype[oldStructure], ValueNull, .done + .loop: + loadp Structure::m_prototype[oldStructure], protoCell + loadp JSCell::m_structure[protoCell], oldStructure + bpneq oldStructure, [scratch], slow + addp 8, scratch + bpneq Structure::m_prototype[oldStructure], ValueNull, .loop + .done: + end) + + +_llint_op_get_by_val: + traceExecution() + loadp CodeBlock[cfr], t1 + loadis 16[PB, PC, 8], t2 + loadis 24[PB, PC, 8], t3 + loadp CodeBlock::m_globalData[t1], t1 + loadConstantOrVariableCell(t2, t0, .opGetByValSlow) + loadp JSGlobalData::jsArrayClassInfo[t1], t2 + loadConstantOrVariableInt32(t3, t1, .opGetByValSlow) + sxi2p t1, t1 + bpneq [t0], t2, .opGetByValSlow + loadp JSArray::m_storage[t0], t3 + biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow + loadis 8[PB, PC, 8], t0 + loadp ArrayStorage::m_vector[t3, t1, 8], t2 + btpz t2, .opGetByValSlow + storep t2, [cfr, t0, 8] + loadp 32[PB, PC, 8], t0 + valueProfile(t2, t0) + dispatch(5) + +.opGetByValSlow: + callSlowPath(_llint_slow_path_get_by_val) + dispatch(5) + + +_llint_op_get_argument_by_val: + traceExecution() + loadis 16[PB, PC, 8], t0 + loadis 24[PB, PC, 8], t1 + btpnz [cfr, t0, 8], .opGetArgumentByValSlow + loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow) + addi 1, t2 + loadi ArgumentCount + PayloadOffset[cfr], t1 + biaeq t2, t1, .opGetArgumentByValSlow + negi t2 + sxi2p t2, t2 + loadis 8[PB, PC, 8], t3 + loadp ThisArgumentOffset[cfr, t2, 8], t0 + storep t0, [cfr, t3, 8] + dispatch(5) + +.opGetArgumentByValSlow: + callSlowPath(_llint_slow_path_get_argument_by_val) + dispatch(5) + + +_llint_op_get_by_pname: + traceExecution() + loadis 24[PB, PC, 8], t1 + loadConstantOrVariable(t1, t0) + loadis 32[PB, PC, 8], t1 + assertNotConstant(t1) + bpneq t0, [cfr, t1, 8], .opGetByPnameSlow + loadis 16[PB, PC, 8], t2 + loadis 40[PB, PC, 8], t3 + loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow) + assertNotConstant(t3) + loadp [cfr, t3, 8], t1 + loadp JSCell::m_structure[t0], t2 + bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow + loadis 48[PB, PC, 8], t3 + loadi PayloadOffset[cfr, t3, 8], t3 + subi 1, t3 + biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow + loadp JSObject::m_propertyStorage[t0], t0 + loadp [t0, t3, 8], t0 + loadis 8[PB, PC, 8], t1 + storep t0, [cfr, t1, 8] + dispatch(7) + +.opGetByPnameSlow: + callSlowPath(_llint_slow_path_get_by_pname) + dispatch(7) + + +_llint_op_put_by_val: + traceExecution() + loadis 8[PB, PC, 8], t0 + loadConstantOrVariableCell(t0, t1, .opPutByValSlow) + loadis 16[PB, PC, 8], t0 + loadConstantOrVariableInt32(t0, t2, .opPutByValSlow) + sxi2p t2, t2 + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalData[t0], t0 + loadp JSGlobalData::jsArrayClassInfo[t0], t0 + bpneq [t1], t0, .opPutByValSlow + biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow + loadp JSArray::m_storage[t1], t0 + btpz ArrayStorage::m_vector[t0, t2, 8], .opPutByValEmpty +.opPutByValStoreResult: + loadis 24[PB, PC, 8], t3 + loadConstantOrVariable(t3, t1) + writeBarrier(t1) + storep t1, ArrayStorage::m_vector[t0, t2, 8] + dispatch(4) + +.opPutByValEmpty: + addi 1, ArrayStorage::m_numValuesInVector[t0] + bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult + addi 1, t2, t1 + storei t1, ArrayStorage::m_length[t0] + jmp .opPutByValStoreResult + +.opPutByValSlow: + callSlowPath(_llint_slow_path_put_by_val) + dispatch(4) + + +_llint_op_loop: + nop +_llint_op_jmp: + traceExecution() + dispatchInt(8[PB, PC, 8]) + + +macro jumpTrueOrFalse(conditionOp, slow) + loadis 8[PB, PC, 8], t1 + loadConstantOrVariable(t1, t0) + xorp ValueFalse, t0 + btpnz t0, -1, .slow + conditionOp(t0, .target) + dispatch(3) + +.target: + dispatchInt(16[PB, PC, 8]) + +.slow: + callSlowPath(slow) + dispatch(0) +end + + +macro equalNull(cellHandler, immediateHandler) + loadis 8[PB, PC, 8], t0 + assertNotConstant(t0) + loadp [cfr, t0, 8], t0 + btpnz t0, tagMask, .immediate + loadp JSCell::m_structure[t0], t2 + cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target) + dispatch(3) + +.target: + dispatch(16[PB, PC, 8]) + +.immediate: + andp ~TagBitUndefined, t0 + immediateHandler(t0, .target) + dispatch(3) +end + +_llint_op_jeq_null: + traceExecution() + equalNull( + macro (value, target) btbnz value, MasqueradesAsUndefined, target end, + macro (value, target) bpeq value, ValueNull, target end) + + +_llint_op_jneq_null: + traceExecution() + equalNull( + macro (value, target) btbz value, MasqueradesAsUndefined, target end, + macro (value, target) bpneq value, ValueNull, target end) + + +_llint_op_jneq_ptr: + traceExecution() + loadis 8[PB, PC, 8], t0 + loadp 16[PB, PC, 8], t1 + bpneq t1, [cfr, t0, 8], .opJneqPtrTarget + dispatch(4) + +.opJneqPtrTarget: + dispatchInt(24[PB, PC, 8]) + + +macro compare(integerCompare, doubleCompare, slowPath) + loadis 8[PB, PC, 8], t2 + loadis 16[PB, PC, 8], t3 + loadConstantOrVariable(t2, t0) + loadConstantOrVariable(t3, t1) + bpb t0, tagTypeNumber, .op1NotInt + bpb t1, tagTypeNumber, .op2NotInt + integerCompare(t0, t1, .jumpTarget) + dispatch(4) + +.op1NotInt: + btpz t0, tagTypeNumber, .slow + bpb t1, tagTypeNumber, .op1NotIntOp2NotInt + ci2d t1, ft1 + jmp .op1NotIntReady +.op1NotIntOp2NotInt: + btpz t1, tagTypeNumber, .slow + addp tagTypeNumber, t1 + fp2d t1, ft1 +.op1NotIntReady: + addp tagTypeNumber, t0 + fp2d t0, ft0 + doubleCompare(ft0, ft1, .jumpTarget) + dispatch(4) + +.op2NotInt: + ci2d t0, ft0 + btpz t1, tagTypeNumber, .slow + addp tagTypeNumber, t1 + fp2d t1, ft1 + doubleCompare(ft0, ft1, .jumpTarget) + dispatch(4) + +.jumpTarget: + dispatchInt(24[PB, PC, 8]) + +.slow: + callSlowPath(slowPath) + dispatch(0) +end + + +_llint_op_switch_imm: + traceExecution() + loadis 24[PB, PC, 8], t2 + loadis 8[PB, PC, 8], t3 + loadConstantOrVariable(t2, t1) + loadp CodeBlock[cfr], t2 + loadp CodeBlock::m_rareData[t2], t2 + muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this! + loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2 + addp t3, t2 + bpb t1, tagTypeNumber, .opSwitchImmNotInt + subi SimpleJumpTable::min[t2], t1 + biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough + loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3 + loadis [t3, t1, 4], t1 + btiz t1, .opSwitchImmFallThrough + dispatch(t1) + +.opSwitchImmNotInt: + btpnz t1, tagTypeNumber, .opSwitchImmSlow # Go slow if it's a double. +.opSwitchImmFallThrough: + dispatchInt(16[PB, PC, 8]) + +.opSwitchImmSlow: + callSlowPath(_llint_slow_path_switch_imm) + dispatch(0) + + +_llint_op_switch_char: + traceExecution() + loadis 24[PB, PC, 8], t2 + loadis 8[PB, PC, 8], t3 + loadConstantOrVariable(t2, t1) + loadp CodeBlock[cfr], t2 + loadp CodeBlock::m_rareData[t2], t2 + muli sizeof SimpleJumpTable, t3 + loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2 + addp t3, t2 + btpnz t1, tagMask, .opSwitchCharFallThrough + loadp JSCell::m_structure[t1], t0 + bbneq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, .opSwitchCharFallThrough + loadp JSString::m_value[t1], t0 + bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough + loadp StringImpl::m_data8[t0], t1 + btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit + loadh [t1], t0 + jmp .opSwitchCharReady +.opSwitchChar8Bit: + loadb [t1], t0 +.opSwitchCharReady: + subi SimpleJumpTable::min[t2], t0 + biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough + loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2 + loadis [t2, t0, 4], t1 + btiz t1, .opSwitchCharFallThrough + dispatch(t1) + +.opSwitchCharFallThrough: + dispatchInt(16[PB, PC, 8]) + + +_llint_op_new_func: + traceExecution() + btiz 24[PB, PC, 8], .opNewFuncUnchecked + loadis 8[PB, PC, 8], t1 + btpnz [cfr, t1, 8], .opNewFuncDone +.opNewFuncUnchecked: + callSlowPath(_llint_slow_path_new_func) +.opNewFuncDone: + dispatch(4) + + +macro doCall(slowPath) + loadis 8[PB, PC, 8], t0 + loadp 32[PB, PC, 8], t1 + loadp LLIntCallLinkInfo::callee[t1], t2 + loadConstantOrVariable(t0, t3) + bpneq t3, t2, .opCallSlow + loadis 24[PB, PC, 8], t3 + addi 6, PC + lshifti 3, t3 + addp cfr, t3 + loadp JSFunction::m_scopeChain[t2], t0 + storep t2, Callee[t3] + storep t0, ScopeChain[t3] + loadis 16 - 48[PB, PC, 8], t2 + storei PC, ArgumentCount + TagOffset[cfr] + storep cfr, CallerFrame[t3] + storei t2, ArgumentCount + PayloadOffset[t3] + move t3, cfr + call LLIntCallLinkInfo::machineCodeTarget[t1] + dispatchAfterCall() + +.opCallSlow: + slowPathForCall(6, slowPath) +end + + +_llint_op_tear_off_activation: + traceExecution() + loadis 8[PB, PC, 8], t0 + loadis 16[PB, PC, 8], t1 + btpnz [cfr, t0, 8], .opTearOffActivationCreated + btpz [cfr, t1, 8], .opTearOffActivationNotCreated +.opTearOffActivationCreated: + callSlowPath(_llint_slow_path_tear_off_activation) +.opTearOffActivationNotCreated: + dispatch(3) + + +_llint_op_tear_off_arguments: + traceExecution() + loadis 8[PB, PC, 8], t0 + subi 1, t0 # Get the unmodifiedArgumentsRegister + btpz [cfr, t0, 8], .opTearOffArgumentsNotCreated + callSlowPath(_llint_slow_path_tear_off_arguments) +.opTearOffArgumentsNotCreated: + dispatch(2) + + +_llint_op_ret: + traceExecution() + checkSwitchToJITForEpilogue() + loadis 8[PB, PC, 8], t2 + loadConstantOrVariable(t2, t0) + doReturn() + + +_llint_op_call_put_result: + loadis 8[PB, PC, 8], t2 + loadp 16[PB, PC, 8], t3 + storep t0, [cfr, t2, 8] + valueProfile(t0, t3) + traceExecution() + dispatch(3) + + +_llint_op_ret_object_or_this: + traceExecution() + checkSwitchToJITForEpilogue() + loadis 8[PB, PC, 8], t2 + loadConstantOrVariable(t2, t0) + btpnz t0, tagMask, .opRetObjectOrThisNotObject + loadp JSCell::m_structure[t0], t2 + bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject + doReturn() + +.opRetObjectOrThisNotObject: + loadis 16[PB, PC, 8], t2 + loadConstantOrVariable(t2, t0) + doReturn() + + +_llint_op_to_primitive: + traceExecution() + loadis 16[PB, PC, 8], t2 + loadis 8[PB, PC, 8], t3 + loadConstantOrVariable(t2, t0) + btpnz t0, tagMask, .opToPrimitiveIsImm + loadp JSCell::m_structure[t0], t2 + bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase +.opToPrimitiveIsImm: + storep t0, [cfr, t3, 8] + dispatch(3) + +.opToPrimitiveSlowCase: + callSlowPath(_llint_slow_path_to_primitive) + dispatch(3) + + +_llint_op_next_pname: + traceExecution() + loadis 24[PB, PC, 8], t1 + loadis 32[PB, PC, 8], t2 + assertNotConstant(t1) + assertNotConstant(t2) + loadi PayloadOffset[cfr, t1, 8], t0 + bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd + loadis 40[PB, PC, 8], t2 + assertNotConstant(t2) + loadp [cfr, t2, 8], t2 + loadp JSPropertyNameIterator::m_jsStrings[t2], t3 + loadp [t3, t0, 8], t3 + addi 1, t0 + storei t0, PayloadOffset[cfr, t1, 8] + loadis 8[PB, PC, 8], t1 + storep t3, [cfr, t1, 8] + loadis 16[PB, PC, 8], t3 + assertNotConstant(t3) + loadp [cfr, t3, 8], t3 + loadp JSCell::m_structure[t3], t1 + bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow + loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0 + loadp StructureChain::m_vector[t0], t0 + btpz [t0], .opNextPnameTarget +.opNextPnameCheckPrototypeLoop: + bpeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow + loadp Structure::m_prototype[t1], t2 + loadp JSCell::m_structure[t2], t1 + bpneq t1, [t0], .opNextPnameSlow + addp 8, t0 + btpnz [t0], .opNextPnameCheckPrototypeLoop +.opNextPnameTarget: + dispatchInt(48[PB, PC, 8]) + +.opNextPnameEnd: + dispatch(7) + +.opNextPnameSlow: + callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target. + dispatch(0) + + +_llint_op_catch: + # This is where we end up from the JIT's throw trampoline (because the + # machine code return address will be set to _llint_op_catch), and from + # the interpreter's throw trampoline (see _llint_throw_trampoline). + # The JIT throwing protocol calls for the cfr to be in t0. The throwing + # code must have known that we were throwing to the interpreter, and have + # set JSGlobalData::targetInterpreterPCForThrow. + move t0, cfr + loadp CodeBlock[cfr], PB + loadp CodeBlock::m_instructions[PB], PB + loadp JITStackFrame::globalData[sp], t3 + loadp JSGlobalData::targetInterpreterPCForThrow[t3], PC + subp PB, PC + urshiftp 3, PC + loadp JSGlobalData::exception[t3], t0 + storep 0, JSGlobalData::exception[t3] + loadis 8[PB, PC, 8], t2 + storep t0, [cfr, t2, 8] + traceExecution() + dispatch(2) + + +_llint_op_jsr: + traceExecution() + loadis 8[PB, PC, 8], t0 + addi 3, PC, t1 + storei t1, [cfr, t0, 8] + dispatchInt(16[PB, PC, 8]) + + +_llint_op_sret: + traceExecution() + loadis 8[PB, PC, 8], t0 + loadi [cfr, t0, 8], PC + dispatch(0) + + +_llint_op_end: + traceExecution() + checkSwitchToJITForEpilogue() + loadis 8[PB, PC, 8], t0 + assertNotConstant(t0) + loadp [cfr, t0, 8], t0 + doReturn() + + +_llint_throw_from_slow_path_trampoline: + # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so + # the throw target is not necessarily interpreted code, we come to here. + # This essentially emulates the JIT's throwing protocol. + loadp JITStackFrame::globalData[sp], t1 + loadp JSGlobalData::callFrameForThrow[t1], t0 + jmp JSGlobalData::targetMachinePCForThrow[t1] + + +_llint_throw_during_call_trampoline: + preserveReturnAddressAfterCall(t2) + loadp JITStackFrame::globalData[sp], t1 + loadp JSGlobalData::callFrameForThrow[t1], t0 + jmp JSGlobalData::targetMachinePCForThrow[t1] + + +macro nativeCallTrampoline(executableOffsetToFunction) + storep 0, CodeBlock[cfr] + loadp CallerFrame[cfr], t0 + loadp ScopeChain[t0], t1 + storep t1, ScopeChain[cfr] + peek 0, t1 + storep t1, ReturnPC[cfr] + move cfr, t5 # t5 = rdi + subp 16 - 8, sp + loadp Callee[cfr], t4 # t4 = rsi + loadp JSFunction::m_executable[t4], t1 + move t0, cfr # Restore cfr to avoid loading from stack + call executableOffsetToFunction[t1] + addp 16 - 8, sp + loadp JITStackFrame::globalData + 8[sp], t3 + btpnz JSGlobalData::exception[t3], .exception + ret +.exception: + preserveReturnAddressAfterCall(t1) + callSlowPath(_llint_throw_from_native_call) + jmp _llint_throw_from_slow_path_trampoline +end + diff --git a/Source/JavaScriptCore/offlineasm/armv7.rb b/Source/JavaScriptCore/offlineasm/armv7.rb index eb8df6869..ed7db5618 100644 --- a/Source/JavaScriptCore/offlineasm/armv7.rb +++ b/Source/JavaScriptCore/offlineasm/armv7.rb @@ -33,29 +33,9 @@ class Node end class SpecialRegister < NoChildren - def initialize(name) - @name = name - end - def armV7Operand @name end - - def address? - false - end - - def label? - false - end - - def immediate? - false - end - - def register? - true - end end ARMv7_EXTRA_GPRS = [SpecialRegister.new("r9"), SpecialRegister.new("r8"), SpecialRegister.new("r3")] @@ -228,7 +208,7 @@ def armV7LowerShiftOps(list) | node | if node.is_a? Instruction case node.opcode - when "lshifti", "rshifti", "urshifti" + when "lshifti", "rshifti", "urshifti", "lshiftp", "rshiftp", "urshiftp" if node.operands.size == 2 newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]]) else @@ -469,7 +449,7 @@ def armV7LowerMalformedImmediates(list) else newList << node.armV7LowerMalformedImmediatesRecurse(newList) end - when "muli" + when "muli", "mulp" if node.operands[0].is_a? Immediate tmp = Tmp.new(codeOrigin, :gpr) newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp]) @@ -535,9 +515,9 @@ def armV7LowerMisplacedAddresses(list) if node.is_a? Instruction postInstructions = [] case node.opcode - when "addi", "addp", "addis", "andi", "andp", "lshifti", "muli", "negi", "noti", "ori", "oris", - "orp", "rshifti", "urshifti", "subi", "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/, - /^btp/, /^ci/, /^cp/, /^ti/ + when "addi", "addp", "addis", "andi", "andp", "lshifti", "lshiftp", "muli", "mulp", "negi", + "negp", "noti", "ori", "oris", "orp", "rshifti", "urshifti", "rshiftp", "urshiftp", "subi", + "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/, /^btp/, /^ci/, /^cp/, /^ti/ newList << Instruction.new(node.codeOrigin, node.opcode, armV7AsRegisters(newList, postInstructions, node.operands, "i")) @@ -649,7 +629,7 @@ end # class Sequence - def lowerARMv7 + def getModifiedListARMv7 myList = @list # Verify that we will only see instructions and labels. @@ -673,10 +653,8 @@ class Sequence myList = armV7LowerRegisterReuse(myList) myList = assignRegistersToTemporaries(myList, :gpr, ARMv7_EXTRA_GPRS) myList = assignRegistersToTemporaries(myList, :fpr, ARMv7_EXTRA_FPRS) - myList.each { - | node | - node.lower("ARMv7") - } + + return myList end end @@ -792,13 +770,13 @@ class Instruction emitArmV7Compact("orrs", "orrs", operands) when "xori", "xorp" emitArmV7Compact("eors", "eor", operands) - when "lshifti" + when "lshifti", "lshiftp" emitArmV7Compact("lsls", "lsls", operands) - when "rshifti" + when "rshifti", "rshiftp" emitArmV7Compact("asrs", "asrs", operands) - when "urshifti" + when "urshifti", "urshiftp" emitArmV7Compact("lsrs", "lsrs", operands) - when "muli" + when "muli", "mulp" if operands.size == 2 or operands[0] == operands[2] or operands[1] == operands[2] emitArmV7("muls", operands) else @@ -807,11 +785,11 @@ class Instruction end when "subi", "subp", "subis" emitArmV7Compact("subs", "subs", operands) - when "negi" + when "negi", "negp" $asm.puts "rsbs #{operands[0].armV7Operand}, #{operands[0].armV7Operand}, \#0" when "noti" $asm.puts "mvns #{operands[0].armV7Operand}, #{operands[0].armV7Operand}" - when "loadi", "loadp" + when "loadi", "loadis", "loadp" $asm.puts "ldr #{armV7FlippedOperands(operands)}" when "storei", "storep" $asm.puts "str #{armV7Operands(operands)}" diff --git a/Source/JavaScriptCore/offlineasm/asm.rb b/Source/JavaScriptCore/offlineasm/asm.rb index a93a8c5dd..12bade022 100644 --- a/Source/JavaScriptCore/offlineasm/asm.rb +++ b/Source/JavaScriptCore/offlineasm/asm.rb @@ -128,11 +128,15 @@ outputFlnm = ARGV.shift $stderr.puts "offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating assembly file #{outputFlnm}." -configurationList = offsetsAndConfigurationIndex(offsetsFile) -inputData = IO::read(asmFile) +begin + configurationList = offsetsAndConfigurationIndex(offsetsFile) +rescue MissingMagicValuesException + $stderr.puts "offlineasm: No magic values found. Skipping assembly file generation assuming the classic interpreter is enabled." + exit 0 +end inputHash = - "// offlineasm input hash: " + Digest::SHA1.hexdigest(inputData) + + "// offlineasm input hash: " + parseHash(asmFile) + " " + Digest::SHA1.hexdigest(configurationList.map{|v| (v[0] + [v[1]]).join(' ')}.join(' ')) + " " + selfHash @@ -154,7 +158,7 @@ File.open(outputFlnm, "w") { $asm = Assembler.new($output) - ast = parse(lex(inputData)) + ast = parse(asmFile) configurationList.each { | configuration | @@ -163,6 +167,7 @@ File.open(outputFlnm, "w") { forSettings(computeSettingsCombinations(ast)[configIndex], ast) { | concreteSettings, lowLevelAST, backend | lowLevelAST = lowLevelAST.resolve(*buildOffsetsMap(lowLevelAST, offsetsList)) + lowLevelAST.validate emitCodeInConfiguration(concreteSettings, lowLevelAST, backend) { $asm.inAsm { lowLevelAST.lower(backend) diff --git a/Source/JavaScriptCore/offlineasm/ast.rb b/Source/JavaScriptCore/offlineasm/ast.rb index f67b0fc60..e555b5d98 100644 --- a/Source/JavaScriptCore/offlineasm/ast.rb +++ b/Source/JavaScriptCore/offlineasm/ast.rb @@ -57,7 +57,7 @@ class Node end def codeOriginString - "line number #{@codeOrigin}" + @codeOrigin.to_s end def descendants @@ -383,6 +383,157 @@ class NegImmediate < Node end end +class OrImmediates < Node + attr_reader :left, :right + + def initialize(codeOrigin, left, right) + super(codeOrigin) + @left = left + @right = right + end + + def children + [@left, @right] + end + + def mapChildren + OrImmediates.new(codeOrigin, (yield @left), (yield @right)) + end + + def dump + "(#{left.dump} | #{right.dump})" + end + + def address? + false + end + + def label? + false + end + + def immediate? + true + end + + def register? + false + end +end + +class AndImmediates < Node + attr_reader :left, :right + + def initialize(codeOrigin, left, right) + super(codeOrigin) + @left = left + @right = right + end + + def children + [@left, @right] + end + + def mapChildren + AndImmediates.new(codeOrigin, (yield @left), (yield @right)) + end + + def dump + "(#{left.dump} & #{right.dump})" + end + + def address? + false + end + + def label? + false + end + + def immediate? + true + end + + def register? + false + end +end + +class XorImmediates < Node + attr_reader :left, :right + + def initialize(codeOrigin, left, right) + super(codeOrigin) + @left = left + @right = right + end + + def children + [@left, @right] + end + + def mapChildren + XorImmediates.new(codeOrigin, (yield @left), (yield @right)) + end + + def dump + "(#{left.dump} ^ #{right.dump})" + end + + def address? + false + end + + def label? + false + end + + def immediate? + true + end + + def register? + false + end +end + +class BitnotImmediate < Node + attr_reader :child + + def initialize(codeOrigin, child) + super(codeOrigin) + @child = child + end + + def children + [@child] + end + + def mapChildren + BitnotImmediate.new(codeOrigin, (yield @child)) + end + + def dump + "(~#{@child.dump})" + end + + def address? + false + end + + def label? + false + end + + def immediate? + true + end + + def register? + false + end +end + class RegisterID < NoChildren attr_reader :name @@ -459,6 +610,28 @@ class FPRegisterID < NoChildren end end +class SpecialRegister < NoChildren + def initialize(name) + @name = name + end + + def address? + false + end + + def label? + false + end + + def immediate? + false + end + + def register? + true + end +end + class Variable < NoChildren attr_reader :name @@ -479,6 +652,10 @@ class Variable < NoChildren def dump name end + + def inspect + "<variable #{name} at #{codeOriginString}>" + end end class Address < Node @@ -757,6 +934,10 @@ class LabelReference < Node def label? true end + + def immediate? + false + end end class LocalLabelReference < NoChildren @@ -790,6 +971,10 @@ class LocalLabelReference < NoChildren def label? true end + + def immediate? + false + end end class Sequence < Node diff --git a/Source/JavaScriptCore/offlineasm/backends.rb b/Source/JavaScriptCore/offlineasm/backends.rb index 2c65b517d..db7a1e218 100644 --- a/Source/JavaScriptCore/offlineasm/backends.rb +++ b/Source/JavaScriptCore/offlineasm/backends.rb @@ -28,6 +28,7 @@ require "x86" BACKENDS = [ "X86", + "X86_64", "ARMv7" ] @@ -39,6 +40,7 @@ BACKENDS = WORKING_BACKENDS = [ "X86", + "X86_64", "ARMv7" ] @@ -46,7 +48,12 @@ BACKEND_PATTERN = Regexp.new('\\A(' + BACKENDS.join(')|(') + ')\\Z') class Node def lower(name) - send("lower" + name) + begin + $activeBackend = name + send("lower" + name) + rescue => e + raise "Got error #{e} at #{codeOriginString}" + end end end @@ -83,7 +90,14 @@ end class Sequence def lower(name) - if respond_to? "lower#{name}" + $activeBackend = name + if respond_to? "getModifiedList#{name}" + newList = send("getModifiedList#{name}") + newList.each { + | node | + node.lower(name) + } + elsif respond_to? "lower#{name}" send("lower#{name}") else @list.each { diff --git a/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb b/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb index 8bdf4505d..b2a8c2c83 100644 --- a/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb +++ b/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb @@ -45,8 +45,7 @@ def emitMagicNumber } end -inputData = IO::read(inputFlnm) -inputHash = "// offlineasm input hash: #{Digest::SHA1.hexdigest(inputData)} #{selfHash}" +inputHash = "// offlineasm input hash: #{parseHash(inputFlnm)} #{selfHash}" if FileTest.exist? outputFlnm File.open(outputFlnm, "r") { @@ -59,7 +58,7 @@ if FileTest.exist? outputFlnm } end -originalAST = parse(lex(inputData)) +originalAST = parse(inputFlnm) # # Optimize the AST to make configuration extraction faster. This reduces the AST to a form diff --git a/Source/JavaScriptCore/offlineasm/instructions.rb b/Source/JavaScriptCore/offlineasm/instructions.rb index 497b47371..cc7e0c6a5 100644 --- a/Source/JavaScriptCore/offlineasm/instructions.rb +++ b/Source/JavaScriptCore/offlineasm/instructions.rb @@ -30,15 +30,20 @@ MACRO_INSTRUCTIONS = "addi", "andi", "lshifti", + "lshiftp", "muli", "negi", + "negp", "noti", "ori", "rshifti", "urshifti", + "rshiftp", + "urshiftp", "subi", "xori", "loadi", + "loadis", "loadb", "loadbs", "loadh", @@ -56,6 +61,8 @@ MACRO_INSTRUCTIONS = "ci2d", "fii2d", # usage: fii2d <gpr with least significant bits>, <gpr with most significant bits>, <fpr> "fd2ii", # usage: fd2ii <fpr>, <gpr with least significant bits>, <gpr with most significant bits> + "fp2d", + "fd2p", "bdeq", "bdneq", "bdgt", @@ -157,6 +164,7 @@ MACRO_INSTRUCTIONS = "bplt", "bplteq", "addp", + "mulp", "andp", "orp", "subp", diff --git a/Source/JavaScriptCore/offlineasm/offsets.rb b/Source/JavaScriptCore/offlineasm/offsets.rb index 21e1706d2..63af014bb 100644 --- a/Source/JavaScriptCore/offlineasm/offsets.rb +++ b/Source/JavaScriptCore/offlineasm/offsets.rb @@ -27,6 +27,16 @@ OFFSET_HEADER_MAGIC_NUMBERS = [ 0x9e43fd66, 0x4379bfba ] OFFSET_MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ] # +# MissingMagicValuesException +# +# Thrown when magic values are missing from the binary. +# This is usually an indication that the classic interpreter is enabled. +# + +class MissingMagicValuesException < Exception +end + +# # offsetsList(ast) # sizesList(ast) # @@ -142,7 +152,7 @@ def offsetsAndConfigurationIndex(file) end } - raise unless result.length >= 1 + raise MissingMagicValuesException unless result.length >= 1 raise if result.map{|v| v[1]}.uniq.size < result.map{|v| v[1]}.size result diff --git a/Source/JavaScriptCore/offlineasm/parser.rb b/Source/JavaScriptCore/offlineasm/parser.rb index f0e4b0045..11863c724 100644 --- a/Source/JavaScriptCore/offlineasm/parser.rb +++ b/Source/JavaScriptCore/offlineasm/parser.rb @@ -23,7 +23,22 @@ require "ast" require "instructions" +require "pathname" require "registers" +require "self_hash" + +class CodeOrigin + attr_reader :fileName, :lineNumber + + def initialize(fileName, lineNumber) + @fileName = fileName + @lineNumber = lineNumber + end + + def to_s + "#{fileName}:#{lineNumber}" + end +end class Token attr_reader :codeOrigin, :string @@ -46,7 +61,7 @@ class Token end def to_s - "#{@string.inspect} at line #{codeOrigin}" + "#{@string.inspect} at #{codeOrigin}" end def parseError(*comment) @@ -62,7 +77,8 @@ end # The lexer. Takes a string and returns an array of tokens. # -def lex(str) +def lex(str, fileName) + fileName = Pathname.new(fileName) result = [] lineNumber = 1 while not str.empty? @@ -70,28 +86,28 @@ def lex(str) when /\A\#([^\n]*)/ # comment, ignore when /\A\n/ - result << Token.new(lineNumber, $&) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) lineNumber += 1 when /\A[a-zA-Z]([a-zA-Z0-9_]*)/ - result << Token.new(lineNumber, $&) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) when /\A\.([a-zA-Z0-9_]*)/ - result << Token.new(lineNumber, $&) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) when /\A_([a-zA-Z0-9_]*)/ - result << Token.new(lineNumber, $&) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) when /\A([ \t]+)/ # whitespace, ignore when /\A0x([0-9a-fA-F]+)/ - result << Token.new(lineNumber, $&.hex.to_s) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&.hex.to_s) when /\A0([0-7]+)/ - result << Token.new(lineNumber, $&.oct.to_s) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&.oct.to_s) when /\A([0-9]+)/ - result << Token.new(lineNumber, $&) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) when /\A::/ - result << Token.new(lineNumber, $&) - when /\A[:,\(\)\[\]=\+\-*]/ - result << Token.new(lineNumber, $&) + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) + when /\A[:,\(\)\[\]=\+\-~\|&^*]/ + result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) else - raise "Lexer error at line number #{lineNumber}, unexpected sequence #{str[0..20].inspect}" + raise "Lexer error at #{CodeOrigin.new(fileName, lineNumber).to_s}, unexpected sequence #{str[0..20].inspect}" end str = $~.post_match end @@ -111,7 +127,7 @@ def isInstruction(token) end def isKeyword(token) - token =~ /\A((true)|(false)|(if)|(then)|(else)|(elsif)|(end)|(and)|(or)|(not)|(macro)|(const)|(sizeof)|(error))\Z/ or + token =~ /\A((true)|(false)|(if)|(then)|(else)|(elsif)|(end)|(and)|(or)|(not)|(macro)|(const)|(sizeof)|(error)|(include))\Z/ or token =~ REGISTER_PATTERN or token =~ INSTRUCTION_PATTERN end @@ -142,8 +158,8 @@ end # class Parser - def initialize(tokens) - @tokens = tokens + def initialize(data, fileName) + @tokens = lex(data, fileName) @idx = 0 end @@ -306,6 +322,9 @@ class Parser if @tokens[@idx] == "-" @idx += 1 NegImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom) + elsif @tokens[@idx] == "~" + @idx += 1 + BitnotImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom) elsif @tokens[@idx] == "(" @idx += 1 result = parseExpression @@ -349,10 +368,10 @@ class Parser end def couldBeExpression - @tokens[@idx] == "-" or @tokens[@idx] == "sizeof" or isInteger(@tokens[@idx]) or isVariable(@tokens[@idx]) or @tokens[@idx] == "(" + @tokens[@idx] == "-" or @tokens[@idx] == "~" or @tokens[@idx] == "sizeof" or isInteger(@tokens[@idx]) or isVariable(@tokens[@idx]) or @tokens[@idx] == "(" end - def parseExpression + def parseExpressionAdd skipNewLine result = parseExpressionMul while @tokens[@idx] == "+" or @tokens[@idx] == "-" @@ -369,6 +388,33 @@ class Parser result end + def parseExpressionAnd + skipNewLine + result = parseExpressionAdd + while @tokens[@idx] == "&" + @idx += 1 + result = AndImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAdd) + end + result + end + + def parseExpression + skipNewLine + result = parseExpressionAnd + while @tokens[@idx] == "|" or @tokens[@idx] == "^" + if @tokens[@idx] == "|" + @idx += 1 + result = OrImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAnd) + elsif @tokens[@idx] == "^" + @idx += 1 + result = XorImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAnd) + else + raise + end + end + result + end + def parseOperand(comment) skipNewLine if couldBeExpression @@ -571,6 +617,14 @@ class Parser list << LocalLabel.forName(codeOrigin, name) end @idx += 1 + elsif @tokens[@idx] == "include" + @idx += 1 + parseError unless isIdentifier(@tokens[@idx]) + moduleName = @tokens[@idx].string + fileName = @tokens[@idx].codeOrigin.fileName.dirname + (moduleName + ".asm") + @idx += 1 + $stderr.puts "offlineasm: Including file #{fileName}" + list << parse(fileName) else parseError "Expecting terminal #{final} #{comment}" end @@ -579,8 +633,16 @@ class Parser end end -def parse(tokens) - parser = Parser.new(tokens) +def parseData(data, fileName) + parser = Parser.new(data, fileName) parser.parseSequence(nil, "") end +def parse(fileName) + parseData(IO::read(fileName), fileName) +end + +def parseHash(fileName) + dirHash(Pathname.new(fileName).dirname, /\.asm$/) +end + diff --git a/Source/JavaScriptCore/offlineasm/registers.rb b/Source/JavaScriptCore/offlineasm/registers.rb index 75fae4192..2c5a4ebf6 100644 --- a/Source/JavaScriptCore/offlineasm/registers.rb +++ b/Source/JavaScriptCore/offlineasm/registers.rb @@ -34,7 +34,13 @@ GPRS = "r0", "r1", "sp", - "lr" + "lr", + + # 64-bit only registers: + "t5", + "t6", # r10 + "csr1", # r14, tag type number register + "csr2" # r15, tag mask register ] FPRS = diff --git a/Source/JavaScriptCore/offlineasm/self_hash.rb b/Source/JavaScriptCore/offlineasm/self_hash.rb index a7b51e112..2c300fccc 100644 --- a/Source/JavaScriptCore/offlineasm/self_hash.rb +++ b/Source/JavaScriptCore/offlineasm/self_hash.rb @@ -25,22 +25,33 @@ require "digest/sha1" require "pathname" # -# selfHash -> SHA1 hexdigest +# dirHash(directory, regexp) -> SHA1 hexdigest # -# Returns a hash of the offlineasm source code. This allows dependency -# tracking for not just changes in input, but also changes in the assembler -# itself. +# Returns a hash of all files in the given directory that fit the given +# pattern. # -def selfHash +def dirHash(directory, regexp) + directory = Pathname.new(directory) contents = "" - myPath = Pathname.new(__FILE__).dirname - Dir.foreach(myPath) { + Dir.foreach(directory) { | entry | - if entry =~ /\.rb$/ - contents += IO::read(myPath + entry) + if entry =~ regexp + contents += IO::read(directory + entry) end } return Digest::SHA1.hexdigest(contents) end +# +# selfHash -> SHA1 hexdigest +# +# Returns a hash of the offlineasm source code. This allows dependency +# tracking for not just changes in input, but also changes in the assembler +# itself. +# + +def selfHash + dirHash(Pathname.new(__FILE__).dirname, /\.rb$/) +end + diff --git a/Source/JavaScriptCore/offlineasm/settings.rb b/Source/JavaScriptCore/offlineasm/settings.rb index 34598181c..b7daa7492 100644 --- a/Source/JavaScriptCore/offlineasm/settings.rb +++ b/Source/JavaScriptCore/offlineasm/settings.rb @@ -53,7 +53,7 @@ def computeSettingsCombinations(ast) settingsCombinator(settingsCombinations, newMap, remaining[1..-1]) end - settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + ["X86", "ARMv7"]).uniq) + settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + BACKENDS).uniq) settingsCombinations end diff --git a/Source/JavaScriptCore/offlineasm/transform.rb b/Source/JavaScriptCore/offlineasm/transform.rb index 5f5024d9e..86c72be67 100644 --- a/Source/JavaScriptCore/offlineasm/transform.rb +++ b/Source/JavaScriptCore/offlineasm/transform.rb @@ -328,6 +328,44 @@ class NegImmediate end end +class OrImmediates + def fold + @left = @left.fold + @right = @right.fold + return self unless @left.is_a? Immediate + return self unless @right.is_a? Immediate + Immediate.new(codeOrigin, @left.value | @right.value) + end +end + +class AndImmediates + def fold + @left = @left.fold + @right = @right.fold + return self unless @left.is_a? Immediate + return self unless @right.is_a? Immediate + Immediate.new(codeOrigin, @left.value & @right.value) + end +end + +class XorImmediates + def fold + @left = @left.fold + @right = @right.fold + return self unless @left.is_a? Immediate + return self unless @right.is_a? Immediate + Immediate.new(codeOrigin, @left.value ^ @right.value) + end +end + +class BitnotImmediate + def fold + @child = @child.fold + return self unless @child.is_a? Immediate + Immediate.new(codeOrigin, ~@child.value) + end +end + # # node.resolveAfterSettings(offsets, sizes) # @@ -340,3 +378,97 @@ class Node end end +# +# node.validate +# +# Checks that the node is ready for backend compilation. +# + +class Node + def validate + raise "Unresolved #{dump} at #{codeOriginString}" + end + + def validateChildren + children.each { + | node | + node.validate + } + end +end + +class Sequence + def validate + validateChildren + end +end + +class Immediate + def validate + end +end + +class RegisterID + def validate + end +end + +class FPRegisterID + def validate + end +end + +class Address + def validate + validateChildren + end +end + +class BaseIndex + def validate + validateChildren + end +end + +class AbsoluteAddress + def validate + validateChildren + end +end + +class Instruction + def validate + validateChildren + end +end + +class Error + def validate + end +end + +class Label + def validate + end +end + +class LocalLabel + def validate + end +end + +class LabelReference + def validate + end +end + +class LocalLabelReference + def validate + end +end + +class Skip + def validate + end +end + diff --git a/Source/JavaScriptCore/offlineasm/x86.rb b/Source/JavaScriptCore/offlineasm/x86.rb index b89f2d90c..4416ec909 100644 --- a/Source/JavaScriptCore/offlineasm/x86.rb +++ b/Source/JavaScriptCore/offlineasm/x86.rb @@ -1,4 +1,4 @@ -# Copyright (C) 2011 Apple Inc. All rights reserved. +# Copyright (C) 2012 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -21,13 +21,48 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. +def isX64 + case $activeBackend + when "X86" + false + when "X86_64" + true + else + raise "bad value for $activeBackend: #{$activeBackend}" + end +end + +class SpecialRegister < NoChildren + def x86Operand(kind) + raise unless @name =~ /^r/ + raise unless isX64 + case kind + when :half + "%" + @name + "w" + when :int + "%" + @name + "d" + when :ptr + "%" + @name + else + raise + end + end + def x86CallOperand(kind) + "*#{x86Operand(kind)}" + end +end + +X64_SCRATCH_REGISTER = SpecialRegister.new("r11") + class RegisterID def supports8BitOnX86 case name when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3" true - when "t4", "cfr" + when "cfr", "ttnr", "tmr" false + when "t4", "t5" + isX64 else raise end @@ -43,6 +78,8 @@ class RegisterID "%ax" when :int "%eax" + when :ptr + isX64 ? "%rax" : "%eax" else raise end @@ -54,6 +91,8 @@ class RegisterID "%dx" when :int "%edx" + when :ptr + isX64 ? "%rdx" : "%edx" else raise end @@ -65,6 +104,8 @@ class RegisterID "%cx" when :int "%ecx" + when :ptr + isX64 ? "%rcx" : "%ecx" else raise end @@ -76,6 +117,8 @@ class RegisterID "%bx" when :int "%ebx" + when :ptr + isX64 ? "%rbx" : "%ebx" else raise end @@ -87,19 +130,36 @@ class RegisterID "%si" when :int "%esi" + when :ptr + isX64 ? "%rsi" : "%esi" else raise end when "cfr" - case kind - when :byte - "%dil" - when :half - "%di" - when :int - "%edi" + if isX64 + case kind + when :half + "%r13w" + when :int + "%r13d" + when :ptr + "%r13" + else + raise + end else - raise + case kind + when :byte + "%dil" + when :half + "%di" + when :int + "%edi" + when :ptr + "%edi" + else + raise + end end when "sp" case kind @@ -109,9 +169,53 @@ class RegisterID "%sp" when :int "%esp" + when :ptr + isX64 ? "%rsp" : "%esp" else raise end + when "t5" + raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 + case kind + when :byte + "%dil" + when :half + "%di" + when :int + "%edi" + when :ptr + "%rdi" + end + when "t6" + raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 + case kind + when :half + "%r10w" + when :int + "%r10d" + when :ptr + "%r10" + end + when "csr1" + raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 + case kind + when :half + "%r14w" + when :int + "%r14d" + when :ptr + "%r14" + end + when "csr2" + raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 + case kind + when :half + "%r15w" + when :int + "%r15d" + when :ptr + "%r15" + end else raise "Bad register #{name} for X86 at #{codeOriginString}" end @@ -147,6 +251,13 @@ class FPRegisterID end class Immediate + def validX86Immediate? + if isX64 + value >= -0x80000000 and value <= 0x7fffffff + else + true + end + end def x86Operand(kind) "$#{value}" end @@ -160,8 +271,11 @@ class Address true end + def x86AddressOperand(addressKind) + "#{offset.value}(#{base.x86Operand(addressKind)})" + end def x86Operand(kind) - "#{offset.value}(#{base.x86Operand(:int)})" + x86AddressOperand(:ptr) end def x86CallOperand(kind) "*#{x86Operand(kind)}" @@ -173,12 +287,16 @@ class BaseIndex true end + def x86AddressOperand(addressKind) + "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})" + end + def x86Operand(kind) - "#{offset.value}(#{base.x86Operand(:int)}, #{index.x86Operand(:int)}, #{scale})" + x86AddressOperand(:ptr) end def x86CallOperand(kind) - "*#{x86operand(kind)}" + "*#{x86Operand(kind)}" end end @@ -187,6 +305,10 @@ class AbsoluteAddress true end + def x86AddressOperand(addressKind) + "#{address.value}" + end + def x86Operand(kind) "#{address.value}" end @@ -208,6 +330,47 @@ class LocalLabelReference end end +class Sequence + def getModifiedListX86_64 + newList = [] + + @list.each { + | node | + newNode = node + if node.is_a? Instruction + unless node.opcode == "move" + usedScratch = false + newOperands = node.operands.map { + | operand | + if operand.immediate? and not operand.validX86Immediate? + if usedScratch + raise "Attempt to use scratch register twice at #{operand.codeOriginString}" + end + newList << Instruction.new(operand.codeOrigin, "move", [operand, X64_SCRATCH_REGISTER]) + usedScratch = true + X64_SCRATCH_REGISTER + else + operand + end + } + newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands) + end + else + unless node.is_a? Label or + node.is_a? LocalLabel or + node.is_a? Skip + raise "Unexpected #{node.inspect} at #{node.codeOrigin}" + end + end + if newNode + newList << newNode + end + } + + return newList + end +end + class Instruction def x86Operands(*kinds) raise unless kinds.size == operands.size @@ -227,6 +390,8 @@ class Instruction "w" when :int "l" + when :ptr + isX64 ? "q" : "l" when :double "sd" else @@ -234,6 +399,23 @@ class Instruction end end + def x86Bytes(kind) + case kind + when :byte + 1 + when :half + 2 + when :int + 4 + when :ptr + isX64 ? 8 : 4 + when :double + 8 + else + raise + end + end + def handleX86OpWithNumOperands(opcode, kind, numOperands) if numOperands == 3 if operands[0] == operands[2] @@ -257,9 +439,10 @@ class Instruction if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2") $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}" else - $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx" + cx = RegisterID.forName(nil, "t2") + $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}" $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}" - $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx" + $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}" end end @@ -295,10 +478,11 @@ class Instruction $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}" $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}" else - $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax" + ax = RegisterID.new(nil, "t0") + $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}" $asm.puts "#{setOpcode} %al" $asm.puts "movzbl %al, %eax" - $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax" + $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}" end end @@ -354,8 +538,8 @@ class Instruction def handleX86SubBranch(branchOpcode, kind) if operands.size == 4 and operands[1] == operands[2] - $asm.puts "negl #{operands[2].x86Operand(:int)}" - $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}" + $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}" + $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" else handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1) end @@ -370,62 +554,120 @@ class Instruction $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}" end - def lowerX86 - $asm.comment codeOriginString - case opcode - when "addi", "addp" - if operands.size == 3 and operands[0].is_a? Immediate - raise unless operands[1].is_a? RegisterID - raise unless operands[2].is_a? RegisterID - if operands[0].value == 0 - unless operands[1] == operands[2] - $asm.puts "movl #{operands[1].x86Operand(:int)}, #{operands[2].x86Operand(:int)}" - end - else - $asm.puts "leal #{operands[0].value}(#{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}" + def handleX86Add(kind) + if operands.size == 3 and operands[0].is_a? Immediate + raise unless operands[1].is_a? RegisterID + raise unless operands[2].is_a? RegisterID + if operands[0].value == 0 + unless operands[1] == operands[2] + $asm.puts "mov#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" end - elsif operands.size == 3 and operands[0].is_a? RegisterID - raise unless operands[1].is_a? RegisterID - raise unless operands[2].is_a? RegisterID - $asm.puts "leal (#{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}" else - unless Immediate.new(nil, 0) == operands[0] - $asm.puts "addl #{x86Operands(:int, :int)}" - end + $asm.puts "lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}" end - when "andi", "andp" + elsif operands.size == 3 and operands[0].is_a? RegisterID + raise unless operands[1].is_a? RegisterID + raise unless operands[2].is_a? RegisterID + $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}" + else + unless Immediate.new(nil, 0) == operands[0] + $asm.puts "add#{x86Suffix(kind)} #{x86Operands(kind, kind)}" + end + end + end + + def handleX86Sub(kind) + if operands.size == 3 and operands[1] == operands[2] + $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}" + $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" + else + handleX86Op("sub#{x86Suffix(kind)}", kind) + end + end + + def handleX86Mul(kind) + if operands.size == 3 and operands[0].is_a? Immediate + $asm.puts "imul#{x86Suffix(kind)} #{x86Operands(kind, kind, kind)}" + else + # FIXME: could do some peephole in case the left operand is immediate and it's + # a power of two. + handleX86Op("imul#{x86Suffix(kind)}", kind) + end + end + + def handleMove + if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID + $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}" + elsif operands[0] != operands[1] + $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}" + end + end + + def lowerX86 + raise unless $activeBackend == "X86" + lowerX86Common + end + + def lowerX86_64 + raise unless $activeBackend == "X86_64" + lowerX86Common + end + + def lowerX86Common + $asm.comment codeOriginString + case opcode + when "addi" + handleX86Add(:int) + when "addp" + handleX86Add(:ptr) + when "andi" handleX86Op("andl", :int) + when "andp" + handleX86Op("and#{x86Suffix(:ptr)}", :ptr) when "lshifti" handleX86Shift("sall", :int) + when "lshiftp" + handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr) when "muli" - if operands.size == 3 and operands[0].is_a? Immediate - $asm.puts "imull #{x86Operands(:int, :int, :int)}" - else - # FIXME: could do some peephole in case the left operand is immediate and it's - # a power of two. - handleX86Op("imull", :int) - end + handleX86Mul(:int) + when "mulp" + handleX86Mul(:ptr) when "negi" $asm.puts "negl #{x86Operands(:int)}" + when "negp" + $asm.puts "neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}" when "noti" $asm.puts "notl #{x86Operands(:int)}" - when "ori", "orp" + when "ori" handleX86Op("orl", :int) + when "orp" + handleX86Op("or#{x86Suffix(:ptr)}", :ptr) when "rshifti" handleX86Shift("sarl", :int) + when "rshiftp" + handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr) when "urshifti" handleX86Shift("shrl", :int) - when "subi", "subp" - if operands.size == 3 and operands[1] == operands[2] - $asm.puts "negl #{operands[2].x86Operand(:int)}" - $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}" - else - handleX86Op("subl", :int) - end - when "xori", "xorp" + when "urshiftp" + handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr) + when "subi" + handleX86Sub(:int) + when "subp" + handleX86Sub(:ptr) + when "xori" handleX86Op("xorl", :int) - when "loadi", "storei", "loadp", "storep" + when "xorp" + handleX86Op("xor#{x86Suffix(:ptr)}", :ptr) + when "loadi", "storei" $asm.puts "movl #{x86Operands(:int, :int)}" + when "loadis" + if isX64 + $asm.puts "movslq #{x86Operands(:int, :ptr)}" + else + $asm.puts "movl #{x86Operands(:int, :int)}" + end + when "loadp", "storep" + $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}" when "loadb" $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}" when "loadbs" @@ -502,37 +744,65 @@ class Instruction when "movdz" $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}" when "pop" - $asm.puts "pop #{operands[0].x86Operand(:int)}" + $asm.puts "pop #{operands[0].x86Operand(:ptr)}" when "push" - $asm.puts "push #{operands[0].x86Operand(:int)}" - when "move", "sxi2p", "zxi2p" - if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID - $asm.puts "xorl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}" - elsif operands[0] != operands[1] - $asm.puts "movl #{x86Operands(:int, :int)}" + $asm.puts "push #{operands[0].x86Operand(:ptr)}" + when "move" + handleMove + when "sxi2p" + if isX64 + $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:ptr)}" + else + handleMove + end + when "zxi2p" + if isX64 + $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}" + else + handleMove end when "nop" $asm.puts "nop" - when "bieq", "bpeq" + when "bieq" handleX86IntBranch("je", :int) - when "bineq", "bpneq" + when "bpeq" + handleX86IntBranch("je", :ptr) + when "bineq" handleX86IntBranch("jne", :int) - when "bia", "bpa" + when "bpneq" + handleX86IntBranch("jne", :ptr) + when "bia" handleX86IntBranch("ja", :int) - when "biaeq", "bpaeq" + when "bpa" + handleX86IntBranch("ja", :ptr) + when "biaeq" handleX86IntBranch("jae", :int) - when "bib", "bpb" + when "bpaeq" + handleX86IntBranch("jae", :ptr) + when "bib" handleX86IntBranch("jb", :int) - when "bibeq", "bpbeq" + when "bpb" + handleX86IntBranch("jb", :ptr) + when "bibeq" handleX86IntBranch("jbe", :int) - when "bigt", "bpgt" + when "bpbeq" + handleX86IntBranch("jbe", :ptr) + when "bigt" handleX86IntBranch("jg", :int) - when "bigteq", "bpgteq" + when "bpgt" + handleX86IntBranch("jg", :ptr) + when "bigteq" handleX86IntBranch("jge", :int) - when "bilt", "bplt" + when "bpgteq" + handleX86IntBranch("jge", :ptr) + when "bilt" handleX86IntBranch("jl", :int) - when "bilteq", "bplteq" + when "bplt" + handleX86IntBranch("jl", :ptr) + when "bilteq" handleX86IntBranch("jle", :int) + when "bplteq" + handleX86IntBranch("jle", :ptr) when "bbeq" handleX86IntBranch("je", :byte) when "bbneq" @@ -553,14 +823,22 @@ class Instruction handleX86IntBranch("jl", :byte) when "bblteq" handleX86IntBranch("jlteq", :byte) - when "btio", "btpo" + when "btio" handleX86BranchTest("jo", :int) - when "btis", "btps" + when "btpo" + handleX86BranchTest("jo", :ptr) + when "btis" handleX86BranchTest("js", :int) - when "btiz", "btpz" + when "btps" + handleX86BranchTest("js", :ptr) + when "btiz" handleX86BranchTest("jz", :int) - when "btinz", "btpnz" + when "btpz" + handleX86BranchTest("jz", :ptr) + when "btinz" handleX86BranchTest("jnz", :int) + when "btpnz" + handleX86BranchTest("jnz", :ptr) when "btbo" handleX86BranchTest("jo", :byte) when "btbs" @@ -570,15 +848,23 @@ class Instruction when "btbnz" handleX86BranchTest("jnz", :byte) when "jmp" - $asm.puts "jmp #{operands[0].x86CallOperand(:int)}" - when "baddio", "baddpo" + $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}" + when "baddio" handleX86OpBranch("addl", "jo", :int) - when "baddis", "baddps" + when "baddpo" + handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr) + when "baddis" handleX86OpBranch("addl", "js", :int) - when "baddiz", "baddpz" + when "baddps" + handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr) + when "baddiz" handleX86OpBranch("addl", "jz", :int) - when "baddinz", "baddpnz" + when "baddpz" + handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr) + when "baddinz" handleX86OpBranch("addl", "jnz", :int) + when "baddpnz" + handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr) when "bsubio" handleX86SubBranch("jo", :int) when "bsubis" @@ -606,29 +892,49 @@ class Instruction when "break" $asm.puts "int $3" when "call" - $asm.puts "call #{operands[0].x86CallOperand(:int)}" + $asm.puts "call #{operands[0].x86CallOperand(:ptr)}" when "ret" $asm.puts "ret" - when "cieq", "cpeq" + when "cieq" handleX86IntCompareSet("sete", :int) - when "cineq", "cpneq" + when "cpeq" + handleX86IntCompareSet("sete", :ptr) + when "cineq" handleX86IntCompareSet("setne", :int) - when "cia", "cpa" + when "cpneq" + handleX86IntCompareSet("setne", :ptr) + when "cia" handleX86IntCompareSet("seta", :int) - when "ciaeq", "cpaeq" + when "cpa" + handleX86IntCompareSet("seta", :ptr) + when "ciaeq" handleX86IntCompareSet("setae", :int) - when "cib", "cpb" + when "cpaeq" + handleX86IntCompareSet("setae", :ptr) + when "cib" handleX86IntCompareSet("setb", :int) - when "cibeq", "cpbeq" + when "cpb" + handleX86IntCompareSet("setb", :ptr) + when "cibeq" handleX86IntCompareSet("setbe", :int) - when "cigt", "cpgt" + when "cpbeq" + handleX86IntCompareSet("setbe", :ptr) + when "cigt" handleX86IntCompareSet("setg", :int) - when "cigteq", "cpgteq" + when "cpgt" + handleX86IntCompareSet("setg", :ptr) + when "cigteq" handleX86IntCompareSet("setge", :int) - when "cilt", "cplt" + when "cpgteq" + handleX86IntCompareSet("setge", :ptr) + when "cilt" handleX86IntCompareSet("setl", :int) - when "cilteq", "cplteq" + when "cplt" + handleX86IntCompareSet("setl", :ptr) + when "cilteq" handleX86IntCompareSet("setle", :int) + when "cplteq" + handleX86IntCompareSet("setle", :ptr) when "tio" handleX86SetTest("seto", :int) when "tis" @@ -646,9 +952,11 @@ class Instruction when "tbnz" handleX86SetTest("setnz", :byte) when "peek" - $asm.puts "movl #{operands[0].value * 4}(%esp), #{operands[1].x86Operand(:int)}" + sp = RegisterID.new(nil, "sp") + $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}" when "poke" - $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].value * 4}(%esp)" + sp = RegisterID.new(nil, "sp") + $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})" when "cdqi" $asm.puts "cdq" when "idivi" @@ -663,6 +971,10 @@ class Instruction $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7" $asm.puts "psrlq $32, %xmm7" $asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}" + when "fp2d" + $asm.puts "movd #{operands[0].x86Operand(:ptr)}, #{operands[1].x86Operand(:double)}" + when "fd2p" + $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:ptr)}" when "bo" $asm.puts "jo #{operands[0].asmLabel}" when "bs" @@ -671,8 +983,10 @@ class Instruction $asm.puts "jz #{operands[0].asmLabel}" when "bnz" $asm.puts "jnz #{operands[0].asmLabel}" - when "leai", "leap" - $asm.puts "leal #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}" + when "leai" + $asm.puts "leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}" + when "leap" + $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}" else raise "Bad opcode: #{opcode}" end diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h index b8718709b..a173cc10f 100644 --- a/Source/JavaScriptCore/parser/ASTBuilder.h +++ b/Source/JavaScriptCore/parser/ASTBuilder.h @@ -77,7 +77,6 @@ public: : m_globalData(globalData) , m_sourceCode(sourceCode) , m_scope(globalData) - , m_evalCount(0) { } @@ -119,7 +118,6 @@ public: ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; } ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; } - int features() const { return m_scope.m_features; } int numConstants() const { return m_scope.m_numConstants; } void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); } @@ -152,17 +150,8 @@ public: incConstants(); return new (m_globalData) VoidNode(lineNumber, expr); } - ExpressionNode* thisExpr(int lineNumber) - { - usesThis(); - return new (m_globalData) ThisNode(lineNumber); - } - ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start) - { - if (m_globalData->propertyNames->arguments == *ident) - usesArguments(); - return new (m_globalData) ResolveNode(lineNumber, *ident, start); - } + ExpressionNode* thisExpr(int lineNumber) { return new (m_globalData) ThisNode(lineNumber); } + ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start) { return new (m_globalData) ResolveNode(lineNumber, *ident, start); } ExpressionNode* createObjectLiteral(int lineNumber) { return new (m_globalData) ObjectLiteralNode(lineNumber); } ExpressionNode* createObjectLiteral(int lineNumber, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(lineNumber, properties); } @@ -263,9 +252,9 @@ public: return result; } - FunctionBodyNode* createFunctionBody(int lineNumber, bool inStrictContext) + FunctionBodyNode* createFunctionBody(int lineNumber, ScopeFlags scopeFlags) { - return FunctionBodyNode::create(m_globalData, lineNumber, inStrictContext); + return FunctionBodyNode::create(m_globalData, lineNumber, scopeFlags); } template <bool> PropertyNode* createGetterOrSetterProperty(int lineNumber, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) @@ -276,6 +265,11 @@ public: return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); } + template <bool> PropertyNode* createGetterOrSetterProperty(JSGlobalData*, int lineNumber, PropertyNode::Type type, double name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + { + body->setLoc(bodyStartLine, bodyEndLine); + return new (m_globalData) PropertyNode(m_globalData, name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); + } ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(); } ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(args); } @@ -307,8 +301,6 @@ public: StatementNode* createFuncDeclStatement(int lineNumber, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) { FuncDeclNode* decl = new (m_globalData) FuncDeclNode(lineNumber, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); - if (*name == m_globalData->propertyNames->arguments) - usesArguments(); m_scope.m_funcDeclarations->data.append(decl->body()); body->setLoc(bodyStartLine, bodyEndLine); return decl; @@ -421,8 +413,6 @@ public: StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine) { TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchBlock, finallyBlock); - if (catchBlock) - usesCatch(); result->setLoc(startLine, endLine); return result; } @@ -458,7 +448,6 @@ public: StatementNode* createWithStatement(int lineNumber, ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine) { - usesWith(); WithNode* result = new (m_globalData) WithNode(lineNumber, expr, statement, end, end - start); result->setLoc(startLine, endLine); return result; @@ -501,8 +490,6 @@ public: void addVar(const Identifier* ident, int attrs) { - if (m_globalData->propertyNames->arguments == *ident) - usesArguments(); m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs)); } @@ -517,8 +504,6 @@ public: return new (m_globalData) CommaNode(lineNumber, list, init); } - int evalCount() const { return m_evalCount; } - void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, bool hasAssignments) { operandStackDepth++; @@ -605,13 +590,11 @@ private: Scope(JSGlobalData* globalData) : m_varDeclarations(new (globalData) ParserArenaData<DeclarationStacks::VarStack>) , m_funcDeclarations(new (globalData) ParserArenaData<DeclarationStacks::FunctionStack>) - , m_features(0) , m_numConstants(0) { } ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; - int m_features; int m_numConstants; }; @@ -621,15 +604,6 @@ private: } void incConstants() { m_scope.m_numConstants++; } - void usesThis() { m_scope.m_features |= ThisFeature; } - void usesCatch() { m_scope.m_features |= CatchFeature; } - void usesArguments() { m_scope.m_features |= ArgumentsFeature; } - void usesWith() { m_scope.m_features |= WithFeature; } - void usesEval() - { - m_evalCount++; - m_scope.m_features |= EvalFeature; - } ExpressionNode* createNumber(int lineNumber, double d) { return new (m_globalData) NumberNode(lineNumber, d); @@ -642,7 +616,6 @@ private: Vector<AssignmentInfo, 10> m_assignmentInfoStack; Vector<pair<int, int>, 10> m_binaryOperatorStack; Vector<pair<int, int>, 10> m_unaryTokenStack; - int m_evalCount; }; ExpressionNode* ASTBuilder::makeTypeOfNode(int lineNumber, ExpressionNode* expr) @@ -792,10 +765,8 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(int lineNumber, ExpressionNode* if (func->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(func); const Identifier& identifier = resolve->identifier(); - if (identifier == m_globalData->propertyNames->eval) { - usesEval(); + if (identifier == m_globalData->propertyNames->eval) return new (m_globalData) EvalFunctionCallNode(lineNumber, args, divot, divot - start, end - divot); - } return new (m_globalData) FunctionCallResolveNode(lineNumber, identifier, args, divot, divot - start, end - divot); } if (func->isBracketAccessorNode()) { diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp index 015c1509d..8d50afc54 100644 --- a/Source/JavaScriptCore/parser/Lexer.cpp +++ b/Source/JavaScriptCore/parser/Lexer.cpp @@ -31,7 +31,7 @@ #include "Identifier.h" #include "NodeInfo.h" #include "Nodes.h" -#include "dtoa.h" +#include <wtf/dtoa.h> #include <ctype.h> #include <limits.h> #include <string.h> @@ -95,8 +95,8 @@ enum CharacterType { CharacterWhiteSpace, }; -// 128 ASCII codes -static const unsigned short typesOfASCIICharacters[128] = { +// 256 Latin-1 codes +static const unsigned short typesOfLatin1Characters[256] = { /* 0 - Null */ CharacterInvalid, /* 1 - Start of Heading */ CharacterInvalid, /* 2 - Start of Text */ CharacterInvalid, @@ -225,6 +225,134 @@ static const unsigned short typesOfASCIICharacters[128] = { /* 125 - } */ CharacterCloseBrace, /* 126 - ~ */ CharacterTilde, /* 127 - Delete */ CharacterInvalid, +/* 128 - Cc category */ CharacterInvalid, +/* 129 - Cc category */ CharacterInvalid, +/* 130 - Cc category */ CharacterInvalid, +/* 131 - Cc category */ CharacterInvalid, +/* 132 - Cc category */ CharacterInvalid, +/* 133 - Cc category */ CharacterInvalid, +/* 134 - Cc category */ CharacterInvalid, +/* 135 - Cc category */ CharacterInvalid, +/* 136 - Cc category */ CharacterInvalid, +/* 137 - Cc category */ CharacterInvalid, +/* 138 - Cc category */ CharacterInvalid, +/* 139 - Cc category */ CharacterInvalid, +/* 140 - Cc category */ CharacterInvalid, +/* 141 - Cc category */ CharacterInvalid, +/* 142 - Cc category */ CharacterInvalid, +/* 143 - Cc category */ CharacterInvalid, +/* 144 - Cc category */ CharacterInvalid, +/* 145 - Cc category */ CharacterInvalid, +/* 146 - Cc category */ CharacterInvalid, +/* 147 - Cc category */ CharacterInvalid, +/* 148 - Cc category */ CharacterInvalid, +/* 149 - Cc category */ CharacterInvalid, +/* 150 - Cc category */ CharacterInvalid, +/* 151 - Cc category */ CharacterInvalid, +/* 152 - Cc category */ CharacterInvalid, +/* 153 - Cc category */ CharacterInvalid, +/* 154 - Cc category */ CharacterInvalid, +/* 155 - Cc category */ CharacterInvalid, +/* 156 - Cc category */ CharacterInvalid, +/* 157 - Cc category */ CharacterInvalid, +/* 158 - Cc category */ CharacterInvalid, +/* 159 - Cc category */ CharacterInvalid, +/* 160 - Zs category (nbsp) */ CharacterWhiteSpace, +/* 161 - Po category */ CharacterInvalid, +/* 162 - Sc category */ CharacterInvalid, +/* 163 - Sc category */ CharacterInvalid, +/* 164 - Sc category */ CharacterInvalid, +/* 165 - Sc category */ CharacterInvalid, +/* 166 - So category */ CharacterInvalid, +/* 167 - So category */ CharacterInvalid, +/* 168 - Sk category */ CharacterInvalid, +/* 169 - So category */ CharacterInvalid, +/* 170 - Ll category */ CharacterIdentifierStart, +/* 171 - Pi category */ CharacterInvalid, +/* 172 - Sm category */ CharacterInvalid, +/* 173 - Cf category */ CharacterInvalid, +/* 174 - So category */ CharacterInvalid, +/* 175 - Sk category */ CharacterInvalid, +/* 176 - So category */ CharacterInvalid, +/* 177 - Sm category */ CharacterInvalid, +/* 178 - No category */ CharacterInvalid, +/* 179 - No category */ CharacterInvalid, +/* 180 - Sk category */ CharacterInvalid, +/* 181 - Ll category */ CharacterIdentifierStart, +/* 182 - So category */ CharacterInvalid, +/* 183 - Po category */ CharacterInvalid, +/* 184 - Sk category */ CharacterInvalid, +/* 185 - No category */ CharacterInvalid, +/* 186 - Ll category */ CharacterIdentifierStart, +/* 187 - Pf category */ CharacterInvalid, +/* 188 - No category */ CharacterInvalid, +/* 189 - No category */ CharacterInvalid, +/* 190 - No category */ CharacterInvalid, +/* 191 - Po category */ CharacterInvalid, +/* 192 - Lu category */ CharacterIdentifierStart, +/* 193 - Lu category */ CharacterIdentifierStart, +/* 194 - Lu category */ CharacterIdentifierStart, +/* 195 - Lu category */ CharacterIdentifierStart, +/* 196 - Lu category */ CharacterIdentifierStart, +/* 197 - Lu category */ CharacterIdentifierStart, +/* 198 - Lu category */ CharacterIdentifierStart, +/* 199 - Lu category */ CharacterIdentifierStart, +/* 200 - Lu category */ CharacterIdentifierStart, +/* 201 - Lu category */ CharacterIdentifierStart, +/* 202 - Lu category */ CharacterIdentifierStart, +/* 203 - Lu category */ CharacterIdentifierStart, +/* 204 - Lu category */ CharacterIdentifierStart, +/* 205 - Lu category */ CharacterIdentifierStart, +/* 206 - Lu category */ CharacterIdentifierStart, +/* 207 - Lu category */ CharacterIdentifierStart, +/* 208 - Lu category */ CharacterIdentifierStart, +/* 209 - Lu category */ CharacterIdentifierStart, +/* 210 - Lu category */ CharacterIdentifierStart, +/* 211 - Lu category */ CharacterIdentifierStart, +/* 212 - Lu category */ CharacterIdentifierStart, +/* 213 - Lu category */ CharacterIdentifierStart, +/* 214 - Lu category */ CharacterIdentifierStart, +/* 215 - Sm category */ CharacterInvalid, +/* 216 - Lu category */ CharacterIdentifierStart, +/* 217 - Lu category */ CharacterIdentifierStart, +/* 218 - Lu category */ CharacterIdentifierStart, +/* 219 - Lu category */ CharacterIdentifierStart, +/* 220 - Lu category */ CharacterIdentifierStart, +/* 221 - Lu category */ CharacterIdentifierStart, +/* 222 - Lu category */ CharacterIdentifierStart, +/* 223 - Ll category */ CharacterIdentifierStart, +/* 224 - Ll category */ CharacterIdentifierStart, +/* 225 - Ll category */ CharacterIdentifierStart, +/* 226 - Ll category */ CharacterIdentifierStart, +/* 227 - Ll category */ CharacterIdentifierStart, +/* 228 - Ll category */ CharacterIdentifierStart, +/* 229 - Ll category */ CharacterIdentifierStart, +/* 230 - Ll category */ CharacterIdentifierStart, +/* 231 - Ll category */ CharacterIdentifierStart, +/* 232 - Ll category */ CharacterIdentifierStart, +/* 233 - Ll category */ CharacterIdentifierStart, +/* 234 - Ll category */ CharacterIdentifierStart, +/* 235 - Ll category */ CharacterIdentifierStart, +/* 236 - Ll category */ CharacterIdentifierStart, +/* 237 - Ll category */ CharacterIdentifierStart, +/* 238 - Ll category */ CharacterIdentifierStart, +/* 239 - Ll category */ CharacterIdentifierStart, +/* 240 - Ll category */ CharacterIdentifierStart, +/* 241 - Ll category */ CharacterIdentifierStart, +/* 242 - Ll category */ CharacterIdentifierStart, +/* 243 - Ll category */ CharacterIdentifierStart, +/* 244 - Ll category */ CharacterIdentifierStart, +/* 245 - Ll category */ CharacterIdentifierStart, +/* 246 - Ll category */ CharacterIdentifierStart, +/* 247 - Sm category */ CharacterInvalid, +/* 248 - Ll category */ CharacterIdentifierStart, +/* 249 - Ll category */ CharacterIdentifierStart, +/* 250 - Ll category */ CharacterIdentifierStart, +/* 251 - Ll category */ CharacterIdentifierStart, +/* 252 - Ll category */ CharacterIdentifierStart, +/* 253 - Ll category */ CharacterIdentifierStart, +/* 254 - Ll category */ CharacterIdentifierStart, +/* 255 - Ll category */ CharacterIdentifierStart }; template <typename T> @@ -350,7 +478,7 @@ int Lexer<T>::getUnicodeCharacter() template <typename T> void Lexer<T>::shiftLineTerminator() { - ASSERT(isLineTerminator(m_current)); + ASSERT(isLineTerminator(static_cast<T>(m_current))); int m_prev = m_current; shift(); @@ -368,28 +496,48 @@ ALWAYS_INLINE bool Lexer<T>::lastTokenWasRestrKeyword() const return m_lastToken == CONTINUE || m_lastToken == BREAK || m_lastToken == RETURN || m_lastToken == THROW; } -static NEVER_INLINE bool isNonASCIIIdentStart(int c) +static NEVER_INLINE bool isNonLatin1IdentStart(int c) { return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other); } -static inline bool isIdentStart(int c) +static ALWAYS_INLINE bool isLatin1(LChar) { - return isASCII(c) ? typesOfASCIICharacters[c] == CharacterIdentifierStart : isNonASCIIIdentStart(c); + return true; +} + +static ALWAYS_INLINE bool isLatin1(UChar c) +{ + return c < 256; } -static NEVER_INLINE bool isNonASCIIIdentPart(int c) +static inline bool isIdentStart(LChar c) +{ + return typesOfLatin1Characters[c] == CharacterIdentifierStart; +} + +static inline bool isIdentStart(UChar c) +{ + return isLatin1(c) ? isIdentStart(static_cast<LChar>(c)) : isNonLatin1IdentStart(c); +} + +static NEVER_INLINE bool isNonLatin1IdentPart(int c) { return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)) || c == 0x200C || c == 0x200D; } -static ALWAYS_INLINE bool isIdentPart(int c) +static ALWAYS_INLINE bool isIdentPart(LChar c) { // Character types are divided into two groups depending on whether they can be part of an // identifier or not. Those whose type value is less or equal than CharacterNumber can be // part of an identifier. (See the CharacterType definition for more details.) - return isASCII(c) ? typesOfASCIICharacters[c] <= CharacterNumber : isNonASCIIIdentPart(c); + return typesOfLatin1Characters[c] <= CharacterNumber; +} + +static ALWAYS_INLINE bool isIdentPart(UChar c) +{ + return isLatin1(c) ? isIdentPart(static_cast<LChar>(c)) : isNonLatin1IdentPart(c); } static inline int singleEscape(int c) @@ -499,7 +647,7 @@ template <> const LChar* identifierStart = currentCharacter(); - while (isIdentPart(m_current)) + while (m_current != -1 && isIdentPart(static_cast<LChar>(m_current))) shift(); if (UNLIKELY(m_current == '\\')) { @@ -550,7 +698,7 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p UChar orAllChars = 0; - while (isIdentPart(m_current)) { + while (m_current != -1 && isIdentPart(static_cast<UChar>(m_current))) { orAllChars |= m_current; shift(); } @@ -604,7 +752,7 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow bool bufferRequired = false; while (true) { - if (LIKELY(isIdentPart(m_current))) { + if (LIKELY(m_current != -1 && isIdentPart(static_cast<T>(m_current)))) { shift(); continue; } @@ -622,10 +770,11 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow int character = getUnicodeCharacter(); if (UNLIKELY(character == -1)) return ERRORTOK; - if (UNLIKELY(m_buffer16.size() ? !isIdentPart(character) : !isIdentStart(character))) + UChar ucharacter = static_cast<UChar>(character); + if (UNLIKELY(m_buffer16.size() ? !isIdentPart(ucharacter) : !isIdentStart(ucharacter))) return ERRORTOK; if (shouldCreateIdentifier) - record16(character); + record16(ucharacter); identifierStart = currentCharacter(); } @@ -692,14 +841,15 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo shiftLineTerminator(); else if (m_current == 'x') { shift(); - if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) { - int prev = m_current; - shift(); - if (shouldBuildStrings) - record8(convertHex(prev, m_current)); - shift(); - } else if (shouldBuildStrings) - record8('x'); + if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) { + m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; + return false; + } + int prev = m_current; + shift(); + if (shouldBuildStrings) + record8(convertHex(prev, m_current)); + shift(); } else { setOffset(startingOffset); setLineNumber(startingLineNumber); @@ -752,18 +902,19 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat if (shouldBuildStrings) record16(escape); shift(); - } else if (UNLIKELY(isLineTerminator(m_current))) + } else if (UNLIKELY(isLineTerminator(static_cast<T>(m_current)))) shiftLineTerminator(); else if (m_current == 'x') { shift(); - if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) { - int prev = m_current; - shift(); - if (shouldBuildStrings) - record16(convertHex(prev, m_current)); - shift(); - } else if (shouldBuildStrings) - record16('x'); + if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) { + m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; + return false; + } + int prev = m_current; + shift(); + if (shouldBuildStrings) + record16(convertHex(prev, m_current)); + shift(); } else if (m_current == 'u') { shift(); int character = getUnicodeCharacter(); @@ -824,7 +975,7 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat // as possible, and lets through all common ASCII characters. if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) { // New-line or end of input is not allowed - if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1)) { + if (UNLIKELY(m_current == -1) || UNLIKELY(isLineTerminator(static_cast<T>(m_current)))) { m_lexErrorMessage = "Unexpected EOF"; return false; } @@ -1004,7 +1155,7 @@ ALWAYS_INLINE bool Lexer<T>::parseMultilineComment() if (UNLIKELY(m_current == -1)) return false; - if (isLineTerminator(m_current)) { + if (isLineTerminator(static_cast<T>(m_current))) { shiftLineTerminator(); m_terminator = true; } else @@ -1033,7 +1184,7 @@ JSTokenType Lexer<T>::lex(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsign m_terminator = false; start: - while (isWhiteSpace(m_current)) + while (m_current != -1 && isWhiteSpace(static_cast<T>(m_current))) shift(); int startOffset = currentOffset(); @@ -1044,11 +1195,11 @@ start: m_delimited = false; CharacterType type; - if (LIKELY(isASCII(m_current))) - type = static_cast<CharacterType>(typesOfASCIICharacters[m_current]); - else if (isNonASCIIIdentStart(m_current)) + if (LIKELY(isLatin1(static_cast<T>(m_current)))) + type = static_cast<CharacterType>(typesOfLatin1Characters[m_current]); + else if (isNonLatin1IdentStart(m_current)) type = CharacterIdentifierStart; - else if (isLineTerminator(m_current)) + else if (isLineTerminator(static_cast<T>(m_current))) type = CharacterLineTerminator; else type = CharacterInvalid; @@ -1335,7 +1486,7 @@ inNumberAfterDecimalPoint: } // No identifiers allowed directly after numeric literal, e.g. "3in" is bad. - if (UNLIKELY(isIdentStart(m_current))) { + if (UNLIKELY(m_current != -1 && isIdentStart(static_cast<T>(m_current)))) { m_lexErrorMessage = "At least one digit must occur after a decimal point"; goto returnError; } @@ -1355,7 +1506,7 @@ inNumberAfterDecimalPoint: token = STRING; break; case CharacterIdentifierStart: - ASSERT(isIdentStart(m_current)); + ASSERT(isIdentStart(static_cast<T>(m_current))); // Fall through into CharacterBackSlash. case CharacterBackSlash: if (lexerFlags & LexexFlagsDontBuildKeywords) @@ -1364,7 +1515,7 @@ inNumberAfterDecimalPoint: token = parseIdentifier<true>(tokenData, lexerFlags, strictMode); break; case CharacterLineTerminator: - ASSERT(isLineTerminator(m_current)); + ASSERT(isLineTerminator(static_cast<T>(m_current))); shiftLineTerminator(); m_atLineStart = true; m_terminator = true; @@ -1382,7 +1533,7 @@ inNumberAfterDecimalPoint: goto returnToken; inSingleLineComment: - while (!isLineTerminator(m_current)) { + while (!isLineTerminator(static_cast<T>(m_current))) { if (UNLIKELY(m_current == -1)) return EOFTOK; shift(); @@ -1430,7 +1581,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, while (true) { int current = m_current; - if (isLineTerminator(current) || current == -1) { + if (isLineTerminator(static_cast<T>(current)) || current == -1) { m_buffer16.resize(0); return false; } @@ -1463,7 +1614,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, pattern = makeIdentifier(m_buffer16.data(), m_buffer16.size()); m_buffer16.resize(0); - while (isIdentPart(m_current)) { + while (m_current != -1 && isIdentPart(static_cast<T>(m_current))) { record16(m_current); shift(); } @@ -1483,7 +1634,7 @@ bool Lexer<T>::skipRegExp() while (true) { int current = m_current; - if (isLineTerminator(current) || current == -1) + if (isLineTerminator(static_cast<T>(current)) || current == -1) return false; shift(); @@ -1509,7 +1660,7 @@ bool Lexer<T>::skipRegExp() } } - while (isIdentPart(m_current)) + while (m_current != -1 && isIdentPart(static_cast<T>(m_current))) shift(); return true; diff --git a/Source/JavaScriptCore/parser/Lexer.h b/Source/JavaScriptCore/parser/Lexer.h index 6fe0c9a1c..81558fa96 100644 --- a/Source/JavaScriptCore/parser/Lexer.h +++ b/Source/JavaScriptCore/parser/Lexer.h @@ -79,8 +79,8 @@ public: ~Lexer(); // Character manipulation functions. - static bool isWhiteSpace(int character); - static bool isLineTerminator(int character); + static bool isWhiteSpace(T character); + static bool isLineTerminator(T character); static unsigned char convertHex(int c1, int c2); static UChar convertUnicode(int c1, int c2, int c3, int c4); @@ -191,14 +191,26 @@ private: JSGlobalData* m_globalData; }; -template <typename T> -ALWAYS_INLINE bool Lexer<T>::isWhiteSpace(int ch) +template <> +ALWAYS_INLINE bool Lexer<LChar>::isWhiteSpace(LChar ch) { - return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF); + return ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC || ch == 0xA0; } -template <typename T> -ALWAYS_INLINE bool Lexer<T>::isLineTerminator(int ch) +template <> +ALWAYS_INLINE bool Lexer<UChar>::isWhiteSpace(UChar ch) +{ + return (ch < 256) ? Lexer<LChar>::isWhiteSpace(static_cast<LChar>(ch)) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF); +} + +template <> +ALWAYS_INLINE bool Lexer<LChar>::isLineTerminator(LChar ch) +{ + return ch == '\r' || ch == '\n'; +} + +template <> +ALWAYS_INLINE bool Lexer<UChar>::isLineTerminator(UChar ch) { return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028; } diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h index eea3f575c..e496d2342 100644 --- a/Source/JavaScriptCore/parser/NodeConstructors.h +++ b/Source/JavaScriptCore/parser/NodeConstructors.h @@ -417,12 +417,13 @@ namespace JSC { } inline NegateNode::NegateNode(int lineNumber, ExpressionNode* expr) - : UnaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr, op_negate) + : UnaryOpNode(lineNumber, ResultType::numberType(), expr, op_negate) { } inline BitwiseNotNode::BitwiseNotNode(int lineNumber, ExpressionNode* expr) - : UnaryOpNode(lineNumber, ResultType::forBitOp(), expr, op_bitnot) + : ExpressionNode(lineNumber, ResultType::forBitOp()) + , m_expr(expr) { } @@ -450,18 +451,18 @@ namespace JSC { } inline MultNode::MultNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_mul, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mul, rightHasAssignments) { } inline DivNode::DivNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_div, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_div, rightHasAssignments) { } inline ModNode::ModNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_mod, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mod, rightHasAssignments) { } @@ -471,7 +472,7 @@ namespace JSC { } inline SubNode::SubNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_sub, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_sub, rightHasAssignments) { } @@ -486,7 +487,7 @@ namespace JSC { } inline UnsignedRightShiftNode::UnsignedRightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_urshift, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_urshift, rightHasAssignments) { } diff --git a/Source/JavaScriptCore/parser/NodeInfo.h b/Source/JavaScriptCore/parser/NodeInfo.h index 4853aec42..e0d4ffec4 100644 --- a/Source/JavaScriptCore/parser/NodeInfo.h +++ b/Source/JavaScriptCore/parser/NodeInfo.h @@ -26,7 +26,7 @@ namespace JSC { template <typename T> struct NodeInfo { T m_node; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; int m_numConstants; }; @@ -44,7 +44,7 @@ namespace JSC { T m_node; ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; int m_numConstants; }; diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp index 8ad474e54..75c848bce 100644 --- a/Source/JavaScriptCore/parser/Nodes.cpp +++ b/Source/JavaScriptCore/parser/Nodes.cpp @@ -73,75 +73,70 @@ StatementNode* SourceElements::singleStatement() const return size == 1 ? m_statements[0] : 0; } -// -----------------------------ScopeNodeData --------------------------- - -ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, int numConstants) - : m_numConstants(numConstants) - , m_statements(statements) -{ - m_arena.swap(arena); - if (varStack) - m_varStack.swap(*varStack); - if (funcStack) - m_functionStack.swap(*funcStack); - m_capturedVariables.swap(capturedVariables); -} - // ------------------------------ ScopeNode ----------------------------- -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) +ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) : StatementNode(lineNumber) , ParserArenaRefCounted(globalData) - , m_features(inStrictContext ? StrictModeFeature : NoFeatures) + , m_scopeFlags(scopeFlags) + , m_numConstants(0) + , m_statements(0) { } -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) +ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, ScopeFlags scopeFlags, int numConstants) : StatementNode(lineNumber) , ParserArenaRefCounted(globalData) - , m_data(adoptPtr(new ScopeNodeData(*globalData->parserArena, children, varStack, funcStack, capturedVariables, numConstants))) - , m_features(features) + , m_scopeFlags(scopeFlags) , m_source(source) + , m_numConstants(numConstants) + , m_statements(children) { + m_arena.swap(*globalData->parserArena); + if (varStack) + m_varStack.swap(*varStack); + if (funcStack) + m_functionStack.swap(*funcStack); + m_capturedVariables.swap(capturedVariables); } StatementNode* ScopeNode::singleStatement() const { - return m_data->m_statements ? m_data->m_statements->singleStatement() : 0; + return m_statements ? m_statements->singleStatement() : 0; } // ------------------------------ ProgramNode ----------------------------- -inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) + : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants) { } -PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) { - RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants); - ASSERT(node->data()->m_arena.last() == node); - node->data()->m_arena.removeLast(); - ASSERT(!node->data()->m_arena.contains(node.get())); + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); return node.release(); } // ------------------------------ EvalNode ----------------------------- -inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) + : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants) { } -PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) { - RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants); - ASSERT(node->data()->m_arena.last() == node); - node->data()->m_arena.removeLast(); - ASSERT(!node->data()->m_arena.contains(node.get())); + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); return node.release(); } @@ -154,13 +149,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter) append(parameter->ident()); } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) - : ScopeNode(globalData, lineNumber, inStrictContext) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) + : ScopeNode(globalData, lineNumber, scopeFlags) { } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, ScopeFlags scopeFlags, int numConstants) + : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants) { } @@ -177,18 +172,18 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, m_ident = ident; } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, bool inStrictContext) +FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) { - return new FunctionBodyNode(globalData, lineNumber, inStrictContext); + return new FunctionBodyNode(globalData, lineNumber, scopeFlags); } -PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, ScopeFlags scopeFlags, int numConstants) { - RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, scopeFlags, numConstants); - ASSERT(node->data()->m_arena.last() == node); - node->data()->m_arena.removeLast(); - ASSERT(!node->data()->m_arena.contains(node.get())); + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); return node.release(); } diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h index 0373766b5..f752b91e9 100644 --- a/Source/JavaScriptCore/parser/Nodes.h +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -47,19 +47,31 @@ namespace JSC { class ScopeChainNode; class ScopeNode; - typedef unsigned CodeFeatures; - - const CodeFeatures NoFeatures = 0; - const CodeFeatures EvalFeature = 1 << 0; - const CodeFeatures ArgumentsFeature = 1 << 1; - const CodeFeatures WithFeature = 1 << 2; - const CodeFeatures CatchFeature = 1 << 3; - const CodeFeatures ThisFeature = 1 << 4; - const CodeFeatures StrictModeFeature = 1 << 5; - const CodeFeatures ShadowsArgumentsFeature = 1 << 6; + typedef unsigned short ScopeFlags; + + const ScopeFlags NoScopeFlags = 0; + + // Some scope flags propagate down the parse tree from parent scopes, like + // strict mode. They are modal to an entire set of nested scopes. + const ScopeFlags StrictModeFlag = 1 << 0; + const ScopeFlags FunctionModeFlag = 1 << 1; + const ScopeFlags AllScopeModeFlags = StrictModeFlag | FunctionModeFlag; + + // Some scope flags refer only to a specific scope, and don't propagate down + // or up. + const ScopeFlags BlockScopeFlag = 1 << 4; + const ScopeFlags AllScopeKindFlags = BlockScopeFlag; + + // Other flags reflect uses within nested scopes, and so propagate up + // from the leaves. + const ScopeFlags UsesEvalFlag = 1 << 8; + const ScopeFlags UsesArgumentsFlag = 1 << 9; + const ScopeFlags UsesWithFlag = 1 << 10; + const ScopeFlags UsesCatchFlag = 1 << 11; + const ScopeFlags UsesThisFlag = 1 << 12; + const ScopeFlags ShadowsArgumentsFlag = 1 << 13; + const ScopeFlags AllScopeUsesFlags = UsesEvalFlag | UsesArgumentsFlag | UsesWithFlag | UsesCatchFlag | UsesThisFlag | ShadowsArgumentsFlag; - const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature; - enum Operator { OpEqual, OpPlusEq, @@ -793,11 +805,20 @@ namespace JSC { NegateNode(int, ExpressionNode*); }; - class BitwiseNotNode : public UnaryOpNode { + class BitwiseNotNode : public ExpressionNode { public: BitwiseNotNode(int, ExpressionNode*); - }; + protected: + ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + class LogicalNotNode : public UnaryOpNode { public: LogicalNotNode(int, ExpressionNode*); @@ -1369,62 +1390,53 @@ namespace JSC { ParameterNode* m_next; }; - struct ScopeNodeData { - WTF_MAKE_FAST_ALLOCATED; + class ScopeNode : public StatementNode, public ParserArenaRefCounted { public: typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants); + ScopeNode(JSGlobalData*, int, ScopeFlags); + ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, ScopeFlags, int numConstants); - ParserArena m_arena; - VarStack m_varStack; - FunctionStack m_functionStack; - int m_numConstants; - SourceElements* m_statements; - IdentifierSet m_capturedVariables; - }; + using ParserArenaRefCounted::operator new; - class ScopeNode : public StatementNode, public ParserArenaRefCounted { - public: - typedef DeclarationStacks::VarStack VarStack; - typedef DeclarationStacks::FunctionStack FunctionStack; + void destroyData() + { + m_arena.reset(); + m_varStack.clear(); + m_functionStack.clear(); + m_statements = 0; + m_capturedVariables.clear(); + } - ScopeNode(JSGlobalData*, int, bool inStrictContext); - ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); + bool hasCapturedVariables() const { return !!m_capturedVariables.size(); } + size_t capturedVariableCount() const { return m_capturedVariables.size(); } + bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); } - using ParserArenaRefCounted::operator new; + void addScopeFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; } + ScopeFlags scopeFlags() const { return m_scopeFlags; } - ScopeNodeData* data() const { return m_data.get(); } - void destroyData() { m_data.clear(); } + bool isStrictMode() const { return m_scopeFlags & StrictModeFlag; } + bool usesEval() const { return m_scopeFlags & UsesEvalFlag; } + bool usesArguments() const { return (m_scopeFlags & UsesArgumentsFlag) && !(m_scopeFlags & ShadowsArgumentsFlag); } + void setUsesArguments() { m_scopeFlags |= UsesArgumentsFlag; } + bool usesThis() const { return m_scopeFlags & UsesThisFlag; } + + bool needsActivationForMoreThanVariables() const { return m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); } + bool needsActivation() const { return hasCapturedVariables() || needsActivationForMoreThanVariables(); } const SourceCode& source() const { return m_source; } const UString& sourceURL() const { return m_source.provider()->url(); } intptr_t sourceID() const { return m_source.provider()->asID(); } - void setFeatures(CodeFeatures features) { m_features = features; } - CodeFeatures features() { return m_features; } - - bool usesEval() const { return m_features & EvalFeature; } - bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } - bool isStrictMode() const { return m_features & StrictModeFeature; } - void setUsesArguments() { m_features |= ArgumentsFeature; } - bool usesThis() const { return m_features & ThisFeature; } - bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); } - bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); } - bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); } - size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); } - bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); } - - VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } - FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } + VarStack& varStack() { return m_varStack; } + FunctionStack& functionStack() { return m_functionStack; } int neededConstants() { - ASSERT(m_data); // We may need 2 more constants than the count given by the parser, // because of the various uses of jsUndefined() and jsNull(). - return m_data->m_numConstants + 2; + return m_numConstants + 2; } StatementNode* singleStatement() const; @@ -1433,22 +1445,27 @@ namespace JSC { protected: void setSource(const SourceCode& source) { m_source = source; } + ParserArena m_arena; private: - OwnPtr<ScopeNodeData> m_data; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; SourceCode m_source; + VarStack m_varStack; + FunctionStack m_functionStack; + int m_numConstants; + SourceElements* m_statements; + IdentifierSet m_capturedVariables; }; class ProgramNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); static const bool scopeIsFunction = false; private: - ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1456,12 +1473,12 @@ namespace JSC { class EvalNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); static const bool scopeIsFunction = false; private: - EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1478,8 +1495,8 @@ namespace JSC { class FunctionBodyNode : public ScopeNode { public: static const bool isFunctionNode = true; - static FunctionBodyNode* create(JSGlobalData*, int, bool isStrictMode); - static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static FunctionBodyNode* create(JSGlobalData*, int, ScopeFlags); + static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); FunctionParameters* parameters() const { return m_parameters.get(); } size_t parameterCount() const { return m_parameters->size(); } @@ -1496,8 +1513,8 @@ namespace JSC { static const bool scopeIsFunction = true; private: - FunctionBodyNode(JSGlobalData*, int, bool inStrictContext); - FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + FunctionBodyNode(JSGlobalData*, int, ScopeFlags); + FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); Identifier m_ident; Identifier m_inferredName; diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index 939d2696c..f58847fd2 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -62,11 +62,12 @@ Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, Fu m_lexer->setCode(source, m_arena); m_functionCache = source.provider()->cache(); - ScopeRef scope = pushScope(); - if (parserMode == JSParseFunctionCode) - scope->setIsFunction(); + ScopeFlags scopeFlags = NoScopeFlags; if (strictness == JSParseStrict) - scope->setStrictMode(); + scopeFlags |= StrictModeFlag; + if (parserMode == JSParseFunctionCode) + scopeFlags |= FunctionModeFlag; + ScopeRef scope = pushScope(scopeFlags); if (parameters) { for (unsigned i = 0; i < parameters->size(); i++) scope->declareParameter(¶meters->at(i)); @@ -96,16 +97,12 @@ UString Parser<LexerType>::parseInner() IdentifierSet capturedVariables; scope->getCapturedVariables(capturedVariables); - CodeFeatures features = context.features(); - if (scope->strictMode()) - features |= StrictModeFeature; - if (scope->shadowsArguments()) - features |= ShadowsArgumentsFeature; + ScopeFlags scopeFlags = scope->modeFlags() | scope->usesFlags(); unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0; if (functionCacheSize != oldFunctionCacheSize) m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize); - didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, + didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), scopeFlags, m_lastLine, context.numConstants(), capturedVariables); return parseError; @@ -113,13 +110,13 @@ UString Parser<LexerType>::parseInner() template <typename LexerType> void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, - ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars) + ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, ScopeFlags scopeFlags, int lastLine, int numConstants, IdentifierSet& capturedVars) { m_sourceElements = sourceElements; m_varDeclarations = varStack; m_funcDeclarations = funcStack; m_capturedVariables.swap(capturedVars); - m_features = features; + m_scopeFlags = scopeFlags; m_lastLine = lastLine; m_numConstants = numConstants; } @@ -147,7 +144,7 @@ template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser< if (directive) { // "use strict" must be the exact literal without escape sequences or line continuation. if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_globalData->propertyNames->useStrictIdentifier == *directive) { - setStrictMode(); + currentScope()->setFlags(StrictModeFlag); hasSetStrict = true; failIfFalse(isValidStrictMode()); m_lexer->setOffset(startOffset); @@ -255,6 +252,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati next(); bool hasInitializer = match(EQUAL); failIfFalseIfStrictWithNameAndMessage(declareVariable(name), "Cannot declare a variable named", name->impl(), "in strict mode."); + if (m_globalData->propertyNames->arguments == *name) + currentScope()->setFlags(UsesArgumentsFlag); context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0); if (hasInitializer) { int varDivot = tokenStart() + 1; @@ -289,6 +288,8 @@ template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDecl next(); bool hasInitializer = match(EQUAL); declareVariable(name); + if (m_globalData->propertyNames->arguments == *name) + currentScope()->setFlags(UsesArgumentsFlag); context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0)); TreeExpression initializer = 0; if (hasInitializer) { @@ -511,7 +512,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement { ASSERT(match(WITH)); failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode"); - currentScope()->setNeedsFullActivation(); + currentScope()->setFlags(UsesWithFlag); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -526,6 +527,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement TreeStatement statement = parseStatement(context, unused); failIfFalse(statement); + currentScope()->setFlags(UsesWithFlag); return context.createWithStatement(m_lexer->lastLineNumber(), expr, statement, start, end, startLine, endLine); } @@ -614,15 +616,15 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement( int lastLine = m_lastLine; if (match(CATCH)) { - currentScope()->setNeedsFullActivation(); + currentScope()->setFlags(UsesCatchFlag); next(); consumeOrFail(OPENPAREN); matchOrFail(IDENT); ident = m_token.m_data.ident; next(); - AutoPopScopeRef catchScope(this, pushScope()); + AutoPopScopeRef catchScope(this, pushScope(currentScope()->modeFlags())); failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode"); - catchScope->preventNewDecls(); + currentScope()->setFlags(BlockScopeFlag | UsesCatchFlag); consumeOrFail(CLOSEPAREN); matchOrFail(OPENBRACE); catchBlock = parseBlockStatement(context); @@ -759,7 +761,7 @@ template <typename LexerType> template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context) { if (match(CLOSEBRACE)) - return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode()); + return context.createFunctionBody(m_lexer->lastLineNumber(), currentScope()->modeFlags()); DepthManager statementDepth(&m_statementDepth); m_statementDepth = 0; typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get()); @@ -770,8 +772,7 @@ template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBo template <typename LexerType> template <FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine) { - AutoPopScopeRef functionScope(this, pushScope()); - functionScope->setIsFunction(); + AutoPopScopeRef functionScope(this, pushScope(currentScope()->modeFlags() | FunctionModeFlag)); if (match(IDENT)) { name = m_token.m_data.ident; next(); @@ -793,8 +794,8 @@ template <FunctionRequirements requirements, bool nameIsInContainingScope, class // If we know about this function already, we can use the cached info and skip the parser to the end of the function. if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) { // If we're in a strict context, the cached function info must say it was strict too. - ASSERT(!strictMode() || cachedInfo->strictMode); - body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->strictMode); + ASSERT(!strictMode() || (cachedInfo->scopeFlags & StrictModeFlag)); + body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->scopeFlags); functionScope->restoreFunctionInfo(cachedInfo); failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); @@ -854,6 +855,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); failIfFalse(name); failIfFalseIfStrict(declareVariable(name)); + if (*name == m_globalData->propertyNames->arguments) + currentScope()->setFlags(UsesArgumentsFlag); return context.createFuncDeclStatement(m_lexer->lastLineNumber(), name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } @@ -1204,7 +1207,6 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars return context.template createProperty<complete>(ident, node, PropertyNode::Constant); } failIfFalse(wasIdent); - matchOrFail(IDENT); const Identifier* accessorName = 0; TreeFormalParameterList parameters = 0; TreeFunctionBody body = 0; @@ -1218,8 +1220,19 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars type = PropertyNode::Setter; else fail(); - failIfFalse((parseFunctionInfo<FunctionNeedsName, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); - return context.template createGetterOrSetterProperty<complete>(m_lexer->lastLineNumber(), type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + const Identifier* stringPropertyName = 0; + double numericPropertyName = 0; + if (m_token.m_type == IDENT || m_token.m_type == STRING) + stringPropertyName = m_token.m_data.ident; + else if (m_token.m_type == NUMBER) + numericPropertyName = m_token.m_data.doubleValue; + else + fail(); + next(); + failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); + if (stringPropertyName) + return context.template createGetterOrSetterProperty<complete>(m_lexer->lastLineNumber(), type, stringPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + return context.template createGetterOrSetterProperty<complete>(const_cast<JSGlobalData*>(m_globalData), m_lexer->lastLineNumber(), type, numericPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } case NUMBER: { double propertyName = m_token.m_data.doubleValue; @@ -1391,13 +1404,18 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre } case THISTOKEN: { next(); + currentScope()->setFlags(UsesThisFlag); return context.thisExpr(m_lexer->lastLineNumber()); } case IDENT: { int start = tokenStart(); const Identifier* ident = m_token.m_data.ident; next(); - currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident); + if (m_globalData->propertyNames->eval == *ident) + currentScope()->setFlags(UsesEvalFlag); + else if (m_globalData->propertyNames->arguments == *ident) + currentScope()->setFlags(UsesArgumentsFlag); + currentScope()->useVariable(ident); m_lastIdentifier = ident; return context.createResolve(m_lexer->lastLineNumber(), ident, start); } diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index 9b76242d4..7513d1f11 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -130,30 +130,19 @@ struct ScopeLabelInfo { }; struct Scope { - Scope(const JSGlobalData* globalData, bool isFunction, bool strictMode) + Scope(const JSGlobalData* globalData, ScopeFlags scopeFlags) : m_globalData(globalData) - , m_shadowsArguments(false) - , m_usesEval(false) - , m_needsFullActivation(false) - , m_allowsNewDecls(true) - , m_strictMode(strictMode) - , m_isFunction(isFunction) - , m_isFunctionBoundary(false) + , m_scopeFlags(scopeFlags) , m_isValidStrictMode(true) , m_loopDepth(0) , m_switchDepth(0) { + ASSERT(!(scopeFlags & ~AllScopeModeFlags)); } Scope(const Scope& rhs) : m_globalData(rhs.m_globalData) - , m_shadowsArguments(rhs.m_shadowsArguments) - , m_usesEval(rhs.m_usesEval) - , m_needsFullActivation(rhs.m_needsFullActivation) - , m_allowsNewDecls(rhs.m_allowsNewDecls) - , m_strictMode(rhs.m_strictMode) - , m_isFunction(rhs.m_isFunction) - , m_isFunctionBoundary(rhs.m_isFunctionBoundary) + , m_scopeFlags(rhs.m_scopeFlags) , m_isValidStrictMode(rhs.m_isValidStrictMode) , m_loopDepth(rhs.m_loopDepth) , m_switchDepth(rhs.m_switchDepth) @@ -168,6 +157,22 @@ struct Scope { } } + ALWAYS_INLINE ScopeFlags scopeFlags() const { return m_scopeFlags; } + ALWAYS_INLINE ScopeFlags modeFlags() const { return m_scopeFlags & AllScopeModeFlags; } + ALWAYS_INLINE ScopeFlags usesFlags() const { return m_scopeFlags & AllScopeUsesFlags; } + ALWAYS_INLINE void setFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; } + + ALWAYS_INLINE bool needsFullActivation() const { return m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); } + ALWAYS_INLINE bool strictMode() const { return m_scopeFlags & StrictModeFlag; } + ALWAYS_INLINE bool shadowsArguments() const { return m_scopeFlags & ShadowsArgumentsFlag; } + ALWAYS_INLINE bool isFunction() const { return m_scopeFlags & FunctionModeFlag; } + ALWAYS_INLINE bool isBlockScope() const { return m_scopeFlags & BlockScopeFlag; } + ALWAYS_INLINE bool isFunctionBoundary() const { return isFunction() && !isBlockScope(); } + + ALWAYS_INLINE bool allowsNewDecls() const { return !isBlockScope(); } + + ALWAYS_INLINE bool isValidStrictMode() const { return m_isValidStrictMode; } + void startSwitch() { m_switchDepth++; } void endSwitch() { m_switchDepth--; } void startLoop() { m_loopDepth++; } @@ -201,14 +206,6 @@ struct Scope { return 0; } - void setIsFunction() - { - m_isFunction = true; - m_isFunctionBoundary = true; - } - bool isFunction() { return m_isFunction; } - bool isFunctionBoundary() { return m_isFunctionBoundary; } - bool declareVariable(const Identifier* ident) { bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident; @@ -219,35 +216,28 @@ struct Scope { void declareWrite(const Identifier* ident) { - ASSERT(m_strictMode); + ASSERT(strictMode()); m_writtenVariables.add(ident->impl()); } - void preventNewDecls() { m_allowsNewDecls = false; } - bool allowsNewDecls() const { return m_allowsNewDecls; } - bool declareParameter(const Identifier* ident) { bool isArguments = m_globalData->propertyNames->arguments == *ident; bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; if (isArguments) - m_shadowsArguments = true; + setFlags(ShadowsArgumentsFlag); return isValidStrictMode; } - void useVariable(const Identifier* ident, bool isEval) + void useVariable(const Identifier* ident) { - m_usesEval |= isEval; m_usedVariables.add(ident->ustring().impl()); } - void setNeedsFullActivation() { m_needsFullActivation = true; } - bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) { - if (nestedScope->m_usesEval) - m_usesEval = true; + setFlags(nestedScope->usesFlags()); IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { if (nestedScope->m_declaredVariables.contains(*ptr)) @@ -279,7 +269,7 @@ struct Scope { void getCapturedVariables(IdentifierSet& capturedVariables) { - if (m_needsFullActivation || m_usesEval) { + if (needsFullActivation()) { capturedVariables.swap(m_declaredVariables); return; } @@ -289,11 +279,6 @@ struct Scope { capturedVariables.add(*ptr); } } - void setStrictMode() { m_strictMode = true; } - bool strictMode() const { return m_strictMode; } - bool isValidStrictMode() const { return m_isValidStrictMode; } - bool shadowsArguments() const { return m_shadowsArguments; } - void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl> >& vector) { IdentifierSet::iterator end = capturedVariables.end(); @@ -307,20 +292,16 @@ struct Scope { void saveFunctionInfo(SourceProviderCacheItem* info) { - ASSERT(m_isFunction); - info->usesEval = m_usesEval; - info->strictMode = m_strictMode; - info->needsFullActivation = m_needsFullActivation; + ASSERT(isFunction()); + info->scopeFlags = m_scopeFlags; copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables); copyCapturedVariablesToVector(m_usedVariables, info->usedVariables); } void restoreFunctionInfo(const SourceProviderCacheItem* info) { - ASSERT(m_isFunction); - m_usesEval = info->usesEval; - m_strictMode = info->strictMode; - m_needsFullActivation = info->needsFullActivation; + ASSERT(isFunction()); + m_scopeFlags |= info->scopeFlags; unsigned size = info->usedVariables.size(); for (unsigned i = 0; i < size; ++i) m_usedVariables.add(info->usedVariables[i]); @@ -331,13 +312,7 @@ struct Scope { private: const JSGlobalData* m_globalData; - bool m_shadowsArguments : 1; - bool m_usesEval : 1; - bool m_needsFullActivation : 1; - bool m_allowsNewDecls : 1; - bool m_strictMode : 1; - bool m_isFunction : 1; - bool m_isFunctionBoundary : 1; + ScopeFlags m_scopeFlags; bool m_isValidStrictMode : 1; int m_loopDepth; int m_switchDepth; @@ -427,20 +402,14 @@ private: Parser* m_parser; }; - ScopeRef currentScope() + ALWAYS_INLINE ScopeRef currentScope() { return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); } - ScopeRef pushScope() + ScopeRef pushScope(ScopeFlags scopeFlags) { - bool isFunction = false; - bool isStrict = false; - if (!m_scopeStack.isEmpty()) { - isStrict = m_scopeStack.last().strictMode(); - isFunction = m_scopeStack.last().isFunction(); - } - m_scopeStack.append(Scope(m_globalData, isFunction, isStrict)); + m_scopeStack.append(Scope(m_globalData, scopeFlags)); return currentScope(); } @@ -492,7 +461,7 @@ private: UString parseInner(); void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, - ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, + ParserArenaData<DeclarationStacks::FunctionStack>*, ScopeFlags, int, int, IdentifierSet&); // Used to determine type of error to report. @@ -823,14 +792,13 @@ private: m_errorMessage = UString(msg); } - void startLoop() { currentScope()->startLoop(); } - void endLoop() { currentScope()->endLoop(); } - void startSwitch() { currentScope()->startSwitch(); } - void endSwitch() { currentScope()->endSwitch(); } - void setStrictMode() { currentScope()->setStrictMode(); } - bool strictMode() { return currentScope()->strictMode(); } - bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } - bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } + ALWAYS_INLINE void startLoop() { currentScope()->startLoop(); } + ALWAYS_INLINE void endLoop() { currentScope()->endLoop(); } + ALWAYS_INLINE void startSwitch() { currentScope()->startSwitch(); } + ALWAYS_INLINE void endSwitch() { currentScope()->endSwitch(); } + ALWAYS_INLINE bool strictMode() { return currentScope()->strictMode(); } + ALWAYS_INLINE bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } + ALWAYS_INLINE bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } bool breakIsValid() { ScopeRef current = currentScope(); @@ -949,7 +917,7 @@ private: ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; IdentifierSet m_capturedVariables; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; int m_numConstants; struct DepthManager { @@ -1010,7 +978,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj m_funcDeclarations ? &m_funcDeclarations->data : 0, m_capturedVariables, *m_source, - m_features, + m_scopeFlags, m_numConstants); result->setLoc(m_source->firstLine(), m_lastLine); } else if (lexicalGlobalObject) { diff --git a/Source/JavaScriptCore/parser/ParserArena.cpp b/Source/JavaScriptCore/parser/ParserArena.cpp index 56c58dacf..c53f30753 100644 --- a/Source/JavaScriptCore/parser/ParserArena.cpp +++ b/Source/JavaScriptCore/parser/ParserArena.cpp @@ -34,7 +34,6 @@ namespace JSC { ParserArena::ParserArena() : m_freeableMemory(0) , m_freeablePoolEnd(0) - , m_identifierArena(adoptPtr(new IdentifierArena)) { } @@ -88,7 +87,8 @@ void ParserArena::reset() m_freeableMemory = 0; m_freeablePoolEnd = 0; - m_identifierArena->clear(); + if (m_identifierArena) + m_identifierArena->clear(); m_freeablePools.clear(); m_deletableObjects.clear(); m_refCountedObjects.clear(); @@ -108,7 +108,7 @@ void ParserArena::allocateFreeablePool() bool ParserArena::isEmpty() const { return !m_freeablePoolEnd - && m_identifierArena->isEmpty() + && (!m_identifierArena || m_identifierArena->isEmpty()) && m_freeablePools.isEmpty() && m_deletableObjects.isEmpty() && m_refCountedObjects.isEmpty(); diff --git a/Source/JavaScriptCore/parser/ParserArena.h b/Source/JavaScriptCore/parser/ParserArena.h index 49f0ab6bf..067b83a26 100644 --- a/Source/JavaScriptCore/parser/ParserArena.h +++ b/Source/JavaScriptCore/parser/ParserArena.h @@ -161,7 +161,12 @@ namespace JSC { bool isEmpty() const; JS_EXPORT_PRIVATE void reset(); - IdentifierArena& identifierArena() { return *m_identifierArena; } + IdentifierArena& identifierArena() + { + if (UNLIKELY (!m_identifierArena)) + m_identifierArena = adoptPtr(new IdentifierArena); + return *m_identifierArena; + } private: static const size_t freeablePoolSize = 8000; diff --git a/Source/JavaScriptCore/parser/ResultType.h b/Source/JavaScriptCore/parser/ResultType.h index 27b8112a0..8f30e5b64 100644 --- a/Source/JavaScriptCore/parser/ResultType.h +++ b/Source/JavaScriptCore/parser/ResultType.h @@ -32,8 +32,7 @@ namespace JSC { friend struct OperandTypes; typedef char Type; - static const Type TypeReusable = 1; - static const Type TypeInt32 = 2; + static const Type TypeInt32 = 1; static const Type TypeMaybeNumber = 0x04; static const Type TypeMaybeString = 0x08; @@ -48,11 +47,6 @@ namespace JSC { { } - bool isReusable() - { - return m_type & TypeReusable; - } - bool isInt32() { return m_type & TypeInt32; @@ -93,19 +87,14 @@ namespace JSC { return ResultType(TypeMaybeNumber); } - static ResultType numberTypeCanReuse() - { - return ResultType(TypeReusable | TypeMaybeNumber); - } - - static ResultType numberTypeCanReuseIsInt32() + static ResultType numberTypeIsInt32() { - return ResultType(TypeReusable | TypeInt32 | TypeMaybeNumber); + return ResultType(TypeInt32 | TypeMaybeNumber); } - static ResultType stringOrNumberTypeCanReuse() + static ResultType stringOrNumberType() { - return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString); + return ResultType(TypeMaybeNumber | TypeMaybeString); } static ResultType stringType() @@ -121,15 +110,15 @@ namespace JSC { static ResultType forAdd(ResultType op1, ResultType op2) { if (op1.definitelyIsNumber() && op2.definitelyIsNumber()) - return numberTypeCanReuse(); + return numberType(); if (op1.definitelyIsString() || op2.definitelyIsString()) return stringType(); - return stringOrNumberTypeCanReuse(); + return stringOrNumberType(); } static ResultType forBitOp() { - return numberTypeCanReuseIsInt32(); + return numberTypeIsInt32(); } private: diff --git a/Source/JavaScriptCore/parser/SourceProvider.h b/Source/JavaScriptCore/parser/SourceProvider.h index dfc8d88e2..f66a921f5 100644 --- a/Source/JavaScriptCore/parser/SourceProvider.h +++ b/Source/JavaScriptCore/parser/SourceProvider.h @@ -47,7 +47,7 @@ namespace JSC { , m_cache(cache ? cache : new SourceProviderCache) , m_cacheOwned(!cache) { - deprecatedTurnOffVerifier(); + turnOffVerifier(); } virtual ~SourceProvider() { diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h index 3662367a0..ad7a759ce 100644 --- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h +++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h @@ -61,9 +61,7 @@ public: int closeBraceLine; int closeBracePos; - bool usesEval; - bool strictMode; - bool needsFullActivation; + unsigned short scopeFlags; Vector<RefPtr<StringImpl> > usedVariables; Vector<RefPtr<StringImpl> > writtenVariables; }; diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h index 32cbf7d6c..2acb5097d 100644 --- a/Source/JavaScriptCore/parser/SyntaxChecker.h +++ b/Source/JavaScriptCore/parser/SyntaxChecker.h @@ -210,11 +210,16 @@ public: return Property(type); return Property(name, type); } + template <bool strict> Property createGetterOrSetterProperty(JSGlobalData* globalData, int, PropertyNode::Type type, double name, int, int, int, int, int, int) + { + if (!strict) + return Property(type); + return Property(&globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name), type); + } void appendStatement(int, int) { } void addVar(const Identifier*, bool) { } int combineCommaNodes(int, int, int) { return 1; } - int evalCount() const { return 0; } void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool) { if (!m_topBinaryExpr) diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index a099adb75..7a53ec1a4 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -196,7 +196,7 @@ void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyN JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode); } -void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value) +void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow) { Arguments* thisObject = jsCast<Arguments*>(cell); if (i < static_cast<unsigned>(thisObject->d->numArguments) && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { @@ -204,7 +204,7 @@ void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue va return; } - PutPropertySlot slot; + PutPropertySlot slot(shouldThrow); JSObject::put(thisObject, exec, Identifier(exec, UString::number(i)), value, slot); } @@ -320,12 +320,15 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, const Ident if (descriptor.isAccessorDescriptor()) { // i. Call the [[Delete]] internal method of map passing P, and false as the arguments. thisObject->d->deletedArguments[i] = true; - } else if (descriptor.value()) { // b. Else i. If Desc.[[Value]] is present, then + } else { // b. Else + // i. If Desc.[[Value]] is present, then // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments. + if (descriptor.value()) + thisObject->argument(i).set(exec->globalData(), thisObject, descriptor.value()); // ii. If Desc.[[Writable]] is present and its value is false, then - thisObject->argument(i).set(exec->globalData(), thisObject, descriptor.value()); + // 1. Call the [[Delete]] internal method of map passing P and false as arguments. if (descriptor.writablePresent() && !descriptor.writable()) - thisObject->d->deletedArguments[i] = true; // 1. Call the [[Delete]] internal method of map passing P and false as arguments. + thisObject->d->deletedArguments[i] = true; } } diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index ee54a49eb..8e7af1844 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -114,7 +114,7 @@ namespace JSC { static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index cb9b12a59..2f000fc74 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -166,6 +166,90 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument return indexDouble > length ? length : static_cast<unsigned>(indexDouble); } + +// The shift/unshift function implement the shift/unshift behaviour required +// by the corresponding array prototype methods, and by splice. In both cases, +// the methods are operating an an array or array like object. +// +// header currentCount (remainder) +// [------][------------][-----------] +// header resultCount (remainder) +// [------][-----------][-----------] +// +// The set of properties in the range 'header' must be unchanged. The set of +// properties in the range 'remainder' (where remainder = length - header - +// currentCount) will be shifted to the left or right as appropriate; in the +// case of shift this must be removing values, in the case of unshift this +// must be introducing new values. +static inline void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length) +{ + ASSERT(currentCount > resultCount); + unsigned count = currentCount - resultCount; + + ASSERT(header <= length); + ASSERT(currentCount <= (length - header)); + + if (!header && isJSArray(thisObj) && asArray(thisObj)->shiftCount(exec, count)) + return; + + for (unsigned k = header; k < length - currentCount; ++k) { + unsigned from = k + currentCount; + unsigned to = k + resultCount; + PropertySlot slot(thisObj); + if (thisObj->getPropertySlot(exec, from, slot)) { + JSValue value = slot.getValue(exec, from); + if (exec->hadException()) + return; + thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true); + if (exec->hadException()) + return; + } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) { + throwTypeError(exec, "Unable to delete property."); + return; + } + } + for (unsigned k = length; k > length - count; --k) { + if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1)) { + throwTypeError(exec, "Unable to delete property."); + return; + } + } +} +static inline void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length) +{ + ASSERT(resultCount > currentCount); + unsigned count = resultCount - currentCount; + + ASSERT(header <= length); + ASSERT(currentCount <= (length - header)); + + // Guard against overflow. + if (count > (UINT_MAX - length)) { + throwOutOfMemoryError(exec); + return; + } + + if (!header && isJSArray(thisObj) && asArray(thisObj)->unshiftCount(exec, count)) + return; + + for (unsigned k = length - currentCount; k > header; --k) { + unsigned from = k + currentCount - 1; + unsigned to = k + resultCount - 1; + PropertySlot slot(thisObj); + if (thisObj->getPropertySlot(exec, from, slot)) { + JSValue value = slot.getValue(exec, from); + if (exec->hadException()) + return; + thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true); + } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) { + throwTypeError(exec, "Unable to delete property."); + return; + } + if (exec->hadException()) + return; + } +} + EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); @@ -265,9 +349,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) strBuffer.append(','); JSValue element = thisObj->get(exec, k); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); if (!element.isUndefinedOrNull()) { JSObject* o = element.toObject(exec); JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); UString str; CallData callData; CallType callType = getCallData(conversionFunction, callData); @@ -275,6 +363,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec); else str = element.toString(exec)->value(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); strBuffer.append(str); } } @@ -368,11 +458,11 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); if (v) - arr->methodTable()->putByIndex(arr, exec, n, v); + arr->putDirectIndex(exec, n, v); n++; } } else { - arr->methodTable()->putByIndex(arr, exec, n, curArg); + arr->putDirectIndex(exec, n, curArg); n++; } if (i == argCount) @@ -402,7 +492,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec) result = jsUndefined(); } else { result = thisObj->get(exec, length - 1); - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1)) { + throwTypeError(exec, "Unable to delete property."); + return JSValue::encode(jsUndefined()); + } putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1)); } return JSValue::encode(result); @@ -426,12 +521,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) for (unsigned n = 0; n < exec->argumentCount(); n++) { // Check for integer overflow; where safe we can do a fast put by index. if (length + n >= length) - thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n)); + thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n), true); else { PutPropertySlot slot; Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec)); thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot); } + if (exec->hadException()) + return JSValue::encode(jsUndefined()); } JSValue newLength(static_cast<int64_t>(length) + static_cast<int64_t>(exec->argumentCount())); putProperty(exec, thisObj, exec->propertyNames().length, newLength); @@ -455,15 +552,23 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); - if (obj2) - thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2); - else - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k); + if (obj2) { + thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k)) { + throwTypeError(exec, "Unable to delete property."); + return JSValue::encode(jsUndefined()); + } - if (obj) - thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj); - else - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1); + if (obj) { + thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1)) { + throwTypeError(exec, "Unable to delete property."); + return JSValue::encode(jsUndefined()); + } } return JSValue::encode(thisObj); } @@ -481,20 +586,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec) result = jsUndefined(); } else { result = thisObj->get(exec, 0); - if (isJSArray(thisObj)) - ((JSArray *)thisObj)->shiftCount(exec, 1); - else { - for (unsigned k = 1; k < length; k++) { - JSValue obj = getProperty(exec, thisObj, k); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (obj) - thisObj->methodTable()->putByIndex(thisObj, exec, k - 1, obj); - else - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1); - } - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1); - } + shift(exec, thisObj, 0, 1, 0, length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1)); } return JSValue::encode(result); @@ -521,7 +615,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); if (v) - resObj->methodTable()->putByIndex(resObj, exec, n, v); + resObj->putDirectIndex(exec, n, v); } resObj->setLength(exec, n); return JSValue::encode(result); @@ -580,8 +674,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) } // Swap themin and i if (themin > i) { - thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj); - thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj); + thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); } } return JSValue::encode(thisObj); @@ -627,41 +725,20 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) resObj->completeInitialization(deleteCount); unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0); - if (additionalArgs != deleteCount) { - if (additionalArgs < deleteCount) { - if ((!begin) && (isJSArray(thisObj))) - ((JSArray *)thisObj)->shiftCount(exec, deleteCount - additionalArgs); - else { - for (unsigned k = begin; k < length - deleteCount; ++k) { - JSValue v = getProperty(exec, thisObj, k + deleteCount); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (v) - thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs, v); - else - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs); - } - for (unsigned k = length; k > length - deleteCount + additionalArgs; --k) - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1); - } - } else { - if ((!begin) && (isJSArray(thisObj))) - ((JSArray *)thisObj)->unshiftCount(exec, additionalArgs - deleteCount); - else { - for (unsigned k = length - deleteCount; k > begin; --k) { - JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (obj) - thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs - 1, obj); - else - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs - 1); - } - } - } + if (additionalArgs < deleteCount) { + shift(exec, thisObj, begin, deleteCount, additionalArgs, length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } else if (additionalArgs > deleteCount) { + unshift(exec, thisObj, begin, deleteCount, additionalArgs, length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } + for (unsigned k = 0; k < additionalArgs; ++k) { + thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2), true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); } - for (unsigned k = 0; k < additionalArgs; ++k) - thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2)); putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs)); return JSValue::encode(result); @@ -677,23 +754,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec) return JSValue::encode(jsUndefined()); unsigned nrArgs = exec->argumentCount(); - if ((nrArgs) && (length)) { - if (isJSArray(thisObj)) - ((JSArray *)thisObj)->unshiftCount(exec, nrArgs); - else { - for (unsigned k = length; k > 0; --k) { - JSValue v = getProperty(exec, thisObj, k - 1); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (v) - thisObj->methodTable()->putByIndex(thisObj, exec, k + nrArgs - 1, v); - else - thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + nrArgs - 1); - } - } + if (nrArgs) { + unshift(exec, thisObj, 0, 0, nrArgs, length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } + for (unsigned k = 0; k < nrArgs; ++k) { + thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k), true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); } - for (unsigned k = 0; k < nrArgs; ++k) - thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k)); JSValue result = jsNumber(length + nrArgs); putProperty(exec, thisObj, exec->propertyNames().length, result); return JSValue::encode(result); @@ -732,7 +802,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) JSValue result = cachedCall.call(); if (result.toBoolean(exec)) - resultArray->methodTable()->putByIndex(resultArray, exec, filterIndex++, v); + resultArray->putDirectIndex(exec, filterIndex++, v); } if (k == length) return JSValue::encode(resultArray); @@ -753,7 +823,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); if (result.toBoolean(exec)) - resultArray->methodTable()->putByIndex(resultArray, exec, filterIndex++, v); + resultArray->putDirectIndex(exec, filterIndex++, v); } return JSValue::encode(resultArray); } @@ -788,7 +858,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) cachedCall.setArgument(1, jsNumber(k)); cachedCall.setArgument(2, thisObj); - JSArray::putByIndex(resultArray, exec, k, cachedCall.call()); + resultArray->putDirectIndex(exec, k, cachedCall.call()); } } for (; k < length && !exec->hadException(); ++k) { @@ -809,7 +879,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) return JSValue::encode(jsUndefined()); JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); - resultArray->methodTable()->putByIndex(resultArray, exec, k, result); + resultArray->putDirectIndex(exec, k, result); } return JSValue::encode(resultArray); diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h index 9ebb33a74..214258cc6 100644 --- a/Source/JavaScriptCore/runtime/ClassInfo.h +++ b/Source/JavaScriptCore/runtime/ClassInfo.h @@ -48,7 +48,7 @@ namespace JSC { typedef void (*PutFunctionPtr)(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); PutFunctionPtr put; - typedef void (*PutByIndexFunctionPtr)(JSCell*, ExecState*, unsigned propertyName, JSValue); + typedef void (*PutByIndexFunctionPtr)(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); PutByIndexFunctionPtr putByIndex; typedef bool (*DeletePropertyFunctionPtr)(JSCell*, ExecState*, const Identifier&); diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h index d79e5c783..0d9580197 100644 --- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h @@ -27,10 +27,6 @@ // MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various // ways without repeating the list. #define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \ - macro(__defineGetter__) \ - macro(__defineSetter__) \ - macro(__lookupGetter__) \ - macro(__lookupSetter__) \ macro(apply) \ macro(arguments) \ macro(bind) \ @@ -52,6 +48,7 @@ macro(input) \ macro(isArray) \ macro(isPrototypeOf) \ + macro(lastIndex) \ macro(length) \ macro(message) \ macro(multiline) \ diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp index 98a66589a..ce620245b 100644 --- a/Source/JavaScriptCore/runtime/Completion.cpp +++ b/Source/JavaScriptCore/runtime/Completion.cpp @@ -30,7 +30,7 @@ #include "Interpreter.h" #include "Parser.h" #include "Debugger.h" -#include "WTFThreadData.h" +#include <wtf/WTFThreadData.h> #include <stdio.h> namespace JSC { diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp index 243dc8856..5266c1ebe 100644 --- a/Source/JavaScriptCore/runtime/Error.cpp +++ b/Source/JavaScriptCore/runtime/Error.cpp @@ -36,6 +36,8 @@ #include "NativeErrorConstructor.h" #include "SourceCode.h" +#include <wtf/text/StringBuilder.h> + namespace JSC { static const char* linePropertyName = "line"; @@ -132,20 +134,14 @@ JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, cons globalObject = globalData->dynamicGlobalObject; else globalObject = error->globalObject(); - // We use the tryCreateUninitialized creation mechanism and related initialization - // functions as they're the only mechanism we currently have that will guarantee we - // don't call setters on the prototype. Technically it's faster than the alternative, - // but the numerous allocations that take place in this loop makes that last bit - // somewhat moot. - JSArray* stackTraceArray = JSArray::tryCreateUninitialized(*globalData, globalObject->arrayStructure(), stackTrace.size()); - if (!stackTraceArray) - return error; + StringBuilder builder; for (unsigned i = 0; i < stackTrace.size(); i++) { - UString stackLevel = stackTrace[i].toString(globalObject->globalExec()); - stackTraceArray->initializeIndex(*globalData, i, jsString(globalData, stackLevel)); + builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl())); + if (i != stackTrace.size() - 1) + builder.append('\n'); } - stackTraceArray->completeInitialization(stackTrace.size()); - error->putDirect(*globalData, globalData->propertyNames->stack, stackTraceArray, ReadOnly | DontDelete); + + error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete); } return error; diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index 25ddf764a..ea40447e4 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -34,7 +34,7 @@ #include "JITDriver.h" #include "Parser.h" #include "UStringBuilder.h" -#include "Vector.h" +#include <wtf/Vector.h> namespace JSC { @@ -177,10 +177,9 @@ JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scop } #if ENABLE(JIT) -void EvalExecutable::jitCompile(JSGlobalData& globalData) +bool EvalExecutable::jitCompile(JSGlobalData& globalData) { - bool result = jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT()); - ASSERT_UNUSED(result, result); + return jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail); } #endif @@ -210,8 +209,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - if (!!m_evalCodeBlock && m_evalCodeBlock->canProduceCopyWithBytecode()) { - BytecodeDestructionBlocker blocker(m_evalCodeBlock.get()); + if (!!m_evalCodeBlock) { OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock)); newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release())); m_evalCodeBlock = newCodeBlock.release(); @@ -223,7 +221,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope ASSERT(exception); return exception; } - recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine()); + recordParse(evalNode->scopeFlags(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine()); JSGlobalObject* globalObject = scopeChainNode->globalObject.get(); @@ -328,10 +326,9 @@ JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* s } #if ENABLE(JIT) -void ProgramExecutable::jitCompile(JSGlobalData& globalData) +bool ProgramExecutable::jitCompile(JSGlobalData& globalData) { - bool result = jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT()); - ASSERT_UNUSED(result, result); + return jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail); } #endif @@ -346,8 +343,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - if (!!m_programCodeBlock && m_programCodeBlock->canProduceCopyWithBytecode()) { - BytecodeDestructionBlocker blocker(m_programCodeBlock.get()); + if (!!m_programCodeBlock) { OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock)); newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release())); m_programCodeBlock = newCodeBlock.release(); @@ -357,7 +353,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc ASSERT(exception); return exception; } - recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine()); + recordParse(programNode->scopeFlags(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine()); JSGlobalObject* globalObject = scopeChainNode->globalObject.get(); @@ -479,33 +475,26 @@ JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, Scop } #if ENABLE(JIT) -void FunctionExecutable::jitCompileForCall(JSGlobalData& globalData) +bool FunctionExecutable::jitCompileForCall(JSGlobalData& globalData) { - bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT()); - ASSERT_UNUSED(result, result); + return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail); } -void FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData) +bool FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData) { - bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT()); - ASSERT_UNUSED(result, result); + return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail); } #endif FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind) { - FunctionCodeBlock* codeBlock = baselineCodeBlockFor(kind); - if (codeBlock->canProduceCopyWithBytecode()) - return codeBlock; - return 0; + return baselineCodeBlockFor(kind); } PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChainNode* scopeChainNode, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception) { - if (!!codeBlockFor(specializationKind) && codeBlockFor(specializationKind)->canProduceCopyWithBytecode()) { - BytecodeDestructionBlocker blocker(codeBlockFor(specializationKind).get()); + if (!!codeBlockFor(specializationKind)) return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind))); - } exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; @@ -519,7 +508,7 @@ PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChain if (m_forceUsesArguments) body->setUsesArguments(); body->finishParsing(m_parameters, m_name); - recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine()); + recordParse(body->scopeFlags(), body->hasCapturedVariables(), body->lineNo(), body->lastLine()); OwnPtr<FunctionCodeBlock> result; ASSERT((compilationKind == FirstCompilation) == !codeBlockFor(specializationKind)); diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index 69e80b28e..08b39fcf0 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -180,13 +180,14 @@ namespace JSC { class NativeExecutable : public ExecutableBase { friend class JIT; + friend class LLIntOffsetsExtractor; public: typedef ExecutableBase Base; #if ENABLE(JIT) static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic) { - ASSERT(globalData.canUseJIT()); + ASSERT(!globalData.interpreter->classicEnabled()); NativeExecutable* executable; if (!callThunk) { executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor); @@ -228,7 +229,7 @@ namespace JSC { #if ENABLE(JIT) void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic) { - ASSERT(globalData.canUseJIT()); + ASSERT(!globalData.interpreter->classicEnabled()); Base::finishCreation(globalData); m_jitCodeForCall = callThunk; m_jitCodeForConstruct = constructThunk; @@ -270,14 +271,14 @@ namespace JSC { ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext) : ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) - , m_features(isInStrictContext ? StrictModeFeature : 0) + , m_scopeFlags(isInStrictContext ? StrictModeFlag : NoScopeFlags) { } ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) - , m_features(isInStrictContext ? StrictModeFeature : 0) + , m_scopeFlags(isInStrictContext ? StrictModeFlag : NoScopeFlags) { } @@ -291,10 +292,10 @@ namespace JSC { int lineNo() const { return m_firstLine; } int lastLine() const { return m_lastLine; } - bool usesEval() const { return m_features & EvalFeature; } - bool usesArguments() const { return m_features & ArgumentsFeature; } - bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); } - bool isStrictMode() const { return m_features & StrictModeFeature; } + bool usesEval() const { return m_scopeFlags & UsesEvalFlag; } + bool usesArguments() const { return m_scopeFlags & UsesArgumentsFlag; } + bool needsActivation() const { return m_hasCapturedVariables || m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); } + bool isStrictMode() const { return m_scopeFlags & StrictModeFlag; } void unlinkCalls(); @@ -310,16 +311,16 @@ namespace JSC { #endif } - void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine) + void recordParse(ScopeFlags scopeFlags, bool hasCapturedVariables, int firstLine, int lastLine) { - m_features = features; + m_scopeFlags = scopeFlags; m_hasCapturedVariables = hasCapturedVariables; m_firstLine = firstLine; m_lastLine = lastLine; } SourceCode m_source; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; bool m_hasCapturedVariables; int m_firstLine; int m_lastLine; @@ -346,7 +347,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCode(JSGlobalData&); - void jitCompile(JSGlobalData&); + bool jitCompile(JSGlobalData&); #endif EvalCodeBlock& generatedBytecode() @@ -421,7 +422,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCode(JSGlobalData&); - void jitCompile(JSGlobalData&); + bool jitCompile(JSGlobalData&); #endif ProgramCodeBlock& generatedBytecode() @@ -520,7 +521,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCodeForCall(JSGlobalData&); - void jitCompileForCall(JSGlobalData&); + bool jitCompileForCall(JSGlobalData&); #endif bool isGeneratedForCall() const @@ -548,7 +549,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCodeForConstruct(JSGlobalData&); - void jitCompileForConstruct(JSGlobalData&); + bool jitCompileForConstruct(JSGlobalData&); #endif bool isGeneratedForConstruct() const @@ -597,14 +598,12 @@ namespace JSC { } } - void jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind) + bool jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind) { - if (kind == CodeForCall) { - jitCompileForCall(globalData); - return; - } + if (kind == CodeForCall) + return jitCompileForCall(globalData); ASSERT(kind == CodeForConstruct); - jitCompileForConstruct(globalData); + return jitCompileForConstruct(globalData); } #endif diff --git a/Source/JavaScriptCore/runtime/ExecutionHarness.h b/Source/JavaScriptCore/runtime/ExecutionHarness.h index 774c5bf6b..e58e6fc74 100644 --- a/Source/JavaScriptCore/runtime/ExecutionHarness.h +++ b/Source/JavaScriptCore/runtime/ExecutionHarness.h @@ -46,7 +46,7 @@ inline bool prepareForExecution(JSGlobalData& globalData, OwnPtr<CodeBlockType>& return true; } #endif // ENABLE(LLINT) - return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType); + return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail); } inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind) @@ -61,7 +61,7 @@ inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<Functio #else UNUSED_PARAM(kind); #endif // ENABLE(LLINT) - return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType); + return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index 2e878bfe3..7f45f0746 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -53,7 +53,6 @@ struct DefaultGCActivityCallbackPlatformData { }; const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10; -const CFTimeInterval triggerInterval = 2; // seconds void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info) { @@ -95,6 +94,7 @@ void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLo void DefaultGCActivityCallback::operator()() { + CFTimeInterval triggerInterval = static_cast<Heap*>(d->context.info)->lastGCLength() * 100.0; CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + triggerInterval); } diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp index 0d233e355..fbc5787ce 100644 --- a/Source/JavaScriptCore/runtime/Identifier.cpp +++ b/Source/JavaScriptCore/runtime/Identifier.cpp @@ -36,20 +36,6 @@ using WTF::ThreadSpecific; namespace JSC { -IdentifierTable::~IdentifierTable() -{ - HashSet<StringImpl*>::iterator end = m_table.end(); - for (HashSet<StringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter) - (*iter)->setIsIdentifier(false); -} - -std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(StringImpl* value) -{ - std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add(value); - (*result.first)->setIsIdentifier(true); - return result; -} - IdentifierTable* createIdentifierTable() { return new IdentifierTable; diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h index 947c95b33..b9e5a1854 100644 --- a/Source/JavaScriptCore/runtime/Identifier.h +++ b/Source/JavaScriptCore/runtime/Identifier.h @@ -22,7 +22,7 @@ #define Identifier_h #include "JSGlobalData.h" -#include "ThreadSpecific.h" +#include <wtf/ThreadSpecific.h> #include "UString.h" #include <wtf/WTFThreadData.h> #include <wtf/text/CString.h> diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp index 2b874c708..b6fd6ce1f 100644 --- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp @@ -37,7 +37,7 @@ #include "JSGlobalObject.h" #include "UString.h" #include "WriteBarrier.h" -#include "dtoa.h" +#include <wtf/dtoa.h> #include <wtf/Threading.h> #include <wtf/dtoa/cached-powers.h> diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 71d520018..4244bc31c 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -41,6 +41,7 @@ using namespace WTF; namespace JSC { + ASSERT_CLASS_FITS_IN_CELL(JSArray); ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSArray); @@ -104,23 +105,16 @@ const ClassInfo JSArray::s_info = {"Array", &JSNonFinalObject::s_info, 0, 0, CRE // This value is capped by the constant FIRST_VECTOR_GROW defined above. static unsigned lastArraySize = 0; -static inline size_t storageSize(unsigned vectorLength) +static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues) { - ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH); - - // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH) - // - as asserted above - the following calculation cannot overflow. - size_t size = (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + (vectorLength * sizeof(WriteBarrier<Unknown>)); - // Assertion to detect integer overflow in previous calculation (should not be possible, provided that - // MAX_STORAGE_VECTOR_LENGTH is correctly defined). - ASSERT(((size - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)))); - - return size; + return length <= MIN_SPARSE_ARRAY_INDEX || length / minDensityMultiplier <= numValues; } -static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues) +static bool reject(ExecState* exec, bool throwException, const char* message) { - return length <= MIN_SPARSE_ARRAY_INDEX || length / minDensityMultiplier <= numValues; + if (throwException) + throwTypeError(exec, message); + return false; } #if !CHECK_ARRAY_CONSISTENCY @@ -213,7 +207,7 @@ inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(J return result; } -inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i, JSValue value) +inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow) { std::pair<SparseArrayValueMap::iterator, bool> result = add(array, i); SparseArrayEntry& entry = result.first->second; @@ -223,14 +217,15 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i // extensible, this is not the right thing to have done - so remove again. if (result.second && !array->isExtensible()) { remove(result.first); - // FIXME: should throw in strict mode. + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } if (!(entry.attributes & Accessor)) { if (entry.attributes & ReadOnly) { - // FIXME: should throw if being called from strict mode. - // throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -243,8 +238,8 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i JSObject* setter = asGetterSetter(accessor)->setter(); if (!setter) { - // FIXME: should throw if being called from strict mode. - // throwTypeError(exec, "setting a property that has only a getter"); + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -255,6 +250,24 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i call(exec, setter, callType, callData, array, args); } +inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow) +{ + std::pair<SparseArrayValueMap::iterator, bool> result = add(array, i); + SparseArrayEntry& entry = result.first->second; + + // To save a separate find & add, we first always add to the sparse map. + // In the uncommon case that this is a new property, and the array is not + // extensible, this is not the right thing to have done - so remove again. + if (result.second && !array->isExtensible()) { + remove(result.first); + return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible."); + } + + entry.attributes = 0; + entry.set(exec->globalData(), array, value); + return true; +} + inline void SparseArrayEntry::get(PropertySlot& slot) const { JSValue value = Base::get(); @@ -395,13 +408,6 @@ void JSArray::putDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, Prope entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor); } -static bool reject(ExecState* exec, bool throwException, const char* message) -{ - if (throwException) - throwTypeError(exec, message); - return false; -} - // Defined in ES5.1 8.12.9 bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, PropertyDescriptor& descriptor, bool throwException) { @@ -414,8 +420,7 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property // state (i.e. defineOwnProperty could be used to set a value without needing to entering 'SparseMode'). if (!descriptor.attributes()) { ASSERT(!descriptor.isAccessorDescriptor()); - putByIndex(this, exec, index, descriptor.value()); - return true; + return putDirectIndex(exec, index, descriptor.value(), throwException); } enterDictionaryMode(exec->globalData()); @@ -721,7 +726,7 @@ void JSArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex) { - putByIndex(thisObject, exec, i, value); + putByIndex(thisObject, exec, i, value, slot.isStrictMode()); return; } @@ -738,7 +743,7 @@ void JSArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSObject::put(thisObject, exec, propertyName, value, slot); } -void JSArray::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value) +void JSArray::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow) { JSArray* thisObject = jsCast<JSArray*>(cell); thisObject->checkConsistency(); @@ -765,17 +770,17 @@ void JSArray::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue valu // Handle 2^32-1 - this is not an array index (see ES5.1 15.4), and is treated as a regular property. if (UNLIKELY(i > MAX_ARRAY_INDEX)) { - PutPropertySlot slot; + PutPropertySlot slot(shouldThrow); thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, i), value, slot); return; } // For all other cases, call putByIndexBeyondVectorLength. - thisObject->putByIndexBeyondVectorLength(exec, i, value); + thisObject->putByIndexBeyondVectorLength(exec, i, value, shouldThrow); thisObject->checkConsistency(); } -NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value) +void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow) { JSGlobalData& globalData = exec->globalData(); @@ -806,7 +811,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value. allocateSparseMap(exec->globalData()); map = m_sparseValueMap; - map->put(exec, this, i, value); + map->put(exec, this, i, value, shouldThrow); return; } @@ -815,7 +820,8 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne if (i >= length) { // Prohibit growing the array if length is not writable. if (map->lengthIsReadOnly() || !isExtensible()) { - // FIXME: should throw in strict mode. + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } length = i + 1; @@ -826,7 +832,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne // We will continue to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails. unsigned numValuesInArray = storage->m_numValuesInVector + map->size(); if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length)) { - map->put(exec, this, i, value); + map->put(exec, this, i, value, shouldThrow); return; } @@ -848,6 +854,77 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne valueSlot.set(globalData, this, value); } +bool JSArray::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow) +{ + JSGlobalData& globalData = exec->globalData(); + + // i should be a valid array index that is outside of the current vector. + ASSERT(i >= m_vectorLength); + ASSERT(i <= MAX_ARRAY_INDEX); + + ArrayStorage* storage = m_storage; + SparseArrayValueMap* map = m_sparseValueMap; + + // First, handle cases where we don't currently have a sparse map. + if (LIKELY(!map)) { + // If the array is not extensible, we should have entered dictionary mode, and created the spare map. + ASSERT(isExtensible()); + + // Update m_length if necessary. + if (i >= storage->m_length) + storage->m_length = i + 1; + + // Check that it is sensible to still be using a vector, and then try to grow the vector. + if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(globalData, i + 1))) { + // success! - reread m_storage since it has likely been reallocated, and store to the vector. + storage = m_storage; + storage->m_vector[i].set(globalData, this, value); + ++storage->m_numValuesInVector; + return true; + } + // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value. + allocateSparseMap(exec->globalData()); + map = m_sparseValueMap; + return map->putDirect(exec, this, i, value, shouldThrow); + } + + // Update m_length if necessary. + unsigned length = storage->m_length; + if (i >= length) { + // Prohibit growing the array if length is not writable. + if (map->lengthIsReadOnly()) + return reject(exec, shouldThrow, StrictModeReadonlyPropertyWriteError); + if (!isExtensible()) + return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible."); + length = i + 1; + storage->m_length = length; + } + + // We are currently using a map - check whether we still want to be doing so. + // We will continue to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails. + unsigned numValuesInArray = storage->m_numValuesInVector + map->size(); + if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length)) + return map->putDirect(exec, this, i, value, shouldThrow); + + // Reread m_storage afterincreaseVectorLength, update m_numValuesInVector. + storage = m_storage; + storage->m_numValuesInVector = numValuesInArray; + + // Copy all values from the map into the vector, and delete the map. + WriteBarrier<Unknown>* vector = storage->m_vector; + SparseArrayValueMap::const_iterator end = map->end(); + for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) + vector[it->first].set(globalData, this, it->second.getNonSparseMode()); + deallocateSparseMap(); + + // Store the new property into the vector. + WriteBarrier<Unknown>& valueSlot = vector[i]; + if (!valueSlot) + ++storage->m_numValuesInVector; + valueSlot.set(globalData, this, value); + return true; +} + bool JSArray::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) { JSArray* thisObject = jsCast<JSArray*>(cell); @@ -1220,18 +1297,19 @@ void JSArray::push(ExecState* exec, JSValue value) // Pushing to an array of length 2^32-1 stores the property, but throws a range error. if (UNLIKELY(storage->m_length == 0xFFFFFFFFu)) { - methodTable()->putByIndex(this, exec, storage->m_length, value); + methodTable()->putByIndex(this, exec, storage->m_length, value, true); // Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d. - throwError(exec, createRangeError(exec, "Invalid array length")); + if (!exec->hadException()) + throwError(exec, createRangeError(exec, "Invalid array length")); return; } // Handled the same as putIndex. - putByIndexBeyondVectorLength(exec, storage->m_length, value); + putByIndexBeyondVectorLength(exec, storage->m_length, value, true); checkConsistency(); } -void JSArray::shiftCount(ExecState* exec, unsigned count) +bool JSArray::shiftCount(ExecState*, unsigned count) { ASSERT(count > 0); @@ -1239,32 +1317,15 @@ void JSArray::shiftCount(ExecState* exec, unsigned count) unsigned oldLength = storage->m_length; - if (!oldLength) - return; - - if (oldLength != storage->m_numValuesInVector) { - // If m_length and m_numValuesInVector aren't the same, we have a sparse vector - // which means we need to go through each entry looking for the the "empty" - // slots and then fill them with possible properties. See ECMA spec. - // 15.4.4.9 steps 11 through 13. - for (unsigned i = count; i < oldLength; ++i) { - if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) { - PropertySlot slot(this); - JSValue p = prototype(); - if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot))) - methodTable()->putByIndex(this, exec, i, slot.getValue(exec, i)); - } - } - - storage = m_storage; // The put() above could have grown the vector and realloc'ed storage. + // If the array contains holes or is otherwise in an abnormal state, + // use the generic algorithm in ArrayPrototype. + if (oldLength != storage->m_numValuesInVector || inSparseMode()) + return false; - // Need to decrement numValuesInvector based on number of real entries - for (unsigned i = 0; i < (unsigned)count; ++i) - if ((i < m_vectorLength) && (storage->m_vector[i])) - --storage->m_numValuesInVector; - } else - storage->m_numValuesInVector -= count; + if (!oldLength) + return true; + storage->m_numValuesInVector -= count; storage->m_length -= count; if (m_vectorLength) { @@ -1280,30 +1341,20 @@ void JSArray::shiftCount(ExecState* exec, unsigned count) m_indexBias += count; } } + return true; } - -void JSArray::unshiftCount(ExecState* exec, unsigned count) + +// Returns true if the unshift can be handled, false to fallback. +bool JSArray::unshiftCount(ExecState* exec, unsigned count) { ArrayStorage* storage = m_storage; unsigned length = storage->m_length; - if (length != storage->m_numValuesInVector) { - // If m_length and m_numValuesInVector aren't the same, we have a sparse vector - // which means we need to go through each entry looking for the the "empty" - // slots and then fill them with possible properties. See ECMA spec. - // 15.4.4.13 steps 8 through 10. - for (unsigned i = 0; i < length; ++i) { - if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) { - PropertySlot slot(this); - JSValue p = prototype(); - if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot))) - methodTable()->putByIndex(this, exec, i, slot.getValue(exec, i)); - } - } - } - - storage = m_storage; // The put() above could have grown the vector and realloc'ed storage. - + // If the array contains holes or is otherwise in an abnormal state, + // use the generic algorithm in ArrayPrototype. + if (length != storage->m_numValuesInVector || inSparseMode()) + return false; + if (m_indexBias >= count) { m_indexBias -= count; char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(WriteBarrier<Unknown>); @@ -1312,12 +1363,13 @@ void JSArray::unshiftCount(ExecState* exec, unsigned count) m_vectorLength += count; } else if (!unshiftCountSlowCase(exec->globalData(), count)) { throwOutOfMemoryError(exec); - return; + return true; } WriteBarrier<Unknown>* vector = m_storage->m_vector; for (unsigned i = 0; i < count; i++) vector[i].clear(); + return true; } void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor) diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index 3bb4c6320..ad98d6619 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -85,7 +85,8 @@ namespace JSC { } // These methods may mutate the contents of the map - void put(ExecState*, JSArray*, unsigned, JSValue); + void put(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow); + bool putDirect(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow); std::pair<iterator, bool> add(JSArray*, unsigned); iterator find(unsigned i) { return m_map.find(i); } // This should ASSERT the remove is valid (check the result of the find). @@ -122,11 +123,17 @@ namespace JSC { uintptr_t m_padding; #endif WriteBarrier<Unknown> m_vector[1]; + + static ptrdiff_t lengthOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_length); } + static ptrdiff_t numValuesInVectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector); } + static ptrdiff_t allocBaseOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_allocBase); } + static ptrdiff_t vectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_vector); } }; class JSArray : public JSNonFinalObject { friend class LLIntOffsetsExtractor; friend class Walker; + friend class JIT; protected: JS_EXPORT_PRIVATE explicit JSArray(JSGlobalData&, Structure*); @@ -153,7 +160,19 @@ namespace JSC { static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); + // This is similar to the JSObject::putDirect* methods: + // - the prototype chain is not consulted + // - accessors are not called. + // This method creates a property with attributes writable, enumerable and configurable all set to true. + bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow = true) + { + if (canSetIndex(propertyName)) { + setIndex(exec->globalData(), propertyName, value); + return true; + } + return putDirectIndexBeyondVectorLength(exec, propertyName, value, shouldThrow); + } static JS_EXPORTDATA const ClassInfo s_info; @@ -168,8 +187,8 @@ namespace JSC { void push(ExecState*, JSValue); JSValue pop(ExecState*); - void shiftCount(ExecState*, unsigned count); - void unshiftCount(ExecState*, unsigned count); + bool shiftCount(ExecState*, unsigned count); + bool unshiftCount(ExecState*, unsigned count); bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; } JSValue getIndex(unsigned i) @@ -262,6 +281,7 @@ namespace JSC { JS_EXPORT_PRIVATE void setSubclassData(void*); private: + static size_t storageSize(unsigned vectorLength); bool isLengthWritable() { SparseArrayValueMap* map = m_sparseValueMap; @@ -275,7 +295,8 @@ namespace JSC { void deallocateSparseMap(); bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); - void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue); + void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow); + JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow); unsigned getNewVectorLength(unsigned desiredLength); bool increaseVectorLength(JSGlobalData&, unsigned newLength); @@ -293,6 +314,10 @@ namespace JSC { // FIXME: Maybe SparseArrayValueMap should be put into its own JSCell? SparseArrayValueMap* m_sparseValueMap; void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily. + + static ptrdiff_t sparseValueMapOffset() { return OBJECT_OFFSETOF(JSArray, m_sparseValueMap); } + static ptrdiff_t subclassDataOffset() { return OBJECT_OFFSETOF(JSArray, m_subclassData); } + static ptrdiff_t indexBiasOffset() { return OBJECT_OFFSETOF(JSArray, m_indexBias); } }; inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength) @@ -334,6 +359,30 @@ namespace JSC { return i; } -} // namespace JSC +// The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize +// function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage +// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + +// (vectorLength * sizeof(WriteBarrier<Unknown>)) must be <= 0xFFFFFFFFU (which is maximum value of size_t). +#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>)) + +// These values have to be macros to be used in max() and min() without introducing +// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. +#define MIN_SPARSE_ARRAY_INDEX 10000U +#define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1) + inline size_t JSArray::storageSize(unsigned vectorLength) + { + ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH); + + // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH) + // - as asserted above - the following calculation cannot overflow. + size_t size = (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + (vectorLength * sizeof(WriteBarrier<Unknown>)); + // Assertion to detect integer overflow in previous calculation (should not be possible, provided that + // MAX_STORAGE_VECTOR_LENGTH is correctly defined). + ASSERT(((size - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)))); + + return size; + } + + } // namespace JSC #endif // JSArray_h diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp index 3df21e6f5..39ea4d0b9 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.cpp +++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp @@ -102,7 +102,7 @@ void JSByteArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyN JSObject::put(thisObject, exec, propertyName, value, slot); } -void JSByteArray::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value) +void JSByteArray::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool) { jsCast<JSByteArray*>(cell)->setIndex(exec, propertyName, value); } diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h index d1f4ad630..06181d901 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.h +++ b/Source/JavaScriptCore/runtime/JSByteArray.h @@ -92,7 +92,7 @@ namespace JSC { JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); JS_EXPORT_PRIVATE static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); - JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue); + JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow); JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode); diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp index 4703b681b..f08d0260a 100644 --- a/Source/JavaScriptCore/runtime/JSCell.cpp +++ b/Source/JavaScriptCore/runtime/JSCell.cpp @@ -97,14 +97,23 @@ bool JSCell::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned i void JSCell::put(JSCell* cell, ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) { + if (cell->isString()) { + JSValue(cell).putToPrimitive(exec, identifier, value, slot); + return; + } JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject()); thisObject->methodTable()->put(thisObject, exec, identifier, value, slot); } -void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value) +void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value, bool shouldThrow) { + if (cell->isString()) { + PutPropertySlot slot(shouldThrow); + JSValue(cell).putToPrimitive(exec, Identifier::from(exec, identifier), value, slot); + return; + } JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject()); - thisObject->methodTable()->putByIndex(thisObject, exec, identifier, value); + thisObject->methodTable()->putByIndex(thisObject, exec, identifier, value, shouldThrow); } bool JSCell::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& identifier) diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 78d2d0801..2ef359b76 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -107,7 +107,7 @@ namespace JSC { const ClassInfo* validatedClassInfo() const; const MethodTable* methodTable() const; static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp index 863073338..882f86fa0 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.cpp +++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp @@ -72,8 +72,6 @@ #include "config.h" #include "JSDateMath.h" -#include "Assertions.h" -#include "ASCIICType.h" #include "CurrentTime.h" #include "JSObject.h" #include "MathExtras.h" @@ -86,6 +84,8 @@ #include <limits> #include <stdint.h> #include <time.h> +#include <wtf/ASCIICType.h> +#include <wtf/Assertions.h> #include <wtf/text/StringBuilder.h> #if HAVE(ERRNO_H) diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index 253128279..fa798f41a 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -181,7 +181,15 @@ JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identi { JSFunction* thisObj = asFunction(slotBase); ASSERT(!thisObj->isHostFunction()); - return exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj); + JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj); + + // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller. + if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info)) + return caller; + JSFunction* function = asFunction(caller); + if (function->isHostFunction() || !function->jsExecutable()->isStrictMode()) + return caller; + return throwTypeError(exec, "Function.caller used to retrieve strict caller"); } JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&) @@ -329,21 +337,80 @@ void JSFunction::put(JSCell* cell, ExecState* exec, const Identifier& propertyNa Base::put(thisObject, exec, propertyName, value, slot); return; } - if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) + if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) { + if (slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; + } Base::put(thisObject, exec, propertyName, value, slot); } bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) { JSFunction* thisObject = jsCast<JSFunction*>(cell); - if (thisObject->isHostFunction()) - return Base::deleteProperty(thisObject, exec, propertyName); - if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) + // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty. + if (!thisObject->isHostFunction() && !exec->globalData().isInDefineOwnProperty() + && (propertyName == exec->propertyNames().arguments + || propertyName == exec->propertyNames().length + || propertyName == exec->propertyNames().prototype + || propertyName == exec->propertyNames().caller)) return false; return Base::deleteProperty(thisObject, exec, propertyName); } +bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException) +{ + JSFunction* thisObject = jsCast<JSFunction*>(object); + if (thisObject->isHostFunction()) + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); + + if (propertyName == exec->propertyNames().prototype) { + // Make sure prototype has been reified, such that it can only be overwritten + // following the rules set out in ECMA-262 8.12.9. + PropertySlot slot; + thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot); + } else if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) { + if (!object->isExtensible()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible.")); + return false; + } + if (descriptor.configurablePresent() && descriptor.configurable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property.")); + return false; + } + if (descriptor.enumerablePresent() && descriptor.enumerable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property.")); + return false; + } + if (descriptor.isAccessorDescriptor()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property.")); + return false; + } + if (descriptor.writablePresent() && descriptor.writable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property.")); + return false; + } + if (!descriptor.value()) + return true; + if (propertyName == exec->propertyNames().arguments && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject))) + return true; + if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()))) + return true; + if (propertyName == exec->propertyNames().caller && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject))) + return true; + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property.")); + return false; + } + + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); +} + // ECMA 13.2.2 [[Construct]] ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData) { diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h index 6e8557f59..288181060 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.h +++ b/Source/JavaScriptCore/runtime/JSFunction.h @@ -133,6 +133,7 @@ namespace JSC { static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties); + static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index 2bdc28ab7..f138e75fb 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -193,7 +193,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); -#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER) +#if ENABLE(JIT) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) #if USE(CF) CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); @@ -213,13 +213,16 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread #endif #endif #if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) +#if ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT) if (m_canUseJIT) m_canUseJIT = executableAllocator.isValid(); + + if (!Options::useJIT) + m_canUseJIT = false; #endif jitStubs = adoptPtr(new JITThunks(this)); #endif - + interpreter->initialize(&llintData, this->canUseJIT()); initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index 7e54c00db..acbcee816 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -47,6 +47,7 @@ #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> +#include <wtf/SimpleStats.h> #include <wtf/ThreadSpecific.h> #include <wtf/WTFThreadData.h> #if ENABLE(REGEXP_TRACING) @@ -201,6 +202,7 @@ namespace JSC { SmallStrings smallStrings; NumericStrings numericStrings; DateInstanceCache dateInstanceCache; + WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT; Vector<CodeBlock*> codeBlocksBeingCompiled; void startedCompiling(CodeBlock* codeBlock) { @@ -229,7 +231,7 @@ namespace JSC { #if !ENABLE(JIT) bool canUseJIT() { return false; } // interpreter only -#elif !ENABLE(CLASSIC_INTERPRETER) +#elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT) bool canUseJIT() { return true; } // jit only #else bool canUseJIT() { return m_canUseJIT; } @@ -367,7 +369,7 @@ namespace JSC { JSGlobalData(GlobalDataType, ThreadStackType, HeapSize); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); -#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER) +#if ENABLE(JIT) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) bool m_canUseJIT; #endif #if ENABLE(GC_VALIDATION) diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index db8ee1d85..75789e602 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -35,7 +35,7 @@ #include "Nodes.h" #include "Parser.h" #include "UStringBuilder.h" -#include "dtoa.h" +#include <wtf/dtoa.h> #include <stdio.h> #include <stdlib.h> #include <wtf/ASCIICType.h> diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp index 682400292..337e3a70c 100644 --- a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -70,7 +70,7 @@ void JSNotAnObject::put(JSCell*, ExecState* exec, const Identifier& , JSValue, P ASSERT_UNUSED(exec, exec->hadException()); } -void JSNotAnObject::putByIndex(JSCell*, ExecState* exec, unsigned, JSValue) +void JSNotAnObject::putByIndex(JSCell*, ExecState* exec, unsigned, JSValue, bool) { ASSERT_UNUSED(exec, exec->hadException()); } diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h index 51ba456e1..5f80688b0 100644 --- a/Source/JavaScriptCore/runtime/JSNotAnObject.h +++ b/Source/JavaScriptCore/runtime/JSNotAnObject.h @@ -73,7 +73,7 @@ namespace JSC { static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp index 83b118429..436e78353 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.cpp +++ b/Source/JavaScriptCore/runtime/JSONObject.cpp @@ -704,12 +704,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue); if (filteredValue.isUndefined()) array->methodTable()->deletePropertyByIndex(array, m_exec, indexStack.last()); - else { - if (isJSArray(array) && array->canSetIndex(indexStack.last())) - array->setIndex(m_exec->globalData(), indexStack.last(), filteredValue); - else - array->methodTable()->putByIndex(array, m_exec, indexStack.last(), filteredValue); - } + else + array->putDirectIndex(m_exec, indexStack.last(), filteredValue, false); if (m_exec->hadException()) return jsNull(); indexStack.last()++; diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index acc4a181e..1bdb90ff6 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -119,11 +119,6 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot); } -static void throwSetterError(ExecState* exec) -{ - throwError(exec, createTypeError(exec, "setting a property that has only a getter")); -} - // ECMA 8.6.2.2 void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { @@ -161,7 +156,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName JSObject* setterFunc = asGetterSetter(gs)->setter(); if (!setterFunc) { if (slot.isStrictMode()) - throwSetterError(exec); + throwError(exec, createTypeError(exec, "setting a property that has only a getter")); return; } @@ -190,9 +185,9 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName return; } -void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value) +void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { - PutPropertySlot slot; + PutPropertySlot slot(shouldThrow); JSObject* thisObject = jsCast<JSObject*>(cell); thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, propertyName), value, slot); } @@ -707,7 +702,7 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi if (descriptor.isGenericDescriptor()) { if (!current.attributesEqual(descriptor)) { object->methodTable()->deleteProperty(object, exec, propertyName); - return putDescriptor(exec, object, propertyName, descriptor, current.attributesWithOverride(descriptor), current); + return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current); } return true; } @@ -720,7 +715,7 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi return false; } object->methodTable()->deleteProperty(object, exec, propertyName); - return putDescriptor(exec, object, propertyName, descriptor, current.attributesWithOverride(descriptor), current); + return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current); } // Changing the value and attributes of an existing property @@ -742,7 +737,7 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi if (current.attributesEqual(descriptor) && !descriptor.value()) return true; object->methodTable()->deleteProperty(object, exec, propertyName); - return putDescriptor(exec, object, propertyName, descriptor, current.attributesWithOverride(descriptor), current); + return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current); } // Changing the accessor functions of an existing accessor property diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index c117cffaf..3f3d281cf 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -109,7 +109,7 @@ namespace JSC { bool allowsAccessFrom(ExecState*); JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); // putDirect is effectively an unchecked vesion of 'defineOwnProperty': // - the prototype chain is not consulted @@ -834,21 +834,20 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { if (UNLIKELY(!isCell())) { - JSObject* thisObject = synthesizeObject(exec); - thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); + putToPrimitive(exec, propertyName, value, slot); return; } asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot); } -inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) +inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { if (UNLIKELY(!isCell())) { - JSObject* thisObject = synthesizeObject(exec); - thisObject->methodTable()->putByIndex(thisObject, exec, propertyName, value); + PutPropertySlot slot(shouldThrow); + putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot); return; } - asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value); + asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow); } // --- JSValue inlines ---------------------------- diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index cfa7d03b4..e84ce3620 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -65,9 +65,10 @@ void JSString::resolveRope(ExecState* exec) const if (is8Bit()) { LChar* buffer; - if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) + if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) { + Heap::heap(this)->reportExtraMemoryCost(newImpl->cost()); m_value = newImpl.release(); - else { + } else { outOfMemory(exec); return; } @@ -92,9 +93,10 @@ void JSString::resolveRope(ExecState* exec) const } UChar* buffer; - if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) + if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) { + Heap::heap(this)->reportExtraMemoryCost(newImpl->cost()); m_value = newImpl.release(); - else { + } else { outOfMemory(exec); return; } diff --git a/Source/JavaScriptCore/runtime/JSStringBuilder.h b/Source/JavaScriptCore/runtime/JSStringBuilder.h index b7e7e781e..1a2b812f0 100644 --- a/Source/JavaScriptCore/runtime/JSStringBuilder.h +++ b/Source/JavaScriptCore/runtime/JSStringBuilder.h @@ -29,7 +29,7 @@ #include "ExceptionHelpers.h" #include "JSString.h" #include "UStringConcatenate.h" -#include "Vector.h" +#include <wtf/Vector.h> namespace JSC { diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index e3843f02b..36697c60c 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -27,6 +27,7 @@ #include "BooleanPrototype.h" #include "Error.h" #include "ExceptionHelpers.h" +#include "GetterSetter.h" #include "JSGlobalObject.h" #include "JSFunction.h" #include "JSNotAnObject.h" @@ -90,30 +91,85 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const return exec->globalThisValue(); } -JSObject* JSValue::synthesizeObject(ExecState* exec) const +JSObject* JSValue::synthesizePrototype(ExecState* exec) const { - ASSERT(!isCell()); + if (isCell()) { + ASSERT(isString()); + return exec->lexicalGlobalObject()->stringPrototype(); + } + if (isNumber()) - return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); + return exec->lexicalGlobalObject()->numberPrototype(); if (isBoolean()) - return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); + return exec->lexicalGlobalObject()->booleanPrototype(); ASSERT(isUndefinedOrNull()); throwError(exec, createNotAnObjectError(exec, *this)); return JSNotAnObject::create(exec); } -JSObject* JSValue::synthesizePrototype(ExecState* exec) const +// ECMA 8.7.2 +void JSValue::putToPrimitive(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - ASSERT(!isCell()); - if (isNumber()) - return exec->lexicalGlobalObject()->numberPrototype(); - if (isBoolean()) - return exec->lexicalGlobalObject()->booleanPrototype(); + JSGlobalData& globalData = exec->globalData(); - ASSERT(isUndefinedOrNull()); - throwError(exec, createNotAnObjectError(exec, *this)); - return JSNotAnObject::create(exec); + // Check if there are any setters or getters in the prototype chain + JSObject* obj = synthesizePrototype(exec); + JSValue prototype; + if (propertyName != exec->propertyNames().underscoreProto) { + for (; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) { + prototype = obj->prototype(); + if (prototype.isNull()) { + if (slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + return; + } + } + } + + for (; ; obj = asObject(prototype)) { + unsigned attributes; + JSCell* specificValue; + size_t offset = obj->structure()->get(globalData, propertyName, attributes, specificValue); + if (offset != WTF::notFound) { + if (attributes & ReadOnly) { + if (slot.isStrictMode()) + throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError)); + return; + } + + JSValue gs = obj->getDirectOffset(offset); + if (gs.isGetterSetter()) { + JSObject* setterFunc = asGetterSetter(gs)->setter(); + if (!setterFunc) { + if (slot.isStrictMode()) + throwError(exec, createTypeError(exec, "setting a property that has only a getter")); + return; + } + + CallData callData; + CallType callType = setterFunc->methodTable()->getCallData(setterFunc, callData); + MarkedArgumentBuffer args; + args.append(value); + + // If this is WebCore's global object then we need to substitute the shell. + call(exec, setterFunc, callType, callData, *this, args); + return; + } + + // If there's an existing property on the object or one of its + // prototypes it should be replaced, so break here. + break; + } + + prototype = obj->prototype(); + if (prototype.isNull()) + break; + } + + if (slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + return; } char* JSValue::description() diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index 9f797e05d..a6f359360 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -221,7 +221,8 @@ namespace JSC { JSValue get(ExecState*, unsigned propertyName) const; JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const; void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - void put(ExecState*, unsigned propertyName, JSValue); + void putToPrimitive(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow); JSObject* toThisObject(ExecState*) const; @@ -252,8 +253,6 @@ namespace JSC { JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const; JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const; - JSObject* synthesizeObject(ExecState*) const; - #if USE(JSVALUE32_64) /* * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index 8d058f1fc..bcfe4ab89 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -32,7 +32,7 @@ #include "JSObject.h" #include "Register.h" #include "SymbolTable.h" -#include "UnusedParam.h" +#include <wtf/UnusedParam.h> #include <wtf/OwnArrayPtr.h> #include <wtf/UnusedParam.h> diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp index fb90bcd17..8f8c3c00f 100644 --- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp @@ -29,7 +29,7 @@ #include "JSString.h" #include "Operations.h" #include "Uint16WithFraction.h" -#include "dtoa.h" +#include <wtf/dtoa.h> #include <wtf/Assertions.h> #include <wtf/MathExtras.h> #include <wtf/Vector.h> diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp index 5500508cf..c4bf39db4 100644 --- a/Source/JavaScriptCore/runtime/Options.cpp +++ b/Source/JavaScriptCore/runtime/Options.cpp @@ -45,6 +45,8 @@ namespace JSC { namespace Options { +bool useJIT; + unsigned maximumOptimizationCandidateInstructionCount; unsigned maximumFunctionForCallInlineCandidateInstructionCount; @@ -52,15 +54,12 @@ unsigned maximumFunctionForConstructInlineCandidateInstructionCount; unsigned maximumInliningDepth; -int32_t executionCounterValueForJITAfterWarmUp; -int32_t executionCounterValueForDontJITAnytimeSoon; -int32_t executionCounterValueForJITSoon; +int32_t thresholdForJITAfterWarmUp; +int32_t thresholdForJITSoon; -int32_t executionCounterValueForOptimizeAfterWarmUp; -int32_t executionCounterValueForOptimizeAfterLongWarmUp; -int32_t executionCounterValueForDontOptimizeAnytimeSoon; -int32_t executionCounterValueForOptimizeSoon; -int32_t executionCounterValueForOptimizeNextInvocation; +int32_t thresholdForOptimizeAfterWarmUp; +int32_t thresholdForOptimizeAfterLongWarmUp; +int32_t thresholdForOptimizeSoon; int32_t executionCounterIncrementForLoop; int32_t executionCounterIncrementForReturn; @@ -96,6 +95,19 @@ unsigned numberOfGCMarkers; unsigned opaqueRootMergeThreshold; #if ENABLE(RUN_TIME_HEURISTICS) +static bool parse(const char* string, bool& value) +{ + if (!strcasecmp(string, "true") || !strcasecmp(string, "yes") || !strcmp(string, "1")) { + value = true; + return true; + } + if (!strcasecmp(string, "false") || !strcasecmp(string, "no") || !strcmp(string, "0")) { + value = false; + return true; + } + return false; +} + static bool parse(const char* string, int32_t& value) { return sscanf(string, "%d", &value) == 1; @@ -134,22 +146,21 @@ void setHeuristic(T& variable, const char* name, U value) void initializeOptions() { - SET(maximumOptimizationCandidateInstructionCount, 1100); + SET(useJIT, true); + + SET(maximumOptimizationCandidateInstructionCount, 10000); SET(maximumFunctionForCallInlineCandidateInstructionCount, 180); SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100); SET(maximumInliningDepth, 5); - SET(executionCounterValueForJITAfterWarmUp, -100); - SET(executionCounterValueForDontJITAnytimeSoon, std::numeric_limits<int32_t>::min()); - SET(executionCounterValueForJITSoon, -100); + SET(thresholdForJITAfterWarmUp, 100); + SET(thresholdForJITSoon, 100); - SET(executionCounterValueForOptimizeAfterWarmUp, -1000); - SET(executionCounterValueForOptimizeAfterLongWarmUp, -5000); - SET(executionCounterValueForDontOptimizeAnytimeSoon, std::numeric_limits<int32_t>::min()); - SET(executionCounterValueForOptimizeSoon, -1000); - SET(executionCounterValueForOptimizeNextInvocation, 0); + SET(thresholdForOptimizeAfterWarmUp, 1000); + SET(thresholdForOptimizeAfterLongWarmUp, 5000); + SET(thresholdForOptimizeSoon, 1000); SET(executionCounterIncrementForLoop, 1); SET(executionCounterIncrementForReturn, 15); @@ -193,15 +204,11 @@ void initializeOptions() if (cpusToUse < 1) cpusToUse = 1; - cpusToUse = 1; - SET(numberOfGCMarkers, cpusToUse); - ASSERT(executionCounterValueForDontOptimizeAnytimeSoon <= executionCounterValueForOptimizeAfterLongWarmUp); - ASSERT(executionCounterValueForOptimizeAfterLongWarmUp <= executionCounterValueForOptimizeAfterWarmUp); - ASSERT(executionCounterValueForOptimizeAfterWarmUp <= executionCounterValueForOptimizeSoon); - ASSERT(executionCounterValueForOptimizeAfterWarmUp < 0); - ASSERT(executionCounterValueForOptimizeSoon <= executionCounterValueForOptimizeNextInvocation); + ASSERT(thresholdForOptimizeAfterLongWarmUp >= thresholdForOptimizeAfterWarmUp); + ASSERT(thresholdForOptimizeAfterWarmUp >= thresholdForOptimizeSoon); + ASSERT(thresholdForOptimizeAfterWarmUp >= 0); // Compute the maximum value of the reoptimization retry counter. This is simply // the largest value at which we don't overflow the execute counter, when using it @@ -209,11 +216,11 @@ void initializeOptions() // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles // total on a 32-bit processor. reoptimizationRetryCounterMax = 0; - while ((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min())) + while ((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max())) reoptimizationRetryCounterMax++; - ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) < 0); - ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min())); + ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) > 0); + ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max())); } } } // namespace JSC::Options diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h index b9e68f90c..fae6a7376 100644 --- a/Source/JavaScriptCore/runtime/Options.h +++ b/Source/JavaScriptCore/runtime/Options.h @@ -30,6 +30,8 @@ namespace JSC { namespace Options { +extern bool useJIT; + extern unsigned maximumOptimizationCandidateInstructionCount; extern unsigned maximumFunctionForCallInlineCandidateInstructionCount; @@ -37,15 +39,13 @@ extern unsigned maximumFunctionForConstructInlineCandidateInstructionCount; extern unsigned maximumInliningDepth; // Depth of inline stack, so 1 = no inlining, 2 = one level, etc. -extern int32_t executionCounterValueForJITAfterWarmUp; -extern int32_t executionCounterValueForDontJITAnytimeSoon; -extern int32_t executionCounterValueForJITSoon; +extern int32_t thresholdForJITAfterWarmUp; +extern int32_t thresholdForJITSoon; -extern int32_t executionCounterValueForOptimizeAfterWarmUp; -extern int32_t executionCounterValueForOptimizeAfterLongWarmUp; -extern int32_t executionCounterValueForDontOptimizeAnytimeSoon; -extern int32_t executionCounterValueForOptimizeSoon; -extern int32_t executionCounterValueForOptimizeNextInvocation; +extern int32_t thresholdForOptimizeAfterWarmUp; +extern int32_t thresholdForOptimizeAfterLongWarmUp; +extern int32_t thresholdForOptimizeSoon; +extern int32_t thresholdForOptimizeNextInvocation; extern int32_t executionCounterIncrementForLoop; extern int32_t executionCounterIncrementForReturn; diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp index 0cb629584..236a8e5ae 100644 --- a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp +++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp @@ -206,22 +206,6 @@ bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const return true; } -unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const -{ - unsigned mismatch = other.m_attributes ^ m_attributes; - unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes; - unsigned newAttributes = m_attributes & defaultAttributes; - if (sharedSeen & WritablePresent && mismatch & ReadOnly) - newAttributes ^= ReadOnly; - if (sharedSeen & ConfigurablePresent && mismatch & DontDelete) - newAttributes ^= DontDelete; - if (sharedSeen & EnumerablePresent && mismatch & DontEnum) - newAttributes ^= DontEnum; - if (isAccessorDescriptor() && other.isDataDescriptor()) - newAttributes |= ReadOnly; - return newAttributes; -} - unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const { unsigned currentAttributes = current.m_attributes; diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.h b/Source/JavaScriptCore/runtime/PropertyDescriptor.h index 98af02e66..2c3878f57 100644 --- a/Source/JavaScriptCore/runtime/PropertyDescriptor.h +++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.h @@ -70,7 +70,6 @@ namespace JSC { bool getterPresent() const { return m_getter; } bool equalTo(ExecState* exec, const PropertyDescriptor& other) const; bool attributesEqual(const PropertyDescriptor& other) const; - unsigned attributesWithOverride(const PropertyDescriptor& other) const; unsigned attributesOverridingCurrent(const PropertyDescriptor& current) const; private: diff --git a/Source/JavaScriptCore/runtime/PropertySlot.cpp b/Source/JavaScriptCore/runtime/PropertySlot.cpp index edabd7a6e..8ac874115 100644 --- a/Source/JavaScriptCore/runtime/PropertySlot.cpp +++ b/Source/JavaScriptCore/runtime/PropertySlot.cpp @@ -34,11 +34,7 @@ JSValue PropertySlot::functionGetter(ExecState* exec) const CallData callData; CallType callType = m_data.getterFunc->methodTable()->getCallData(m_data.getterFunc, callData); - - // Only objects can have accessor properties. - // If the base is WebCore's global object then we need to substitute the shell. - ASSERT(m_slotBase.isObject()); - return call(exec, m_data.getterFunc, callType, callData, m_thisValue.toThisObject(exec), exec->emptyList()); + return call(exec, m_data.getterFunc, callType, callData, m_thisValue.isObject() ? m_thisValue.toThisObject(exec) : m_thisValue, exec->emptyList()); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp index 2b7feb4b5..1a3362b2d 100644 --- a/Source/JavaScriptCore/runtime/RegExp.cpp +++ b/Source/JavaScriptCore/runtime/RegExp.cpp @@ -363,7 +363,33 @@ int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffs #endif } else #endif - result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), offsetVector); + result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), reinterpret_cast<unsigned*>(offsetVector)); + + // FIXME: The YARR engine should handle unsigned or size_t length matches. + // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed. + // The offset vector handling needs to change as well. + // Right now we convert a match where the offsets overflowed into match failure. + // There are two places in WebCore that call the interpreter directly that need to + // have their offsets changed to int as well. They are platform/text/RegularExpression.cpp + // and inspector/ContentSearchUtils.cpp. + if (s.length() > INT_MAX) { + bool overflowed = false; + + if (result < -1) + overflowed = true; + + for (unsigned i = 0; i <= m_numSubpatterns; i++) { + if ((offsetVector[i*2] < -1) || ((offsetVector[i*2] >= 0) && (offsetVector[i*2+1] < -1))) { + overflowed = true; + offsetVector[i*2] = -1; + offsetVector[i*2+1] = -1; + } + } + + if (overflowed) + result = -1; + } + ASSERT(result >= -1); #if REGEXP_FUNC_TEST_DATA_GEN diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 53e880e70..90082f07e 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -153,9 +153,9 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec) for (unsigned i = 0; i <= lastNumSubpatterns; ++i) { int start = m_regExpResult.ovector[2 * i]; if (start >= 0) - JSArray::putByIndex(this, exec, i, jsSubstring(exec, m_regExpResult.input, start, m_regExpResult.ovector[2 * i + 1] - start)); + putDirectIndex(exec, i, jsSubstring(exec, m_regExpResult.input, start, m_regExpResult.ovector[2 * i + 1] - start), false); else - JSArray::putByIndex(this, exec, i, jsUndefined()); + putDirectIndex(exec, i, jsUndefined(), false); } PutPropertySlot slot; diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h index c34920d8d..a3c4497fc 100644 --- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -82,12 +82,12 @@ namespace JSC { JSArray::put(thisObject, exec, propertyName, v, slot); } - static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v) + static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v, bool shouldThrow) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); - JSArray::putByIndex(thisObject, exec, propertyName, v); + JSArray::putByIndex(thisObject, exec, propertyName, v, shouldThrow); } static bool deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index 4c192ff90..a81799c46 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2003, 2007, 2008, 2012 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,8 +40,6 @@ static JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&); static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&); static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&); static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&); -static JSValue regExpObjectLastIndex(ExecState*, JSValue, const Identifier&); -static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue); } // namespace JSC @@ -59,14 +57,15 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSNonFinalObject::s_info, 0, ignoreCase regExpObjectIgnoreCase DontDelete|ReadOnly|DontEnum multiline regExpObjectMultiline DontDelete|ReadOnly|DontEnum source regExpObjectSource DontDelete|ReadOnly|DontEnum - lastIndex regExpObjectLastIndex DontDelete|DontEnum @end */ RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp) : JSNonFinalObject(globalObject->globalData(), structure) - , d(adoptPtr(new RegExpObjectData(globalObject->globalData(), this, regExp))) + , m_regExp(globalObject->globalData(), this, regExp) + , m_lastIndexIsWritable(true) { + m_lastIndex.setWithoutWriteBarrier(jsNumber(0)); } void RegExpObject::finishCreation(JSGlobalObject* globalObject) @@ -75,11 +74,6 @@ void RegExpObject::finishCreation(JSGlobalObject* globalObject) ASSERT(inherits(&s_info)); } -void RegExpObject::destroy(JSCell* cell) -{ - jsCast<RegExpObject*>(cell)->RegExpObject::~RegExpObject(); -} - void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor) { RegExpObject* thisObject = jsCast<RegExpObject*>(cell); @@ -87,22 +81,87 @@ void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor) COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); Base::visitChildren(thisObject, visitor); - if (thisObject->d->regExp) - visitor.append(&thisObject->d->regExp); - if (UNLIKELY(!thisObject->d->lastIndex.get().isInt32())) - visitor.append(&thisObject->d->lastIndex); + if (thisObject->m_regExp) + visitor.append(&thisObject->m_regExp); + if (UNLIKELY(!thisObject->m_lastIndex.get().isInt32())) + visitor.append(&thisObject->m_lastIndex); } bool RegExpObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { + if (propertyName == exec->propertyNames().lastIndex) { + RegExpObject* regExp = asRegExpObject(cell); + slot.setValue(regExp, regExp->getLastIndex()); + return true; + } return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), propertyName, slot); } bool RegExpObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { + if (propertyName == exec->propertyNames().lastIndex) { + RegExpObject* regExp = asRegExpObject(object); + descriptor.setDescriptor(regExp->getLastIndex(), regExp->m_lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly); + return true; + } return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, descriptor); } +bool RegExpObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) +{ + if (propertyName == exec->propertyNames().lastIndex) + return false; + return Base::deleteProperty(cell, exec, propertyName); +} + +void RegExpObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (mode == IncludeDontEnumProperties) + propertyNames.add(exec->propertyNames().lastIndex); + Base::getOwnPropertyNames(object, exec, propertyNames, mode); +} + +void RegExpObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (mode == IncludeDontEnumProperties) + propertyNames.add(exec->propertyNames().lastIndex); + Base::getPropertyNames(object, exec, propertyNames, mode); +} + +static bool reject(ExecState* exec, bool throwException, const char* message) +{ + if (throwException) + throwTypeError(exec, message); + return false; +} + +bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow) +{ + if (propertyName == exec->propertyNames().lastIndex) { + RegExpObject* regExp = asRegExpObject(object); + if (descriptor.configurablePresent() && descriptor.configurable()) + return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property."); + if (descriptor.enumerablePresent() && descriptor.enumerable()) + return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property."); + if (descriptor.isAccessorDescriptor()) + return reject(exec, shouldThrow, "Attempting to change access mechanism for an unconfigurable property."); + if (!regExp->m_lastIndexIsWritable) { + if (descriptor.writablePresent() && descriptor.writable()) + return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property."); + if (!sameValue(exec, regExp->getLastIndex(), descriptor.value())) + return reject(exec, shouldThrow, "Attempting to change value of a readonly property."); + return true; + } + if (descriptor.writablePresent() && !descriptor.writable()) + regExp->m_lastIndexIsWritable = false; + if (descriptor.value()) + regExp->setLastIndex(exec, descriptor.value(), false); + return true; + } + + return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); +} + JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&) { return jsBoolean(asRegExpObject(slotBase)->regExp()->global()); @@ -127,6 +186,14 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&) bool inBrackets = false; bool shouldEscape = false; + // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/', + // and also states that the result must be a valid RegularExpressionLiteral. '//' is + // not a valid RegularExpressionLiteral (since it is a single line comment), and hence + // source cannot ever validly be "". If the source is empty, return a different Pattern + // that would match the same thing. + if (!length) + return jsString(exec, "(?:)"); + // early return for strings that don't contain a forwards slash and LineTerminator for (unsigned i = 0; i < length; ++i) { UChar ch = characters[i]; @@ -200,21 +267,15 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&) return jsString(exec, result.toUString()); } -JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&) -{ - return asRegExpObject(slotBase)->getLastIndex(); -} - void RegExpObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { + if (propertyName == exec->propertyNames().lastIndex) { + asRegExpObject(cell)->setLastIndex(exec, value, slot.isStrictMode()); + return; + } lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), slot); } -void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value) -{ - asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value); -} - JSValue RegExpObject::test(ExecState* exec) { return jsBoolean(match(exec)); @@ -236,7 +297,7 @@ bool RegExpObject::match(ExecState* exec) if (!regExp()->global()) { int position; int length; - regExpConstructor->performMatch(*globalData, d->regExp.get(), input, 0, position, length); + regExpConstructor->performMatch(*globalData, m_regExp.get(), input, 0, position, length); return position >= 0; } @@ -245,13 +306,13 @@ bool RegExpObject::match(ExecState* exec) if (LIKELY(jsLastIndex.isUInt32())) { lastIndex = jsLastIndex.asUInt32(); if (lastIndex > input.length()) { - setLastIndex(0); + setLastIndex(exec, 0); return false; } } else { double doubleLastIndex = jsLastIndex.toInteger(exec); if (doubleLastIndex < 0 || doubleLastIndex > input.length()) { - setLastIndex(0); + setLastIndex(exec, 0); return false; } lastIndex = static_cast<unsigned>(doubleLastIndex); @@ -259,13 +320,13 @@ bool RegExpObject::match(ExecState* exec) int position; int length = 0; - regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length); + regExpConstructor->performMatch(*globalData, m_regExp.get(), input, lastIndex, position, length); if (position < 0) { - setLastIndex(0); + setLastIndex(exec, 0); return false; } - setLastIndex(position + length); + setLastIndex(exec, position + length); return true; } diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h index 081a7f111..456cfa683 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.h +++ b/Source/JavaScriptCore/runtime/RegExpObject.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2003, 2007, 2008, 2012 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,20 +44,27 @@ namespace JSC { return object; } - void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); } - RegExp* regExp() const { return d->regExp.get(); } + void setRegExp(JSGlobalData& globalData, RegExp* r) { m_regExp.set(globalData, this, r); } + RegExp* regExp() const { return m_regExp.get(); } - void setLastIndex(size_t lastIndex) + void setLastIndex(ExecState* exec, size_t lastIndex) { - d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); + m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); + if (LIKELY(m_lastIndexIsWritable)) + m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); + else + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); } - void setLastIndex(JSGlobalData& globalData, JSValue lastIndex) + void setLastIndex(ExecState* exec, JSValue lastIndex, bool shouldThrow) { - d->lastIndex.set(globalData, this, lastIndex); + if (LIKELY(m_lastIndexIsWritable)) + m_lastIndex.set(exec->globalData(), this, lastIndex); + else if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); } JSValue getLastIndex() const { - return d->lastIndex.get(); + return m_lastIndex.get(); } JSValue test(ExecState*); @@ -77,31 +84,22 @@ namespace JSC { protected: JS_EXPORT_PRIVATE RegExpObject(JSGlobalObject*, Structure*, RegExp*); JS_EXPORT_PRIVATE void finishCreation(JSGlobalObject*); - static void destroy(JSCell*); static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags; static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); + private: bool match(ExecState*); - struct RegExpObjectData { - WTF_MAKE_FAST_ALLOCATED; - public: - RegExpObjectData(JSGlobalData& globalData, RegExpObject* owner, RegExp* regExp) - : regExp(globalData, owner, regExp) - { - lastIndex.setWithoutWriteBarrier(jsNumber(0)); - } - - WriteBarrier<RegExp> regExp; - WriteBarrier<Unknown> lastIndex; - }; -#if COMPILER(MSVC) - friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*); -#endif - OwnPtr<RegExpObjectData> d; + WriteBarrier<RegExp> m_regExp; + WriteBarrier<Unknown> m_lastIndex; + bool m_lastIndexIsWritable; }; RegExpObject* asRegExpObject(JSValue); diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 9074e97c3..8e4b5a9d5 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -129,7 +129,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage())); asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp); - asRegExpObject(thisValue)->setLastIndex(0); + asRegExpObject(thisValue)->setLastIndex(exec, 0); return JSValue::encode(jsUndefined()); } @@ -155,7 +155,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec) postfix[index] = 'm'; UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec); // If source is empty, use "/(?:)/" to avoid colliding with comment syntax - return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix)); + return JSValue::encode(jsMakeNontrivialString(exec, "/", source, postfix)); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp index 4a24698fb..d7e1c8a17 100644 --- a/Source/JavaScriptCore/runtime/StringObject.cpp +++ b/Source/JavaScriptCore/runtime/StringObject.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "StringObject.h" +#include "Error.h" #include "PropertyNameArray.h" namespace JSC { @@ -68,11 +69,56 @@ bool StringObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, c void StringObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - if (propertyName == exec->propertyNames().length) + if (propertyName == exec->propertyNames().length) { + if (slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; + } JSObject::put(cell, exec, propertyName, value, slot); } +bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException) +{ + StringObject* thisObject = jsCast<StringObject*>(object); + + if (propertyName == exec->propertyNames().length) { + if (!object->isExtensible()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible.")); + return false; + } + if (descriptor.configurablePresent() && descriptor.configurable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property.")); + return false; + } + if (descriptor.enumerablePresent() && descriptor.enumerable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property.")); + return false; + } + if (descriptor.isAccessorDescriptor()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property.")); + return false; + } + if (descriptor.writablePresent() && descriptor.writable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property.")); + return false; + } + if (!descriptor.value()) + return true; + if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length()))) + return true; + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property.")); + return false; + } + + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); +} + bool StringObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) { StringObject* thisObject = jsCast<StringObject*>(cell); diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h index 248c71601..bad5595c3 100644 --- a/Source/JavaScriptCore/runtime/StringObject.h +++ b/Source/JavaScriptCore/runtime/StringObject.h @@ -53,6 +53,7 @@ namespace JSC { static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); static const JS_EXPORTDATA ClassInfo s_info; diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index 63c00e27e..708c1fb77 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -455,11 +455,19 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS unsigned sourceLen = source.length(); if (exec->hadException()) return JSValue::encode(JSValue()); - RegExp* regExp = asRegExpObject(searchValue)->regExp(); + RegExpObject* regExpObject = asRegExpObject(searchValue); + RegExp* regExp = regExpObject->regExp(); bool global = regExp->global(); - if (global && callType == CallTypeNone && !replacementString.length()) - return removeUsingRegExpSearch(exec, string, source, regExp); + if (global) { + // ES5.1 15.5.4.10 step 8.a. + regExpObject->setLastIndex(exec, 0); + if (exec->hadException()) + return JSValue::encode(JSValue()); + + if (callType == CallTypeNone && !replacementString.length()) + return removeUsingRegExpSearch(exec, string, source, regExp); + } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); @@ -808,9 +816,17 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) JSValue a0 = exec->argument(0); RegExp* reg; - if (a0.inherits(&RegExpObject::s_info)) - reg = asRegExpObject(a0)->regExp(); - else { + bool global = false; + if (a0.inherits(&RegExpObject::s_info)) { + RegExpObject* regExpObject = asRegExpObject(a0); + reg = regExpObject->regExp(); + if ((global = reg->global())) { + // ES5.1 15.5.4.10 step 8.a. + regExpObject->setLastIndex(exec, 0); + if (exec->hadException()) + return JSValue::encode(JSValue()); + } + } else { /* * ECMA 15.5.4.12 String.prototype.search (regexp) * If regexp is not an object whose [[Class]] property is "RegExp", it is @@ -825,7 +841,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) int pos; int matchLength = 0; regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength); - if (!(reg->global())) { + if (!global) { // case without 'g' flag is handled like RegExp.prototype.exec if (pos < 0) return JSValue::encode(jsNull()); @@ -948,7 +964,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) if (separatorValue.isUndefined()) { // a. Call the [[DefineOwnProperty]] internal method of A with arguments "0", // Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. - result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input)); + result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false); // b. Return A. return JSValue::encode(result); } @@ -961,7 +977,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. // d. Return A. if (reg->match(*globalData, input, 0) < 0) - result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input)); + result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false); return JSValue::encode(result); } @@ -992,7 +1008,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // through q (exclusive). // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), // Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. - result->methodTable()->putByIndex(result, exec, resultLength, jsSubstring(exec, input, position, matchPosition - position)); + result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false); // 3. Increment lengthA by 1. // 4. If lengthA == lim, return A. if (++resultLength == limit) @@ -1011,7 +1027,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // ToString(lengthA), Property Descriptor {[[Value]]: cap[i], [[Writable]]: // true, [[Enumerable]]: true, [[Configurable]]: true}, and false. int sub = ovector[i * 2]; - result->methodTable()->putByIndex(result, exec, resultLength, sub < 0 ? jsUndefined() : jsSubstring(exec, input, sub, ovector[i * 2 + 1] - sub)); + result->putDirectIndex(exec, resultLength, sub < 0 ? jsUndefined() : jsSubstring(exec, input, sub, ovector[i * 2 + 1] - sub), false); // c Increment lengthA by 1. // d If lengthA == lim, return A. if (++resultLength == limit) @@ -1030,7 +1046,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) if (separatorValue.isUndefined()) { // a. Call the [[DefineOwnProperty]] internal method of A with arguments "0", // Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. - result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input)); + result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false); // b. Return A. return JSValue::encode(result); } @@ -1043,7 +1059,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. // d. Return A. if (!separator.isEmpty()) - result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input)); + result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false); return JSValue::encode(result); } @@ -1054,7 +1070,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) ASSERT(limit); do { - result->methodTable()->putByIndex(result, exec, position, jsSingleCharacterSubstring(exec, input, position)); + result->putDirectIndex(exec, position, jsSingleCharacterSubstring(exec, input, position), false); } while (++position < limit); return JSValue::encode(result); @@ -1071,7 +1087,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // through q (exclusive). // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), // Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. - result->methodTable()->putByIndex(result, exec, resultLength, jsSubstring(exec, input, position, matchPosition - position)); + result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false); // 3. Increment lengthA by 1. // 4. If lengthA == lim, return A. if (++resultLength == limit) @@ -1087,7 +1103,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // through s (exclusive). // 15. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), Property Descriptor // {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. - result->methodTable()->putByIndex(result, exec, resultLength++, jsSubstring(exec, input, position, input.length() - position)); + result->putDirectIndex(exec, resultLength++, jsSubstring(exec, input, position, input.length() - position), false); // 16. Return A. return JSValue::encode(result); diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h index 81731222b..f540a12c7 100644 --- a/Source/JavaScriptCore/runtime/SymbolTable.h +++ b/Source/JavaScriptCore/runtime/SymbolTable.h @@ -125,7 +125,7 @@ namespace JSC { public: static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); } private: - SharedSymbolTable() { deprecatedTurnOffVerifier(); } + SharedSymbolTable() { turnOffVerifier(); } }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h index 7e9db12fb..05f3bc5bb 100644 --- a/Source/JavaScriptCore/runtime/WriteBarrier.h +++ b/Source/JavaScriptCore/runtime/WriteBarrier.h @@ -30,7 +30,7 @@ #include "HandleTypes.h" #include "Heap.h" #include "SamplingCounter.h" -#include "TypeTraits.h" +#include <wtf/TypeTraits.h> namespace JSC { diff --git a/Source/JavaScriptCore/tests/mozilla/ecma/Array/15.4.5.1-1.js b/Source/JavaScriptCore/tests/mozilla/ecma/Array/15.4.5.1-1.js index e57408b03..71a45e66e 100644 --- a/Source/JavaScriptCore/tests/mozilla/ecma/Array/15.4.5.1-1.js +++ b/Source/JavaScriptCore/tests/mozilla/ecma/Array/15.4.5.1-1.js @@ -104,6 +104,8 @@ function getTestCases() { for ( var i = 0X0020, TEST_STRING = "var A = new Array( " ; i < 0x00ff; i++ ) { + if ( i === 0x58 || i === 0x78 ) // x or X - skip testing invalid hex escapes. + continue; TEST_STRING += "\'\\"+ String.fromCharCode( i ) +"\'"; if ( i < 0x00FF - 1 ) { TEST_STRING += ","; @@ -112,7 +114,7 @@ function getTestCases() { } } - var LENGTH = 0x00ff - 0x0020; + var LENGTH = 0x00ff - 0x0020 - 2; // x & X array[item++] = new TestCase( SECTION, TEST_STRING +" A[150] = 'hello'; A[150]", diff --git a/Source/JavaScriptCore/tests/mozilla/ecma/LexicalConventions/7.7.4.js b/Source/JavaScriptCore/tests/mozilla/ecma/LexicalConventions/7.7.4.js index 769b81989..d8e26afd5 100644 --- a/Source/JavaScriptCore/tests/mozilla/ecma/LexicalConventions/7.7.4.js +++ b/Source/JavaScriptCore/tests/mozilla/ecma/LexicalConventions/7.7.4.js @@ -170,9 +170,9 @@ function getTestCases() { array[item++] = new TestCase( SECTION, "\\x0F0", String.fromCharCode(15)+"0", "\x0F0" ); // G is out of hex range - - array[item++] = new TestCase( SECTION, "\\xG", "xG", "\xG" ); - array[item++] = new TestCase( SECTION, "\\xCG", "xCG", "\xCG" ); +// Invalid hex escapes are syntax error; these are covered in the sputnik test suite. +// array[item++] = new TestCase( SECTION, "\\xG", "xG", "\xG" ); +// array[item++] = new TestCase( SECTION, "\\xCG", "xCG", "\xCG" ); // DoubleStringCharacter::EscapeSequence::CharacterEscapeSequence::\ NonEscapeCharacter array[item++] = new TestCase( SECTION, "\\a", "a", "\a" ); @@ -193,7 +193,8 @@ function getTestCases() { array[item++] = new TestCase( SECTION, "\\u", "u", "\u" ); array[item++] = new TestCase( SECTION, "\\w", "w", "\w" ); - array[item++] = new TestCase( SECTION, "\\x", "x", "\x" ); +// Invalid hex escapes are syntax error; these are covered in the sputnik test suite. +// array[item++] = new TestCase( SECTION, "\\x", "x", "\x" ); array[item++] = new TestCase( SECTION, "\\y", "y", "\y" ); array[item++] = new TestCase( SECTION, "\\z", "z", "\z" ); array[item++] = new TestCase( SECTION, "\\9", "9", "\9" ); diff --git a/Source/JavaScriptCore/tests/mozilla/ecma/TypeConversion/9.3.1-3.js b/Source/JavaScriptCore/tests/mozilla/ecma/TypeConversion/9.3.1-3.js index 69407fb5f..083226e5d 100644 --- a/Source/JavaScriptCore/tests/mozilla/ecma/TypeConversion/9.3.1-3.js +++ b/Source/JavaScriptCore/tests/mozilla/ecma/TypeConversion/9.3.1-3.js @@ -82,7 +82,7 @@ testcases[tc++] = new TestCase( SECTION, testcases[tc++] = new TestCase( SECTION, '- "-0x123456789abcde8"', - 81985529216486880, + NaN, - "-0x123456789abcde8" ); // Convert some large numbers to string @@ -474,7 +474,7 @@ testcases[tc++] = new TestCase( SECTION, testcases[tc++] = new TestCase( SECTION, "parseInt(\"0022\")", - 18, + 22, parseInt("0022") ); testcases[tc++] = new TestCase( SECTION, @@ -664,7 +664,7 @@ testcases[tc++] = new TestCase( SECTION, testcases[tc++] = new TestCase( SECTION, "- \"-0x123456789abcde8\"", - 81985529216486880, + NaN, - "-0x123456789abcde8" ); // the following two tests are not strictly ECMA 1.0 diff --git a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/constructor-001.js b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/constructor-001.js index be904e576..ceaa39d3d 100644 --- a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/constructor-001.js +++ b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/constructor-001.js @@ -40,7 +40,7 @@ AddTestCase( "(new RegExp()).source", - "", + "(?:)", re.source ); AddTestCase( diff --git a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/function-001.js b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/function-001.js index 67c4f21d4..96c3ccfdc 100644 --- a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/function-001.js +++ b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/function-001.js @@ -40,7 +40,7 @@ AddTestCase( "(new RegExp()).source", - "", + "(?:)", re.source ); AddTestCase( diff --git a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/hex-001.js b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/hex-001.js index 122d59cd3..4a04e944d 100644 --- a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/hex-001.js +++ b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/hex-001.js @@ -16,7 +16,8 @@ AddRegExpCases( new RegExp("\x41"), "new RegExp('\\x41')", "A", "A", 1, 0, ["A"] ); AddRegExpCases( new RegExp("\x412"),"new RegExp('\\x412')", "A2", "A2", 1, 0, ["A2"] ); - AddRegExpCases( new RegExp("\x1g"), "new RegExp('\\x1g')", "x1g","x1g", 1, 0, ["x1g"] ); +// Invalid hex escapes are syntax error; these are covered in the sputnik test suite. +// AddRegExpCases( new RegExp("\x1g"), "new RegExp('\\x1g')", "x1g","x1g", 1, 0, ["x1g"] ); AddRegExpCases( new RegExp("A"), "new RegExp('A')", "\x41", "\\x41", 1, 0, ["A"] ); AddRegExpCases( new RegExp("A"), "new RegExp('A')", "\x412", "\\x412", 1, 0, ["A"] ); diff --git a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/properties-001.js b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/properties-001.js index 3eb51cbcd..122b94171 100644 --- a/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/properties-001.js +++ b/Source/JavaScriptCore/tests/mozilla/ecma_2/RegExp/properties-001.js @@ -52,10 +52,6 @@ function AddRegExpCases( re, s, g, i, m, l ) { // properties - AddTestCase( re + ".source", - s, - re.source ); - /* * http://bugzilla.mozilla.org/show_bug.cgi?id=225550 changed * the behavior of toString() and toSource() on empty regexps. @@ -63,6 +59,10 @@ function AddRegExpCases( re, s, g, i, m, l ) { */ var S = s? s : '(?:)'; + AddTestCase( re + ".source", + S, + re.source ); + AddTestCase( re + ".toString()", "/" + S +"/" + (g?"g":"") + (i?"i":"") +(m?"m":""), re.toString() ); diff --git a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/hexadecimal.js b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/hexadecimal.js index 8f68c9ab9..14e555869 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/hexadecimal.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/hexadecimal.js @@ -30,7 +30,7 @@ var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; var VERSION = 'no version'; startTest(); - var TITLE = 'RegExp: \x# (hex) '; + var TITLE = 'RegExp: \\x# (hex) '; writeHeaderToLog('Executing script: hexadecimal.js'); writeHeaderToLog( SECTION + " "+ TITLE); diff --git a/Source/JavaScriptCore/tests/mozilla/js1_6/Array/regress-304828.js b/Source/JavaScriptCore/tests/mozilla/js1_6/Array/regress-304828.js index 5cab4a75d..fb751e555 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_6/Array/regress-304828.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_6/Array/regress-304828.js @@ -100,7 +100,7 @@ reportCompare('abc', value, summary + ': push'); // pop value = 'abc'; -expect = 'c'; +expect = 'TypeError: Unable to delete property.'; try { actual = Array.prototype.pop.call(value); @@ -128,7 +128,7 @@ reportCompare('def', value, summary + ': unshift'); // shift value = 'abc'; -expect = 'a'; +expect = 'TypeError: Unable to delete property.'; try { actual = Array.prototype.shift.call(value); @@ -142,7 +142,7 @@ reportCompare('abc', value, summary + ': shift'); // splice value = 'abc'; -expect = 'b'; +expect = 'TypeError: Unable to delete property.'; try { actual = Array.prototype.splice.call(value, 1, 1) + ''; diff --git a/Source/JavaScriptCore/tools/CodeProfile.cpp b/Source/JavaScriptCore/tools/CodeProfile.cpp index 349353eb2..beed4b2d5 100644 --- a/Source/JavaScriptCore/tools/CodeProfile.cpp +++ b/Source/JavaScriptCore/tools/CodeProfile.cpp @@ -30,7 +30,7 @@ #include "CodeProfiling.h" #include "LinkBuffer.h" #include "ProfileTreeNode.h" -#include "Vector.h" +#include <wtf/Vector.h> #include <wtf/text/WTFString.h> #if PLATFORM(MAC) diff --git a/Source/JavaScriptCore/tools/TieredMMapArray.h b/Source/JavaScriptCore/tools/TieredMMapArray.h index fa6e5ae1f..03d9df2b7 100644 --- a/Source/JavaScriptCore/tools/TieredMMapArray.h +++ b/Source/JavaScriptCore/tools/TieredMMapArray.h @@ -26,7 +26,7 @@ #ifndef TieredMMapArray_h #define TieredMMapArray_h -#include "OSAllocator.h" +#include <wtf/OSAllocator.h> namespace JSC { diff --git a/Source/JavaScriptCore/wscript b/Source/JavaScriptCore/wscript index d6f1ae899..2093601df 100644 --- a/Source/JavaScriptCore/wscript +++ b/Source/JavaScriptCore/wscript @@ -33,7 +33,7 @@ def build(bld): import Options - jscore_excludes = ['jsc.cpp', 'ExecutableAllocatorPosix.cpp'] + jscore_excludes = ['jsc.cpp', 'ExecutableAllocatorPosix.cpp', 'LLIntOffsetsExtractor.cpp'] jscore_excludes.extend(get_excludes(jscore_dir, ['*CF.cpp', '*Symbian.cpp'])) jscore_excludes.extend(get_excludes(jscore_dir, ['*None.cpp'])) diff --git a/Source/JavaScriptCore/wtf/AVLTree.h b/Source/JavaScriptCore/wtf/AVLTree.h index ec8a63951..f2f82e170 100644 --- a/Source/JavaScriptCore/wtf/AVLTree.h +++ b/Source/JavaScriptCore/wtf/AVLTree.h @@ -32,7 +32,7 @@ #ifndef AVL_TREE_H_ #define AVL_TREE_H_ -#include "Assertions.h" +#include <wtf/Assertions.h> #include <wtf/FixedArray.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Alignment.h b/Source/JavaScriptCore/wtf/Alignment.h index 9b443efc6..ac780b96e 100644 --- a/Source/JavaScriptCore/wtf/Alignment.h +++ b/Source/JavaScriptCore/wtf/Alignment.h @@ -21,7 +21,7 @@ #ifndef WTF_Alignment_h #define WTF_Alignment_h -#include "Platform.h" +#include <wtf/Platform.h> #include <algorithm> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/AlwaysInline.h b/Source/JavaScriptCore/wtf/AlwaysInline.h index de12ddd90..68b7ae1a8 100644 --- a/Source/JavaScriptCore/wtf/AlwaysInline.h +++ b/Source/JavaScriptCore/wtf/AlwaysInline.h @@ -20,4 +20,4 @@ /* This file is no longer necessary, since all the functionality has been moved to Compiler.h. */ -#include "Platform.h" +#include <wtf/Platform.h> diff --git a/Source/JavaScriptCore/wtf/ArrayBuffer.h b/Source/JavaScriptCore/wtf/ArrayBuffer.h index ee95f5bc6..3257df3d0 100644 --- a/Source/JavaScriptCore/wtf/ArrayBuffer.h +++ b/Source/JavaScriptCore/wtf/ArrayBuffer.h @@ -88,7 +88,7 @@ public: void addView(ArrayBufferView*); void removeView(ArrayBufferView*); - bool transfer(ArrayBufferContents&, Vector<RefPtr<ArrayBufferView> >& neuteredViews); + WTF_EXPORT_PRIVATE bool transfer(ArrayBufferContents&, Vector<RefPtr<ArrayBufferView> >& neuteredViews); bool isNeutered() { return !m_contents.m_data; } ~ArrayBuffer() { } diff --git a/Source/JavaScriptCore/wtf/ArrayBufferView.h b/Source/JavaScriptCore/wtf/ArrayBufferView.h index 24ce25a5e..f314dd56c 100644 --- a/Source/JavaScriptCore/wtf/ArrayBufferView.h +++ b/Source/JavaScriptCore/wtf/ArrayBufferView.h @@ -26,7 +26,7 @@ #ifndef ArrayBufferView_h #define ArrayBufferView_h -#include "ArrayBuffer.h" +#include <wtf/ArrayBuffer.h> #include <algorithm> #include <limits.h> @@ -36,7 +36,7 @@ namespace WTF { -class ArrayBufferView : public RefCounted<ArrayBufferView> { +class WTF_EXPORT_PRIVATE_RTTI ArrayBufferView : public RefCounted<ArrayBufferView> { public: virtual bool isByteArray() const { return false; } virtual bool isUnsignedByteArray() const { return false; } @@ -186,6 +186,8 @@ void ArrayBufferView::calculateOffsetAndLength(int start, int end, unsigned arra end += arraySize; if (end < 0) end = 0; + if (static_cast<unsigned>(end) > arraySize) + end = arraySize; if (end < start) end = start; *offset = static_cast<unsigned>(start); diff --git a/Source/JavaScriptCore/wtf/Assertions.cpp b/Source/JavaScriptCore/wtf/Assertions.cpp index 80afcf414..9e744d387 100644 --- a/Source/JavaScriptCore/wtf/Assertions.cpp +++ b/Source/JavaScriptCore/wtf/Assertions.cpp @@ -70,8 +70,15 @@ static void vprintf_stderr_common(const char* format, va_list args) #if PLATFORM(MAC) if (strstr(format, "%@")) { CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); - CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args); +#if COMPILER(CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif + CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args); +#if COMPILER(CLANG) +#pragma clang diagnostic pop +#endif int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char* buffer = (char*)malloc(length + 1); diff --git a/Source/JavaScriptCore/wtf/Assertions.h b/Source/JavaScriptCore/wtf/Assertions.h index e7358dccb..14b9091fd 100644 --- a/Source/JavaScriptCore/wtf/Assertions.h +++ b/Source/JavaScriptCore/wtf/Assertions.h @@ -42,7 +42,7 @@ http://msdn2.microsoft.com/en-us/library/ms177415(VS.80).aspx */ -#include "Platform.h" +#include <wtf/Platform.h> #include <stddef.h> diff --git a/Source/JavaScriptCore/wtf/Atomics.h b/Source/JavaScriptCore/wtf/Atomics.h index 5e10460c6..d30926897 100644 --- a/Source/JavaScriptCore/wtf/Atomics.h +++ b/Source/JavaScriptCore/wtf/Atomics.h @@ -59,9 +59,9 @@ #ifndef Atomics_h #define Atomics_h -#include "Platform.h" -#include "StdLibExtras.h" -#include "UnusedParam.h" +#include <wtf/Platform.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> #if OS(WINDOWS) #include <windows.h> @@ -118,7 +118,11 @@ inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_ #endif +#if COMPILER(GCC) && !COMPILER(CLANG) // Work around a gcc bug +inline bool weakCompareAndSwap(volatile unsigned* location, unsigned expected, unsigned newValue) +#else inline bool weakCompareAndSwap(unsigned* location, unsigned expected, unsigned newValue) +#endif { #if ENABLE(COMPARE_AND_SWAP) bool result; @@ -181,7 +185,7 @@ inline bool weakCompareAndSwap(void*volatile* location, void* expected, void* ne #endif // ENABLE(COMPARE_AND_SWAP) } -inline bool weakCompareAndSwap(volatile uintptr_t* location, uintptr_t expected, uintptr_t newValue) +inline bool weakCompareAndSwapUIntPtr(volatile uintptr_t* location, uintptr_t expected, uintptr_t newValue) { return weakCompareAndSwap(reinterpret_cast<void*volatile*>(location), reinterpret_cast<void*>(expected), reinterpret_cast<void*>(newValue)); } diff --git a/Source/JavaScriptCore/wtf/Bitmap.h b/Source/JavaScriptCore/wtf/Bitmap.h index d7e2528a3..76a2ca4b3 100644 --- a/Source/JavaScriptCore/wtf/Bitmap.h +++ b/Source/JavaScriptCore/wtf/Bitmap.h @@ -19,9 +19,9 @@ #ifndef Bitmap_h #define Bitmap_h -#include "Atomics.h" -#include "FixedArray.h" -#include "StdLibExtras.h" +#include <wtf/Atomics.h> +#include <wtf/FixedArray.h> +#include <wtf/StdLibExtras.h> #include <stdint.h> #include <string.h> diff --git a/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h b/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h index d5d42fc1c..1f7caab63 100644 --- a/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h +++ b/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h @@ -29,8 +29,8 @@ #ifndef WTF_BoundsCheckedPointer_h #define WTF_BoundsCheckedPointer_h -#include "Assertions.h" -#include "UnusedParam.h" +#include <wtf/Assertions.h> +#include <wtf/UnusedParam.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/CMakeLists.txt b/Source/JavaScriptCore/wtf/CMakeLists.txt index 63fc59c73..72420128a 100644 --- a/Source/JavaScriptCore/wtf/CMakeLists.txt +++ b/Source/JavaScriptCore/wtf/CMakeLists.txt @@ -206,14 +206,9 @@ WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() WEBKIT_WRAP_SOURCELIST(${WTF_SOURCES}) INCLUDE_DIRECTORIES(${WTF_INCLUDE_DIRECTORIES}) ADD_DEFINITIONS(-DBUILDING_WTF) -ADD_LIBRARY(${WTF_LIBRARY_NAME} ${WTF_LIBRARY_TYPE} ${WTF_HEADERS} ${WTF_SOURCES}) +ADD_LIBRARY(${WTF_LIBRARY_NAME} STATIC ${WTF_HEADERS} ${WTF_SOURCES}) TARGET_LINK_LIBRARIES(${WTF_LIBRARY_NAME} ${WTF_LIBRARIES}) IF (WTF_LINK_FLAGS) ADD_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} LINK_FLAGS "${WTF_LINK_FLAGS}") ENDIF () - -IF (SHARED_CORE) - SET_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) - INSTALL(TARGETS ${WTF_LIBRARY_NAME} DESTINATION lib) -ENDIF () diff --git a/Source/JavaScriptCore/wtf/CheckedArithmetic.h b/Source/JavaScriptCore/wtf/CheckedArithmetic.h index f90efae41..b18916538 100644 --- a/Source/JavaScriptCore/wtf/CheckedArithmetic.h +++ b/Source/JavaScriptCore/wtf/CheckedArithmetic.h @@ -26,8 +26,8 @@ #ifndef CheckedArithmetic_h #define CheckedArithmetic_h -#include "Assertions.h" -#include "TypeTraits.h" +#include <wtf/Assertions.h> +#include <wtf/TypeTraits.h> #include <limits> #include <stdint.h> diff --git a/Source/JavaScriptCore/wtf/DateMath.cpp b/Source/JavaScriptCore/wtf/DateMath.cpp index dc503ca2a..cf601a5ec 100644 --- a/Source/JavaScriptCore/wtf/DateMath.cpp +++ b/Source/JavaScriptCore/wtf/DateMath.cpp @@ -935,6 +935,14 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT } } } + + // The year may be after the time but before the time zone. + if (isASCIIDigit(*dateString) && year == -1) { + if (!parseLong(dateString, &newPosStr, 10, &year)) + return std::numeric_limits<double>::quiet_NaN(); + dateString = newPosStr; + skipSpacesAndComments(dateString); + } // Don't fail if the time zone is missing. // Some websites omit the time zone (4275206). @@ -987,10 +995,9 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT if (!parseLong(dateString, &newPosStr, 10, &year)) return std::numeric_limits<double>::quiet_NaN(); dateString = newPosStr; + skipSpacesAndComments(dateString); } - skipSpacesAndComments(dateString); - // Trailing garbage if (*dateString) return std::numeric_limits<double>::quiet_NaN(); diff --git a/Source/JavaScriptCore/wtf/Deque.h b/Source/JavaScriptCore/wtf/Deque.h index 18eb10582..47c0dfffa 100644 --- a/Source/JavaScriptCore/wtf/Deque.h +++ b/Source/JavaScriptCore/wtf/Deque.h @@ -33,8 +33,8 @@ // FIXME: Could move what Vector and Deque share into a separate file. // Deque doesn't actually use Vector. -#include "PassTraits.h" -#include "Vector.h" +#include <wtf/PassTraits.h> +#include <wtf/Vector.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/ExportMacros.h b/Source/JavaScriptCore/wtf/ExportMacros.h index a6b3bce5a..4d3219329 100644 --- a/Source/JavaScriptCore/wtf/ExportMacros.h +++ b/Source/JavaScriptCore/wtf/ExportMacros.h @@ -30,7 +30,7 @@ #ifndef ExportMacros_h #define ExportMacros_h -#include "Platform.h" +#include <wtf/Platform.h> // See note in wtf/Platform.h for more info on EXPORT_MACROS. #if USE(EXPORT_MACROS) @@ -83,6 +83,14 @@ #define WTF_EXPORT_PRIVATE WTF_IMPORT #endif +// wxWebKit uses RTTI because wx itself does, so use a special macro for +// extra exports it needs. +#if PLATFORM(WX) +#define WTF_EXPORT_PRIVATE_RTTI WTF_EXPORT_PRIVATE +#else +#define WTF_EXPORT_PRIVATE_RTTI +#endif + #define WTF_EXPORT_HIDDEN WTF_HIDDEN #define HIDDEN_INLINE WTF_EXPORT_HIDDEN inline diff --git a/Source/JavaScriptCore/wtf/FastAllocBase.h b/Source/JavaScriptCore/wtf/FastAllocBase.h index b9ab0cab1..a0804ad3d 100644 --- a/Source/JavaScriptCore/wtf/FastAllocBase.h +++ b/Source/JavaScriptCore/wtf/FastAllocBase.h @@ -88,10 +88,10 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> -#include "Assertions.h" -#include "FastMalloc.h" -#include "StdLibExtras.h" -#include "TypeTraits.h" +#include <wtf/Assertions.h> +#include <wtf/FastMalloc.h> +#include <wtf/StdLibExtras.h> +#include <wtf/TypeTraits.h> #define WTF_MAKE_FAST_ALLOCATED \ public: \ diff --git a/Source/JavaScriptCore/wtf/FastMalloc.h b/Source/JavaScriptCore/wtf/FastMalloc.h index b115908ba..871be3756 100644 --- a/Source/JavaScriptCore/wtf/FastMalloc.h +++ b/Source/JavaScriptCore/wtf/FastMalloc.h @@ -21,8 +21,8 @@ #ifndef WTF_FastMalloc_h #define WTF_FastMalloc_h -#include "Platform.h" -#include "PossiblyNull.h" +#include <wtf/Platform.h> +#include <wtf/PossiblyNull.h> #include <stdlib.h> #include <new> diff --git a/Source/JavaScriptCore/wtf/Float32Array.h b/Source/JavaScriptCore/wtf/Float32Array.h index 230a768aa..55e61e006 100644 --- a/Source/JavaScriptCore/wtf/Float32Array.h +++ b/Source/JavaScriptCore/wtf/Float32Array.h @@ -27,7 +27,7 @@ #ifndef Float32Array_h #define Float32Array_h -#include "TypedArrayBase.h" +#include <wtf/TypedArrayBase.h> #include <wtf/MathExtras.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Float64Array.h b/Source/JavaScriptCore/wtf/Float64Array.h index 46713556c..30633dbec 100644 --- a/Source/JavaScriptCore/wtf/Float64Array.h +++ b/Source/JavaScriptCore/wtf/Float64Array.h @@ -27,7 +27,7 @@ #ifndef Float64Array_h #define Float64Array_h -#include "TypedArrayBase.h" +#include <wtf/TypedArrayBase.h> #include <wtf/MathExtras.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Functional.h b/Source/JavaScriptCore/wtf/Functional.h index bd0f3e282..bfc813b2a 100644 --- a/Source/JavaScriptCore/wtf/Functional.h +++ b/Source/JavaScriptCore/wtf/Functional.h @@ -26,10 +26,10 @@ #ifndef WTF_Functional_h #define WTF_Functional_h -#include "Assertions.h" -#include "PassRefPtr.h" -#include "RefPtr.h" -#include "ThreadSafeRefCounted.h" +#include <wtf/Assertions.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/ThreadSafeRefCounted.h> #if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) #include <objc/objc-runtime.h> diff --git a/Source/JavaScriptCore/wtf/HashCountedSet.h b/Source/JavaScriptCore/wtf/HashCountedSet.h index b97d8c8fd..cafb2649e 100644 --- a/Source/JavaScriptCore/wtf/HashCountedSet.h +++ b/Source/JavaScriptCore/wtf/HashCountedSet.h @@ -21,9 +21,9 @@ #ifndef WTF_HashCountedSet_h #define WTF_HashCountedSet_h -#include "Assertions.h" -#include "HashMap.h" -#include "Vector.h" +#include <wtf/Assertions.h> +#include <wtf/HashMap.h> +#include <wtf/Vector.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/HashFunctions.h b/Source/JavaScriptCore/wtf/HashFunctions.h index 2c66a2d9f..808b2b1e5 100644 --- a/Source/JavaScriptCore/wtf/HashFunctions.h +++ b/Source/JavaScriptCore/wtf/HashFunctions.h @@ -21,7 +21,7 @@ #ifndef WTF_HashFunctions_h #define WTF_HashFunctions_h -#include "RefPtr.h" +#include <wtf/RefPtr.h> #include <stdint.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/HashMap.h b/Source/JavaScriptCore/wtf/HashMap.h index 13e6d496d..be7e9ebed 100644 --- a/Source/JavaScriptCore/wtf/HashMap.h +++ b/Source/JavaScriptCore/wtf/HashMap.h @@ -21,7 +21,7 @@ #ifndef WTF_HashMap_h #define WTF_HashMap_h -#include "HashTable.h" +#include <wtf/HashTable.h> namespace WTF { @@ -486,6 +486,6 @@ namespace WTF { using WTF::HashMap; -#include "RefPtrHashMap.h" +#include <wtf/RefPtrHashMap.h> #endif /* WTF_HashMap_h */ diff --git a/Source/JavaScriptCore/wtf/HashSet.h b/Source/JavaScriptCore/wtf/HashSet.h index 7fce19348..33cb14daa 100644 --- a/Source/JavaScriptCore/wtf/HashSet.h +++ b/Source/JavaScriptCore/wtf/HashSet.h @@ -21,8 +21,8 @@ #ifndef WTF_HashSet_h #define WTF_HashSet_h -#include "FastAllocBase.h" -#include "HashTable.h" +#include <wtf/FastAllocBase.h> +#include <wtf/HashTable.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/HashTable.h b/Source/JavaScriptCore/wtf/HashTable.h index cbcc09817..05722d9c5 100644 --- a/Source/JavaScriptCore/wtf/HashTable.h +++ b/Source/JavaScriptCore/wtf/HashTable.h @@ -22,13 +22,13 @@ #ifndef WTF_HashTable_h #define WTF_HashTable_h -#include "Alignment.h" -#include "Assertions.h" -#include "FastMalloc.h" -#include "HashTraits.h" -#include "StdLibExtras.h" -#include "Threading.h" -#include "ValueCheck.h" +#include <wtf/Alignment.h> +#include <wtf/Assertions.h> +#include <wtf/FastMalloc.h> +#include <wtf/HashTraits.h> +#include <wtf/StdLibExtras.h> +#include <wtf/Threading.h> +#include <wtf/ValueCheck.h> namespace WTF { @@ -310,7 +310,8 @@ namespace WTF { ~HashTable() { invalidateIterators(); - deallocateTable(m_table, m_tableSize); + if (m_table) + deallocateTable(m_table, m_tableSize); #if CHECK_HASHTABLE_USE_AFTER_DESTRUCTION m_table = (ValueType*)(uintptr_t)0xbbadbeef; #endif @@ -979,6 +980,9 @@ namespace WTF { void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::clear() { invalidateIterators(); + if (!m_table) + return; + deallocateTable(m_table, m_tableSize); m_table = 0; m_tableSize = 0; @@ -1240,6 +1244,6 @@ namespace WTF { } // namespace WTF -#include "HashIterators.h" +#include <wtf/HashIterators.h> #endif // WTF_HashTable_h diff --git a/Source/JavaScriptCore/wtf/HashTraits.h b/Source/JavaScriptCore/wtf/HashTraits.h index e3783ed42..10f14d1af 100644 --- a/Source/JavaScriptCore/wtf/HashTraits.h +++ b/Source/JavaScriptCore/wtf/HashTraits.h @@ -21,9 +21,9 @@ #ifndef WTF_HashTraits_h #define WTF_HashTraits_h -#include "HashFunctions.h" -#include "StdLibExtras.h" -#include "TypeTraits.h" +#include <wtf/HashFunctions.h> +#include <wtf/StdLibExtras.h> +#include <wtf/TypeTraits.h> #include <utility> #include <limits> diff --git a/Source/JavaScriptCore/wtf/Int16Array.h b/Source/JavaScriptCore/wtf/Int16Array.h index 34a52de90..df3dcc265 100644 --- a/Source/JavaScriptCore/wtf/Int16Array.h +++ b/Source/JavaScriptCore/wtf/Int16Array.h @@ -26,7 +26,7 @@ #ifndef Int16Array_h #define Int16Array_h -#include "IntegralTypedArrayBase.h" +#include <wtf/IntegralTypedArrayBase.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Int32Array.h b/Source/JavaScriptCore/wtf/Int32Array.h index 0b61457b3..f3148c7bc 100644 --- a/Source/JavaScriptCore/wtf/Int32Array.h +++ b/Source/JavaScriptCore/wtf/Int32Array.h @@ -27,7 +27,7 @@ #ifndef Int32Array_h #define Int32Array_h -#include "IntegralTypedArrayBase.h" +#include <wtf/IntegralTypedArrayBase.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Int8Array.h b/Source/JavaScriptCore/wtf/Int8Array.h index 6db7b6899..cb5d343e4 100644 --- a/Source/JavaScriptCore/wtf/Int8Array.h +++ b/Source/JavaScriptCore/wtf/Int8Array.h @@ -27,7 +27,7 @@ #ifndef Int8Array_h #define Int8Array_h -#include "IntegralTypedArrayBase.h" +#include <wtf/IntegralTypedArrayBase.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h b/Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h index 48f82a361..f276400f8 100644 --- a/Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h +++ b/Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h @@ -27,7 +27,7 @@ #ifndef IntegralTypedArrayBase_h #define IntegralTypedArrayBase_h -#include "TypedArrayBase.h" +#include <wtf/TypedArrayBase.h> #include <limits> #include <wtf/MathExtras.h> diff --git a/Source/JavaScriptCore/wtf/ListHashSet.h b/Source/JavaScriptCore/wtf/ListHashSet.h index 32bd23832..799466fa9 100644 --- a/Source/JavaScriptCore/wtf/ListHashSet.h +++ b/Source/JavaScriptCore/wtf/ListHashSet.h @@ -22,9 +22,9 @@ #ifndef WTF_ListHashSet_h #define WTF_ListHashSet_h -#include "HashSet.h" -#include "OwnPtr.h" -#include "PassOwnPtr.h" +#include <wtf/HashSet.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/MainThread.h b/Source/JavaScriptCore/wtf/MainThread.h index 4839c8117..24200779a 100644 --- a/Source/JavaScriptCore/wtf/MainThread.h +++ b/Source/JavaScriptCore/wtf/MainThread.h @@ -30,7 +30,7 @@ #ifndef MainThread_h #define MainThread_h -#include "Platform.h" +#include <wtf/Platform.h> #include <stdint.h> diff --git a/Source/JavaScriptCore/wtf/MetaAllocator.cpp b/Source/JavaScriptCore/wtf/MetaAllocator.cpp index ac6cba8d1..649fbf2bc 100644 --- a/Source/JavaScriptCore/wtf/MetaAllocator.cpp +++ b/Source/JavaScriptCore/wtf/MetaAllocator.cpp @@ -64,6 +64,7 @@ MetaAllocatorHandle::MetaAllocatorHandle(MetaAllocator* allocator, void* start, ASSERT(allocator); ASSERT(start); ASSERT(sizeInBytes); + turnOffVerifier(); } MetaAllocatorHandle::~MetaAllocatorHandle() @@ -169,8 +170,6 @@ PassRefPtr<MetaAllocatorHandle> MetaAllocator::allocate(size_t sizeInBytes, void #endif MetaAllocatorHandle* handle = new MetaAllocatorHandle(this, start, sizeInBytes, ownerUID); - // FIXME: Implement a verifier scheme that groks MetaAllocatorHandles - handle->deprecatedTurnOffVerifier(); if (UNLIKELY(!!m_tracker)) m_tracker->notify(handle); diff --git a/Source/JavaScriptCore/wtf/MetaAllocator.h b/Source/JavaScriptCore/wtf/MetaAllocator.h index ffd55667e..8a73a3b03 100644 --- a/Source/JavaScriptCore/wtf/MetaAllocator.h +++ b/Source/JavaScriptCore/wtf/MetaAllocator.h @@ -29,15 +29,15 @@ #ifndef WTF_MetaAllocator_h #define WTF_MetaAllocator_h -#include "Assertions.h" -#include "HashMap.h" -#include "MetaAllocatorHandle.h" -#include "Noncopyable.h" -#include "PageBlock.h" -#include "RedBlackTree.h" -#include "RefCounted.h" -#include "RefPtr.h" -#include "TCSpinLock.h" +#include <wtf/Assertions.h> +#include <wtf/HashMap.h> +#include <wtf/MetaAllocatorHandle.h> +#include <wtf/Noncopyable.h> +#include <wtf/PageBlock.h> +#include <wtf/RedBlackTree.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/TCSpinLock.h> namespace WTF { @@ -204,6 +204,7 @@ inline MetaAllocator::~MetaAllocator() freeFreeSpaceNode(node); node = next; } + m_lock.Finalize(); #ifndef NDEBUG ASSERT(!m_mallocBalance); #endif diff --git a/Source/JavaScriptCore/wtf/Noncopyable.h b/Source/JavaScriptCore/wtf/Noncopyable.h index 9f93f173b..1e95cbb92 100644 --- a/Source/JavaScriptCore/wtf/Noncopyable.h +++ b/Source/JavaScriptCore/wtf/Noncopyable.h @@ -21,7 +21,7 @@ #ifndef WTF_Noncopyable_h #define WTF_Noncopyable_h -#include "Compiler.h" +#include <wtf/Compiler.h> #if COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS) #define WTF_MAKE_NONCOPYABLE(ClassName) \ diff --git a/Source/JavaScriptCore/wtf/OwnArrayPtr.h b/Source/JavaScriptCore/wtf/OwnArrayPtr.h index 0fc8e71b3..b3d72dfdb 100644 --- a/Source/JavaScriptCore/wtf/OwnArrayPtr.h +++ b/Source/JavaScriptCore/wtf/OwnArrayPtr.h @@ -21,10 +21,10 @@ #ifndef WTF_OwnArrayPtr_h #define WTF_OwnArrayPtr_h -#include "Assertions.h" -#include "Noncopyable.h" -#include "NullPtr.h" -#include "PassOwnArrayPtr.h" +#include <wtf/Assertions.h> +#include <wtf/Noncopyable.h> +#include <wtf/NullPtr.h> +#include <wtf/PassOwnArrayPtr.h> #include <algorithm> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/OwnPtr.h b/Source/JavaScriptCore/wtf/OwnPtr.h index 097967964..326e3fd61 100644 --- a/Source/JavaScriptCore/wtf/OwnPtr.h +++ b/Source/JavaScriptCore/wtf/OwnPtr.h @@ -21,10 +21,10 @@ #ifndef WTF_OwnPtr_h #define WTF_OwnPtr_h -#include "Assertions.h" -#include "NullPtr.h" -#include "OwnPtrCommon.h" -#include "TypeTraits.h" +#include <wtf/Assertions.h> +#include <wtf/NullPtr.h> +#include <wtf/OwnPtrCommon.h> +#include <wtf/TypeTraits.h> #include <algorithm> #include <memory> diff --git a/Source/JavaScriptCore/wtf/PackedIntVector.h b/Source/JavaScriptCore/wtf/PackedIntVector.h index 76fa48a1d..9289eb6b3 100644 --- a/Source/JavaScriptCore/wtf/PackedIntVector.h +++ b/Source/JavaScriptCore/wtf/PackedIntVector.h @@ -26,7 +26,7 @@ #ifndef PackedIntVector_h #define PackedIntVector_h -#include "BitVector.h" +#include <wtf/BitVector.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/ParallelJobs.h b/Source/JavaScriptCore/wtf/ParallelJobs.h index 92b9c5b5b..0923886ad 100644 --- a/Source/JavaScriptCore/wtf/ParallelJobs.h +++ b/Source/JavaScriptCore/wtf/ParallelJobs.h @@ -28,9 +28,9 @@ #ifndef ParallelJobs_h #define ParallelJobs_h -#include "Assertions.h" -#include "Noncopyable.h" -#include "RefPtr.h" +#include <wtf/Assertions.h> +#include <wtf/Noncopyable.h> +#include <wtf/RefPtr.h> #include <wtf/Vector.h> // Usage: @@ -50,13 +50,13 @@ // #if ENABLE(THREADING_GENERIC) -#include "ParallelJobsGeneric.h" +#include <wtf/ParallelJobsGeneric.h> #elif ENABLE(THREADING_OPENMP) -#include "ParallelJobsOpenMP.h" +#include <wtf/ParallelJobsOpenMP.h> #elif ENABLE(THREADING_LIBDISPATCH) -#include "ParallelJobsLibdispatch.h" +#include <wtf/ParallelJobsLibdispatch.h> #else #error "No parallel processing API for ParallelJobs" diff --git a/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h b/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h index 3748f18c6..1db7343de 100644 --- a/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h +++ b/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h @@ -26,9 +26,9 @@ #ifndef WTF_PassOwnArrayPtr_h #define WTF_PassOwnArrayPtr_h -#include "Assertions.h" -#include "NullPtr.h" -#include "TypeTraits.h" +#include <wtf/Assertions.h> +#include <wtf/NullPtr.h> +#include <wtf/TypeTraits.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/PassOwnPtr.h b/Source/JavaScriptCore/wtf/PassOwnPtr.h index 262ac3bfe..5ebf83d65 100644 --- a/Source/JavaScriptCore/wtf/PassOwnPtr.h +++ b/Source/JavaScriptCore/wtf/PassOwnPtr.h @@ -26,10 +26,10 @@ #ifndef WTF_PassOwnPtr_h #define WTF_PassOwnPtr_h -#include "Assertions.h" -#include "NullPtr.h" -#include "OwnPtrCommon.h" -#include "TypeTraits.h" +#include <wtf/Assertions.h> +#include <wtf/NullPtr.h> +#include <wtf/OwnPtrCommon.h> +#include <wtf/TypeTraits.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/PassRefPtr.h b/Source/JavaScriptCore/wtf/PassRefPtr.h index a13dee794..207721c96 100644 --- a/Source/JavaScriptCore/wtf/PassRefPtr.h +++ b/Source/JavaScriptCore/wtf/PassRefPtr.h @@ -21,8 +21,8 @@ #ifndef WTF_PassRefPtr_h #define WTF_PassRefPtr_h -#include "AlwaysInline.h" -#include "NullPtr.h" +#include <wtf/AlwaysInline.h> +#include <wtf/NullPtr.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/PassTraits.h b/Source/JavaScriptCore/wtf/PassTraits.h index 346273486..9564e3ad3 100644 --- a/Source/JavaScriptCore/wtf/PassTraits.h +++ b/Source/JavaScriptCore/wtf/PassTraits.h @@ -29,8 +29,8 @@ #ifndef WTF_PassTraits_h #define WTF_PassTraits_h -#include "OwnPtr.h" -#include "RefPtr.h" +#include <wtf/OwnPtr.h> +#include <wtf/RefPtr.h> // The PassTraits template exists to help optimize (or make possible) use // of WTF data structures with WTF smart pointers that have a Pass diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h index 76b11fe88..c374b03c9 100644 --- a/Source/JavaScriptCore/wtf/Platform.h +++ b/Source/JavaScriptCore/wtf/Platform.h @@ -29,7 +29,7 @@ #define WTF_Platform_h /* Include compiler specific macros */ -#include "Compiler.h" +#include <wtf/Compiler.h> /* ==== PLATFORM handles OS, operating environment, graphics API, and CPU. This macro will be phased out in favor of platform adaptation @@ -295,7 +295,7 @@ #endif /* ARM */ -#if CPU(ARM) || CPU(MIPS) || CPU(SH4) +#if CPU(ARM) || CPU(MIPS) || CPU(SH4) || CPU(SPARC) #define WTF_CPU_NEEDS_ALIGNED_ACCESS 1 #endif @@ -558,6 +558,9 @@ #if defined(ENABLE_VIDEO) #define ENABLE_VIDEO_TRACK 1 #endif +#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) +#define HAVE_LAYER_HOSTING_IN_WINDOW_SERVER 1 +#endif #endif /* PLATFORM(MAC) && !PLATFORM(IOS) */ #if PLATFORM(CHROMIUM) && OS(DARWIN) @@ -607,8 +610,9 @@ #define ENABLE_JIT 0 #define ENABLE_YARR_JIT 0 #else - #define ENABLE_CLASSIC_INTERPRETER 1 + #define ENABLE_CLASSIC_INTERPRETER 0 #define ENABLE_JIT 1 + #define ENABLE_LLINT 1 #define ENABLE_YARR_JIT 1 #endif @@ -920,7 +924,7 @@ #define ENABLE_JIT 0 #endif -/* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */ +/* The JIT is enabled by default on all x86, x86-64, ARM & MIPS platforms. */ #if !defined(ENABLE_JIT) \ && (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \ && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \ @@ -931,7 +935,7 @@ /* On some of the platforms where we have a JIT, we want to also have the low-level interpreter. */ -#if !defined(ENABLE_LLINT) && ENABLE(JIT) && OS(DARWIN) && (CPU(X86) || CPU(ARM_THUMB2)) && USE(JSVALUE32_64) +#if !defined(ENABLE_LLINT) && ENABLE(JIT) && OS(DARWIN) && (CPU(X86) || CPU(X86_64) || CPU(ARM_THUMB2)) #define ENABLE_LLINT 1 #endif @@ -1074,6 +1078,11 @@ #define WTF_USE_ACCELERATED_COMPOSITING 1 #endif +/* Compositing on the UI-process in WebKit2 */ +#if PLATFORM(QT) +#define WTF_USE_UI_SIDE_COMPOSITING 1 +#endif + #if (PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)) || PLATFORM(IOS) #define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1 #endif @@ -1098,6 +1107,10 @@ #define WTF_USE_CROSS_PLATFORM_CONTEXT_MENUS 1 #endif +#if PLATFORM(MAC) && HAVE(ACCESSIBILITY) +#define WTF_USE_ACCESSIBILITY_CONTEXT_MENUS 1 +#endif + /* Geolocation request policy. pre-emptive policy is to acquire user permission before acquiring location. Client based implementations will have option to choose between pre-emptive and nonpre-emptive permission policy. pre-emptive permission policy is enabled by default for all client-based implementations. */ @@ -1118,7 +1131,7 @@ #endif #if ENABLE(GLIB_SUPPORT) -#include "GTypedefs.h" +#include <wtf/gobject/GTypedefs.h> #endif /* FIXME: This define won't be needed once #27551 is fully landed. However, @@ -1194,4 +1207,8 @@ #define WTF_USE_WTFURL 0 #endif +#if !PLATFORM(QT) && !PLATFORM(EFL) +#define WTF_USE_ZLIB 1 +#endif + #endif /* WTF_Platform_h */ diff --git a/Source/JavaScriptCore/wtf/PossiblyNull.h b/Source/JavaScriptCore/wtf/PossiblyNull.h index 79c4d8200..46a7d713b 100644 --- a/Source/JavaScriptCore/wtf/PossiblyNull.h +++ b/Source/JavaScriptCore/wtf/PossiblyNull.h @@ -26,7 +26,7 @@ #ifndef PossiblyNull_h #define PossiblyNull_h -#include "Assertions.h" +#include <wtf/Assertions.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/RefCounted.h b/Source/JavaScriptCore/wtf/RefCounted.h index 51c5dc26e..cea1434e1 100644 --- a/Source/JavaScriptCore/wtf/RefCounted.h +++ b/Source/JavaScriptCore/wtf/RefCounted.h @@ -21,12 +21,12 @@ #ifndef RefCounted_h #define RefCounted_h -#include "Assertions.h" -#include "FastAllocBase.h" -#include "ThreadRestrictionVerifier.h" -#include "Noncopyable.h" -#include "OwnPtr.h" -#include "UnusedParam.h" +#include <wtf/Assertions.h> +#include <wtf/FastAllocBase.h> +#include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> +#include <wtf/ThreadRestrictionVerifier.h> +#include <wtf/UnusedParam.h> namespace WTF { @@ -77,8 +77,15 @@ public: // Turns off verification. Use of this method is discouraged (instead extend // ThreadRestrictionVerifier to verify your case). - // FIXME: remove this method. - void deprecatedTurnOffVerifier() + // NB. It is necessary to call this in the constructor of many objects in + // JavaScriptCore, because JavaScriptCore objects may be used from multiple + // threads even if the reference counting is done in a racy manner. This is + // because a JSC instance may be used from multiple threads so long as all + // accesses into that instance are protected by a per-instance lock. It would + // be absolutely wrong to prohibit this pattern, and it would be a disastrous + // regression to require that the objects within that instance use a thread- + // safe version of reference counting. + void turnOffVerifier() { #ifndef NDEBUG m_verifier.turnOffVerification(); diff --git a/Source/JavaScriptCore/wtf/RefCountedArray.h b/Source/JavaScriptCore/wtf/RefCountedArray.h new file mode 100644 index 000000000..2610a69b8 --- /dev/null +++ b/Source/JavaScriptCore/wtf/RefCountedArray.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RefCountedArray_h +#define RefCountedArray_h + +#include <wtf/FastMalloc.h> +#include <wtf/StdLibExtras.h> +#include <wtf/Vector.h> + +// This implements a reference counted array for POD** values, which is optimized for: +// - An empty array only uses one word. +// - A copy of the array only uses one word (i.e. assignment means aliasing). +// - The vector can't grow beyond 2^32-1 elements. +// - In all other regards this has similar space usage to a Vector. +// +// ** This could be modified to support non-POD values quite easily. It just +// hasn't been, so far, because there has been no need. Moreover, even now, +// it's used for things that aren't quite POD according to the official +// defintion, such as JSC::Instruction. + +namespace WTF { + +template<typename T> +class RefCountedArray { +public: + RefCountedArray() + : m_data(0) + { + } + + RefCountedArray(const RefCountedArray& other) + : m_data(other.m_data) + { + if (m_data) + Header::fromPayload(m_data)->refCount++; + } + + explicit RefCountedArray(const Vector<T>& other) + { + if (other.isEmpty()) { + m_data = 0; + return; + } + + m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * other.size())))->payload(); + Header::fromPayload(m_data)->refCount = 1; + Header::fromPayload(m_data)->length = other.size(); + ASSERT(Header::fromPayload(m_data)->length == other.size()); + memcpy(m_data, other.begin(), sizeof(T) * other.size()); + } + + RefCountedArray& operator=(const RefCountedArray& other) + { + T* oldData = m_data; + m_data = other.m_data; + if (m_data) + Header::fromPayload(m_data)->refCount++; + + if (!oldData) + return *this; + if (--Header::fromPayload(oldData)->refCount) + return *this; + fastFree(Header::fromPayload(oldData)); + return *this; + } + + ~RefCountedArray() + { + if (!m_data) + return; + if (--Header::fromPayload(m_data)->refCount) + return; + fastFree(Header::fromPayload(m_data)); + } + + size_t size() const + { + if (!m_data) + return 0; + return Header::fromPayload(m_data)->length; + } + + T* data() { return m_data; } + T* begin() { return m_data; } + T* end() + { + if (!m_data) + return 0; + return m_data + Header::fromPayload(m_data)->length; + } + + const T* data() const { return m_data; } + const T* begin() const { return m_data; } + const T* end() const { return const_cast<RefCountedArray*>(this)->end(); } + + T& at(size_t i) + { + ASSERT(i < size()); + return begin()[i]; + } + + const T& at(size_t i) const + { + ASSERT(i < size()); + return begin()[i]; + } + + T& operator[](size_t i) { return at(i); } + const T& operator[](size_t i) const { return at(i); } + +private: + struct Header { + unsigned refCount; + unsigned length; + + static size_t size() + { + return (sizeof(Header) + 7) & ~7; + } + + T* payload() + { + char* result = reinterpret_cast<char*>(this) + size(); + ASSERT(!(bitwise_cast<uintptr_t>(result) & 7)); + return reinterpret_cast<T*>(result); + } + + static Header* fromPayload(T* payload) + { + return reinterpret_cast_ptr<Header*>(reinterpret_cast<char*>(payload) - size()); + } + }; + + T* m_data; +}; + +} // namespace WTF + +using WTF::RefCountedArray; + +#endif // RefCountedArray_h + diff --git a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h b/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h index 476b1735a..8d894dd91 100644 --- a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h +++ b/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h @@ -21,8 +21,8 @@ #ifndef RefCountedLeakCounter_h #define RefCountedLeakCounter_h -#include "Assertions.h" -#include "Threading.h" +#include <wtf/Assertions.h> +#include <wtf/Threading.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/RefPtr.h b/Source/JavaScriptCore/wtf/RefPtr.h index ac94993e3..70ab60003 100644 --- a/Source/JavaScriptCore/wtf/RefPtr.h +++ b/Source/JavaScriptCore/wtf/RefPtr.h @@ -24,8 +24,8 @@ #define WTF_RefPtr_h #include <algorithm> -#include "FastAllocBase.h" -#include "PassRefPtr.h" +#include <wtf/FastAllocBase.h> +#include <wtf/PassRefPtr.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/RetainPtr.h b/Source/JavaScriptCore/wtf/RetainPtr.h index 3d4b0c3f9..a3489577a 100644 --- a/Source/JavaScriptCore/wtf/RetainPtr.h +++ b/Source/JavaScriptCore/wtf/RetainPtr.h @@ -21,9 +21,9 @@ #ifndef RetainPtr_h #define RetainPtr_h -#include "HashTraits.h" -#include "NullPtr.h" -#include "TypeTraits.h" +#include <wtf/HashTraits.h> +#include <wtf/NullPtr.h> +#include <wtf/TypeTraits.h> #include <algorithm> #if USE(CF) diff --git a/Source/JavaScriptCore/wtf/SimpleStats.h b/Source/JavaScriptCore/wtf/SimpleStats.h new file mode 100644 index 000000000..f1fd7e10a --- /dev/null +++ b/Source/JavaScriptCore/wtf/SimpleStats.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SimpleStats_h +#define SimpleStats_h + +#include <wtf/MathExtras.h> +#include <wtf/StdLibExtras.h> + +namespace WTF { + +// Simple and cheap way of tracking statistics if you're not worried about chopping on +// the sum of squares (i.e. the sum of squares is unlikely to exceed 2^52). +class SimpleStats { +public: + SimpleStats() + : m_count(0) + , m_sum(0) + , m_sumOfSquares(0) + { + } + + void add(double value) + { + m_count++; + m_sum += value; + m_sumOfSquares += value * value; + } + + bool operator!() const + { + return !m_count; + } + + double count() const + { + return m_count; + } + + double sum() const + { + return m_sum; + } + + double sumOfSquares() const + { + return m_sumOfSquares; + } + + double mean() const + { + return m_sum / m_count; + } + + // NB. This gives a biased variance as it divides by the number of samples rather + // than the degrees of freedom. This is fine once the count grows large, which in + // our case will happen rather quickly. + double variance() const + { + if (m_count < 2) + return 0; + + // Compute <x^2> - <x>^2 + double secondMoment = m_sumOfSquares / m_count; + double firstMoment = m_sum / m_count; + + return secondMoment - firstMoment * firstMoment; + } + + // NB. This gives a biased standard deviation. See above. + double standardDeviation() const + { + return sqrt(variance()); + } + +private: + double m_count; + double m_sum; + double m_sumOfSquares; +}; + +} // namespace WTF + +#endif // SimpleStats_h + diff --git a/Source/JavaScriptCore/wtf/Spectrum.h b/Source/JavaScriptCore/wtf/Spectrum.h index c403eda18..59bc4a29a 100644 --- a/Source/JavaScriptCore/wtf/Spectrum.h +++ b/Source/JavaScriptCore/wtf/Spectrum.h @@ -26,8 +26,8 @@ #ifndef Spectrum_h #define Spectrum_h -#include "HashMap.h" -#include "Vector.h" +#include <wtf/HashMap.h> +#include <wtf/Vector.h> #include <algorithm> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/StdLibExtras.h b/Source/JavaScriptCore/wtf/StdLibExtras.h index 2a0a9f950..0387e5b05 100644 --- a/Source/JavaScriptCore/wtf/StdLibExtras.h +++ b/Source/JavaScriptCore/wtf/StdLibExtras.h @@ -26,8 +26,8 @@ #ifndef WTF_StdLibExtras_h #define WTF_StdLibExtras_h -#include "CheckedArithmetic.h" -#include "Assertions.h" +#include <wtf/Assertions.h> +#include <wtf/CheckedArithmetic.h> // Use these to declare and define a static local variable (static T;) so that // it is leaked so that its destructors are not called at exit. Using this diff --git a/Source/JavaScriptCore/wtf/TCPageMap.h b/Source/JavaScriptCore/wtf/TCPageMap.h index 99bdc400e..92fe0b065 100644 --- a/Source/JavaScriptCore/wtf/TCPageMap.h +++ b/Source/JavaScriptCore/wtf/TCPageMap.h @@ -54,7 +54,7 @@ #endif #include <string.h> -#include "Assertions.h" +#include <wtf/Assertions.h> // Single-level array template <int BITS> diff --git a/Source/JavaScriptCore/wtf/TCSpinLock.h b/Source/JavaScriptCore/wtf/TCSpinLock.h index 81b7d0cae..7f19b6c25 100644 --- a/Source/JavaScriptCore/wtf/TCSpinLock.h +++ b/Source/JavaScriptCore/wtf/TCSpinLock.h @@ -128,6 +128,7 @@ struct TCMalloc_SpinLock { } inline void Init() { lockword_ = 0; } + inline void Finalize() { } volatile unsigned int lockword_; }; @@ -221,6 +222,7 @@ struct TCMalloc_SpinLock { } inline void Init() { m_lockword = 0; } + inline void Finalize() { } LONG m_lockword; }; diff --git a/Source/JavaScriptCore/wtf/TemporaryChange.h b/Source/JavaScriptCore/wtf/TemporaryChange.h index fe374b194..95df1728b 100644 --- a/Source/JavaScriptCore/wtf/TemporaryChange.h +++ b/Source/JavaScriptCore/wtf/TemporaryChange.h @@ -26,7 +26,7 @@ #ifndef TemporaryChange_h #define TemporaryChange_h -#include "Noncopyable.h" +#include <wtf/Noncopyable.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h b/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h index 8497b3bc2..44035e547 100644 --- a/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h +++ b/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h @@ -59,7 +59,7 @@ #ifndef ThreadSafeRefCounted_h #define ThreadSafeRefCounted_h -#include "Platform.h" +#include <wtf/Platform.h> #include <wtf/Atomics.h> #include <wtf/DynamicAnnotations.h> diff --git a/Source/JavaScriptCore/wtf/Threading.h b/Source/JavaScriptCore/wtf/Threading.h index b5d432681..3e558fc68 100644 --- a/Source/JavaScriptCore/wtf/Threading.h +++ b/Source/JavaScriptCore/wtf/Threading.h @@ -59,7 +59,7 @@ #ifndef Threading_h #define Threading_h -#include "Platform.h" +#include <wtf/Platform.h> #include <stdint.h> #include <wtf/Assertions.h> diff --git a/Source/JavaScriptCore/wtf/ThreadingPrimitives.h b/Source/JavaScriptCore/wtf/ThreadingPrimitives.h index 2ac42c8f1..9ed38bc9f 100644 --- a/Source/JavaScriptCore/wtf/ThreadingPrimitives.h +++ b/Source/JavaScriptCore/wtf/ThreadingPrimitives.h @@ -31,7 +31,7 @@ #ifndef ThreadingPrimitives_h #define ThreadingPrimitives_h -#include "Platform.h" +#include <wtf/Platform.h> #include <wtf/Assertions.h> #include <wtf/FastAllocBase.h> diff --git a/Source/JavaScriptCore/wtf/TypeTraits.h b/Source/JavaScriptCore/wtf/TypeTraits.h index 34e8b79a3..bfed2aa7b 100644 --- a/Source/JavaScriptCore/wtf/TypeTraits.h +++ b/Source/JavaScriptCore/wtf/TypeTraits.h @@ -22,7 +22,7 @@ #ifndef TypeTraits_h #define TypeTraits_h -#include "Platform.h" +#include <wtf/Platform.h> #if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) #include <type_traits> diff --git a/Source/JavaScriptCore/wtf/TypedArrayBase.h b/Source/JavaScriptCore/wtf/TypedArrayBase.h index dba95d55f..7f989198a 100644 --- a/Source/JavaScriptCore/wtf/TypedArrayBase.h +++ b/Source/JavaScriptCore/wtf/TypedArrayBase.h @@ -27,8 +27,8 @@ #ifndef TypedArrayBase_h #define TypedArrayBase_h -#include "ArrayBuffer.h" -#include "ArrayBufferView.h" +#include <wtf/ArrayBuffer.h> +#include <wtf/ArrayBufferView.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Uint16Array.h b/Source/JavaScriptCore/wtf/Uint16Array.h index 2d0765051..e73c8ddff 100644 --- a/Source/JavaScriptCore/wtf/Uint16Array.h +++ b/Source/JavaScriptCore/wtf/Uint16Array.h @@ -27,7 +27,7 @@ #ifndef Uint16Array_h #define Uint16Array_h -#include "IntegralTypedArrayBase.h" +#include <wtf/IntegralTypedArrayBase.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Uint32Array.h b/Source/JavaScriptCore/wtf/Uint32Array.h index 3765f8077..b2a391267 100644 --- a/Source/JavaScriptCore/wtf/Uint32Array.h +++ b/Source/JavaScriptCore/wtf/Uint32Array.h @@ -27,7 +27,7 @@ #ifndef Uint32Array_h #define Uint32Array_h -#include "IntegralTypedArrayBase.h" +#include <wtf/IntegralTypedArrayBase.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Uint8Array.h b/Source/JavaScriptCore/wtf/Uint8Array.h index a0959706c..f46ef0fc0 100644 --- a/Source/JavaScriptCore/wtf/Uint8Array.h +++ b/Source/JavaScriptCore/wtf/Uint8Array.h @@ -27,7 +27,7 @@ #ifndef Uint8Array_h #define Uint8Array_h -#include "IntegralTypedArrayBase.h" +#include <wtf/IntegralTypedArrayBase.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/Uint8ClampedArray.h b/Source/JavaScriptCore/wtf/Uint8ClampedArray.h index f1044091b..2b77dacc3 100644 --- a/Source/JavaScriptCore/wtf/Uint8ClampedArray.h +++ b/Source/JavaScriptCore/wtf/Uint8ClampedArray.h @@ -28,7 +28,7 @@ #ifndef Uint8ClampedArray_h #define Uint8ClampedArray_h -#include "Uint8Array.h" +#include <wtf/Uint8Array.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/UnusedParam.h b/Source/JavaScriptCore/wtf/UnusedParam.h index 6ff6fd895..4b7234b8d 100644 --- a/Source/JavaScriptCore/wtf/UnusedParam.h +++ b/Source/JavaScriptCore/wtf/UnusedParam.h @@ -24,7 +24,7 @@ /* don't use this for C++, it should only be used in plain C files or ObjC methods, where leaving off the parameter name is not allowed. */ -#include "Platform.h" +#include <wtf/Platform.h> #if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) template<typename T> diff --git a/Source/JavaScriptCore/wtf/Vector.h b/Source/JavaScriptCore/wtf/Vector.h index 29bbd37d9..19e6ffb8c 100644 --- a/Source/JavaScriptCore/wtf/Vector.h +++ b/Source/JavaScriptCore/wtf/Vector.h @@ -21,13 +21,13 @@ #ifndef WTF_Vector_h #define WTF_Vector_h -#include "Alignment.h" -#include "FastAllocBase.h" -#include "Noncopyable.h" -#include "NotFound.h" -#include "StdLibExtras.h" -#include "ValueCheck.h" -#include "VectorTraits.h" +#include <wtf/Alignment.h> +#include <wtf/FastAllocBase.h> +#include <wtf/Noncopyable.h> +#include <wtf/NotFound.h> +#include <wtf/StdLibExtras.h> +#include <wtf/ValueCheck.h> +#include <wtf/VectorTraits.h> #include <limits> #include <utility> @@ -281,10 +281,14 @@ namespace WTF { void deallocateBuffer(T* bufferToDeallocate) { + if (!bufferToDeallocate) + return; + if (m_buffer == bufferToDeallocate) { m_buffer = 0; m_capacity = 0; } + fastFree(bufferToDeallocate); } diff --git a/Source/JavaScriptCore/wtf/VectorTraits.h b/Source/JavaScriptCore/wtf/VectorTraits.h index 6777c9ebf..4041217ab 100644 --- a/Source/JavaScriptCore/wtf/VectorTraits.h +++ b/Source/JavaScriptCore/wtf/VectorTraits.h @@ -21,9 +21,9 @@ #ifndef WTF_VectorTraits_h #define WTF_VectorTraits_h -#include "OwnPtr.h" -#include "RefPtr.h" -#include "TypeTraits.h" +#include <wtf/OwnPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/TypeTraits.h> #include <utility> #include <memory> diff --git a/Source/JavaScriptCore/wtf/WTFThreadData.cpp b/Source/JavaScriptCore/wtf/WTFThreadData.cpp index 241fbe449..ec5de7220 100644 --- a/Source/JavaScriptCore/wtf/WTFThreadData.cpp +++ b/Source/JavaScriptCore/wtf/WTFThreadData.cpp @@ -51,4 +51,25 @@ WTFThreadData::~WTFThreadData() #endif } +} // namespace WTF + +#if USE(JSC) +namespace JSC { + +IdentifierTable::~IdentifierTable() +{ + HashSet<StringImpl*>::iterator end = m_table.end(); + for (HashSet<StringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter) + (*iter)->setIsIdentifier(false); +} + +std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(StringImpl* value) +{ + std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add(value); + (*result.first)->setIsIdentifier(true); + return result; } + +} // namespace JSC +#endif + diff --git a/Source/JavaScriptCore/wtf/dtoa/double-conversion.h b/Source/JavaScriptCore/wtf/dtoa/double-conversion.h index 4d6fc2f57..eec956a21 100644 --- a/Source/JavaScriptCore/wtf/dtoa/double-conversion.h +++ b/Source/JavaScriptCore/wtf/dtoa/double-conversion.h @@ -28,7 +28,7 @@ #ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ #define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ -#include "utils.h" +#include <wtf/dtoa/utils.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/dtoa/utils.h b/Source/JavaScriptCore/wtf/dtoa/utils.h index 64e5ad42f..da6e13226 100644 --- a/Source/JavaScriptCore/wtf/dtoa/utils.h +++ b/Source/JavaScriptCore/wtf/dtoa/utils.h @@ -28,7 +28,7 @@ #ifndef DOUBLE_CONVERSION_UTILS_H_ #define DOUBLE_CONVERSION_UTILS_H_ -#include "Assertions.h" +#include <wtf/Assertions.h> #include <stdlib.h> #include <string.h> diff --git a/Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp b/Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp index 1cd22c532..30df2c9a6 100644 --- a/Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp +++ b/Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp @@ -37,6 +37,32 @@ template <> void derefGPtr(GHashTable* ptr) g_hash_table_unref(ptr); } +template <> GMainContext* refGPtr(GMainContext* ptr) +{ + if (ptr) + g_main_context_ref(ptr); + return ptr; +} + +template <> void derefGPtr(GMainContext* ptr) +{ + if (ptr) + g_main_context_unref(ptr); +} + +template <> GMainLoop* refGPtr(GMainLoop* ptr) +{ + if (ptr) + g_main_loop_ref(ptr); + return ptr; +} + +template <> void derefGPtr(GMainLoop* ptr) +{ + if (ptr) + g_main_loop_unref(ptr); +} + #if GLIB_CHECK_VERSION(2, 24, 0) template <> GVariant* refGPtr(GVariant* ptr) { diff --git a/Source/JavaScriptCore/wtf/gobject/GRefPtr.h b/Source/JavaScriptCore/wtf/gobject/GRefPtr.h index 10ebf0753..92acffc0c 100644 --- a/Source/JavaScriptCore/wtf/gobject/GRefPtr.h +++ b/Source/JavaScriptCore/wtf/gobject/GRefPtr.h @@ -25,9 +25,8 @@ #if ENABLE(GLIB_SUPPORT) -#include "AlwaysInline.h" -#include "GRefPtr.h" -#include "RefPtr.h" +#include <wtf/AlwaysInline.h> +#include <wtf/RefPtr.h> #include <algorithm> extern "C" void g_object_unref(gpointer); @@ -201,6 +200,10 @@ template <typename T> GRefPtr<T> adoptGRef(T* p) template <> GHashTable* refGPtr(GHashTable* ptr); template <> void derefGPtr(GHashTable* ptr); +template <> GMainContext* refGPtr(GMainContext* ptr); +template <> void derefGPtr(GMainContext* ptr); +template <> GMainLoop* refGPtr(GMainLoop* ptr); +template <> void derefGPtr(GMainLoop* ptr); template <> GVariant* refGPtr(GVariant* ptr); template <> void derefGPtr(GVariant* ptr); template <> GSource* refGPtr(GSource* ptr); diff --git a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h b/Source/JavaScriptCore/wtf/gobject/GTypedefs.h index cb3842b78..e29250bef 100644 --- a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h +++ b/Source/JavaScriptCore/wtf/gobject/GTypedefs.h @@ -51,6 +51,8 @@ typedef struct _GFile GFile; typedef struct _GHashTable GHashTable; typedef struct _GInputStream GInputStream; typedef struct _GList GList; +typedef struct _GMainContext GMainContext; +typedef struct _GMainLoop GMainLoop; typedef struct _GPatternSpec GPatternSpec; typedef struct _GPollableOutputStream GPollableOutputStream; typedef struct _GSList GSList; diff --git a/Source/JavaScriptCore/wtf/gobject/GlibUtilities.h b/Source/JavaScriptCore/wtf/gobject/GlibUtilities.h index 5577bf58e..ce10a05c8 100644 --- a/Source/JavaScriptCore/wtf/gobject/GlibUtilities.h +++ b/Source/JavaScriptCore/wtf/gobject/GlibUtilities.h @@ -20,8 +20,8 @@ #ifndef GlibUtilities_h #define GlibUtilities_h -#include "Assertions.h" -#include "CString.h" +#include <wtf/Assertions.h> +#include <wtf/text/CString.h> CString getCurrentExecutablePath(); diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.h b/Source/JavaScriptCore/wtf/text/AtomicString.h index b135845fe..e7323f94a 100644 --- a/Source/JavaScriptCore/wtf/text/AtomicString.h +++ b/Source/JavaScriptCore/wtf/text/AtomicString.h @@ -21,8 +21,8 @@ #ifndef AtomicString_h #define AtomicString_h -#include "AtomicStringImpl.h" -#include "WTFString.h" +#include <wtf/text/AtomicStringImpl.h> +#include <wtf/text/WTFString.h> // Define 'NO_IMPLICIT_ATOMICSTRING' before including this header, // to disallow (expensive) implicit String-->AtomicString conversions. @@ -213,5 +213,5 @@ using WTF::xmlAtom; using WTF::xmlnsAtom; #endif -#include "StringConcatenate.h" +#include <wtf/text/StringConcatenate.h> #endif // AtomicString_h diff --git a/Source/JavaScriptCore/wtf/text/AtomicStringImpl.h b/Source/JavaScriptCore/wtf/text/AtomicStringImpl.h index 3f0c37606..0716275a8 100644 --- a/Source/JavaScriptCore/wtf/text/AtomicStringImpl.h +++ b/Source/JavaScriptCore/wtf/text/AtomicStringImpl.h @@ -21,7 +21,7 @@ #ifndef AtomicStringImpl_h #define AtomicStringImpl_h -#include "StringImpl.h" +#include <wtf/text/StringImpl.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/text/CString.h b/Source/JavaScriptCore/wtf/text/CString.h index d43ad4bd7..9abfa70f7 100644 --- a/Source/JavaScriptCore/wtf/text/CString.h +++ b/Source/JavaScriptCore/wtf/text/CString.h @@ -26,9 +26,9 @@ #ifndef CString_h #define CString_h -#include "PassRefPtr.h" -#include "RefCounted.h" -#include "Vector.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/text/StringConcatenate.h b/Source/JavaScriptCore/wtf/text/StringConcatenate.h index 08d67dcf0..479ed8ca2 100644 --- a/Source/JavaScriptCore/wtf/text/StringConcatenate.h +++ b/Source/JavaScriptCore/wtf/text/StringConcatenate.h @@ -27,7 +27,7 @@ #define StringConcatenate_h #ifndef WTFString_h -#include "AtomicString.h" +#include <wtf/text/AtomicString.h> #endif // This macro is helpful for testing how many intermediate Strings are created while evaluating an @@ -960,5 +960,5 @@ String makeString(StringType1 string1, StringType2 string2, StringType3 string3, using WTF::makeString; -#include "StringOperators.h" +#include <wtf/text/StringOperators.h> #endif diff --git a/Source/JavaScriptCore/wtf/text/StringHash.h b/Source/JavaScriptCore/wtf/text/StringHash.h index 1b7a2ee2c..acc97b995 100644 --- a/Source/JavaScriptCore/wtf/text/StringHash.h +++ b/Source/JavaScriptCore/wtf/text/StringHash.h @@ -22,8 +22,8 @@ #ifndef StringHash_h #define StringHash_h -#include "AtomicString.h" -#include "WTFString.h" +#include <wtf/text/AtomicString.h> +#include <wtf/text/WTFString.h> #include <wtf/Forward.h> #include <wtf/HashTraits.h> #include <wtf/StringHasher.h> diff --git a/Source/JavaScriptCore/wtf/text/WTFString.h b/Source/JavaScriptCore/wtf/text/WTFString.h index edc842154..85e223f9e 100644 --- a/Source/JavaScriptCore/wtf/text/WTFString.h +++ b/Source/JavaScriptCore/wtf/text/WTFString.h @@ -25,8 +25,8 @@ // This file would be called String.h, but that conflicts with <string.h> // on systems without case-sensitive file systems. -#include "ASCIIFastPath.h" -#include "StringImpl.h" +#include <wtf/text/ASCIIFastPath.h> +#include <wtf/text/StringImpl.h> #ifdef __OBJC__ #include <objc/objc.h> @@ -646,5 +646,5 @@ using WTF::isSpaceOrNewline; using WTF::reverseFind; using WTF::ShouldRoundDecimalPlaces; -#include "AtomicString.h" +#include <wtf/text/AtomicString.h> #endif diff --git a/Source/JavaScriptCore/wtf/unicode/CharacterNames.h b/Source/JavaScriptCore/wtf/unicode/CharacterNames.h index 4acb5f0b1..78b7bf7b9 100644 --- a/Source/JavaScriptCore/wtf/unicode/CharacterNames.h +++ b/Source/JavaScriptCore/wtf/unicode/CharacterNames.h @@ -26,7 +26,7 @@ #ifndef CharacterNames_h #define CharacterNames_h -#include "Unicode.h" +#include <wtf/unicode/Unicode.h> namespace WTF { namespace Unicode { diff --git a/Source/JavaScriptCore/wtf/unicode/UTF8.h b/Source/JavaScriptCore/wtf/unicode/UTF8.h index bc2497b72..59f6994be 100644 --- a/Source/JavaScriptCore/wtf/unicode/UTF8.h +++ b/Source/JavaScriptCore/wtf/unicode/UTF8.h @@ -26,7 +26,7 @@ #ifndef WTF_UTF8_h #define WTF_UTF8_h -#include "Unicode.h" +#include <wtf/unicode/Unicode.h> namespace WTF { namespace Unicode { diff --git a/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h b/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h index 7bff934ba..8ad532917 100644 --- a/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h +++ b/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h @@ -25,9 +25,9 @@ #ifndef UnicodeGLib_h #define UnicodeGLib_h -#include "GOwnPtr.h" -#include "ScriptCodesFromICU.h" -#include "UnicodeMacrosFromICU.h" +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/unicode/ScriptCodesFromICU.h> +#include <wtf/unicode/UnicodeMacrosFromICU.h> #include <glib.h> #include <pango/pango.h> diff --git a/Source/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/Source/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index e4f39b292..a2d1ad4c1 100644 --- a/Source/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/Source/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -23,8 +23,8 @@ #ifndef WTF_UNICODE_QT4_H #define WTF_UNICODE_QT4_H -#include "ScriptCodesFromICU.h" -#include "UnicodeMacrosFromICU.h" +#include <wtf/unicode/ScriptCodesFromICU.h> +#include <wtf/unicode/UnicodeMacrosFromICU.h> #include <QChar> #include <QString> diff --git a/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h b/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h index af6ff0748..1663fc969 100644 --- a/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h +++ b/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h @@ -24,8 +24,8 @@ #ifndef WTF_UnicodeWinCE_h #define WTF_UnicodeWinCE_h -#include "ScriptCodesFromICU.h" -#include "UnicodeMacrosFromICU.h" +#include <wtf/unicode/ScriptCodesFromICU.h> +#include <wtf/unicode/UnicodeMacrosFromICU.h> #include "ce_unicode.h" diff --git a/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp b/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp index 3c1519136..f69162a67 100644 --- a/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp +++ b/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp @@ -33,13 +33,21 @@ namespace WTF { -ParsedURL::ParsedURL(const URLString& spec) - : m_spec(spec) +ParsedURL::ParsedURL(const String& urlString) + : m_spec(urlString) { // FIXME: Handle non-standard URLs. - if (spec.string().isEmpty()) + if (urlString.isEmpty()) return; - URLParser<UChar>::parseStandardURL(spec.string().characters(), spec.string().length(), m_segments); + URLParser<UChar>::parseStandardURL(urlString.characters(), urlString.length(), m_segments); +} + +ParsedURL ParsedURL::isolatedCopy() const +{ + ParsedURL copy; + copy.m_segments = this->m_segments; + copy.m_spec = URLString(this->m_spec.string().isolatedCopy()); + return copy; } String ParsedURL::scheme() const @@ -82,11 +90,22 @@ String ParsedURL::fragment() const return segment(m_segments.fragment); } +String ParsedURL::baseAsString() const +{ + // FIXME: Add WTFURL Implementation. + return String(); +} + String ParsedURL::segment(const URLComponent& component) const { + ASSERT(isValid()); + if (!component.isValid()) return String(); - return m_spec.string().substring(component.begin(), component.length()); + + String segment = m_spec.string().substring(component.begin(), component.length()); + ASSERT_WITH_MESSAGE(!segment.isEmpty(), "A valid URL component should not be empty."); + return segment; } } diff --git a/Source/JavaScriptCore/wtf/url/api/ParsedURL.h b/Source/JavaScriptCore/wtf/url/api/ParsedURL.h index 023589564..2bb3330cf 100644 --- a/Source/JavaScriptCore/wtf/url/api/ParsedURL.h +++ b/Source/JavaScriptCore/wtf/url/api/ParsedURL.h @@ -28,27 +28,35 @@ #if USE(WTFURL) -#include "URLSegments.h" -#include "URLString.h" +#include <wtf/url/api/URLString.h> +#include <wtf/url/src/URLSegments.h> namespace WTF { class URLComponent; +// ParsedURL represents a valid URL decomposed by components. class ParsedURL { public: - explicit ParsedURL(const URLString&); - // FIXME: Add a method for parsing non-canonicalized URLs. + ParsedURL() { }; + WTF_EXPORT_PRIVATE explicit ParsedURL(const String&); + + WTF_EXPORT_PRIVATE ParsedURL isolatedCopy() const; + + bool isValid() const { return !m_spec.string().isEmpty(); } + + // Return a URL component or a null String if the component is undefined for the URL. + WTF_EXPORT_PRIVATE String scheme() const; + WTF_EXPORT_PRIVATE String username() const; + WTF_EXPORT_PRIVATE String password() const; + WTF_EXPORT_PRIVATE String host() const; + WTF_EXPORT_PRIVATE String port() const; + WTF_EXPORT_PRIVATE String path() const; + WTF_EXPORT_PRIVATE String query() const; + WTF_EXPORT_PRIVATE String fragment() const; - String scheme() const; - String username() const; - String password() const; - String host() const; - String port() const; - String path() const; - String query() const; - String fragment() const; + WTF_EXPORT_PRIVATE String baseAsString() const; URLString spec() { return m_spec; } diff --git a/Source/JavaScriptCore/wtf/url/api/URLString.h b/Source/JavaScriptCore/wtf/url/api/URLString.h index 329f51e2f..9ae30d7a9 100644 --- a/Source/JavaScriptCore/wtf/url/api/URLString.h +++ b/Source/JavaScriptCore/wtf/url/api/URLString.h @@ -28,7 +28,7 @@ #if USE(WTFURL) -#include "WTFString.h" +#include <wtf/text/WTFString.h> namespace WTF { diff --git a/Source/JavaScriptCore/wtf/wince/FastMallocWinCE.h b/Source/JavaScriptCore/wtf/wince/FastMallocWinCE.h index d91a5f2c9..3601249cf 100644 --- a/Source/JavaScriptCore/wtf/wince/FastMallocWinCE.h +++ b/Source/JavaScriptCore/wtf/wince/FastMallocWinCE.h @@ -26,7 +26,7 @@ #ifdef __cplusplus #include <new> -#include "MemoryManager.h" +#include <wtf/wince/MemoryManager.h> extern "C" { #endif diff --git a/Source/JavaScriptCore/yarr/Yarr.h b/Source/JavaScriptCore/yarr/Yarr.h index 3495fc7e4..57a3846c0 100644 --- a/Source/JavaScriptCore/yarr/Yarr.h +++ b/Source/JavaScriptCore/yarr/Yarr.h @@ -43,6 +43,7 @@ namespace JSC { namespace Yarr { #define YarrStackSpaceForBackTrackInfoParentheses 2 static const unsigned quantifyInfinite = UINT_MAX; +static const unsigned offsetNoMatch = (unsigned)-1; // The below limit restricts the number of "recursive" match calls in order to // avoid spending exponential time on complex regular expressions. @@ -63,7 +64,7 @@ enum YarrCharSize { }; JS_EXPORT_PRIVATE PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*); -JS_EXPORT_PRIVATE int interpret(BytecodePattern*, const UString& input, unsigned start, unsigned length, int* output); +JS_EXPORT_PRIVATE unsigned interpret(BytecodePattern*, const UString& input, unsigned start, unsigned length, unsigned* output); } } // namespace JSC::Yarr diff --git a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp index 4472538e9..743f16048 100644 --- a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp @@ -121,7 +121,7 @@ public: struct ParenthesesDisjunctionContext { - ParenthesesDisjunctionContext(int* output, ByteTerm& term) + ParenthesesDisjunctionContext(unsigned* output, ByteTerm& term) : next(0) { unsigned firstSubpatternId = term.atom.subpatternId; @@ -129,7 +129,7 @@ public: for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i) { subpatternBackup[i] = output[(firstSubpatternId << 1) + i]; - output[(firstSubpatternId << 1) + i] = -1; + output[(firstSubpatternId << 1) + i] = offsetNoMatch; } new (getDisjunctionContext(term)) DisjunctionContext(); @@ -140,7 +140,7 @@ public: return where; } - void restoreOutput(int* output, unsigned firstSubpatternId, unsigned numNestedSubpatterns) + void restoreOutput(unsigned* output, unsigned firstSubpatternId, unsigned numNestedSubpatterns) { for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i) output[(firstSubpatternId << 1) + i] = subpatternBackup[i]; @@ -152,12 +152,12 @@ public: } ParenthesesDisjunctionContext* next; - int subpatternBackup[1]; + unsigned subpatternBackup[1]; }; - ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, int* output, ByteTerm& term) + ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, unsigned* output, ByteTerm& term) { - size_t size = sizeof(ParenthesesDisjunctionContext) - sizeof(int) + (term.atom.parenthesesDisjunction->m_numSubpatterns << 1) * sizeof(int) + sizeof(DisjunctionContext) - sizeof(uintptr_t) + disjunction->m_frameSize * sizeof(uintptr_t); + size_t size = sizeof(ParenthesesDisjunctionContext) - sizeof(unsigned) + (term.atom.parenthesesDisjunction->m_numSubpatterns << 1) * sizeof(unsigned) + sizeof(DisjunctionContext) - sizeof(uintptr_t) + disjunction->m_frameSize * sizeof(uintptr_t); allocatorPool = allocatorPool->ensureCapacity(size); if (!allocatorPool) CRASH(); @@ -249,11 +249,11 @@ public: return input[pos] | input[pos + 1] << 16; } - int readChecked(int position) + int readChecked(unsigned negativePositionOffest) { - ASSERT(position < 0); - ASSERT(static_cast<unsigned>(-position) <= pos); - unsigned p = pos + position; + if (pos < negativePositionOffest) + CRASH(); + unsigned p = pos - negativePositionOffest; ASSERT(p < length); return input[p]; } @@ -297,33 +297,37 @@ public: return length; } - bool checkInput(int count) + bool checkInput(unsigned count) { - if ((pos + count) <= length) { + if (((pos + count) <= length) && ((pos + count) >= pos)) { pos += count; return true; } return false; } - void uncheckInput(int count) + void uncheckInput(unsigned count) { + if (pos < count) + CRASH(); pos -= count; } - bool atStart(int position) + bool atStart(unsigned negativePositionOffest) { - return (pos + position) == 0; + return pos == negativePositionOffest; } - bool atEnd(int position) + bool atEnd(unsigned negativePositionOffest) { - return (pos + position) == length; + if (pos < negativePositionOffest) + CRASH(); + return (pos - negativePositionOffest) == length; } - bool isNotAvailableInput(int position) + bool isAvailableInput(unsigned offset) { - return (pos + position) > length; + return (((pos + offset) <= length) && ((pos + offset) >= pos)); } private: @@ -353,45 +357,45 @@ public: return false; } - bool checkCharacter(int testChar, int inputPosition) + bool checkCharacter(int testChar, unsigned negativeInputOffset) { - return testChar == input.readChecked(inputPosition); + return testChar == input.readChecked(negativeInputOffset); } - bool checkCasedCharacter(int loChar, int hiChar, int inputPosition) + bool checkCasedCharacter(int loChar, int hiChar, unsigned negativeInputOffset) { - int ch = input.readChecked(inputPosition); + int ch = input.readChecked(negativeInputOffset); return (loChar == ch) || (hiChar == ch); } - bool checkCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition) + bool checkCharacterClass(CharacterClass* characterClass, bool invert, unsigned negativeInputOffset) { - bool match = testCharacterClass(characterClass, input.readChecked(inputPosition)); + bool match = testCharacterClass(characterClass, input.readChecked(negativeInputOffset)); return invert ? !match : match; } - bool tryConsumeBackReference(int matchBegin, int matchEnd, int inputOffset) + bool tryConsumeBackReference(int matchBegin, int matchEnd, unsigned negativeInputOffset) { - int matchSize = matchEnd - matchBegin; + unsigned matchSize = (unsigned)(matchEnd - matchBegin); if (!input.checkInput(matchSize)) return false; if (pattern->m_ignoreCase) { - for (int i = 0; i < matchSize; ++i) { + for (unsigned i = 0; i < matchSize; ++i) { int ch = input.reread(matchBegin + i); int lo = Unicode::toLower(ch); int hi = Unicode::toUpper(ch); - if ((lo != hi) ? (!checkCasedCharacter(lo, hi, inputOffset - matchSize + i)) : (!checkCharacter(ch, inputOffset - matchSize + i))) { + if ((lo != hi) ? (!checkCasedCharacter(lo, hi, negativeInputOffset + matchSize - i)) : (!checkCharacter(ch, negativeInputOffset + matchSize - i))) { input.uncheckInput(matchSize); return false; } } } else { - for (int i = 0; i < matchSize; ++i) { - if (!checkCharacter(input.reread(matchBegin + i), inputOffset - matchSize + i)) { + for (unsigned i = 0; i < matchSize; ++i) { + if (!checkCharacter(input.reread(matchBegin + i), negativeInputOffset + matchSize - i)) { input.uncheckInput(matchSize); return false; } @@ -403,7 +407,7 @@ public: bool matchAssertionBOL(ByteTerm& term) { - return (input.atStart(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition - 1))); + return (input.atStart(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition + 1))); } bool matchAssertionEOL(ByteTerm& term) @@ -416,7 +420,7 @@ public: bool matchAssertionWordBoundary(ByteTerm& term) { - bool prevIsWordchar = !input.atStart(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition - 1)); + bool prevIsWordchar = !input.atStart(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition + 1)); bool readIsWordchar; if (term.inputPosition) readIsWordchar = !input.atEnd(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition)); @@ -446,7 +450,7 @@ public: case QuantifierNonGreedy: if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) { ++backTrack->matchAmount; - if (checkCharacter(term.atom.patternCharacter, term.inputPosition - 1)) + if (checkCharacter(term.atom.patternCharacter, term.inputPosition + 1)) return true; } input.uncheckInput(backTrack->matchAmount); @@ -475,7 +479,7 @@ public: case QuantifierNonGreedy: if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) { ++backTrack->matchAmount; - if (checkCasedCharacter(term.atom.casedCharacter.lo, term.atom.casedCharacter.hi, term.inputPosition - 1)) + if (checkCasedCharacter(term.atom.casedCharacter.lo, term.atom.casedCharacter.hi, term.inputPosition + 1)) return true; } input.uncheckInput(backTrack->matchAmount); @@ -493,7 +497,7 @@ public: switch (term.atom.quantityType) { case QuantifierFixedCount: { for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) { - if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + matchAmount)) + if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - matchAmount)) return false; } return true; @@ -502,7 +506,7 @@ public: case QuantifierGreedy: { unsigned matchAmount = 0; while ((matchAmount < term.atom.quantityCount) && input.checkInput(1)) { - if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1)) { + if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + 1)) { input.uncheckInput(1); break; } @@ -542,7 +546,7 @@ public: case QuantifierNonGreedy: if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) { ++backTrack->matchAmount; - if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1)) + if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + 1)) return true; } input.uncheckInput(backTrack->matchAmount); @@ -557,16 +561,16 @@ public: ASSERT(term.type == ByteTerm::TypeBackReference); BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation); - int matchBegin = output[(term.atom.subpatternId << 1)]; - int matchEnd = output[(term.atom.subpatternId << 1) + 1]; + unsigned matchBegin = output[(term.atom.subpatternId << 1)]; + unsigned matchEnd = output[(term.atom.subpatternId << 1) + 1]; // If the end position of the referenced match hasn't set yet then the backreference in the same parentheses where it references to that. // In this case the result of match is empty string like when it references to a parentheses with zero-width match. // Eg.: /(a\1)/ - if (matchEnd == -1) + if (matchEnd == offsetNoMatch) return true; - if (matchBegin == -1) + if (matchBegin == offsetNoMatch) return true; ASSERT(matchBegin <= matchEnd); @@ -609,10 +613,10 @@ public: ASSERT(term.type == ByteTerm::TypeBackReference); BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation); - int matchBegin = output[(term.atom.subpatternId << 1)]; - int matchEnd = output[(term.atom.subpatternId << 1) + 1]; + unsigned matchBegin = output[(term.atom.subpatternId << 1)]; + unsigned matchEnd = output[(term.atom.subpatternId << 1) + 1]; - if (matchBegin == -1) + if (matchBegin == offsetNoMatch) return false; ASSERT(matchBegin <= matchEnd); @@ -704,7 +708,7 @@ public: if (term.capture()) { unsigned subpatternId = term.atom.subpatternId; - output[(subpatternId << 1)] = input.getPos() + term.inputPosition; + output[(subpatternId << 1)] = input.getPos() - term.inputPosition; } return true; @@ -736,8 +740,8 @@ public: if (term.capture()) { unsigned subpatternId = term.atom.subpatternId; - output[(subpatternId << 1)] = -1; - output[(subpatternId << 1) + 1] = -1; + output[(subpatternId << 1)] = offsetNoMatch; + output[(subpatternId << 1) + 1] = offsetNoMatch; } switch (term.atom.quantityType) { @@ -1194,7 +1198,7 @@ public: case ByteTerm::TypePatternCharacterOnce: case ByteTerm::TypePatternCharacterFixed: { for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) { - if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + matchAmount)) + if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition - matchAmount)) BACKTRACK(); } MATCH_NEXT(); @@ -1203,7 +1207,7 @@ public: BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation); unsigned matchAmount = 0; while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) { - if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition - 1)) { + if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + 1)) { input.uncheckInput(1); break; } @@ -1222,7 +1226,7 @@ public: case ByteTerm::TypePatternCasedCharacterOnce: case ByteTerm::TypePatternCasedCharacterFixed: { for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) { - if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition + matchAmount)) + if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - matchAmount)) BACKTRACK(); } MATCH_NEXT(); @@ -1231,7 +1235,7 @@ public: BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation); unsigned matchAmount = 0; while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) { - if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - 1)) { + if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition + 1)) { input.uncheckInput(1); break; } @@ -1449,13 +1453,13 @@ public: return result; } - int interpret() + unsigned interpret() { - if (input.isNotAvailableInput(0)) - return -1; + if (!input.isAvailableInput(0)) + return offsetNoMatch; for (unsigned i = 0; i < pattern->m_body->m_numSubpatterns + 1; ++i) - output[i << 1] = -1; + output[i << 1] = offsetNoMatch; allocatorPool = pattern->m_allocator->startAllocator(); if (!allocatorPool) @@ -1473,11 +1477,11 @@ public: pattern->m_allocator->stopAllocator(); - ASSERT((result == JSRegExpMatch) == (output[0] != -1)); + ASSERT((result == JSRegExpMatch) == (output[0] != offsetNoMatch)); return output[0]; } - Interpreter(BytecodePattern* pattern, int* output, const UString input, unsigned start, unsigned length) + Interpreter(BytecodePattern* pattern, unsigned* output, const UString input, unsigned start, unsigned length) : pattern(pattern) , output(output) , input(input, start, length) @@ -1488,7 +1492,7 @@ public: private: BytecodePattern* pattern; - int* output; + unsigned* output; InputStream input; BumpPointerPool* allocatorPool; unsigned remainingMatchCount; @@ -1533,22 +1537,22 @@ public: m_bodyDisjunction->terms.append(ByteTerm::UncheckInput(count)); } - void assertionBOL(int inputPosition) + void assertionBOL(unsigned inputPosition) { m_bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition)); } - void assertionEOL(int inputPosition) + void assertionEOL(unsigned inputPosition) { m_bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition)); } - void assertionWordBoundary(bool invert, int inputPosition) + void assertionWordBoundary(bool invert, unsigned inputPosition) { m_bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition)); } - void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) + void atomPatternCharacter(UChar ch, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) { if (m_pattern.m_ignoreCase) { UChar lo = Unicode::toLower(ch); @@ -1563,7 +1567,7 @@ public: m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType)); } - void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) + void atomCharacterClass(CharacterClass* characterClass, bool invert, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) { m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition)); @@ -1572,7 +1576,7 @@ public: m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation; } - void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) + void atomBackReference(unsigned subpatternId, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) { ASSERT(subpatternId); @@ -1583,7 +1587,7 @@ public: m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation; } - void atomParenthesesOnceBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation) + void atomParenthesesOnceBegin(unsigned subpatternId, bool capture, unsigned inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation) { int beginTerm = m_bodyDisjunction->terms.size(); @@ -1596,7 +1600,7 @@ public: m_currentAlternativeIndex = beginTerm + 1; } - void atomParenthesesTerminalBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation) + void atomParenthesesTerminalBegin(unsigned subpatternId, bool capture, unsigned inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation) { int beginTerm = m_bodyDisjunction->terms.size(); @@ -1609,7 +1613,7 @@ public: m_currentAlternativeIndex = beginTerm + 1; } - void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation) + void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, unsigned inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation) { // Errrk! - this is a little crazy, we initially generate as a TypeParenthesesSubpatternOnceBegin, // then fix this up at the end! - simplifying this should make it much clearer. @@ -1639,7 +1643,7 @@ public: m_currentAlternativeIndex = beginTerm + 1; } - void atomParentheticalAssertionEnd(int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) + void atomParentheticalAssertionEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) { unsigned beginTerm = popParenthesesStack(); closeAlternative(beginTerm + 1); @@ -1871,27 +1875,27 @@ public: switch (term.type) { case PatternTerm::TypeAssertionBOL: - assertionBOL(term.inputPosition - currentCountAlreadyChecked); + assertionBOL(currentCountAlreadyChecked - term.inputPosition); break; case PatternTerm::TypeAssertionEOL: - assertionEOL(term.inputPosition - currentCountAlreadyChecked); + assertionEOL(currentCountAlreadyChecked - term.inputPosition); break; case PatternTerm::TypeAssertionWordBoundary: - assertionWordBoundary(term.invert(), term.inputPosition - currentCountAlreadyChecked); + assertionWordBoundary(term.invert(), currentCountAlreadyChecked - term.inputPosition); break; case PatternTerm::TypePatternCharacter: - atomPatternCharacter(term.patternCharacter, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType); + atomPatternCharacter(term.patternCharacter, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityCount, term.quantityType); break; case PatternTerm::TypeCharacterClass: - atomCharacterClass(term.characterClass, term.invert(), term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType); + atomCharacterClass(term.characterClass, term.invert(), currentCountAlreadyChecked- term.inputPosition, term.frameLocation, term.quantityCount, term.quantityType); break; case PatternTerm::TypeBackReference: - atomBackReference(term.backReferenceSubpatternId, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType); + atomBackReference(term.backReferenceSubpatternId, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityCount, term.quantityType); break; case PatternTerm::TypeForwardReference: @@ -1907,17 +1911,17 @@ public: else alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce; unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked; - atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, alternativeFrameLocation); + atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, term.frameLocation, alternativeFrameLocation); emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount); atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType); } else if (term.parentheses.isTerminal) { unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked; - atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesOnce); + atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesOnce); emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount); atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType); } else { unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked; - atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, 0); + atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, term.frameLocation, 0); emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0); atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize); } @@ -1967,7 +1971,7 @@ PassOwnPtr<BytecodePattern> byteCompile(YarrPattern& pattern, BumpPointerAllocat return ByteCompiler(pattern).compile(allocator); } -int interpret(BytecodePattern* bytecode, const UString& input, unsigned start, unsigned length, int* output) +unsigned interpret(BytecodePattern* bytecode, const UString& input, unsigned start, unsigned length, unsigned* output) { return Interpreter(bytecode, output, input, start, length).interpret(); } diff --git a/Source/JavaScriptCore/yarr/YarrInterpreter.h b/Source/JavaScriptCore/yarr/YarrInterpreter.h index eb5fdc6dc..4bb1efc50 100644 --- a/Source/JavaScriptCore/yarr/YarrInterpreter.h +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.h @@ -105,7 +105,7 @@ struct ByteTerm { unsigned frameLocation; bool m_capture : 1; bool m_invert : 1; - int inputPosition; + unsigned inputPosition; ByteTerm(UChar ch, int inputPos, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType) : frameLocation(frameLocation) diff --git a/Source/JavaScriptCore/yarr/YarrJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp index cd861ecf3..2269792ec 100644 --- a/Source/JavaScriptCore/yarr/YarrJIT.cpp +++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "YarrJIT.h" -#include "ASCIICType.h" +#include <wtf/ASCIICType.h> #include "LinkBuffer.h" #include "Yarr.h" @@ -1748,7 +1748,7 @@ class YarrGenerator : private MacroAssembler { if (alternative->m_minimumSize) sub32(Imm32(alternative->m_minimumSize - 1), regT0); else - add32(Imm32(1), regT0); + add32(TrustedImm32(1), regT0); store32(regT0, Address(output)); } } @@ -1847,7 +1847,7 @@ class YarrGenerator : private MacroAssembler { if (alternative->m_minimumSize == m_pattern.m_body->m_minimumSize) { // If the last alternative had the same minimum size as the disjunction, // just simply increment input pos by 1, no adjustment based on minimum size. - add32(Imm32(1), index); + add32(TrustedImm32(1), index); } else { // If the minumum for the last alternative was one greater than than that // for the disjunction, we're already progressed by 1, nothing to do! diff --git a/Source/JavaScriptCore/yarr/YarrParser.h b/Source/JavaScriptCore/yarr/YarrParser.h index e6694560a..1182d7907 100644 --- a/Source/JavaScriptCore/yarr/YarrParser.h +++ b/Source/JavaScriptCore/yarr/YarrParser.h @@ -54,6 +54,7 @@ private: PatternTooLarge, QuantifierOutOfOrder, QuantifierWithoutAtom, + QuantifierTooLarge, MissingParentheses, ParenthesesUnmatched, ParenthesesTypeInvalid, @@ -546,6 +547,11 @@ private: ASSERT(!m_err); ASSERT(min <= max); + if (min == UINT_MAX) { + m_err = QuantifierTooLarge; + return; + } + if (lastTokenWasAnAtom) m_delegate.quantifyAtom(min, max, !tryConsume('?')); else @@ -685,6 +691,7 @@ private: REGEXP_ERROR_PREFIX "regular expression too large", REGEXP_ERROR_PREFIX "numbers out of order in {} quantifier", REGEXP_ERROR_PREFIX "nothing to repeat", + REGEXP_ERROR_PREFIX "number too large in {} quantifier", REGEXP_ERROR_PREFIX "missing )", REGEXP_ERROR_PREFIX "unmatched parentheses", REGEXP_ERROR_PREFIX "unrecognized character after (?", @@ -696,7 +703,6 @@ private: return errorMessages[m_err]; } - // Misc helper functions: typedef unsigned ParseState; |