diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-06-25 13:35:59 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-06-25 13:35:59 +0200 |
commit | 79ad030d505ccf79cf10aa9f8189ca3e2f61f6f4 (patch) | |
tree | 0287b1a69d84492c901e8bc820e635e7133809a0 /Source/JavaScriptCore | |
parent | 682ab87480e7757346802ce7f54cfdbdfeb2339e (diff) | |
download | qtwebkit-79ad030d505ccf79cf10aa9f8189ca3e2f61f6f4.tar.gz |
Imported WebKit commit c4b613825abd39ac739a47d7b4410468fcef66dc (http://svn.webkit.org/repository/webkit/trunk@121147)
New snapshot that includes Win32 debug build fix (use SVGAllInOne)
Diffstat (limited to 'Source/JavaScriptCore')
64 files changed, 1647 insertions, 302 deletions
diff --git a/Source/JavaScriptCore/API/JSBase.h b/Source/JavaScriptCore/API/JSBase.h index f46a41755..fed54fe23 100644 --- a/Source/JavaScriptCore/API/JSBase.h +++ b/Source/JavaScriptCore/API/JSBase.h @@ -71,7 +71,7 @@ typedef struct OpaqueJSValue* JSObjectRef; #elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) #define JS_EXPORT __attribute__((visibility("default"))) #elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE) || defined(__CC_ARM) || defined(__ARMCC__) -#if defined(BUILDING_JavaScriptCore) || defined(STATICALLY_LINKED_WITH_JavaScriptCore) +#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) #define JS_EXPORT __declspec(dllexport) #else #define JS_EXPORT __declspec(dllimport) diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index 24e67b940..06139a4d2 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -54,6 +54,7 @@ SET(JavaScriptCore_SOURCES bytecode/PolymorphicPutByIdList.cpp bytecode/SpeculatedType.cpp bytecode/PutByIdStatus.cpp + bytecode/ResolveGlobalStatus.cpp bytecode/SamplingTool.cpp bytecode/StructureStubInfo.cpp bytecode/Watchpoint.cpp @@ -71,6 +72,7 @@ SET(JavaScriptCore_SOURCES dfg/DFGConstantFoldingPhase.cpp dfg/DFGCorrectableJumpPoint.cpp dfg/DFGCSEPhase.cpp + dfg/DFGDisassembler.cpp dfg/DFGDominators.cpp dfg/DFGDriver.cpp dfg/DFGFixupPhase.cpp diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 3907efc13..20df558bb 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,33 +1,608 @@ -2012-06-19 Joel Dillon <joel.dillon@codethink.co.uk> Jocelyn Turcotte <jocelyn.turcotte@nokia.com> +2012-06-23 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r121058. + http://trac.webkit.org/changeset/121058 + https://bugs.webkit.org/show_bug.cgi?id=89809 + + Patch causes plugins tests to crash in GTK debug builds + (Requested by zdobersek on #webkit). + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): + (APIEntryShimWithoutLock): + (JSC::APIEntryShim::APIEntryShim): + (APIEntryShim): + (JSC::APICallbackShim::~APICallbackShim): + * API/JSContextRef.cpp: + (JSGlobalContextCreate): + (JSGlobalContextCreateInGroup): + (JSGlobalContextRelease): + (JSContextCreateBacktrace): + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::tryAllocateSlowCase): + * heap/Heap.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + (JSC::Heap::collect): + (JSC::Heap::setActivityCallback): + (JSC::Heap::activityCallback): + (JSC::Heap::sweeper): + * heap/Heap.h: + (Heap): + * heap/HeapTimer.cpp: + (JSC::HeapTimer::~HeapTimer): + (JSC::HeapTimer::invalidate): + (JSC::HeapTimer::timerDidFire): + (JSC): + * heap/HeapTimer.h: + (HeapTimer): + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::doWork): + (JSC::IncrementalSweeper::create): + * heap/IncrementalSweeper.h: + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::allocateSlowCase): + * heap/WeakBlock.cpp: + (JSC::WeakBlock::reap): + * jsc.cpp: + (functionGC): + (functionReleaseExecutableMemory): + (jscmain): + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + * runtime/GCActivityCallback.h: + (DefaultGCActivityCallback): + (JSC::DefaultGCActivityCallback::create): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::~JSGlobalData): + (JSC::JSGlobalData::sharedInstance): + (JSC::JSGlobalData::sharedInstanceInternal): + * runtime/JSGlobalData.h: + (JSGlobalData): + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::~JSGlobalObject): + (JSC::JSGlobalObject::init): + * runtime/JSLock.cpp: + (JSC): + (JSC::createJSLockCount): + (JSC::JSLock::lockCount): + (JSC::setLockCount): + (JSC::JSLock::JSLock): + (JSC::JSLock::lock): + (JSC::JSLock::unlock): + (JSC::JSLock::currentThreadIsHoldingLock): + (JSC::JSLock::DropAllLocks::DropAllLocks): + (JSC::JSLock::DropAllLocks::~DropAllLocks): + * runtime/JSLock.h: + (JSC): + (JSLock): + (JSC::JSLock::JSLock): + (JSC::JSLock::~JSLock): + (DropAllLocks): + * runtime/WeakGCMap.h: + (JSC::WeakGCMap::set): + * testRegExp.cpp: + (realMain): - [Qt][Win] Fix broken QtWebKit5.lib linking - https://bugs.webkit.org/show_bug.cgi?id=88321 +2012-06-22 Alexandru Chiculita <achicu@adobe.com> - Reviewed by NOBODY (OOPS!). + [CSS Shaders] Re-enable the CSS Shaders compile time flag on Safari Mac + https://bugs.webkit.org/show_bug.cgi?id=89781 - Also update the Wx build to use the new define. + Reviewed by Dean Jackson. - * API/JSBase.h: - * runtime/JSExportMacros.h: - * wscript: + Added ENABLE_CSS_SHADERS flag as enabled by default on Safari for Mac. + + * Configurations/FeatureDefines.xcconfig: -2012-06-13 Patrick Gansterer <paroga@webkit.org> +2012-06-22 Filip Pizlo <fpizlo@apple.com> + + DFG tier-up should happen in prologues, not epilogues + https://bugs.webkit.org/show_bug.cgi?id=89752 + + Reviewed by Geoffrey Garen. + + This change has two outcomes: + + 1) Slightly reduces the likelihood that a function will be optimized both + standalone and via inlining. Previously, if you had a call sequence like foo() + calls bar() exactly once, and nobody else calls bar(), then bar() would get + optimized first (because it returns first) and then foo() gets optimized. If foo() + can inline bar() then that means that bar() gets optimized twice. But now, if we + optimize in prologues, then foo() will be optimized first. If it inlines bar(), + that means that there will no longer be any calls to bar(). + + 2) It lets us kill some code in JITStubs. Epilogue tier-up was very different from + loop tier-up, since epilogue tier-up should not attempt OSR. But prologue tier-up + requires OSR (albeit really easy OSR since it's the top of the compilation unit), + so it becomes just like loop tier-up. As a result, we now have one optimization + hook (cti_optimize) instead of two (cti_optimize_from_loop and + cti_optimize_from_ret). + + As a consequence of not having an optimization check in epilogues, the OSR exit + code must now trigger reoptimization itself instead of just signaling the epilogue + check to fire. + + This also adds the ability to count the number of DFG compilations, which was + useful for debugging this patch and might be useful for other things in the future. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::reoptimize): + (JSC): + * bytecode/CodeBlock.h: + (CodeBlock): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseCodeBlock): + * dfg/DFGDriver.cpp: + (DFG): + (JSC::DFG::getNumCompilations): + (JSC::DFG::compile): + * dfg/DFGDriver.h: + (DFG): + * dfg/DFGOSRExitCompiler.cpp: + (JSC::DFG::OSRExitCompiler::handleExitCounts): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * jit/JIT.cpp: + (JSC::JIT::emitOptimizationCheck): + * jit/JIT.h: + * jit/JITCall32_64.cpp: + (JSC::JIT::emit_op_ret): + (JSC::JIT::emit_op_ret_object_or_this): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_ret): + (JSC::JIT::emit_op_ret_object_or_this): + (JSC::JIT::emit_op_enter): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_enter): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * jit/JITStubs.h: + +2012-06-20 Mark Hahnenberg <mhahnenberg@apple.com> + + JSLock should be per-JSGlobalData + https://bugs.webkit.org/show_bug.cgi?id=89123 + + Reviewed by Gavin Barraclough. - [WIN] Remove dependency on pthread from MachineStackMarker - https://bugs.webkit.org/show_bug.cgi?id=68429 + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * API/APIShims.h: + (APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): Added an extra parameter to the constructor to + determine whether we should ref the JSGlobalData or not. We want to ref all the time except for in the + HeapTimer class because timerDidFire could run after somebody has started to tear down that particular + JSGlobalData, so we wouldn't want to resurrect the ref count of that JSGlobalData from 0 back to 1 after + its destruction has begun. + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): Now derefs if it also refed. + (JSC::APIEntryShim::APIEntryShim): + (APIEntryShim): + (JSC::APIEntryShim::~APIEntryShim): + (JSC::APIEntryShim::init): Factored out common initialization code for the various APIEntryShim constructors. + Also moved the timeoutChecker stop and start here because we need to start after we've grabbed the API lock + and before we've released it, which can only done in APIEntryShim. + (JSC::APICallbackShim::~APICallbackShim): We no longer need to synchronize here. + * API/JSContextRef.cpp: + (JSGlobalContextCreate): + (JSGlobalContextCreateInGroup): + (JSGlobalContextRelease): + (JSContextCreateBacktrace): + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::tryAllocateSlowCase): + * heap/Heap.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + (JSC::Heap::collect): + (JSC::Heap::setActivityCallback): + (JSC::Heap::activityCallback): + (JSC::Heap::sweeper): + * heap/Heap.h: Changed m_activityCallback and m_sweeper to be raw pointers rather than OwnPtrs because they + are now responsible for their own lifetime. Also changed the order of declaration of the GCActivityCallback + and the IncrementalSweeper to make sure they're the last things that get initialized during construction to + prevent any issues with uninitialized memory in the JSGlobalData/Heap they might care about. + (Heap): + * heap/HeapTimer.cpp: Refactored to allow for thread-safe operation and shutdown. + (JSC::HeapTimer::~HeapTimer): + (JSC::HeapTimer::invalidate): + (JSC): + (JSC::HeapTimer::didStartVMShutdown): Called at the beginning of ~JSGlobalData. If we're on the same thread + that the HeapTimer is running on, we kill the HeapTimer ourselves. If not, then we set some state in the + HeapTimer and schedule it to fire immediately so that it can notice and kill itself. + (JSC::HeapTimer::timerDidFire): We grab our mutex and check our JSGlobalData pointer. If it has been zero-ed + out, then we know the VM has started to shutdown and we should kill ourselves. Otherwise, grab the APIEntryShim, + but without ref-ing the JSGlobalData (we don't want to bring the JSGlobalData's ref-count from 0 to 1) in case + we were interrupted between releasing our mutex and trying to grab the APILock. + * heap/HeapTimer.h: + (HeapTimer): + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::doWork): We no longer need the API shim here since HeapTimer::timerDidFire handles + all of that for us. + (JSC::IncrementalSweeper::create): + * heap/IncrementalSweeper.h: + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::allocateSlowCase): + * heap/WeakBlock.cpp: + (JSC::WeakBlock::reap): + * jsc.cpp: + (functionGC): + (functionReleaseExecutableMemory): + (jscmain): + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + * runtime/GCActivityCallback.h: + (DefaultGCActivityCallback): + (JSC::DefaultGCActivityCallback::create): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::~JSGlobalData): Signals to the two HeapTimers (GCActivityCallback and IncrementalSweeper) + that the VM has started shutting down. It then waits until the HeapTimer is done with whatever activity + it needs to do before continuing with any further destruction. Also asserts that we do not currently hold the + APILock because this could potentially cause deadlock when we try to signal to the HeapTimers using their mutexes. + (JSC::JSGlobalData::sharedInstance): Protect the initialization for the shared instance with the GlobalJSLock. + (JSC::JSGlobalData::sharedInstanceInternal): + * runtime/JSGlobalData.h: Change to be ThreadSafeRefCounted so that we don't have to worry about refing and + de-refing JSGlobalDatas on separate threads since we don't do it that often anyways. + (JSGlobalData): + (JSC::JSGlobalData::apiLock): + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::~JSGlobalObject): + (JSC::JSGlobalObject::init): + * runtime/JSLock.cpp: + (JSC): + (JSC::GlobalJSLock::GlobalJSLock): For accessing the shared instance. + (JSC::GlobalJSLock::~GlobalJSLock): + (JSC::JSLockHolder::JSLockHolder): MutexLocker for JSLock. Also refs the JSGlobalData to keep it alive so that + it can successfully unlock it later without it disappearing from underneath it. + (JSC::JSLockHolder::~JSLockHolder): + (JSC::JSLock::JSLock): + (JSC::JSLock::~JSLock): + (JSC::JSLock::lock): Uses the spin lock for guarding the lock count and owner thread fields. Uses the mutex for + actually waiting for long periods. + (JSC::JSLock::unlock): + (JSC::JSLock::currentThreadIsHoldingLock): + (JSC::JSLock::dropAllLocks): + (JSC::JSLock::dropAllLocksUnconditionally): + (JSC::JSLock::grabAllLocks): + (JSC::JSLock::DropAllLocks::DropAllLocks): + (JSC::JSLock::DropAllLocks::~DropAllLocks): + * runtime/JSLock.h: + (JSC): + (GlobalJSLock): + (JSLockHolder): + (JSLock): + (DropAllLocks): + * runtime/WeakGCMap.h: + (JSC::WeakGCMap::set): + * testRegExp.cpp: + (realMain): + +2012-06-22 Peter Beverloo <peter@chromium.org> + + [Chromium] Disable c++0x compatibility warnings in JavaScriptCore.gyp when building for Android + https://bugs.webkit.org/show_bug.cgi?id=88853 + + Reviewed by Steve Block. + + The Android exclusions were necessary to fix a gyp generation error, as + the gcc_version variable wasn't being defined for Android. Remove these + exceptions when Chromium is able to define the gcc_version variable. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2012-06-21 Filip Pizlo <fpizlo@apple.com> + + op_resolve_global should not prevent DFG inlining + https://bugs.webkit.org/show_bug.cgi?id=89726 + + Reviewed by Gavin Barraclough. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::CodeBlock): + (JSC::CodeBlock::shrinkToFit): + * bytecode/GlobalResolveInfo.h: + (JSC::GlobalResolveInfo::GlobalResolveInfo): + (GlobalResolveInfo): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry): + * dfg/DFGCapabilities.h: + (JSC::DFG::canInlineOpcode): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-06-20 Filip Pizlo <fpizlo@apple.com> + + DFG should inline 'new Array()' + https://bugs.webkit.org/show_bug.cgi?id=89632 + + Reviewed by Geoffrey Garen. + + This adds support for treating InternalFunction like intrinsics. The code + to do so is actually quite clean, so I don't feel bad about perpetuating + the InternalFunction vs. JSFunction-with-NativeExecutable dichotomy. + + Currently this newfound power is only used to inline 'new Array()'. + + * dfg/DFGByteCodeParser.cpp: + (ByteCodeParser): + (JSC::DFG::ByteCodeParser::handleCall): + (JSC::DFG::ByteCodeParser::handleConstantInternalFunction): + (DFG): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::isInternalFunctionConstant): + (JSC::DFG::Graph::valueOfInternalFunctionConstant): - Reviewed by NOBODY (OOPS!). +2012-06-21 Mark Hahnenberg <mhahnenberg@apple.com> - Implement pthread TLS functionality with native windows functions. + Adding copyrights to new files. - * heap/MachineStackMarker.cpp: Use the new functions instead of pthread directly. - * heap/MachineStackMarker.h: - * wtf/ThreadSpecific.h: - (WTF::ThreadSpecificKeyCreate): Added wrapper around pthread_key_create. - (WTF::ThreadSpecificKeyDelete): Added wrapper around pthread_key_delete. - (WTF::ThreadSpecificSet): Added wrapper around pthread_setspecific. - (WTF::ThreadSpecificGet): Added wrapper around pthread_getspecific. - * wtf/ThreadSpecificWin.cpp: + * heap/HeapTimer.cpp: + * heap/HeapTimer.h: + * heap/IncrementalSweeper.cpp: + * heap/IncrementalSweeper.h: + +2012-06-21 Arnaud Renevier <arno@renevier.net> + + make sure headers are included only once per file + https://bugs.webkit.org/show_bug.cgi?id=88922 + + Reviewed by Alexey Proskuryakov. + + * bytecode/CodeBlock.h: + * heap/MachineStackMarker.cpp: + * runtime/JSVariableObject.h: + +2012-06-21 Ryuan Choi <ryuan.choi@gmail.com> + + [EFL][WK2] Make WebKit2/Efl headers and resources installable. + https://bugs.webkit.org/show_bug.cgi?id=88207 + + Reviewed by Chang Shu. + + * shell/CMakeLists.txt: Use ${EXEC_INSTALL_DIR} instead of hardcoding "bin" + +2012-06-20 Geoffrey Garen <ggaren@apple.com> + + Reduced (but did not eliminate) use of "berzerker GC" + https://bugs.webkit.org/show_bug.cgi?id=89237 + + Reviewed by Gavin Barraclough. + + (PART 1) + + This patch turned out to be crashy, so I'm landing the non-crashy bits + first. + + This part is pre-requisite refactoring. I didn't actually turn off + "berzerker GC" or turn on incremental shrinking. + + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::removeBlock): Make sure to clear the free list when + we throw away the block we're currently allocating out of. Otherwise, we'll + allocate out of a stale free list. + + * heap/MarkedSpace.cpp: + (JSC::Free::Free): + (JSC::Free::operator()): + (JSC::Free::returnValue): Refactored this functor to use a shared helper + function, so we can share our implementation with the incremental sweeper. + + Also changed to freeing individual blocks immediately instead of linking + them into a list for later freeing. This makes the programming interface + simpler, and it's slightly more efficient to boot. + + (JSC::MarkedSpace::~MarkedSpace): Updated for rename. + + (JSC::MarkedSpace::freeBlock): + (JSC::MarkedSpace::freeOrShrinkBlock): New helper functions to share behavior + with the incremental sweeper. + + (JSC::MarkedSpace::shrink): Updated for new functor behavior. + + * heap/MarkedSpace.h: Statically typed languages are awesome. + +2012-06-20 Filip Pizlo <fpizlo@apple.com> + + DFG should optimize ResolveGlobal + https://bugs.webkit.org/show_bug.cgi?id=89617 + + Reviewed by Oliver Hunt. + + This adds inlining of ResolveGlobal accesses that are known monomorphic. It also + adds the specific function optimization to ResolveGlobal, when it is inlined. And, + it makes internal functions act like specific functions, since that will be the + most common use-case of this optimization. + + This is only a slighy speed-up (sub 1%), since we don't yet do the obvious thing + with this optimization, which is to completely inline common "globally resolved" + function and constructor calls, like "new Array()". + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::globalResolveInfoForBytecodeOffset): + * bytecode/CodeBlock.h: + (CodeBlock): + (JSC::CodeBlock::numberOfGlobalResolveInfos): + * bytecode/GlobalResolveInfo.h: + (JSC::getGlobalResolveInfoBytecodeOffset): + (JSC): + * bytecode/ResolveGlobalStatus.cpp: Added. + (JSC): + (JSC::computeForStructure): + (JSC::computeForLLInt): + (JSC::ResolveGlobalStatus::computeFor): + * bytecode/ResolveGlobalStatus.h: Added. + (JSC): + (ResolveGlobalStatus): + (JSC::ResolveGlobalStatus::ResolveGlobalStatus): + (JSC::ResolveGlobalStatus::state): + (JSC::ResolveGlobalStatus::isSet): + (JSC::ResolveGlobalStatus::operator!): + (JSC::ResolveGlobalStatus::isSimple): + (JSC::ResolveGlobalStatus::takesSlowPath): + (JSC::ResolveGlobalStatus::structure): + (JSC::ResolveGlobalStatus::offset): + (JSC::ResolveGlobalStatus::specificValue): + * dfg/DFGByteCodeParser.cpp: + (ByteCodeParser): + (JSC::DFG::ByteCodeParser::handleGetByOffset): + (DFG): + (JSC::DFG::ByteCodeParser::handleGetById): + (JSC::DFG::ByteCodeParser::parseBlock): + * runtime/JSObject.cpp: + (JSC::getCallableObjectSlow): + (JSC): + (JSC::JSObject::put): + (JSC::JSObject::putDirectVirtual): + (JSC::JSObject::putDirectAccessor): + * runtime/JSObject.h: + (JSC): + (JSC::getCallableObject): + (JSC::JSObject::putOwnDataProperty): + (JSC::JSObject::putDirect): + (JSC::JSObject::putDirectWithoutTransition): + +2012-06-20 Filip Pizlo <fpizlo@apple.com> + + Functions on global objects should be specializable + https://bugs.webkit.org/show_bug.cgi?id=89615 + + Reviewed by Oliver Hunt. + + I tested to see if this brought back the bug in https://bugs.webkit.org/show_bug.cgi?id=33343, + and it didn't. Bug 33343 was the reason why we disabled global object function specialization + to begin with. So I'm guessing this is safe. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::init): + +2012-06-20 Filip Pizlo <fpizlo@apple.com> + + build-webkit failure due to illegal 32-bit integer constants in code + generated by offlineasm + https://bugs.webkit.org/show_bug.cgi?id=89347 + + Reviewed by Geoffrey Garen. + + The offending constants are the magic numbers used by offlineasm to find + offsets in the generated machine code. Added code to turn them into what + the C++ compiler will believe to be valid 32-bit values. + + * offlineasm/offsets.rb: + +2012-06-19 Geoffrey Garen <ggaren@apple.com> + + Made the incremental sweeper more aggressive + https://bugs.webkit.org/show_bug.cgi?id=89527 + + Reviewed by Oliver Hunt. + + This is a pre-requisite to getting rid of "berzerker GC" because we need + the sweeper to reclaim memory in a timely fashion, or we'll see a memory + footprint regression. + + * heap/IncrementalSweeper.h: + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::scheduleTimer): Since the time slice is predictable, + no need to use a data member to record it. + + (JSC::IncrementalSweeper::doSweep): Sweep as many blocks as we can in a + small time slice. This is better than sweeping only one block per timer + fire because that strategy has a heavy timer overhead, and artificially + delays memory reclamation. + +2012-06-20 Filip Pizlo <fpizlo@apple.com> + + DFG should be able to print disassembly interleaved with the IR + https://bugs.webkit.org/show_bug.cgi?id=89551 + + Reviewed by Geoffrey Garen. + + This change also removes running Dominators unconditionally on every DFG + compile. Dominators are designed to be computed on-demand, and currently + the only demand is graph dumps. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::labelIgnoringWatchpoints): + (ARMv7Assembler): + * assembler/AbstractMacroAssembler.h: + (AbstractMacroAssembler): + (JSC::AbstractMacroAssembler::labelIgnoringWatchpoints): + * assembler/X86Assembler.h: + (X86Assembler): + (JSC::X86Assembler::labelIgnoringWatchpoints): + * dfg/DFGCommon.h: + (JSC::DFG::shouldShowDisassembly): + (DFG): + * dfg/DFGDisassembler.cpp: Added. + (DFG): + (JSC::DFG::Disassembler::Disassembler): + (JSC::DFG::Disassembler::dump): + (JSC::DFG::Disassembler::dumpDisassembly): + * dfg/DFGDisassembler.h: Added. + (DFG): + (Disassembler): + (JSC::DFG::Disassembler::setStartOfCode): + (JSC::DFG::Disassembler::setForBlock): + (JSC::DFG::Disassembler::setForNode): + (JSC::DFG::Disassembler::setEndOfMainPath): + (JSC::DFG::Disassembler::setEndOfCode): + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dumpCodeOrigin): + (JSC::DFG::Graph::amountOfNodeWhiteSpace): + (DFG): + (JSC::DFG::Graph::printNodeWhiteSpace): + (JSC::DFG::Graph::dump): + (JSC::DFG::Graph::dumpBlockHeader): + * dfg/DFGGraph.h: + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::JITCompiler): + (DFG): + (JSC::DFG::JITCompiler::compile): + (JSC::DFG::JITCompiler::compileFunction): + * dfg/DFGJITCompiler.h: + (JITCompiler): + (JSC::DFG::JITCompiler::setStartOfCode): + (JSC::DFG::JITCompiler::setForBlock): + (JSC::DFG::JITCompiler::setForNode): + (JSC::DFG::JITCompiler::setEndOfMainPath): + (JSC::DFG::JITCompiler::setEndOfCode): + * dfg/DFGNode.h: + (Node): + (JSC::DFG::Node::willHaveCodeGen): + * dfg/DFGNodeFlags.cpp: + (JSC::DFG::nodeFlagsAsString): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + * runtime/Options.cpp: + (Options): + (JSC::Options::initializeOptions): + * runtime/Options.h: + (Options): 2012-06-19 Filip Pizlo <fpizlo@apple.com> diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig index b96b21db3..ae2c393b1 100644 --- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -40,6 +40,7 @@ ENABLE_CSP_NEXT = ; ENABLE_CSS3_FLEXBOX = ENABLE_CSS3_FLEXBOX; ENABLE_CSS_EXCLUSIONS = ENABLE_CSS_EXCLUSIONS; ENABLE_CSS_FILTERS = ENABLE_CSS_FILTERS; +ENABLE_CSS_SHADERS = ENABLE_CSS_SHADERS; ENABLE_CSS_IMAGE_RESOLUTION = ; ENABLE_CSS_REGIONS = ENABLE_CSS_REGIONS; ENABLE_CSS_VARIABLES = ; diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am index 77409fe93..84d6e60ff 100644 --- a/Source/JavaScriptCore/GNUmakefile.list.am +++ b/Source/JavaScriptCore/GNUmakefile.list.am @@ -126,6 +126,8 @@ javascriptcore_sources += \ Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \ Source/JavaScriptCore/bytecode/PutByIdStatus.h \ Source/JavaScriptCore/bytecode/PutKind.h \ + Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp \ + Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h \ Source/JavaScriptCore/bytecode/SamplingTool.cpp \ Source/JavaScriptCore/bytecode/SamplingTool.h \ Source/JavaScriptCore/bytecode/StructureSet.h \ @@ -168,6 +170,8 @@ javascriptcore_sources += \ Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.h \ Source/JavaScriptCore/dfg/DFGCSEPhase.cpp \ Source/JavaScriptCore/dfg/DFGCSEPhase.h \ + Source/JavaScriptCore/dfg/DFGDisassembler.cpp \ + Source/JavaScriptCore/dfg/DFGDisassembler.h \ Source/JavaScriptCore/dfg/DFGDominators.cpp \ Source/JavaScriptCore/dfg/DFGDominators.h \ Source/JavaScriptCore/dfg/DFGDoubleFormatState.h \ diff --git a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp index 8da950f5e..c60a2e68d 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp +++ b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp @@ -47,7 +47,7 @@ ], }, 'conditions': [ - ['os_posix == 1 and OS != "mac" and OS != "android" and gcc_version==46', { + ['os_posix == 1 and OS != "mac" and gcc_version==46', { 'target_defaults': { # Disable warnings about c++0x compatibility, as some names (such as nullptr) conflict # with upcoming c++0x types. diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri index f6580c51f..380bbaf1b 100644 --- a/Source/JavaScriptCore/JavaScriptCore.pri +++ b/Source/JavaScriptCore/JavaScriptCore.pri @@ -34,6 +34,12 @@ INCLUDEPATH += \ win32-* { LIBS += -lwinmm + + win32-g++* { + LIBS += -lpthreadGC2 + } else:win32-msvc* { + LIBS += -lpthreadVC2 + } } wince* { diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 365038cee..c48ef49c6 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -189,6 +189,7 @@ EXPORTS ?get@Structure@JSC@@QAEIAAVJSGlobalData@2@VPropertyName@2@AAIAAPAVJSCell@2@@Z ?getCalculatedDisplayName@JSC@@YA?AVUString@1@PAVExecState@1@PAVJSObject@1@@Z ?getCallData@JSCell@JSC@@SA?AW4CallType@2@PAV12@AATCallData@2@@Z + ?getCallableObjectSlow@JSC@@YAPAVJSCell@1@PAV21@@Z ?getConstructData@JSCell@JSC@@SA?AW4ConstructType@2@PAV12@AATConstructData@2@@Z ?getCurrentLocalTime@WTF@@YAXPAUtm@@@Z ?getObject@JSCell@JSC@@QAEPAVJSObject@2@XZ diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 2ffc9e266..a64a1065f 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -209,6 +209,10 @@ 0FF4274B158EBE91004CB9FF /* udis86.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4273F158EBD94004CB9FF /* udis86.h */; }; 0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */; }; 0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */; }; + 0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */; }; + 0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0FF42771159275D5004CB9FF /* ResolveGlobalStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4276E159275D2004CB9FF /* ResolveGlobalStatus.cpp */; }; + 0FF42772159275D8004CB9FF /* ResolveGlobalStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4276F159275D2004CB9FF /* ResolveGlobalStatus.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; }; 0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; }; 0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -929,6 +933,10 @@ 0FF4273F158EBD94004CB9FF /* udis86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86.h; path = disassembler/udis86/udis86.h; sourceTree = "<group>"; }; 0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_itab_holder.c; path = disassembler/udis86/udis86_itab_holder.c; sourceTree = "<group>"; }; 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkBuffer.cpp; sourceTree = "<group>"; }; + 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDisassembler.cpp; path = dfg/DFGDisassembler.cpp; sourceTree = "<group>"; }; + 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDisassembler.h; path = dfg/DFGDisassembler.h; sourceTree = "<group>"; }; + 0FF4276E159275D2004CB9FF /* ResolveGlobalStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResolveGlobalStatus.cpp; sourceTree = "<group>"; }; + 0FF4276F159275D2004CB9FF /* ResolveGlobalStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResolveGlobalStatus.h; sourceTree = "<group>"; }; 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; }; 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; }; 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; }; @@ -2201,6 +2209,8 @@ 0F3B3A18153E68EF003ED0FF /* DFGConstantFoldingPhase.h */, 0FC0979D146B271E00CF2442 /* DFGCorrectableJumpPoint.cpp */, 0FC0979A146A772000CF2442 /* DFGCorrectableJumpPoint.h */, + 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */, + 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */, 0FD81ACF154FB4EB00983E72 /* DFGDominators.cpp */, 0FD81AD0154FB4EB00983E72 /* DFGDominators.h */, 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */, @@ -2341,6 +2351,8 @@ 0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */, 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */, 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */, + 0FF4276E159275D2004CB9FF /* ResolveGlobalStatus.cpp */, + 0FF4276F159275D2004CB9FF /* ResolveGlobalStatus.h */, 0F93329B14CA7DC10085F3C6 /* StructureSet.h */, 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */, 0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */, @@ -2759,6 +2771,8 @@ 0FF42748158EBE91004CB9FF /* udis86_syn.h in Headers */, 0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */, 0FF4274B158EBE91004CB9FF /* udis86.h in Headers */, + 0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */, + 0FF42772159275D8004CB9FF /* ResolveGlobalStatus.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3345,6 +3359,8 @@ C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */, 0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */, C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */, + 0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */, + 0FF42771159275D5004CB9FF /* ResolveGlobalStatus.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri index e3488c74e..2f479222a 100644 --- a/Source/JavaScriptCore/Target.pri +++ b/Source/JavaScriptCore/Target.pri @@ -64,6 +64,7 @@ SOURCES += \ bytecode/Opcode.cpp \ bytecode/PolymorphicPutByIdList.cpp \ bytecode/PutByIdStatus.cpp \ + bytecode/ResolveGlobalStatus.cpp \ bytecode/SamplingTool.cpp \ bytecode/SpeculatedType.cpp \ bytecode/StructureStubInfo.cpp \ @@ -102,6 +103,7 @@ SOURCES += \ dfg/DFGConstantFoldingPhase.cpp \ dfg/DFGCorrectableJumpPoint.cpp \ dfg/DFGCSEPhase.cpp \ + dfg/DFGDisassembler.cpp \ dfg/DFGDominators.cpp \ dfg/DFGDriver.cpp \ dfg/DFGFixupPhase.cpp \ diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h index 95c812c94..81977e2bd 100644 --- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h @@ -1827,6 +1827,11 @@ public: m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0); } + AssemblerLabel labelIgnoringWatchpoints() + { + return m_formatter.label(); + } + AssemblerLabel labelForWatchpoint() { AssemblerLabel result = m_formatter.label(); diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index 27b8a58d1..0080446c2 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -555,6 +555,15 @@ public: // Section 3: Misc admin methods +#if ENABLE(DFG_JIT) + Label labelIgnoringWatchpoints() + { + Label result; + result.m_label = m_assembler.labelIgnoringWatchpoints(); + return result; + } +#endif + Label label() { return Label(this); diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index 8c5606972..9c35be8b5 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -1730,6 +1730,11 @@ public: m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize(); return result; } + + AssemblerLabel labelIgnoringWatchpoints() + { + return m_formatter.label(); + } AssemblerLabel label() { diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 60596d1c2..bcbb51f63 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -1583,7 +1583,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab) , m_source(other.m_source) , m_sourceOffset(other.m_sourceOffset) #if ENABLE(JIT) - , m_globalResolveInfos(other.m_globalResolveInfos) + , m_globalResolveInfos(other.m_globalResolveInfos.size()) #endif #if ENABLE(VALUE_PROFILER) , m_executionEntryCount(0) @@ -1609,6 +1609,11 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab) optimizeAfterWarmUp(); jitAfterWarmUp(); +#if ENABLE(JIT) + for (unsigned i = m_globalResolveInfos.size(); i--;) + m_globalResolveInfos[i] = GlobalResolveInfo(other.m_globalResolveInfos[i].bytecodeOffset); +#endif + if (other.m_rareData) { createRareDataIfNecessary(); @@ -2258,6 +2263,10 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) return false; return true; } +GlobalResolveInfo& CodeBlock::globalResolveInfoForBytecodeOffset(unsigned bytecodeOffset) +{ + return *(binarySearch<GlobalResolveInfo, unsigned, getGlobalResolveInfoBytecodeOffset>(m_globalResolveInfos.begin(), m_globalResolveInfos.size(), bytecodeOffset)); +} #endif void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) @@ -2269,7 +2278,8 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) #endif #if ENABLE(JIT) m_structureStubInfos.shrinkToFit(); - m_globalResolveInfos.shrinkToFit(); + if (shrinkMode == EarlyShrink) + m_globalResolveInfos.shrinkToFit(); m_callLinkInfos.shrinkToFit(); m_methodCallLinkInfos.shrinkToFit(); #endif @@ -2454,6 +2464,16 @@ void CodeBlock::copyPostParseDataFromAlternative() } #if ENABLE(JIT) +void CodeBlock::reoptimize() +{ + ASSERT(replacement() != this); + ASSERT(replacement()->alternative() == this); + replacement()->tallyFrequentExitSites(); + replacement()->jettison(); + countReoptimization(); + optimizeAfterWarmUp(); +} + CodeBlock* ProgramCodeBlock::replacement() { return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode(); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 573d422d3..b73dcb2b6 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -69,7 +69,6 @@ #include <wtf/RefPtr.h> #include <wtf/SegmentedVector.h> #include <wtf/Vector.h> -#include "StructureStubInfo.h" namespace JSC { @@ -553,6 +552,8 @@ namespace JSC { } GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; } bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset); + GlobalResolveInfo& globalResolveInfoForBytecodeOffset(unsigned bytecodeOffset); + unsigned numberOfGlobalResolveInfos() { return m_globalResolveInfos.size(); } void setNumberOfCallLinkInfos(size_t size) { m_callLinkInfos.grow(size); } size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); } @@ -1104,15 +1105,7 @@ namespace JSC { #endif #if ENABLE(JIT) - void reoptimize() - { - ASSERT(replacement() != this); - ASSERT(replacement()->alternative() == this); - replacement()->tallyFrequentExitSites(); - replacement()->jettison(); - countReoptimization(); - optimizeAfterWarmUp(); - } + void reoptimize(); #endif #if ENABLE(VERBOSE_VALUE_PROFILE) diff --git a/Source/JavaScriptCore/bytecode/GlobalResolveInfo.h b/Source/JavaScriptCore/bytecode/GlobalResolveInfo.h index 5576cfacd..c466c750d 100644 --- a/Source/JavaScriptCore/bytecode/GlobalResolveInfo.h +++ b/Source/JavaScriptCore/bytecode/GlobalResolveInfo.h @@ -31,6 +31,8 @@ namespace JSC { struct GlobalResolveInfo { + GlobalResolveInfo() { } + GlobalResolveInfo(unsigned bytecodeOffset) : offset(0) , bytecodeOffset(bytecodeOffset) @@ -39,9 +41,14 @@ struct GlobalResolveInfo { WriteBarrier<Structure> structure; unsigned offset; - unsigned bytecodeOffset; + unsigned bytecodeOffset; // Only valid in old JIT code. This means nothing in the DFG. }; +inline unsigned getGlobalResolveInfoBytecodeOffset(GlobalResolveInfo* globalResolveInfo) +{ + return globalResolveInfo->bytecodeOffset; +} + } // namespace JSC #endif // GlobalResolveInfo_h diff --git a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp new file mode 100644 index 000000000..ff138704c --- /dev/null +++ b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp @@ -0,0 +1,88 @@ +/* + * 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 "ResolveGlobalStatus.h" + +#include "CodeBlock.h" +#include "JSValue.h" +#include "Structure.h" + +namespace JSC { + +static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure* structure, Identifier& identifier) +{ + unsigned attributesIgnored; + JSCell* specificValue; + size_t offset = structure->get( + *codeBlock->globalData(), identifier, attributesIgnored, specificValue); + if (offset == notFound) + return ResolveGlobalStatus(); + + return ResolveGlobalStatus(ResolveGlobalStatus::Simple, structure, offset, specificValue); +} + +static ResolveGlobalStatus computeForLLInt(CodeBlock* codeBlock, unsigned bytecodeIndex, Identifier& identifier) +{ +#if ENABLE(LLINT) + Instruction* instruction = codeBlock->instructions().begin() + bytecodeIndex; + + ASSERT(instruction[0].u.opcode == llint_op_resolve_global); + + Structure* structure = instruction[3].u.structure.get(); + if (!structure) + return ResolveGlobalStatus(); + + return computeForStructure(codeBlock, structure, identifier); +#else + UNUSED_PARAM(codeBlock); + UNUSED_PARAM(bytecodeIndex); + UNUSED_PARAM(identifier); + return ResolveGlobalStatus(); +#endif +} + +ResolveGlobalStatus ResolveGlobalStatus::computeFor(CodeBlock* codeBlock, unsigned bytecodeIndex, Identifier& identifier) +{ +#if ENABLE(JIT) && ENABLE(VALUE_PROFILER) + if (!codeBlock->numberOfGlobalResolveInfos()) + return computeForLLInt(codeBlock, bytecodeIndex, identifier); + + if (codeBlock->likelyToTakeSlowCase(bytecodeIndex)) + return ResolveGlobalStatus(TakesSlowPath); + + GlobalResolveInfo& globalResolveInfo = codeBlock->globalResolveInfoForBytecodeOffset(bytecodeIndex); + + if (!globalResolveInfo.structure) + return computeForLLInt(codeBlock, bytecodeIndex, identifier); + + return computeForStructure(codeBlock, globalResolveInfo.structure.get(), identifier); +#else + return computeForLLInt(codeBlock, bytecodeIndex, identifier); +#endif +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h new file mode 100644 index 000000000..4698332f7 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h @@ -0,0 +1,86 @@ +/* + * 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 ResolveGlobalStatus_h +#define ResolveGlobalStatus_h + +#include "JSValue.h" +#include <wtf/NotFound.h> + +namespace JSC { + +class CodeBlock; +class Identifier; +class Structure; + +class ResolveGlobalStatus { +public: + enum State { + NoInformation, + Simple, + TakesSlowPath + }; + + ResolveGlobalStatus() + : m_state(NoInformation) + , m_structure(0) + , m_offset(notFound) + { + } + + ResolveGlobalStatus( + State state, Structure* structure = 0, size_t offset = notFound, + JSValue specificValue = JSValue()) + : m_state(state) + , m_structure(structure) + , m_offset(offset) + , m_specificValue(specificValue) + { + } + + static ResolveGlobalStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); + + State state() const { return m_state; } + + bool isSet() const { return m_state != NoInformation; } + bool operator!() const { return !isSet(); } + bool isSimple() const { return m_state == Simple; } + bool takesSlowPath() const { return m_state == TakesSlowPath; } + + Structure* structure() const { return m_structure; } + size_t offset() const { return m_offset; } + JSValue specificValue() const { return m_specificValue; } + +private: + State m_state; + Structure* m_structure; + size_t m_offset; + JSValue m_specificValue; +}; // class ResolveGlobalStatus + +} // namespace JSC + +#endif // ResolveGlobalStatus_h + diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 317a08504..75611972e 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -28,6 +28,7 @@ #if ENABLE(DFG_JIT) +#include "ArrayConstructor.h" #include "CallLinkStatus.h" #include "CodeBlock.h" #include "DFGByteCodeCache.h" @@ -35,6 +36,7 @@ #include "GetByIdStatus.h" #include "MethodCallLinkStatus.h" #include "PutByIdStatus.h" +#include "ResolveGlobalStatus.h" #include <wtf/HashMap.h> #include <wtf/MathExtras.h> @@ -94,6 +96,10 @@ private: void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex); // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call. bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction); + bool handleConstantInternalFunction(bool usesResult, int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind); + void handleGetByOffset( + int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber, + bool useInlineStorage, size_t offset); void handleGetById( int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber, const GetByIdStatus&); @@ -1124,7 +1130,12 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct)); NodeIndex callTarget = get(currentInstruction[1].u.operand); - enum { ConstantFunction, LinkedFunction, UnknownFunction } callType; + enum { + ConstantFunction, + ConstantInternalFunction, + LinkedFunction, + UnknownFunction + } callType; CallLinkStatus callLinkStatus = CallLinkStatus::computeFor( m_inlineStackTop->m_profiledBlock, m_currentIndex); @@ -1147,6 +1158,13 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn m_graph.valueOfFunctionConstant(callTarget), m_graph.valueOfFunctionConstant(callTarget)->executable()); #endif + } else if (m_graph.isInternalFunctionConstant(callTarget)) { + callType = ConstantInternalFunction; +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("Call at [@%lu, bc#%u] has an internal function constant: %p.\n", + m_graph.size(), m_currentIndex, + m_graph.valueOfInternalFunctionConstant(callTarget)); +#endif } else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath() && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) { callType = LinkedFunction; @@ -1179,6 +1197,16 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn prediction = getPrediction(); nextOffset += OPCODE_LENGTH(op_call_put_result); } + + if (callType == ConstantInternalFunction) { + if (handleConstantInternalFunction(usesResult, resultOperand, m_graph.valueOfInternalFunctionConstant(callTarget), registerOffset, argumentCountIncludingThis, prediction, kind)) + return; + + // Can only handle this using the generic call handler. + addCall(interpreter, currentInstruction, op); + return; + } + JSFunction* expectedFunction; Intrinsic intrinsic; bool certainAboutExpectedFunction; @@ -1210,7 +1238,7 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn } else if (handleInlining(usesResult, currentInstruction[1].u.operand, callTarget, resultOperand, certainAboutExpectedFunction, expectedFunction, registerOffset, argumentCountIncludingThis, nextOffset, kind)) return; } - + addCall(interpreter, currentInstruction, op); } @@ -1567,6 +1595,60 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins } } +bool ByteCodeParser::handleConstantInternalFunction( + bool usesResult, int resultOperand, InternalFunction* function, int registerOffset, + int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind kind) +{ + // If we ever find that we have a lot of internal functions that we specialize for, + // then we should probably have some sort of hashtable dispatch, or maybe even + // dispatch straight through the MethodTable of the InternalFunction. But for now, + // it seems that this case is hit infrequently enough, and the number of functions + // we know about is small enough, that having just a linear cascade of if statements + // is good enough. + + UNUSED_PARAM(registerOffset); // Remove this once we do more things to the arguments. + UNUSED_PARAM(prediction); // Remove this once we do more things. + UNUSED_PARAM(kind); // Remove this once we do more things. + + if (function->classInfo() == &ArrayConstructor::s_info) { + // We could handle this but don't for now. + if (argumentCountIncludingThis != 1) + return false; + + setIntrinsicResult( + usesResult, resultOperand, + addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0))); + return true; + } + + return false; +} + +void ByteCodeParser::handleGetByOffset( + int destinationOperand, SpeculatedType prediction, NodeIndex base, unsigned identifierNumber, + bool useInlineStorage, size_t offset) +{ + NodeIndex propertyStorage; + size_t offsetOffset; + if (useInlineStorage) { + propertyStorage = base; + ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue))); + offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue); + } else { + propertyStorage = addToGraph(GetPropertyStorage, base); + offsetOffset = 0; + } + set(destinationOperand, + addToGraph( + GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), + propertyStorage)); + + StorageAccessData storageAccessData; + storageAccessData.offset = offset + offsetOffset; + storageAccessData.identifierNumber = identifierNumber; + m_graph.m_storageAccessData.append(storageAccessData); +} + void ByteCodeParser::handleGetById( int destinationOperand, SpeculatedType prediction, NodeIndex base, unsigned identifierNumber, const GetByIdStatus& getByIdStatus) @@ -1620,25 +1702,9 @@ void ByteCodeParser::handleGetById( return; } - NodeIndex propertyStorage; - size_t offsetOffset; - if (useInlineStorage) { - propertyStorage = base; - ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue))); - offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue); - } else { - propertyStorage = addToGraph(GetPropertyStorage, base); - offsetOffset = 0; - } - set(destinationOperand, - addToGraph( - GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), - propertyStorage)); - - StorageAccessData storageAccessData; - storageAccessData.offset = getByIdStatus.offset() + offsetOffset; - storageAccessData.identifierNumber = identifierNumber; - m_graph.m_storageAccessData.append(storageAccessData); + handleGetByOffset( + destinationOperand, prediction, base, identifierNumber, useInlineStorage, + getByIdStatus.offset()); } void ByteCodeParser::prepareToParseBlock() @@ -2648,10 +2714,39 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_resolve_global: { SpeculatedType prediction = getPrediction(); + unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[ + currentInstruction[2].u.operand]; + + ResolveGlobalStatus status = ResolveGlobalStatus::computeFor( + m_inlineStackTop->m_profiledBlock, m_currentIndex, + m_codeBlock->identifier(identifierNumber)); + if (status.isSimple()) { + ASSERT(status.structure()); + + NodeIndex globalObject = addStructureTransitionCheck( + m_inlineStackTop->m_codeBlock->globalObject(), status.structure()); + + if (status.specificValue()) { + ASSERT(status.specificValue().isCell()); + + set(currentInstruction[1].u.operand, + cellConstant(status.specificValue().asCell())); + } else { + handleGetByOffset( + currentInstruction[1].u.operand, prediction, globalObject, + identifierNumber, status.structure()->isUsingInlineStorage(), + status.offset()); + } + + m_globalResolveNumber++; // Skip over the unused global resolve info. + + NEXT_OPCODE(op_resolve_global); + } + NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction)); m_graph.m_resolveGlobalData.append(ResolveGlobalData()); ResolveGlobalData& data = m_graph.m_resolveGlobalData.last(); - data.identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand]; + data.identifierNumber = identifierNumber; data.resolveInfoIndex = m_globalResolveNumber++; set(currentInstruction[1].u.operand, resolve); @@ -3077,6 +3172,8 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry( } m_constantRemap[i] = result.iterator->second; } + for (unsigned i = 0; i < codeBlock->numberOfGlobalResolveInfos(); ++i) + byteCodeParser->m_codeBlock->addGlobalResolveInfo(std::numeric_limits<unsigned>::max()); m_callsiteBlockHeadNeedsLinking = true; } else { @@ -3160,6 +3257,9 @@ void ByteCodeParser::parseCodeBlock() ASSERT(m_inlineStackTop->m_unlinkedBlocks.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex]->bytecodeBegin < m_currentIndex); m_inlineStackTop->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.m_blocks.size())); m_inlineStackTop->m_blockLinkingTargets.append(m_graph.m_blocks.size()); + // The first block is definitely an OSR target. + if (!m_graph.m_blocks.size()) + block->isOSRTarget = true; m_graph.m_blocks.append(block.release()); prepareToParseBlock(); } diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h index 027b0f78b..1aec0bca1 100644 --- a/Source/JavaScriptCore/dfg/DFGCapabilities.h +++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h @@ -193,7 +193,6 @@ inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction case op_put_scoped_var: case op_resolve: case op_resolve_base: - case op_resolve_global: // Constant buffers aren't copied correctly. This is easy to fix, but for // now we just disable inlining for functions that use them. diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h index fce76c68c..c9d3cbc32 100644 --- a/Source/JavaScriptCore/dfg/DFGCommon.h +++ b/Source/JavaScriptCore/dfg/DFGCommon.h @@ -134,6 +134,11 @@ enum NoResultTag { NoResult }; enum OptimizationFixpointState { FixpointConverged, FixpointNotConverged }; +inline bool shouldShowDisassembly() +{ + return Options::showDisassembly || Options::showDFGDisassembly; +} + } } // namespace JSC::DFG #endif // ENABLE(DFG_JIT) diff --git a/Source/JavaScriptCore/dfg/DFGDisassembler.cpp b/Source/JavaScriptCore/dfg/DFGDisassembler.cpp new file mode 100644 index 000000000..1dde37cf2 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGDisassembler.cpp @@ -0,0 +1,115 @@ +/* + * 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 "DFGDisassembler.h" + +#if ENABLE(DFG_JIT) + +#include "DFGGraph.h" + +namespace JSC { namespace DFG { + +Disassembler::Disassembler(Graph& graph) + : m_graph(graph) +{ + m_labelForBlockIndex.resize(graph.m_blocks.size()); + m_labelForNodeIndex.resize(graph.size()); +} + +void Disassembler::dump(LinkBuffer& linkBuffer) +{ + m_graph.m_dominators.computeIfNecessary(m_graph); + + dataLog("Generated JIT code for DFG CodeBlock %p:\n", m_graph.m_codeBlock); + dataLog(" Code at [%p, %p):\n", linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()); + + const char* prefix = " "; + const char* disassemblyPrefix = " "; + + NodeIndex lastNodeIndex = NoNode; + MacroAssembler::Label previousLabel = m_startOfCode; + for (size_t blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { + BasicBlock* block = m_graph.m_blocks[blockIndex].get(); + if (!block) + continue; + dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, m_labelForBlockIndex[blockIndex], lastNodeIndex); + m_graph.dumpBlockHeader(prefix, blockIndex, Graph::DumpLivePhisOnly); + NodeIndex lastNodeIndexForDisassembly = block->at(0); + for (size_t i = 0; i < block->size(); ++i) { + if (!m_graph[block->at(i)].willHaveCodeGen()) + continue; + MacroAssembler::Label currentLabel; + if (m_labelForNodeIndex[block->at(i)].isSet()) + currentLabel = m_labelForNodeIndex[block->at(i)]; + else { + // Dump the last instruction by using the first label of the next block + // as the end point. This case is hit either during peephole compare + // optimizations (the Branch won't have its own label) or if we have a + // forced OSR exit. + if (blockIndex + 1 < m_graph.m_blocks.size()) + currentLabel = m_labelForBlockIndex[blockIndex + 1]; + else + currentLabel = m_endOfMainPath; + } + dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, currentLabel, lastNodeIndexForDisassembly); + m_graph.dumpCodeOrigin(prefix, lastNodeIndex, block->at(i)); + m_graph.dump(prefix, block->at(i)); + lastNodeIndex = block->at(i); + lastNodeIndexForDisassembly = block->at(i); + } + } + dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, m_endOfMainPath, lastNodeIndex); + dataLog("%s(End Of Main Path)\n", prefix); + dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, m_endOfCode, NoNode); +} + +void Disassembler::dumpDisassembly(const char* prefix, LinkBuffer& linkBuffer, MacroAssembler::Label& previousLabel, MacroAssembler::Label currentLabel, NodeIndex context) +{ + size_t prefixLength = strlen(prefix); + int amountOfNodeWhiteSpace; + if (context == NoNode) + amountOfNodeWhiteSpace = 0; + else + amountOfNodeWhiteSpace = Graph::amountOfNodeWhiteSpace(m_graph[context]); + OwnArrayPtr<char> prefixBuffer = adoptArrayPtr(new char[prefixLength + amountOfNodeWhiteSpace + 1]); + strcpy(prefixBuffer.get(), prefix); + for (int i = 0; i < amountOfNodeWhiteSpace; ++i) + prefixBuffer[i + prefixLength] = ' '; + prefixBuffer[prefixLength + amountOfNodeWhiteSpace] = 0; + + CodeLocationLabel start = linkBuffer.locationOf(previousLabel); + CodeLocationLabel end = linkBuffer.locationOf(currentLabel); + previousLabel = currentLabel; + ASSERT(bitwise_cast<uintptr_t>(end.executableAddress()) >= bitwise_cast<uintptr_t>(start.executableAddress())); + if (tryToDisassemble(start, bitwise_cast<uintptr_t>(end.executableAddress()) - bitwise_cast<uintptr_t>(start.executableAddress()), prefixBuffer.get(), WTF::dataFile())) + return; + + dataLog("%s disassembly not available for range %p...%p\n", prefixBuffer.get(), start.executableAddress(), end.executableAddress()); +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) diff --git a/Source/JavaScriptCore/dfg/DFGDisassembler.h b/Source/JavaScriptCore/dfg/DFGDisassembler.h new file mode 100644 index 000000000..470a989ef --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGDisassembler.h @@ -0,0 +1,82 @@ +/* + * 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 DFGDisassembler_h +#define DFGDisassembler_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +#include "DFGCommon.h" +#include "LinkBuffer.h" +#include "MacroAssembler.h" +#include <wtf/Vector.h> + +namespace JSC { namespace DFG { + +class Graph; + +class Disassembler { + WTF_MAKE_FAST_ALLOCATED; +public: + Disassembler(Graph&); + + void setStartOfCode(MacroAssembler::Label label) { m_startOfCode = label; } + void setForBlock(BlockIndex blockIndex, MacroAssembler::Label label) + { + m_labelForBlockIndex[blockIndex] = label; + } + void setForNode(NodeIndex nodeIndex, MacroAssembler::Label label) + { + m_labelForNodeIndex[nodeIndex] = label; + } + void setEndOfMainPath(MacroAssembler::Label label) + { + m_endOfMainPath = label; + } + void setEndOfCode(MacroAssembler::Label label) + { + m_endOfCode = label; + } + + void dump(LinkBuffer&); + +private: + void dumpDisassembly(const char* prefix, LinkBuffer&, MacroAssembler::Label& previousLabel, MacroAssembler::Label currentLabel, NodeIndex context); + + Graph& m_graph; + MacroAssembler::Label m_startOfCode; + Vector<MacroAssembler::Label> m_labelForBlockIndex; + Vector<MacroAssembler::Label> m_labelForNodeIndex; + MacroAssembler::Label m_endOfMainPath; + MacroAssembler::Label m_endOfCode; +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGDisassembler_h diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp index e932792df..5033aa2c0 100644 --- a/Source/JavaScriptCore/dfg/DFGDriver.cpp +++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp @@ -43,11 +43,20 @@ namespace JSC { namespace DFG { +static unsigned numCompilations; + +unsigned getNumCompilations() +{ + return numCompilations; +} + enum CompileMode { CompileFunction, CompileOther }; inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck) { SamplingRegion samplingRegion("DFG Compilation (Driver)"); + numCompilations++; + ASSERT(codeBlock); ASSERT(codeBlock->alternative()); ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT); @@ -92,7 +101,6 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("DFG optimization fixpoint converged in %u iterations.\n", cnt); #endif - dfg.m_dominators.compute(dfg); performVirtualRegisterAllocation(dfg); GraphDumpMode modeForFinalValidate = DumpGraph; diff --git a/Source/JavaScriptCore/dfg/DFGDriver.h b/Source/JavaScriptCore/dfg/DFGDriver.h index ce798d0a6..a6e82fef5 100644 --- a/Source/JavaScriptCore/dfg/DFGDriver.h +++ b/Source/JavaScriptCore/dfg/DFGDriver.h @@ -38,6 +38,8 @@ class MacroAssemblerCodePtr; namespace DFG { +JS_EXPORT_PRIVATE unsigned getNumCompilations(); + #if ENABLE(DFG_JIT) bool tryCompile(ExecState*, CodeBlock*, JITCode&); bool tryCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr& jitCodeWithArityCheck); diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp index 93de024d7..4689470c8 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.cpp +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -89,7 +89,7 @@ static void printWhiteSpace(unsigned amount) dataLog(" "); } -void Graph::dumpCodeOrigin(NodeIndex prevNodeIndex, NodeIndex nodeIndex) +void Graph::dumpCodeOrigin(const char* prefix, NodeIndex prevNodeIndex, NodeIndex nodeIndex) { if (prevNodeIndex == NoNode) return; @@ -112,18 +112,30 @@ void Graph::dumpCodeOrigin(NodeIndex prevNodeIndex, NodeIndex nodeIndex) // Print the pops. for (unsigned i = previousInlineStack.size(); i-- > indexOfDivergence;) { + dataLog("%s", prefix); printWhiteSpace(i * 2); dataLog("<-- %p\n", previousInlineStack[i].inlineCallFrame->executable.get()); } // Print the pushes. for (unsigned i = indexOfDivergence; i < currentInlineStack.size(); ++i) { + dataLog("%s", prefix); printWhiteSpace(i * 2); dataLog("--> %p\n", currentInlineStack[i].inlineCallFrame->executable.get()); } } -void Graph::dump(NodeIndex nodeIndex) +int Graph::amountOfNodeWhiteSpace(Node& node) +{ + return (node.codeOrigin.inlineDepth() - 1) * 2; +} + +void Graph::printNodeWhiteSpace(Node& node) +{ + printWhiteSpace(amountOfNodeWhiteSpace(node)); +} + +void Graph::dump(const char* prefix, NodeIndex nodeIndex) { Node& node = at(nodeIndex); NodeType op = node.op(); @@ -134,7 +146,8 @@ void Graph::dump(NodeIndex nodeIndex) if (mustGenerate) --refCount; - printWhiteSpace((node.codeOrigin.inlineDepth() - 1) * 2); + dataLog("%s", prefix); + printNodeWhiteSpace(node); // Example/explanation of dataflow dump output // @@ -288,6 +301,54 @@ void Graph::dump(NodeIndex nodeIndex) dataLog("\n"); } +void Graph::dumpBlockHeader(const char* prefix, BlockIndex blockIndex, PhiNodeDumpMode phiNodeDumpMode) +{ + BasicBlock* block = m_blocks[blockIndex].get(); + + dataLog("%sBlock #%u (bc#%u): %s%s\n", prefix, (int)blockIndex, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : ""); + dataLog("%s Predecessors:", prefix); + for (size_t i = 0; i < block->m_predecessors.size(); ++i) + dataLog(" #%u", block->m_predecessors[i]); + dataLog("\n"); + if (m_dominators.isValid()) { + dataLog("%s Dominated by:", prefix); + for (size_t i = 0; i < m_blocks.size(); ++i) { + if (!m_dominators.dominates(i, blockIndex)) + continue; + dataLog(" #%lu", static_cast<unsigned long>(i)); + } + dataLog("\n"); + dataLog("%s Dominates:", prefix); + for (size_t i = 0; i < m_blocks.size(); ++i) { + if (!m_dominators.dominates(blockIndex, i)) + continue; + dataLog(" #%lu", static_cast<unsigned long>(i)); + } + dataLog("\n"); + } + dataLog("%s Phi Nodes:", prefix); + unsigned count = 0; + for (size_t i = 0; i < block->phis.size(); ++i) { + NodeIndex phiNodeIndex = block->phis[i]; + Node& phiNode = at(phiNodeIndex); + if (!phiNode.shouldGenerate() && phiNodeDumpMode == DumpLivePhisOnly) + continue; + if (!((++count) % 4)) + dataLog("\n%s ", prefix); + dataLog(" @%u->(", phiNodeIndex); + if (phiNode.child1()) { + dataLog("@%u", phiNode.child1().index()); + if (phiNode.child2()) { + dataLog(", @%u", phiNode.child2().index()); + if (phiNode.child3()) + dataLog(", @%u", phiNode.child3().index()); + } + } + dataLog(")%s", i + 1 < block->phis.size() ? "," : ""); + } + dataLog("\n"); +} + void Graph::dump() { NodeIndex lastNodeIndex = NoNode; @@ -295,33 +356,7 @@ void Graph::dump() BasicBlock* block = m_blocks[b].get(); if (!block) continue; - dataLog("Block #%u (bc#%u): %s%s\n", (int)b, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : ""); - dataLog(" Predecessors:"); - for (size_t i = 0; i < block->m_predecessors.size(); ++i) - dataLog(" #%u", block->m_predecessors[i]); - dataLog("\n"); - if (m_dominators.isValid()) { - dataLog(" Dominated by:"); - for (size_t i = 0; i < m_blocks.size(); ++i) { - if (!m_dominators.dominates(i, b)) - continue; - dataLog(" #%lu", static_cast<unsigned long>(i)); - } - dataLog("\n"); - dataLog(" Dominates:"); - for (size_t i = 0; i < m_blocks.size(); ++i) { - if (!m_dominators.dominates(b, i)) - continue; - dataLog(" #%lu", static_cast<unsigned long>(i)); - } - dataLog("\n"); - } - dataLog(" Phi Nodes:\n"); - for (size_t i = 0; i < block->phis.size(); ++i) { - dumpCodeOrigin(lastNodeIndex, block->phis[i]); - dump(block->phis[i]); - lastNodeIndex = block->phis[i]; - } + dumpBlockHeader("", b, DumpAllPhis); dataLog(" vars before: "); if (block->cfaHasVisited) dumpOperands(block->valuesAtHead, WTF::dataFile()); @@ -332,8 +367,8 @@ void Graph::dump() dumpOperands(block->variablesAtHead, WTF::dataFile()); dataLog("\n"); for (size_t i = 0; i < block->size(); ++i) { - dumpCodeOrigin(lastNodeIndex, block->at(i)); - dump(block->at(i)); + dumpCodeOrigin("", lastNodeIndex, block->at(i)); + dump("", block->at(i)); lastNodeIndex = block->at(i); } dataLog(" vars after: "); diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index acc9ff472..9e4a28fc3 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -179,11 +179,15 @@ public: // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names). void dump(); - void dump(NodeIndex); + enum PhiNodeDumpMode { DumpLivePhisOnly, DumpAllPhis }; + void dumpBlockHeader(const char* prefix, BlockIndex, PhiNodeDumpMode); + void dump(const char* prefix, NodeIndex); + static int amountOfNodeWhiteSpace(Node&); + static void printNodeWhiteSpace(Node&); // Dump the code origin of the given node as a diff from the code origin of the // preceding node. - void dumpCodeOrigin(NodeIndex, NodeIndex); + void dumpCodeOrigin(const char* prefix, NodeIndex, NodeIndex); BlockIndex blockIndexForBytecodeOffset(Vector<BlockIndex>& blocks, unsigned bytecodeBegin); @@ -273,6 +277,18 @@ public: return false; return true; } + bool isInternalFunctionConstant(NodeIndex nodeIndex) + { + if (!isJSConstant(nodeIndex)) + return false; + JSValue value = valueOfJSConstant(nodeIndex); + if (!value.isCell() || !value) + return false; + JSCell* cell = value.asCell(); + if (!cell->inherits(&InternalFunction::s_info)) + return false; + return true; + } // Helper methods get constant values from nodes. JSValue valueOfJSConstant(NodeIndex nodeIndex) { @@ -296,6 +312,10 @@ public: ASSERT(function); return jsCast<JSFunction*>(function); } + InternalFunction* valueOfInternalFunctionConstant(NodeIndex nodeIndex) + { + return jsCast<InternalFunction*>(valueOfJSConstant(nodeIndex).asCell()); + } static const char *opName(NodeType); diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp index 561f51615..3c85cc77c 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp @@ -40,6 +40,15 @@ namespace JSC { namespace DFG { +JITCompiler::JITCompiler(Graph& dfg) + : CCallHelpers(&dfg.m_globalData, dfg.m_codeBlock) + , m_graph(dfg) + , m_currentCodeOriginIndex(0) +{ + if (shouldShowDisassembly()) + m_disassembler = adoptPtr(new Disassembler(dfg)); +} + void JITCompiler::linkOSRExits() { for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) { @@ -201,9 +210,11 @@ void JITCompiler::link(LinkBuffer& linkBuffer) bool JITCompiler::compile(JITCode& entry) { + setStartOfCode(); compileEntry(); SpeculativeJIT speculative(*this); compileBody(speculative); + setEndOfMainPath(); // Generate slow path code. speculative.runSlowPathGenerators(); @@ -213,6 +224,7 @@ bool JITCompiler::compile(JITCode& entry) // Create OSR entry trampolines if necessary. speculative.createOSREntries(); + setEndOfCode(); LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock, JITCompilationCanFail); if (linkBuffer.didFailToAllocate()) @@ -220,14 +232,18 @@ bool JITCompiler::compile(JITCode& entry) link(linkBuffer); speculative.linkOSREntries(linkBuffer); + if (m_disassembler) + m_disassembler->dump(linkBuffer); + entry = JITCode( - FINALIZE_CODE(linkBuffer, ("DFG program/eval CodeBlock %p", m_codeBlock)), + linkBuffer.finalizeCodeWithoutDisassembly(), JITCode::DFGJIT); return true; } bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck) { + setStartOfCode(); compileEntry(); // === Function header code generation === @@ -246,6 +262,7 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi // === Function body code generation === SpeculativeJIT speculative(*this); compileBody(speculative); + setEndOfMainPath(); // === Function footer code generation === // @@ -290,7 +307,7 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi // Create OSR entry trampolines if necessary. speculative.createOSREntries(); - + setEndOfCode(); // === Link === LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock, JITCompilationCanFail); @@ -302,10 +319,13 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs. linkBuffer.link(callRegisterFileCheck, cti_register_file_check); linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck); + + if (m_disassembler) + m_disassembler->dump(linkBuffer); entryWithArityCheck = linkBuffer.locationOf(arityCheck); entry = JITCode( - FINALIZE_CODE(linkBuffer, ("DFG function CodeBlock %p", m_codeBlock)), + linkBuffer.finalizeCodeWithoutDisassembly(), JITCode::DFGJIT); return true; } diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h index 9d69ec9f3..ed16459cc 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h @@ -30,6 +30,7 @@ #include "CodeBlock.h" #include "DFGCCallHelpers.h" +#include "DFGDisassembler.h" #include "DFGFPRInfo.h" #include "DFGGPRInfo.h" #include "DFGGraph.h" @@ -208,12 +209,7 @@ struct PropertyAccessRecord { // call to be linked). class JITCompiler : public CCallHelpers { public: - JITCompiler(Graph& dfg) - : CCallHelpers(&dfg.m_globalData, dfg.m_codeBlock) - , m_graph(dfg) - , m_currentCodeOriginIndex(0) - { - } + JITCompiler(Graph& dfg); bool compile(JITCode& entry); bool compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck); @@ -221,6 +217,42 @@ public: // Accessors for properties. Graph& graph() { return m_graph; } + // Methods to set labels for the disassembler. + void setStartOfCode() + { + if (LIKELY(!m_disassembler)) + return; + m_disassembler->setStartOfCode(labelIgnoringWatchpoints()); + } + + void setForBlock(BlockIndex blockIndex) + { + if (LIKELY(!m_disassembler)) + return; + m_disassembler->setForBlock(blockIndex, labelIgnoringWatchpoints()); + } + + void setForNode(NodeIndex nodeIndex) + { + if (LIKELY(!m_disassembler)) + return; + m_disassembler->setForNode(nodeIndex, labelIgnoringWatchpoints()); + } + + void setEndOfMainPath() + { + if (LIKELY(!m_disassembler)) + return; + m_disassembler->setEndOfMainPath(labelIgnoringWatchpoints()); + } + + void setEndOfCode() + { + if (LIKELY(!m_disassembler)) + return; + m_disassembler->setEndOfCode(labelIgnoringWatchpoints()); + } + // Get a token for beginning a call, and set the current code origin index in // the call frame. CallBeginToken beginCall() @@ -353,6 +385,8 @@ private: // The dataflow graph currently being generated. Graph& m_graph; + OwnPtr<Disassembler> m_disassembler; + // Vector of calls out from JIT code, including exception handler information. // Count of the number of CallRecords with exception handlers. Vector<CallLinkRecord> m_calls; diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index 64e6fe097..40701c3bd 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -730,6 +730,11 @@ struct Node { { return m_refCount; } + + bool willHaveCodeGen() + { + return shouldGenerate() && op() != Phantom && op() != Nop; + } unsigned refCount() { diff --git a/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp index ca6257401..480a7dab9 100644 --- a/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp +++ b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp @@ -46,19 +46,19 @@ const char* nodeFlagsAsString(NodeFlags flags) if (flags & NodeResultMask) { switch (flags & NodeResultMask) { case NodeResultJS: - ptr.strcat("ResultJS"); + ptr.strcat("JS"); break; case NodeResultNumber: - ptr.strcat("ResultNumber"); + ptr.strcat("Number"); break; case NodeResultInt32: - ptr.strcat("ResultInt32"); + ptr.strcat("Int32"); break; case NodeResultBoolean: - ptr.strcat("ResultBoolean"); + ptr.strcat("Boolean"); break; case NodeResultStorage: - ptr.strcat("ResultStorage"); + ptr.strcat("Storage"); break; default: ASSERT_NOT_REACHED(); @@ -70,21 +70,21 @@ const char* nodeFlagsAsString(NodeFlags flags) if (flags & NodeMustGenerate) { if (hasPrinted) ptr.strcat("|"); - ptr.strcat("MustGenerate"); + ptr.strcat("MustGen"); hasPrinted = true; } if (flags & NodeHasVarArgs) { if (hasPrinted) ptr.strcat("|"); - ptr.strcat("HasVarArgs"); + ptr.strcat("VarArgs"); hasPrinted = true; } if (flags & NodeClobbersWorld) { if (hasPrinted) ptr.strcat("|"); - ptr.strcat("ClobbersWorld"); + ptr.strcat("Clobbers"); hasPrinted = true; } @@ -95,18 +95,23 @@ const char* nodeFlagsAsString(NodeFlags flags) hasPrinted = true; } - if (flags & NodeUsedAsNumber) { - if (hasPrinted) - ptr.strcat("|"); - ptr.strcat("UsedAsNum"); - hasPrinted = true; - } - - if (flags & NodeNeedsNegZero) { - if (hasPrinted) - ptr.strcat("|"); - ptr.strcat("NeedsNegZero"); - hasPrinted = true; + if (flags & NodeResultMask) { + if (!(flags & NodeUsedAsNumber) && !(flags & NodeNeedsNegZero)) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("PureInt"); + hasPrinted = true; + } else if (!(flags & NodeUsedAsNumber)) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("PureInt(w/ neg zero)"); + hasPrinted = true; + } else if (!(flags & NodeNeedsNegZero)) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("PureNum"); + hasPrinted = true; + } } if (flags & NodeMayOverflow) { @@ -126,7 +131,7 @@ const char* nodeFlagsAsString(NodeFlags flags) if (flags & NodeUsedAsInt) { if (hasPrinted) ptr.strcat("|"); - ptr.strcat("UsedAsInt"); + ptr.strcat("UseAsInt"); hasPrinted = true; } diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp index d46d59650..e617b5479 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp @@ -115,7 +115,10 @@ void OSRExitCompiler::handleExitCounts(const OSRExit& exit) m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter())); m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); + m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0); + tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(Options::forcedOSRExitCountForReoptimization))); + } else { // Proceed based on the assumption that we can handle these exits so long as they // don't get too frequent. @@ -136,8 +139,14 @@ void OSRExitCompiler::handleExitCounts(const OSRExit& exit) } // Reoptimize as soon as possible. - m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); - m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); +#if !NUMBER_OF_ARGUMENT_REGISTERS + m_jit.poke(GPRInfo::regT0); +#else + m_jit.move(GPRInfo::regT0, GPRInfo::argumentGPR0); + ASSERT(GPRInfo::argumentGPR0 != GPRInfo::regT1); +#endif + m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::regT1); + m_jit.call(GPRInfo::regT1); AssemblyHelpers::Jump doneAdjusting = m_jit.jump(); tooFewFails.link(&m_jit); diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 06a1cf883..b056a3c6d 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -32,14 +32,15 @@ #include "DFGRepatch.h" #include "HostCallReturnValue.h" #include "GetterSetter.h" -#include <wtf/InlineASM.h> #include "Interpreter.h" +#include "JIT.h" #include "JITExceptions.h" #include "JSActivation.h" #include "JSGlobalData.h" #include "JSStaticScopeObject.h" #include "NameInstance.h" #include "Operations.h" +#include <wtf/InlineASM.h> #if ENABLE(DFG_JIT) @@ -968,13 +969,11 @@ EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState* exec, Iden return JSValue::encode(base); } -EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState* exec, GlobalResolveInfo* resolveInfo, Identifier* propertyName) +EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState* exec, GlobalResolveInfo* resolveInfo, JSGlobalObject* globalObject, Identifier* propertyName) { JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); - JSGlobalObject* globalObject = exec->lexicalGlobalObject(); - PropertySlot slot(globalObject); if (globalObject->getPropertySlot(exec, *propertyName, slot)) { JSValue result = slot.getValue(exec, *propertyName); @@ -1253,6 +1252,27 @@ void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* } #endif +extern "C" void DFG_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock) +{ +#if ENABLE(JIT_VERBOSE_OSR) + dataLog("%p: Entered reoptimize\n", codeBlock); +#endif + // We must be called with the baseline code block. + ASSERT(JITCode::isBaselineCode(codeBlock->getJITType())); + + // If I am my own replacement, then reoptimization has already been triggered. + // This can happen in recursive functions. + if (codeBlock->replacement() == codeBlock) + return; + + // Otherwise, the replacement must be optimized code. Use this as an opportunity + // to check our logic. + ASSERT(codeBlock->hasOptimizedReplacement()); + ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT); + + codeBlock->reoptimize(); +} + } // extern "C" } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index 38166a83f..7477ab2fc 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -65,7 +65,7 @@ typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EA)(ExecState*, JSArray*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGI)(ExecState*, GlobalResolveInfo*, Identifier*); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGriJsgI)(ExecState*, GlobalResolveInfo*, JSGlobalObject*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EI)(ExecState*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJ)(ExecState*, EncodedJSValue); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJA)(ExecState*, EncodedJSValue, JSArray*); @@ -121,7 +121,7 @@ void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet) W EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*) WTF_INTERNAL; -EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, Identifier*) WTF_INTERNAL; +EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, JSGlobalObject*, Identifier*) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t) WTF_INTERNAL; @@ -227,6 +227,8 @@ size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue) WTF_ void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*) WTF_INTERNAL; #endif +void DFG_OPERATION triggerReoptimizationNow(CodeBlock*) WTF_INTERNAL; + } // extern "C" } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index 852f74387..d9a79f13a 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -1026,6 +1026,7 @@ void SpeculativeJIT::compile(BasicBlock& block) for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) { m_compileIndex = block[m_indexInBlock]; + m_jit.setForNode(m_compileIndex); Node& node = at(m_compileIndex); m_codeOriginForOSR = node.codeOrigin; if (!node.shouldGenerate()) { @@ -1321,6 +1322,7 @@ bool SpeculativeJIT::compile() ASSERT(!m_compileIndex); for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) { + m_jit.setForBlock(m_block); BasicBlock* block = m_jit.graph().m_blocks[m_block].get(); if (block) compile(*block); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index 933784685..6c6948b90 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -1229,9 +1229,9 @@ public: m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result); return call; } - JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg result, GPRReg arg1, Identifier* identifier) + JITCompiler::Call callOperation(J_DFGOperation_EGriJsgI operation, GPRReg result, GPRReg arg1, GPRReg arg2, Identifier* identifier) { - m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier)); + m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(identifier)); return appendCallWithExceptionCheckSetResult(operation, result); } JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg result, Identifier* identifier) @@ -1482,9 +1482,9 @@ public: m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer)); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } - JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier) + JITCompiler::Call callOperation(J_DFGOperation_EGriJsgI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2, Identifier* identifier) { - m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier)); + m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(identifier)); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1) @@ -2369,7 +2369,7 @@ public: Vector<SlowPathGenerator*, 8> m_slowPathGenerators; // doesn't use OwnPtr<> because I don't want to include DFGSlowPathGenerator.h Vector<SilentRegisterSavePlan> m_plans; - + ValueRecovery computeValueRecoveryFor(const ValueSource&); ValueRecovery computeValueRecoveryFor(int operand) diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 0c33e0748..21d94e9e8 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -3840,7 +3840,7 @@ void SpeculativeJIT::compile(Node& node) addSlowPathGenerator( slowPathCall( structuresNotMatch, this, operationResolveGlobal, - JSValueRegs(resultTagGPR, resultPayloadGPR), resolveInfoGPR, + JSValueRegs(resultTagGPR, resultPayloadGPR), resolveInfoGPR, globalObjectGPR, &m_jit.codeBlock()->identifier(data.identifierNumber))); jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 0b7606b2c..a6c283584 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -3843,11 +3843,11 @@ void SpeculativeJIT::compile(Node& node) m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfPropertyStorage()), resultGPR); m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR); m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr), resultGPR); - + addSlowPathGenerator( slowPathCall( structuresDontMatch, this, operationResolveGlobal, - resultGPR, resolveInfoGPR, + resultGPR, resolveInfoGPR, globalObjectGPR, &m_jit.codeBlock()->identifier(data.identifierNumber))); jsValueResult(resultGPR, m_compileIndex); diff --git a/Source/JavaScriptCore/heap/HeapTimer.cpp b/Source/JavaScriptCore/heap/HeapTimer.cpp index bc42032f5..b4d928a34 100644 --- a/Source/JavaScriptCore/heap/HeapTimer.cpp +++ b/Source/JavaScriptCore/heap/HeapTimer.cpp @@ -1,3 +1,28 @@ +/* + * 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 "HeapTimer.h" diff --git a/Source/JavaScriptCore/heap/HeapTimer.h b/Source/JavaScriptCore/heap/HeapTimer.h index ccd6ba8c5..fea013975 100644 --- a/Source/JavaScriptCore/heap/HeapTimer.h +++ b/Source/JavaScriptCore/heap/HeapTimer.h @@ -1,3 +1,28 @@ +/* + * 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 HeapTimer_h #define HeapTimer_h diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp index 0d0116f42..165bfeaff 100644 --- a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp +++ b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp @@ -1,3 +1,28 @@ +/* + * 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 "IncrementalSweeper.h" @@ -14,9 +39,10 @@ namespace JSC { #if USE(CF) -static const CFTimeInterval sweepTimeSlicePerBlock = 0.01; -static const CFTimeInterval sweepTimeMultiplier = 1.0 / sweepTimeSlicePerBlock; - +static const CFTimeInterval sweepTimeSlice = .01; // seconds +static const CFTimeInterval sweepTimeTotal = .10; +static const CFTimeInterval sweepTimeMultiplier = 1.0 / sweepTimeTotal; + void IncrementalSweeper::doWork() { APIEntryShim shim(m_globalData); @@ -26,7 +52,6 @@ void IncrementalSweeper::doWork() IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop) : HeapTimer(heap->globalData(), runLoop) , m_currentBlockToSweepIndex(0) - , m_lengthOfLastSweepIncrement(0.0) { } @@ -37,7 +62,7 @@ PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap) void IncrementalSweeper::scheduleTimer() { - CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + (m_lengthOfLastSweepIncrement * sweepTimeMultiplier)); + CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + (sweepTimeSlice * sweepTimeMultiplier)); } void IncrementalSweeper::cancelTimer() @@ -47,14 +72,17 @@ void IncrementalSweeper::cancelTimer() void IncrementalSweeper::doSweep(double sweepBeginTime) { - for (; m_currentBlockToSweepIndex < m_blocksToSweep.size(); m_currentBlockToSweepIndex++) { - MarkedBlock* nextBlock = m_blocksToSweep[m_currentBlockToSweepIndex]; - if (!nextBlock->needsSweeping()) + while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) { + MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++]; + if (!block->needsSweeping()) + continue; + + block->sweep(); + + CFTimeInterval elapsedTime = WTF::monotonicallyIncreasingTime() - sweepBeginTime; + if (elapsedTime < sweepTimeSlice) continue; - nextBlock->sweep(); - m_blocksToSweep[m_currentBlockToSweepIndex++] = 0; - m_lengthOfLastSweepIncrement = WTF::monotonicallyIncreasingTime() - sweepBeginTime; scheduleTimer(); return; } diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.h b/Source/JavaScriptCore/heap/IncrementalSweeper.h index 80d674ca9..20f4e3ca8 100644 --- a/Source/JavaScriptCore/heap/IncrementalSweeper.h +++ b/Source/JavaScriptCore/heap/IncrementalSweeper.h @@ -1,3 +1,28 @@ +/* + * 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 IncrementalSweeper_h #define IncrementalSweeper_h @@ -27,7 +52,6 @@ private: void cancelTimer(); unsigned m_currentBlockToSweepIndex; - double m_lengthOfLastSweepIncrement; Vector<MarkedBlock*> m_blocksToSweep; #else diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp index 06190f118..7eb57479b 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp @@ -45,7 +45,6 @@ #elif OS(UNIX) -#include <stdlib.h> #include <sys/mman.h> #include <unistd.h> @@ -142,8 +141,10 @@ MachineThreads::MachineThreads(Heap* heap) MachineThreads::~MachineThreads() { - if (m_threadSpecific) - ThreadSpecificKeyDelete(m_threadSpecific); + if (m_threadSpecific) { + int error = pthread_key_delete(m_threadSpecific); + ASSERT_UNUSED(error, !error); + } MutexLocker registeredThreadsLock(m_registeredThreadsMutex); for (Thread* t = m_registeredThreads; t;) { @@ -180,17 +181,19 @@ void MachineThreads::makeUsableFromMultipleThreads() if (m_threadSpecific) return; - ThreadSpecificKeyCreate(&m_threadSpecific, removeThread); + int error = pthread_key_create(&m_threadSpecific, removeThread); + if (error) + CRASH(); } void MachineThreads::addCurrentThread() { ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); - if (!m_threadSpecific || ThreadSpecificGet(m_threadSpecific)) + if (!m_threadSpecific || pthread_getspecific(m_threadSpecific)) return; - ThreadSpecificSet(m_threadSpecific, this); + pthread_setspecific(m_threadSpecific, this); Thread* thread = new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin()); MutexLocker lock(m_registeredThreadsMutex); diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.h b/Source/JavaScriptCore/heap/MachineStackMarker.h index 2209f97e9..0f5a4c3aa 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.h +++ b/Source/JavaScriptCore/heap/MachineStackMarker.h @@ -22,8 +22,8 @@ #ifndef MachineThreads_h #define MachineThreads_h +#include <pthread.h> #include <wtf/Noncopyable.h> -#include <wtf/ThreadSpecific.h> #include <wtf/ThreadingPrimitives.h> namespace JSC { @@ -55,7 +55,7 @@ namespace JSC { Heap* m_heap; Mutex m_registeredThreadsMutex; Thread* m_registeredThreads; - WTF::ThreadSpecificKey m_threadSpecific; + pthread_key_t m_threadSpecific; }; } // namespace JSC diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.cpp b/Source/JavaScriptCore/heap/MarkedAllocator.cpp index 9552a54ea..9cac906a1 100644 --- a/Source/JavaScriptCore/heap/MarkedAllocator.cpp +++ b/Source/JavaScriptCore/heap/MarkedAllocator.cpp @@ -107,8 +107,10 @@ void MarkedAllocator::addBlock(MarkedBlock* block) void MarkedAllocator::removeBlock(MarkedBlock* block) { - if (m_currentBlock == block) - m_currentBlock = 0; + if (m_currentBlock == block) { + m_currentBlock = static_cast<MarkedBlock*>(m_currentBlock->next()); + m_freeList = MarkedBlock::FreeList(); + } m_blockList.remove(block); } diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp index 42247a385..a742d8d9a 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.cpp +++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp @@ -30,38 +30,37 @@ namespace JSC { class Structure; -class Take { +class Free { public: typedef MarkedBlock* ReturnType; - enum TakeMode { TakeIfEmpty, TakeAll }; + enum FreeMode { FreeOrShrink, FreeAll }; - Take(TakeMode, MarkedSpace*); + Free(FreeMode, MarkedSpace*); void operator()(MarkedBlock*); ReturnType returnValue(); private: - TakeMode m_takeMode; + FreeMode m_freeMode; MarkedSpace* m_markedSpace; DoublyLinkedList<MarkedBlock> m_blocks; }; -inline Take::Take(TakeMode takeMode, MarkedSpace* newSpace) - : m_takeMode(takeMode) +inline Free::Free(FreeMode freeMode, MarkedSpace* newSpace) + : m_freeMode(freeMode) , m_markedSpace(newSpace) { } -inline void Take::operator()(MarkedBlock* block) +inline void Free::operator()(MarkedBlock* block) { - if (m_takeMode == TakeIfEmpty && !block->isEmpty()) - return; - - m_markedSpace->allocatorFor(block).removeBlock(block); - m_blocks.append(block); + if (m_freeMode == FreeOrShrink) + m_markedSpace->freeOrShrinkBlock(block); + else + m_markedSpace->freeBlock(block); } -inline Take::ReturnType Take::returnValue() +inline Free::ReturnType Free::returnValue() { return m_blocks.head(); } @@ -93,9 +92,8 @@ MarkedSpace::MarkedSpace(Heap* heap) MarkedSpace::~MarkedSpace() { - // We record a temporary list of empties to avoid modifying m_blocks while iterating it. - Take take(Take::TakeAll, this); - freeBlocks(forEachBlock(take)); + Free free(Free::FreeAll, this); + forEachBlock(free); } struct LastChanceToFinalize : MarkedBlock::VoidFunctor { @@ -160,17 +158,21 @@ bool MarkedSpace::isPagedOut(double deadline) return false; } -void MarkedSpace::freeBlocks(MarkedBlock* head) +void MarkedSpace::freeBlock(MarkedBlock* block) { - MarkedBlock* next; - for (MarkedBlock* block = head; block; block = next) { - next = static_cast<MarkedBlock*>(block->next()); - - m_blocks.remove(block); - block->sweep(); + allocatorFor(block).removeBlock(block); + m_blocks.remove(block); + m_heap->blockAllocator().deallocate(MarkedBlock::destroy(block)); +} - m_heap->blockAllocator().deallocate(MarkedBlock::destroy(block)); +void MarkedSpace::freeOrShrinkBlock(MarkedBlock* block) +{ + if (!block->isEmpty()) { + block->shrink(); + return; } + + freeBlock(block); } struct Shrink : MarkedBlock::VoidFunctor { @@ -179,11 +181,8 @@ struct Shrink : MarkedBlock::VoidFunctor { void MarkedSpace::shrink() { - // We record a temporary list of empties to avoid modifying m_blocks while iterating it. - Take takeIfEmpty(Take::TakeIfEmpty, this); - freeBlocks(forEachBlock(takeIfEmpty)); - - forEachBlock<Shrink>(); + Free freeOrShrink(Free::FreeOrShrink, this); + forEachBlock(freeOrShrink); } #if ENABLE(GGC) diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h index 3f82bac96..62d4e5d9e 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.h +++ b/Source/JavaScriptCore/heap/MarkedSpace.h @@ -98,7 +98,8 @@ public: template<typename Functor> typename Functor::ReturnType forEachBlock(); void shrink(); - void freeBlocks(MarkedBlock* head); + void freeBlock(MarkedBlock*); + void freeOrShrinkBlock(MarkedBlock*); void didAddBlock(MarkedBlock*); void didConsumeFreeList(MarkedBlock*); diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp index 2aca35146..e1e034b19 100644 --- a/Source/JavaScriptCore/jit/JIT.cpp +++ b/Source/JavaScriptCore/jit/JIT.cpp @@ -100,9 +100,10 @@ void JIT::emitOptimizationCheck(OptimizationCheckKind kind) return; 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(TrustedImm32(m_bytecodeOffset)); + JITStubCall stubCall(this, cti_optimize); + stubCall.addArgument(TrustedImm32(m_bytecodeOffset)); + if (kind == EnterOptimizationCheck) + ASSERT(!m_bytecodeOffset); stubCall.call(); skipOptimize.link(this); } diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h index 6491edbed..6d4c578c0 100644 --- a/Source/JavaScriptCore/jit/JIT.h +++ b/Source/JavaScriptCore/jit/JIT.h @@ -806,7 +806,7 @@ namespace JSC { // Loads the character value of a single character string into dst. void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures); - enum OptimizationCheckKind { LoopOptimizationCheck, RetOptimizationCheck }; + enum OptimizationCheckKind { LoopOptimizationCheck, EnterOptimizationCheck }; #if ENABLE(DFG_JIT) void emitOptimizationCheck(OptimizationCheckKind); #else diff --git a/Source/JavaScriptCore/jit/JITCall32_64.cpp b/Source/JavaScriptCore/jit/JITCall32_64.cpp index 81266052b..7d86e615f 100644 --- a/Source/JavaScriptCore/jit/JITCall32_64.cpp +++ b/Source/JavaScriptCore/jit/JITCall32_64.cpp @@ -56,8 +56,6 @@ void JIT::emit_op_call_put_result(Instruction* instruction) void JIT::emit_op_ret(Instruction* currentInstruction) { - emitOptimizationCheck(RetOptimizationCheck); - unsigned dst = currentInstruction[1].u.operand; emitLoad(dst, regT1, regT0); @@ -70,8 +68,6 @@ void JIT::emit_op_ret(Instruction* currentInstruction) void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) { - emitOptimizationCheck(RetOptimizationCheck); - unsigned result = currentInstruction[1].u.operand; unsigned thisReg = currentInstruction[2].u.operand; diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index ad7a56e12..2e448dd52 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -576,8 +576,6 @@ void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction) void JIT::emit_op_ret(Instruction* currentInstruction) { - emitOptimizationCheck(RetOptimizationCheck); - ASSERT(callFrameRegister != regT1); ASSERT(regT1 != returnValueRegister); ASSERT(returnValueRegister != callFrameRegister); @@ -598,8 +596,6 @@ void JIT::emit_op_ret(Instruction* currentInstruction) void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) { - emitOptimizationCheck(RetOptimizationCheck); - ASSERT(callFrameRegister != regT1); ASSERT(regT1 != returnValueRegister); ASSERT(returnValueRegister != callFrameRegister); @@ -1218,13 +1214,14 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) void JIT::emit_op_enter(Instruction*) { + emitOptimizationCheck(EnterOptimizationCheck); + // Even though CTI doesn't use them, we initialize our constant // registers to zap stale pointers, to avoid unnecessarily prolonging // object lifetime and increasing GC pressure. size_t count = m_codeBlock->m_numVars; for (size_t j = 0; j < count; ++j) emitInitRegister(j); - } void JIT::emit_op_create_activation(Instruction* currentInstruction) diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index 57ef7ef2f..4f8589557 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -1487,6 +1487,8 @@ void JIT::emit_op_debug(Instruction* currentInstruction) void JIT::emit_op_enter(Instruction*) { + emitOptimizationCheck(EnterOptimizationCheck); + // Even though JIT code doesn't use them, we initialize our constant // registers to zap stale pointers, to avoid unnecessarily prolonging // object lifetime and increasing GC pressure. diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index 12f3ec344..b0ff4a0c7 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -1919,17 +1919,16 @@ DEFINE_STUB_FUNCTION(void, op_check_has_instance) } #if ENABLE(DFG_JIT) -DEFINE_STUB_FUNCTION(void, optimize_from_loop) +DEFINE_STUB_FUNCTION(void, optimize) { STUB_INIT_STACK_FRAME(stackFrame); CallFrame* callFrame = stackFrame.callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); - 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()); + dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter()); #endif if (!codeBlock->checkIfOptimizationThresholdReached()) @@ -1937,7 +1936,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) 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()); + dataLog("Considering OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); #endif if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) { #if ENABLE(JIT_VERBOSE_OSR) @@ -1959,14 +1958,14 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain); #if ENABLE(JIT_VERBOSE_OSR) if (error) - dataLog("WARNING: optimized compilation from loop failed.\n"); + dataLog("WARNING: optimized compilation failed.\n"); #else UNUSED_PARAM(error); #endif if (codeBlock->replacement() == codeBlock) { #if ENABLE(JIT_VERBOSE_OSR) - dataLog("Optimizing %p from loop failed.\n", codeBlock); + dataLog("Optimizing %p failed.\n", codeBlock); #endif ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT); @@ -1980,7 +1979,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) { #if ENABLE(JIT_VERBOSE_OSR) - dataLog("Optimizing %p from loop succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter()); + dataLog("Optimizing %p succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter()); #endif codeBlock->optimizeSoon(); @@ -1990,7 +1989,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) } #if ENABLE(JIT_VERBOSE_OSR) - dataLog("Optimizing %p from loop succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter()); + dataLog("Optimizing %p succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter()); #endif // Count the OSR failure as a speculation failure. If this happens a lot, then @@ -1998,7 +1997,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) optimizedCodeBlock->countSpeculationFailure(); #if ENABLE(JIT_VERBOSE_OSR) - dataLog("Encountered loop OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); + dataLog("Encountered OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter()); #endif // We are a lot more conservative about triggering reoptimization after OSR failure than @@ -2011,7 +2010,7 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) // reoptimization trigger. if (optimizedCodeBlock->shouldReoptimizeNow()) { #if ENABLE(JIT_VERBOSE_OSR) - dataLog("Triggering reoptimization of %p(%p) (in loop after OSR fail).\n", codeBlock, codeBlock->replacement()); + dataLog("Triggering reoptimization of %p(%p) (after OSR fail).\n", codeBlock, codeBlock->replacement()); #endif codeBlock->reoptimize(); return; @@ -2021,71 +2020,6 @@ DEFINE_STUB_FUNCTION(void, optimize_from_loop) // longer and then try again. codeBlock->optimizeAfterWarmUp(); } - -DEFINE_STUB_FUNCTION(void, optimize_from_ret) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - CallFrame* callFrame = stackFrame.callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - -#if ENABLE(JIT_VERBOSE_OSR) - 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()); - CallFrame* callerFrame = callFrame->callerFrame(); - if (callerFrame) - dataLog(", callerFrame = %p, returnPC = %p, caller code block = %p", callerFrame, callFrame->returnPC().value(), callerFrame->codeBlock()); - dataLog("\n"); -#endif - if (codeBlock->replacement()->shouldReoptimizeNow()) { -#if ENABLE(JIT_VERBOSE_OSR) - dataLog("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement()); -#endif - codeBlock->reoptimize(); - } - - codeBlock->optimizeSoon(); - return; - } - - if (!codeBlock->shouldOptimizeNow()) { -#if ENABLE(JIT_VERBOSE_OSR) - dataLog("Delaying optimization for %p (in return) because of insufficient profiling.\n", codeBlock); -#endif - return; - } - - ScopeChainNode* scopeChain = callFrame->scopeChain(); - - JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain); - if (error) - dataLog("WARNING: optimized compilation from ret failed.\n"); - - if (codeBlock->replacement() == codeBlock) { -#if ENABLE(JIT_VERBOSE_OSR) - dataLog("Optimizing %p from return failed.\n", codeBlock); -#endif - - ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT); - codeBlock->dontOptimizeAnytimeSoon(); - return; - } - - ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT); - -#if ENABLE(JIT_VERBOSE_OSR) - dataLog("Optimizing %p from return succeeded after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter()); -#endif - - codeBlock->optimizeSoon(); -} #endif // ENABLE(DFG_JIT) DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof) diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h index 251776075..d2bc15e64 100644 --- a/Source/JavaScriptCore/jit/JITStubs.h +++ b/Source/JavaScriptCore/jit/JITStubs.h @@ -450,8 +450,7 @@ extern "C" { void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION) WTF_INTERNAL; void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION) WTF_INTERNAL; #if ENABLE(DFG_JIT) - void JIT_STUB cti_optimize_from_loop(STUB_ARGS_DECLARATION) WTF_INTERNAL; - void JIT_STUB cti_optimize_from_ret(STUB_ARGS_DECLARATION) WTF_INTERNAL; + void JIT_STUB cti_optimize(STUB_ARGS_DECLARATION) WTF_INTERNAL; #endif void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION) WTF_INTERNAL; void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION) WTF_INTERNAL; diff --git a/Source/JavaScriptCore/offlineasm/offsets.rb b/Source/JavaScriptCore/offlineasm/offsets.rb index 63af014bb..4f2734f86 100644 --- a/Source/JavaScriptCore/offlineasm/offsets.rb +++ b/Source/JavaScriptCore/offlineasm/offsets.rb @@ -23,8 +23,15 @@ require "ast" -OFFSET_HEADER_MAGIC_NUMBERS = [ 0x9e43fd66, 0x4379bfba ] -OFFSET_MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ] +def to32Bit(value) + if value > 0x7fffffff + value -= 1 << 32 + end + value +end + +OFFSET_HEADER_MAGIC_NUMBERS = [ to32Bit(0x9e43fd66), to32Bit(0x4379bfba) ] +OFFSET_MAGIC_NUMBERS = [ to32Bit(0xec577ac7), to32Bit(0x0ff5e755) ] # # MissingMagicValuesException diff --git a/Source/JavaScriptCore/runtime/JSExportMacros.h b/Source/JavaScriptCore/runtime/JSExportMacros.h index 19e2c286f..884805f86 100644 --- a/Source/JavaScriptCore/runtime/JSExportMacros.h +++ b/Source/JavaScriptCore/runtime/JSExportMacros.h @@ -36,7 +36,7 @@ // See note in wtf/Platform.h for more info on EXPORT_MACROS. #if USE(EXPORT_MACROS) -#if defined(BUILDING_JavaScriptCore) || defined(STATICALLY_LINKED_WITH_JavaScriptCore) +#if defined(BUILDING_JavaScriptCore) #define JS_EXPORT_PRIVATE WTF_EXPORT #else #define JS_EXPORT_PRIVATE WTF_IMPORT @@ -50,7 +50,7 @@ #if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) -#if defined(BUILDING_JavaScriptCore) || defined(STATICALLY_LINKED_WITH_JavaScriptCore) +#if defined(BUILDING_JavaScriptCore) #define JS_EXPORTDATA __declspec(dllexport) #else #define JS_EXPORTDATA __declspec(dllimport) diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 7b6109599..d38570dfb 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -132,8 +132,6 @@ void JSGlobalObject::init(JSObject* thisValue) { ASSERT(JSLock::currentThreadIsHoldingLock()); - structure()->disableSpecificFunctionTracking(); - m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue)); JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0); diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index aa71b8a7b..66cc89809 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -43,6 +43,16 @@ namespace JSC { +JSCell* getCallableObjectSlow(JSCell* cell) +{ + Structure* structure = cell->structure(); + if (structure->typeInfo().type() == JSFunctionType) + return cell; + if (structure->classInfo()->isSubClassOf(&InternalFunction::s_info)) + return cell; + return 0; +} + ASSERT_CLASS_FITS_IN_CELL(JSObject); ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject); ASSERT_CLASS_FITS_IN_CELL(JSFinalObject); @@ -133,7 +143,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV for (JSObject* obj = thisObject; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) { prototype = obj->prototype(); if (prototype.isNull()) { - if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode()) + if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value)) && slot.isStrictMode()) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -180,7 +190,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV break; } - if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode()) + if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value)) && slot.isStrictMode()) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -196,7 +206,7 @@ void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); PutPropertySlot slot; - object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getJSFunction(value)); + object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getCallableObject(value)); } bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype) @@ -226,7 +236,7 @@ void JSObject::putDirectAccessor(JSGlobalData& globalData, PropertyName property ASSERT(value.isGetterSetter() && (attributes & Accessor)); PutPropertySlot slot; - putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value)); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getCallableObject(value)); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index ac8601deb..fdb708dd9 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -46,6 +46,15 @@ namespace JSC { return 0; } + JS_EXPORT_PRIVATE JSCell* getCallableObjectSlow(JSCell*); + + inline JSCell* getCallableObject(JSValue value) + { + if (!value.isCell()) + return 0; + return getCallableObjectSlow(value.asCell()); + } + class GetterSetter; class HashEntry; class InternalFunction; @@ -759,20 +768,20 @@ inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, PropertyName ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); ASSERT(!structure()->hasGetterSetterProperties()); - return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)); + return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value)); } inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); PutPropertySlot slot; - putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value)); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getCallableObject(value)); } inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(!value.isGetterSetter()); - putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getJSFunction(value)); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getCallableObject(value)); } inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes) @@ -781,7 +790,7 @@ inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, Prope PropertyStorage newStorage = propertyStorage(); if (structure()->shouldGrowPropertyStorage()) newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize()); - size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value)); + size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getCallableObject(value)); setPropertyStorage(globalData, newStorage, structure()); putDirectOffset(globalData, offset, value); } diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index 46fe72684..2f0dd42e5 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -35,7 +35,6 @@ #include "SymbolTable.h" #include <wtf/UnusedParam.h> #include <wtf/OwnArrayPtr.h> -#include <wtf/UnusedParam.h> namespace JSC { diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp index ec228f82a..7b6da6536 100644 --- a/Source/JavaScriptCore/runtime/Options.cpp +++ b/Source/JavaScriptCore/runtime/Options.cpp @@ -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 @@ -48,6 +48,7 @@ namespace JSC { namespace Options { bool useJIT; bool showDisassembly; +bool showDFGDisassembly; unsigned maximumOptimizationCandidateInstructionCount; @@ -165,6 +166,7 @@ void initializeOptions() SET(useJIT, true); SET(showDisassembly, false); + SET(showDFGDisassembly, false); SET(maximumOptimizationCandidateInstructionCount, 10000); diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h index e5cc99590..0adb59e9b 100644 --- a/Source/JavaScriptCore/runtime/Options.h +++ b/Source/JavaScriptCore/runtime/Options.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 @@ -33,6 +33,7 @@ namespace JSC { namespace Options { extern bool useJIT; extern bool showDisassembly; +extern bool showDFGDisassembly; // showDisassembly implies showDFGDisassembly. extern unsigned maximumOptimizationCandidateInstructionCount; diff --git a/Source/JavaScriptCore/shell/CMakeLists.txt b/Source/JavaScriptCore/shell/CMakeLists.txt index 561d779dd..71b8963cc 100644 --- a/Source/JavaScriptCore/shell/CMakeLists.txt +++ b/Source/JavaScriptCore/shell/CMakeLists.txt @@ -20,5 +20,5 @@ IF (JSC_LINK_FLAGS) ENDIF () IF (SHOULD_INSTALL_JS_SHELL) - INSTALL(TARGETS ${JSC_EXECUTABLE_NAME} DESTINATION bin) + INSTALL(TARGETS ${JSC_EXECUTABLE_NAME} DESTINATION "${EXEC_INSTALL_DIR}") ENDIF () diff --git a/Source/JavaScriptCore/wscript b/Source/JavaScriptCore/wscript index 58696d9c5..4afb4d26a 100644 --- a/Source/JavaScriptCore/wscript +++ b/Source/JavaScriptCore/wscript @@ -66,7 +66,7 @@ def build(bld): features = 'cc cxx cshlib', includes = '. .. assembler ../WTF ' + ' '.join(includes), source = sources, - defines = ['BUILDING_JavaScriptCore', 'STATICALLY_LINKED_WITH_WTF'], + defines = ['BUILDING_JavaScriptCore'], target = 'jscore', uselib = 'WX ICU ' + get_config(), uselib_local = '', |