Source/JavaScriptCore/ChangeLog

 12013-05-18 Filip Pizlo <fpizlo@apple.com>
 2
 3 fourthTier: DFG should be able to run on a separate thread
 4 https://bugs.webkit.org/show_bug.cgi?id=112839
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Work in progress.
 9
 10 * bytecode/CodeBlock.cpp:
 11 (JSC::CodeBlock::checkIfOptimizationThresholdReached):
 12 (JSC::CodeBlock::setOptimizationThresholdBasedOnCompilationResult):
 13 (JSC):
 14 * bytecode/CodeBlock.h:
 15 (CodeBlock):
 16 * bytecode/ExecutionCounter.cpp:
 17 (JSC::ExecutionCounter::forceSlowPath):
 18 (JSC):
 19 (JSC::ExecutionCounter::setThreshold):
 20 * bytecode/ExecutionCounter.h:
 21 (ExecutionCounter):
 22 * dfg/DFGDriver.cpp:
 23 (JSC::DFG::compile):
 24 * dfg/DFGPlan.cpp:
 25 (JSC::DFG::Plan::Plan):
 26 (JSC::DFG::Plan::key):
 27 (DFG):
 28 * dfg/DFGPlan.h:
 29 (Plan):
 30 * dfg/DFGWorklist.cpp: Added.
 31 (DFG):
 32 (JSC::DFG::Worklist::Worklist):
 33 (JSC::DFG::Worklist::~Worklist):
 34 (JSC::DFG::Worklist::finishCreation):
 35 (JSC::DFG::Worklist::create):
 36 (JSC::DFG::Worklist::enqueue):
 37 (JSC::DFG::Worklist::complete):
 38 (JSC::DFG::Worklist::compilationState):
 39 (JSC::DFG::Worklist::completeAllForVM):
 40 (JSC::DFG::Worklist::runThread):
 41 (JSC::DFG::Worklist::completeAsynchronousPlan):
 42 (JSC::DFG::Worklist::threadFunction):
 43 (JSC::DFG::initializeGlobalWorklistOnce):
 44 (JSC::DFG::globalWorklist):
 45 * dfg/DFGWorklist.h: Added.
 46 (DFG):
 47 (Worklist):
 48 * heap/Heap.cpp:
 49 (JSC::Heap::collect):
 50 * jit/JITStubs.cpp:
 51 (JSC::logOSR):
 52 (JSC):
 53 (JSC::DEFINE_STUB_FUNCTION):
 54 * runtime/Options.h:
 55 (JSC):
 56 * runtime/VM.cpp:
 57 * runtime/VM.h:
 58 (DFG):
 59 (VM):
 60
1612013-05-17 Filip Pizlo <fpizlo@apple.com>
262
363 fourthTier: getCTIStub should be thread-safe
150341

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

331331 0FDB2CE01742D804007B3C1B /* DFGPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CD81742D804007B3C1B /* DFGPlan.h */; settings = {ATTRIBUTES = (Private, ); }; };
332332 0FDB2CE21746C1FA007B3C1B /* CompilationResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CE11746C1F8007B3C1B /* CompilationResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
333333 0FDB2CE41746CE9F007B3C1B /* CompilationResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDB2CE31746CE9D007B3C1B /* CompilationResult.cpp */; };
 334 0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */; };
 335 0FDB2CE8174830A2007B3C1B /* DFGWorklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CE6174830A2007B3C1B /* DFGWorklist.h */; settings = {ATTRIBUTES = (Private, ); }; };
334336 0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */; };
335337 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; settings = {ATTRIBUTES = (Private, ); }; };
336338 0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; };

13381340 0FDB2CD81742D804007B3C1B /* DFGPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPlan.h; path = dfg/DFGPlan.h; sourceTree = "<group>"; };
13391341 0FDB2CE11746C1F8007B3C1B /* CompilationResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompilationResult.h; sourceTree = "<group>"; };
13401342 0FDB2CE31746CE9D007B3C1B /* CompilationResult.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompilationResult.cpp; sourceTree = "<group>"; };
 1343 0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGWorklist.cpp; path = dfg/DFGWorklist.cpp; sourceTree = "<group>"; };
 1344 0FDB2CE6174830A2007B3C1B /* DFGWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGWorklist.h; path = dfg/DFGWorklist.h; sourceTree = "<group>"; };
13411345 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessDataDump.cpp; path = dfg/DFGVariableAccessDataDump.cpp; sourceTree = "<group>"; };
13421346 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = "<group>"; };
13431347 0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; };

30303034 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */,
30313035 0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */,
30323036 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */,
 3037 0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */,
 3038 0FDB2CE6174830A2007B3C1B /* DFGWorklist.h */,
30333039 );
30343040 name = dfg;
30353041 sourceTree = "<group>";

35763582 BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */,
35773583 BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */,
35783584 BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */,
 3585 0FDB2CE8174830A2007B3C1B /* DFGWorklist.h in Headers */,
35793586 BC18C4430E16F5CD00B34460 /* NumberObject.h in Headers */,
35803587 BC18C4440E16F5CD00B34460 /* NumberPrototype.h in Headers */,
35813588 142D3939103E4560007DCB52 /* NumericStrings.h in Headers */,

43664373 14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */,
43674374 0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */,
43684375 1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */,
 4376 0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */,
43694377 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
43704378 0FEA0A2A1709629600BB722C /* FTLOutput.cpp in Sources */,
43714379 0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */,
150339

Source/JavaScriptCore/bytecode/CodeBlock.cpp

3636#include "DFGCommon.h"
3737#include "DFGNode.h"
3838#include "DFGRepatch.h"
 39#include "DFGWorklist.h"
3940#include "Debugger.h"
4041#include "FTLJITCode.h"
4142#include "Interpreter.h"

@@int32_t CodeBlock::counterValueForOptimi
30263027
30273028bool CodeBlock::checkIfOptimizationThresholdReached()
30283029{
 3030#if ENABLE(DFG_JIT)
 3031 if (m_vm->worklist
 3032 && m_vm->worklist->compilationState(this) == DFG::Worklist::Compiled) {
 3033 optimizeNextInvocation();
 3034 return true;
 3035 }
 3036#endif
 3037
30293038 return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
30303039}
30313040

@@void CodeBlock::optimizeNextInvocation()
30373046void CodeBlock::dontOptimizeAnytimeSoon()
30383047{
30393048 m_jitExecuteCounter.deferIndefinitely();
 3049
 3050#if ENABLE(DFG_JIT)
 3051 // There is a race here. We may been called just after the concurrent
 3052 // compilation thread completed. Check if this is the case, and if so,
 3053 // switch to optimizing the next invocation.
 3054 if (m_vm->worklist
 3055 && m_vm->worklist->compilationState(this) == DFG::Worklist::Compiled)
 3056 optimizeNextInvocation();
 3057#endif
30403058}
30413059
30423060void CodeBlock::optimizeAfterWarmUp()

@@void CodeBlock::optimizeSoon()
30543072 m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeSoon(), this);
30553073}
30563074
 3075void CodeBlock::forceOptimizationSlowPathConcurrently()
 3076{
 3077 m_jitExecuteCounter.forceSlowPathConcurrently();
 3078}
 3079
 3080void CodeBlock::setOptimizationThresholdBasedOnCompilationResult(CompilationResult result)
 3081{
 3082 RELEASE_ASSERT(getJITType() == JITCode::BaselineJIT);
 3083 RELEASE_ASSERT((result == CompilationSuccessful) == (replacement() != this));
 3084 switch (result) {
 3085 case CompilationSuccessful:
 3086 RELEASE_ASSERT(JITCode::isOptimizingJIT(replacement()->getJITType()));
 3087 optimizeNextInvocation();
 3088 break;
 3089 case CompilationFailed:
 3090 case CompilationDeferred:
 3091 dontOptimizeAnytimeSoon();
 3092 break;
 3093 case CompilationInvalidated:
 3094 // Retry with exponential backoff.
 3095 countReoptimization();
 3096 optimizeAfterWarmUp();
 3097 break;
 3098 default:
 3099 RELEASE_ASSERT_NOT_REACHED();
 3100 break;
 3101 }
 3102}
 3103
30573104#if ENABLE(JIT)
30583105uint32_t CodeBlock::adjustedExitCountThreshold(uint32_t desiredThreshold)
30593106{

@@ArrayProfile* CodeBlock::getOrAddArrayPr
31123159void CodeBlock::updateAllPredictionsAndCountLiveness(
31133160 OperationInProgress operation, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
31143161{
3115  CodeBlockLock locker(m_lock);
 3162 CodeBlockLocker locker(m_lock);
31163163
31173164 numberOfLiveNonArgumentValueProfiles = 0;
31183165 numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.

@@void CodeBlock::updateAllValueProfilePre
31443191
31453192void CodeBlock::updateAllArrayPredictions(OperationInProgress operation)
31463193{
3147  CodeBlockLock locker(m_lock);
 3194 CodeBlockLocker locker(m_lock);
31483195
31493196 for (unsigned i = m_arrayProfiles.size(); i--;)
31503197 m_arrayProfiles[i].computeUpdatedPrediction(locker, this, operation);
150339

Source/JavaScriptCore/bytecode/CodeBlock.h

@@class CodeBlock : public ThreadSafeRefCo
865865 // to trigger optimization if one of those functions becomes hot
866866 // in the baseline code.
867867 void optimizeSoon();
 868
 869 void forceOptimizationSlowPathConcurrently();
 870
 871 void setOptimizationThresholdBasedOnCompilationResult(CompilationResult);
868872
869873 uint32_t osrExitCounter() const { return m_osrExitCounter; }
870874
150339

Source/JavaScriptCore/bytecode/ExecutionCounter.cpp

@@ExecutionCounter::ExecutionCounter()
3737 reset();
3838}
3939
 40void ExecutionCounter::forceSlowPathConcurrently()
 41{
 42 m_counter = 0;
 43}
 44
4045bool ExecutionCounter::checkIfThresholdCrossedAndSet(CodeBlock* codeBlock)
4146{
4247 if (hasCrossedThreshold(codeBlock))

@@bool ExecutionCounter::setThreshold(Code
124129 return false;
125130 }
126131
127  ASSERT(!hasCrossedThreshold(codeBlock));
 132 ASSERT(!m_activeThreshold || !hasCrossedThreshold(codeBlock));
128133
129134 // Compute the true total count.
130135 double trueTotalCount = count();
131 
 136
132137 // Correct the threshold for current memory usage.
133138 double threshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock);
134139
150339

Source/JavaScriptCore/bytecode/ExecutionCounter.h

@@class CodeBlock;
3838class ExecutionCounter {
3939public:
4040 ExecutionCounter();
 41 void forceSlowPathConcurrently(); // If you use this, checkIfThresholdCrossedAndSet() may still return false.
4142 bool checkIfThresholdCrossedAndSet(CodeBlock*);
4243 void setNewThreshold(int32_t threshold, CodeBlock*);
4344 void deferIndefinitely();

@@private:
7475 void reset();
7576
7677public:
77 
7878 // NB. These are intentionally public because it will be modified from machine code.
7979
8080 // This counter is incremented by the JIT or LLInt. It starts out negative and is
150339

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

@@private:
270270 {
271271 ASSERT(node->op() == GetLocal);
272272 ASSERT(node->codeOrigin.bytecodeIndex == m_currentIndex);
273  CodeBlockLock locker(m_inlineStackTop->m_profiledBlock->m_lock);
 273 CodeBlockLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
274274 LazyOperandValueProfileKey key(m_currentIndex, node->local());
275275 SpeculatedType prediction = m_inlineStackTop->m_lazyOperands.prediction(locker, key);
276276#if DFG_ENABLE(DEBUG_VERBOSE)

@@private:
839839
840840 ArrayMode getArrayMode(ArrayProfile* profile, Array::Action action)
841841 {
842  CodeBlockLock locker(m_inlineStackTop->m_profiledBlock->m_lock);
 842 CodeBlockLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
843843 profile->computeUpdatedPrediction(locker, m_inlineStackTop->m_profiledBlock);
844844 return ArrayMode::fromObserved(locker, profile, action, false);
845845 }

@@private:
851851
852852 ArrayMode getArrayModeAndEmitChecks(ArrayProfile* profile, Array::Action action, Node* base)
853853 {
854  CodeBlockLock locker(m_inlineStackTop->m_profiledBlock->m_lock);
 854 CodeBlockLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
855855
856856 profile->computeUpdatedPrediction(locker, m_inlineStackTop->m_profiledBlock);
857857
150339

Source/JavaScriptCore/dfg/DFGDriver.cpp

3535#include "DFGJITCode.h"
3636#include "DFGPlan.h"
3737#include "DFGThunks.h"
 38#include "DFGWorklist.h"
3839#include "FTLThunks.h"
3940#include "JITCode.h"
4041#include "Operations.h"
4142#include "Options.h"
4243#include "SamplingTool.h"
 44#include <wtf/Atomics.h>
4345
4446namespace JSC { namespace DFG {
4547

@@static CompilationResult compile(Compile
6870 if (logCompilationChanges())
6971 dataLog("DFG compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
7072
 73 VM& vm = exec->vm();
 74
7175 // Make sure that any stubs that the DFG is going to use are initialized. We want to
7276 // make sure that al JIT code generation does finalization on the main thread.
73  exec->vm().getCTIStub(osrExitGenerationThunkGenerator);
74  exec->vm().getCTIStub(throwExceptionFromCallSlowPathGenerator);
75  exec->vm().getCTIStub(linkCallThunkGenerator);
76  exec->vm().getCTIStub(linkConstructThunkGenerator);
77  exec->vm().getCTIStub(linkClosureCallThunkGenerator);
78  exec->vm().getCTIStub(virtualCallThunkGenerator);
79  exec->vm().getCTIStub(virtualConstructThunkGenerator);
 77 vm.getCTIStub(osrExitGenerationThunkGenerator);
 78 vm.getCTIStub(throwExceptionFromCallSlowPathGenerator);
 79 vm.getCTIStub(linkCallThunkGenerator);
 80 vm.getCTIStub(linkConstructThunkGenerator);
 81 vm.getCTIStub(linkClosureCallThunkGenerator);
 82 vm.getCTIStub(virtualCallThunkGenerator);
 83 vm.getCTIStub(virtualConstructThunkGenerator);
8084#if ENABLE(FTL_JIT)
81  exec->vm().getCTIStub(FTL::osrExitGenerationThunkGenerator);
 85 vm.getCTIStub(FTL::osrExitGenerationThunkGenerator);
8286#endif
8387
8488 // Derive our set of must-handle values. The compilation must be at least conservative

@@static CompilationResult compile(Compile
105109 plan->mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
106110 }
107111
108  plan->compileInThread();
 112 if (Options::enableConcurrentCompilation()) {
 113 if (logCompilationChanges())
 114 dataLog("Deferring DFG compilation of ", *codeBlock, "\n");
 115 if (!vm.worklist)
 116 vm.worklist = globalWorklist();
 117 vm.worklist->enqueue(plan);
 118 return CompilationDeferred;
 119 }
 120
 121 plan->compileInThread(*vm.dfgState);
109122 return plan->finalize(jitCode, jitCodeWithArityCheck);
110123}
111124
150339

Source/JavaScriptCore/dfg/DFGGraph.cpp

11/*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@static const char* dfgOpNames[] = {
4444#undef STRINGIZE_DFG_OP_ENUM
4545};
4646
47 Graph::Graph(VM& vm, Plan& plan)
 47Graph::Graph(VM& vm, Plan& plan, LongLivedState& longLivedState)
4848 : m_vm(vm)
4949 , m_plan(plan)
5050 , m_codeBlock(m_plan.codeBlock.get())
5151 , m_profiledBlock(m_codeBlock->alternative())
52  , m_allocator(vm.m_dfgState->m_allocator)
 52 , m_allocator(longLivedState.m_allocator)
5353 , m_hasArguments(false)
5454 , m_fixpointState(BeforeFixpoint)
5555 , m_form(LoadStore)
150339

Source/JavaScriptCore/dfg/DFGGraph.h

@@enum AddSpeculationMode {
9090// Nodes that are 'dead' remain in the vector with refCount 0.
9191class Graph {
9292public:
93  Graph(VM&, Plan&);
 93 Graph(VM&, Plan&, LongLivedState&);
9494 ~Graph();
9595
9696 void changeChild(Edge& edge, Node* newNode)
150339

Source/JavaScriptCore/dfg/DFGPlan.cpp

@@Plan::Plan(
7878 , mustHandleValues(codeBlock->numParameters(), numVarsWithValues)
7979 , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), Profiler::DFG)) : 0)
8080 , identifiers(codeBlock.get())
 81 , isCompiled(false)
8182{
8283}
8384

@@Plan::~Plan()
8586{
8687}
8788
88 void Plan::compileInThread()
 89void Plan::compileInThread(LongLivedState& longLivedState)
8990{
9091 SamplingRegion samplingRegion("DFG Compilation (Plan)");
9192 CompilationScope compilationScope;
9293
93  Graph dfg(vm, *this);
 94 Graph dfg(vm, *this, longLivedState);
9495
9596 if (!parse(dfg)) {
9697 finalizer = adoptPtr(new FailedFinalizer(*this));

@@CompilationResult Plan::finalize(RefPtr<
199200 return CompilationSuccessful;
200201}
201202
 203CodeBlock* Plan::key()
 204{
 205 return codeBlock->alternative();
 206}
 207
202208} } // namespace JSC::DFG
203209
204210#endif // ENABLE(DFG_JIT)
150339

Source/JavaScriptCore/dfg/DFGPlan.h

@@class CodeBlock;
4343
4444namespace DFG {
4545
 46class LongLivedState;
 47
4648enum CompileMode { CompileFunction, CompileOther };
4749
4850#if ENABLE(DFG_JIT)

@@struct Plan : public ThreadSafeRefCounte
5355 unsigned osrEntryBytecodeIndex, unsigned numVarsWithValues);
5456 ~Plan();
5557
56  void compileInThread();
 58 void compileInThread(LongLivedState&);
5759
5860 CompilationResult finalize(RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck);
5961
 62 CodeBlock* key();
 63
6064 const CompileMode compileMode;
6165 VM& vm;
6266 RefPtr<CodeBlock> codeBlock;

@@struct Plan : public ThreadSafeRefCounte
7175 DesiredWatchpoints watchpoints;
7276 DesiredIdentifiers identifiers;
7377 DesiredStructureChains chains;
 78
 79 bool isCompiled;
7480
7581private:
7682 bool isStillValid();
150339

Source/JavaScriptCore/dfg/DFGWorklist.cpp

 1/*
 2 * Copyright (C) 2013 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "DFGWorklist.h"
 28
 29#if ENABLE(DFG_JIT)
 30
 31#include "CodeBlock.h"
 32#include "DFGLongLivedState.h"
 33
 34namespace JSC { namespace DFG {
 35
 36Worklist::Worklist()
 37{
 38}
 39
 40Worklist::~Worklist()
 41{
 42 m_queue.append(nullptr); // Use null plan to indicate that we want the thread to terminate.
 43 waitForThreadCompletion(m_thread);
 44}
 45
 46void Worklist::finishCreation()
 47{
 48 m_thread = createThread(threadFunction, this, "JSC Compilation Thread");
 49}
 50
 51PassRefPtr<Worklist> Worklist::create()
 52{
 53 RefPtr<Worklist> result = adoptRef(new Worklist());
 54 result->finishCreation();
 55 return result;
 56}
 57
 58void Worklist::enqueue(PassRefPtr<Plan> passedPlan)
 59{
 60 RefPtr<Plan> plan = passedPlan;
 61 MutexLocker locker(m_lock);
 62 ASSERT(m_plans.find(plan->key()) == m_plans.end());
 63 m_plans.add(plan->key(), plan);
 64 m_queue.append(plan);
 65 m_condition.broadcast();
 66}
 67
 68CompilationResult Worklist::completeAndScheduleOSR(CodeBlock* profiledBlock)
 69{
 70 RefPtr<Plan> plan;
 71
 72 {
 73 MutexLocker locker(m_lock);
 74 plan = m_plans.take(profiledBlock);
 75 }
 76
 77 ASSERT(plan);
 78 ASSERT(plan->isCompiled);
 79
 80 CompilationResult result = profiledBlock->replaceWithDeferredOptimizedCode(plan);
 81
 82 RELEASE_ASSERT(result != CompilationDeferred);
 83 profiledBlock->setOptimizationThresholdBasedOnCompilationResult(result);
 84
 85 return result;
 86}
 87
 88Worklist::State Worklist::compilationState(CodeBlock* profiledBlock)
 89{
 90 MutexLocker locker(m_lock);
 91 PlanMap::iterator iter = m_plans.find(profiledBlock);
 92 if (iter == m_plans.end())
 93 return NotKnown;
 94 return iter->value->isCompiled ? Compiled : Compiling;
 95}
 96
 97Vector<RefPtr<CodeBlock> > Worklist::waitUntilAllForVMAreComplete(VM& vm)
 98{
 99 // Wait for all of the plans for the given VM to complete, and collect the
 100 // CodeBlock*'s that are the keys to those plans. The idea here is that we
 101 // want all of the caller VM's plans to be done. We don't care about any
 102 // other VM's plans, and we won't attempt to complete those. After we
 103 // release this lock, we know that although other VMs may still be adding
 104 // plans, our VM will not be.
 105 Vector<RefPtr<CodeBlock> > keyBlocks;
 106 {
 107 MutexLocker locker(m_lock);
 108 for (;;) {
 109 bool allAreCompleted = true;
 110 PlanMap::iterator end = m_plans.end();
 111 for (PlanMap::iterator iter = m_plans.begin(); iter != end; ++iter) {
 112 if (&iter->value->vm != &vm)
 113 continue;
 114 if (!iter->value->isCompiled) {
 115 allAreCompleted = false;
 116 break;
 117 }
 118 }
 119
 120 if (allAreCompleted)
 121 break;
 122
 123 m_condition.wait(m_lock);
 124 }
 125
 126 PlanMap::iterator end = m_plans.end();
 127 for (PlanMap::iterator iter = m_plans.begin(); iter != end; ++iter) {
 128 if (&iter->value->vm != &vm)
 129 continue;
 130 keyBlocks.append(iter->key);
 131 }
 132 }
 133 return keyBlocks;
 134}
 135
 136void Worklist::completeAllForVM(VM& vm)
 137{
 138 Vector<RefPtr<CodeBlock> > keyBlocks = waitUntilAllForVMAreComplete(vm);
 139
 140 // Now complete all of the plans for this VM.
 141 for (unsigned i = keyBlocks.size(); i--;)
 142 completeAndScheduleOSR(keyBlocks[i].get());
 143}
 144
 145void Worklist::runThread()
 146{
 147 LongLivedState longLivedState;
 148
 149 for (;;) {
 150 RefPtr<Plan> plan;
 151 {
 152 MutexLocker locker(m_lock);
 153 while (m_queue.isEmpty())
 154 m_condition.wait(m_lock);
 155 plan = m_queue.takeFirst();
 156 }
 157
 158 if (!plan)
 159 return;
 160
 161 plan->compileInThread(longLivedState);
 162 completeAsynchronousPlan(plan.get());
 163 }
 164}
 165
 166void Worklist::completeAsynchronousPlan(Plan* plan)
 167{
 168 MutexLocker locker(m_lock);
 169 plan->key()->forceOptimizationSlowPathConcurrently();
 170 plan->isCompiled = true;
 171 m_condition.broadcast();
 172}
 173
 174void Worklist::threadFunction(void* argument)
 175{
 176 static_cast<Worklist*>(argument)->runThread();
 177}
 178
 179static pthread_once_t initializeGlobalWorklistKeyOnce = PTHREAD_ONCE_INIT;
 180static Worklist* theGlobalWorklist;
 181
 182static void initializeGlobalWorklistOnce()
 183{
 184 theGlobalWorklist = Worklist::create().leakRef();
 185}
 186
 187Worklist* globalWorklist()
 188{
 189 pthread_once(&initializeGlobalWorklistKeyOnce, initializeGlobalWorklistOnce);
 190 return theGlobalWorklist;
 191}
 192
 193} } // namespace JSC::DFG
 194
 195#endif // ENABLE(DFG_JIT)
 196
0

Source/JavaScriptCore/dfg/DFGWorklist.h

 1/*
 2 * Copyright (C) 2013 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef DFGWorklist_h
 27#define DFGWorklist_h
 28
 29#include <wtf/Platform.h>
 30
 31#if ENABLE(DFG_JIT)
 32
 33#include "DFGPlan.h"
 34#include <wtf/Deque.h>
 35#include <wtf/HashMap.h>
 36#include <wtf/Noncopyable.h>
 37#include <wtf/PassOwnPtr.h>
 38#include <wtf/ThreadingPrimitives.h>
 39
 40namespace JSC { namespace DFG {
 41
 42class Worklist : public RefCounted<Worklist> {
 43public:
 44 ~Worklist();
 45
 46 static PassRefPtr<Worklist> create();
 47
 48 void enqueue(PassRefPtr<Plan>);
 49
 50 // This is equivalent to:
 51 // Vector<RefPtr<CodeBlock> > blocks = worklist->waitUntilAllForVMAreComplete(vm);
 52 // for (CodeBlock* block in blocks)
 53 // worklist->completeAndScheduleOSR(block);
 54 void completeAllForVM(VM&);
 55
 56 Vector<RefPtr<CodeBlock> > waitUntilAllForVMAreComplete(VM&);
 57 CompilationResult completeAndScheduleOSR(CodeBlock* profiledBlock);
 58
 59 enum State { NotKnown, Compiling, Compiled };
 60 State compilationState(CodeBlock* profiledBlock);
 61
 62private:
 63 Worklist();
 64 void finishCreation();
 65
 66 void runThread();
 67 static void threadFunction(void* argument);
 68
 69 void completeAsynchronousPlan(Plan*);
 70
 71 Deque<RefPtr<Plan> > m_queue;
 72 typedef HashMap<RefPtr<CodeBlock>, RefPtr<Plan> > PlanMap;
 73 PlanMap m_plans;
 74 Mutex m_lock;
 75 // We broadcast on this condition whenever:
 76 // - Something is enqueued.
 77 // - Something is completed.
 78 ThreadCondition m_condition;
 79 ThreadIdentifier m_thread;
 80};
 81
 82// For now we use a single global worklist. It's not clear that this
 83// is the right thing to do, but it is what we do, for now. This function
 84// will lazily create one when it's needed. Currently this is only called
 85// from DFGDriver.cpp, when it actually wants to enqueue something.
 86Worklist* globalWorklist();
 87
 88} } // namespace JSC::DFG
 89
 90#endif // ENABLE(DFG_JIT)
 91
 92#endif // DFGWorklist_h
 93
0

Source/JavaScriptCore/heap/Heap.cpp

2626#include "CopiedSpace.h"
2727#include "CopiedSpaceInlines.h"
2828#include "CopyVisitorInlines.h"
 29#include "DFGWorklist.h"
2930#include "GCActivityCallback.h"
3031#include "HeapRootVisitor.h"
3132#include "HeapStatistics.h"

@@void Heap::collect(SweepToggle sweepTogg
703704 ASSERT(m_isSafeToCollect);
704705 JAVASCRIPTCORE_GC_BEGIN();
705706 RELEASE_ASSERT(m_operationInProgress == NoOperation);
 707
 708#if ENABLE(DFG_JIT)
 709 Vector<RefPtr<CodeBlock> > keyBlocks;
 710 if (m_vm->worklist)
 711 keyBlocks = m_vm->worklist->waitUntilAllForVMAreComplete(*m_vm);
 712#endif
 713
706714 m_operationInProgress = Collection;
707715
 716#if ENABLE(DFG_JIT)
 717 // Do the completion while indicating that we're in the GC, so that we
 718 // don't try to recursively GC.
 719 if (m_vm->worklist) {
 720 for (unsigned i = keyBlocks.size(); i--;)
 721 m_vm->worklist->completeAndScheduleOSR(keyBlocks[i].get());
 722 }
 723 keyBlocks.resize(0);
 724#endif
 725
708726 m_activityCallback->willCollect();
709727
710728 double lastGCStartTime = WTF::currentTime();
150339

Source/JavaScriptCore/heap/Heap.h

@@namespace JSC {
110110
111111 JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
112112
 113 // true if collection is in progress
 114 inline bool isCollecting();
113115 // true if an allocation or collection is in progress
114116 inline bool isBusy();
115117

@@namespace JSC {
293295 return m_operationInProgress != NoOperation;
294296 }
295297
 298 bool Heap::isCollecting()
 299 {
 300 return m_operationInProgress == Collection;
 301 }
 302
296303 inline Heap* Heap::heap(const JSCell* cell)
297304 {
298305 return MarkedBlock::blockFor(cell)->heap();
150339

Source/JavaScriptCore/jit/JITStubs.cpp

4040#include "CodeProfiling.h"
4141#include "CommonSlowPaths.h"
4242#include "DFGOSREntry.h"
 43#include "DFGWorklist.h"
4344#include "Debugger.h"
4445#include "ExceptionHelpers.h"
4546#include "GetterSetter.h"

@@DEFINE_STUB_FUNCTION(EncodedJSValue, op_
898899}
899900
900901#if ENABLE(DFG_JIT)
 902static bool logOSR()
 903{
 904 return Options::verboseCompilation()
 905 || Options::showDisassembly()
 906 || Options::showDFGDisassembly();
 907}
 908
901909DEFINE_STUB_FUNCTION(void, optimize)
902910{
903911 STUB_INIT_STACK_FRAME(stackFrame);

@@DEFINE_STUB_FUNCTION(void, optimize)
906914 CodeBlock* codeBlock = callFrame->codeBlock();
907915 unsigned bytecodeIndex = stackFrame.args[0].int32();
908916
909 #if ENABLE(JIT_VERBOSE_OSR)
910  dataLog(
911  *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
912  ", executeCounter = ", codeBlock->jitExecuteCounter(),
913  ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
914  ", exitCounter = ");
915  if (codeBlock->hasOptimizedReplacement())
916  dataLog(codeBlock->replacement()->osrExitCounter());
917  else
918  dataLog("N/A");
919  dataLog("\n");
920 #endif
 917 if (logOSR()) {
 918 dataLog(
 919 *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
 920 ", executeCounter = ", codeBlock->jitExecuteCounter(),
 921 ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
 922 ", exitCounter = ");
 923 if (codeBlock->hasOptimizedReplacement())
 924 dataLog(codeBlock->replacement()->osrExitCounter());
 925 else
 926 dataLog("N/A");
 927 dataLog("\n");
 928 }
921929
922930 if (!codeBlock->checkIfOptimizationThresholdReached()) {
923931 codeBlock->updateAllPredictions();
924 #if ENABLE(JIT_VERBOSE_OSR)
925  dataLog("Choosing not to optimize ", *codeBlock, " yet.\n");
926 #endif
 932 if (logOSR())
 933 dataLog("Choosing not to optimize ", *codeBlock, " yet.\n");
927934 return;
928935 }
929 
930  if (codeBlock->hasOptimizedReplacement()) {
931 #if ENABLE(JIT_VERBOSE_OSR)
932  dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
933 #endif
 936
 937 DFG::Worklist::State worklistState;
 938 if (stackFrame.vm->worklist)
 939 worklistState = stackFrame.vm->worklist->compilationState(codeBlock);
 940 else
 941 worklistState = DFG::Worklist::NotKnown;
 942
 943 // We cannot be in the process of asynchronous compilation and also have an optimized
 944 // replacement.
 945 RELEASE_ASSERT(
 946 !(worklistState != DFG::Worklist::NotKnown && codeBlock->hasOptimizedReplacement()));
 947
 948 if (worklistState == DFG::Worklist::Compiling) {
 949 codeBlock->dontOptimizeAnytimeSoon();
 950 return;
 951 }
 952
 953 if (worklistState == DFG::Worklist::Compiled) {
 954 if (logOSR())
 955 dataLog("Installing deferred compilation for ", *codeBlock, ".\n");
 956
 957 CompilationResult result = stackFrame.vm->worklist->completeAndScheduleOSR(codeBlock);
 958 if (logOSR())
 959 dataLog("Deferred optimizing compilation of ", *codeBlock, " result: ", result, "\n");
 960
 961 if (result != CompilationSuccessful)
 962 return;
 963 } else if (codeBlock->hasOptimizedReplacement()) {
 964 if (logOSR())
 965 dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
934966 // If we have an optimized replacement, then it must be the case that we entered
935967 // cti_optimize from a loop. That's because is there's an optimized replacement,
936968 // then all calls to this function will be relinked to the replacement and so

@@DEFINE_STUB_FUNCTION(void, optimize)
945977 // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
946978 // additional checking anyway, to reduce the amount of recompilation thrashing.
947979 if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
948 #if ENABLE(JIT_VERBOSE_OSR)
949  dataLog("Triggering reoptimization of ", *codeBlock, "(", *codeBlock->replacement(), ") (in loop).\n");
950 #endif
 980 if (logOSR()) {
 981 dataLog(
 982 "Triggering reoptimization of ", *codeBlock,
 983 "(", *codeBlock->replacement(), ") (in loop).\n");
 984 }
951985 codeBlock->reoptimize();
952986 return;
953987 }
954988 } else {
955989 if (!codeBlock->shouldOptimizeNow()) {
956 #if ENABLE(JIT_VERBOSE_OSR)
957  dataLog("Delaying optimization for ", *codeBlock, " (in loop) because of insufficient profiling.\n");
958 #endif
 990 if (logOSR()) {
 991 dataLog(
 992 "Delaying optimization for ", *codeBlock,
 993 " (in loop) because of insufficient profiling.\n");
 994 }
959995 return;
960996 }
961997
962 #if ENABLE(JIT_VERBOSE_OSR)
963  dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
964 #endif
 998 if (logOSR())
 999 dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
9651000
9661001 JSScope* scope = callFrame->scope();
9671002 CompilationResult result;
9681003 JSObject* error = codeBlock->compileOptimized(callFrame, scope, result, bytecodeIndex);
969  if (Options::verboseCompilation()
970  || Options::showDisassembly()
971  || Options::showDFGDisassembly())
 1004 if (logOSR()) {
9721005 dataLog("Optimizing compilation of ", *codeBlock, " result: ", result, "\n");
973 #if ENABLE(JIT_VERBOSE_OSR)
974  if (error)
975  dataLog("WARNING: optimized compilation failed with a JS error.\n");
976 #else
977  UNUSED_PARAM(error);
978 #endif
 1006 if (error)
 1007 dataLog("WARNING: optimized compilation failed with a JS error.\n");
 1008 }
9791009
980  RELEASE_ASSERT((result == CompilationSuccessful) == (codeBlock->replacement() != codeBlock));
981  switch (result) {
982  case CompilationSuccessful:
983  break;
984  case CompilationFailed:
985  case CompilationDeferred:
986 #if ENABLE(JIT_VERBOSE_OSR)
987  dataLog("Optimizing ", *codeBlock, " failed.\n");
988 #endif
989  ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
990  codeBlock->dontOptimizeAnytimeSoon();
991  return;
992  case CompilationInvalidated:
993  ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
994  // Retry with exponential backoff.
995  codeBlock->countReoptimization();
996  codeBlock->optimizeAfterWarmUp();
 1010 codeBlock->setOptimizationThresholdBasedOnCompilationResult(result);
 1011 if (result != CompilationSuccessful)
9971012 return;
998  default:
999  RELEASE_ASSERT_NOT_REACHED();
1000  return;
1001  }
10021013 }
10031014
10041015 CodeBlock* optimizedCodeBlock = codeBlock->replacement();

@@DEFINE_STUB_FUNCTION(void, optimize)
10141025 }
10151026
10161027 if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
1017  if (Options::showDFGDisassembly()) {
 1028 if (logOSR()) {
10181029 dataLog(
10191030 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ",
10201031 RawPointer((STUB_RETURN_ADDRESS).value()), " -> ", RawPointer(address), ".\n");
10211032 }
1022 #if ENABLE(JIT_VERBOSE_OSR)
1023  dataLog("Optimizing ", *codeBlock, " succeeded, performing OSR after a delay of ", codeBlock->optimizationDelayCounter(), ".\n");
1024 #endif
10251033
10261034 codeBlock->optimizeSoon();
10271035 STUB_SET_RETURN_ADDRESS(address);
10281036 return;
10291037 }
1030 
1031 #if ENABLE(JIT_VERBOSE_OSR)
1032  dataLog("Optimizing ", *codeBlock, " succeeded, OSR failed, after a delay of ", codeBlock->optimizationDelayCounter(), ".\n");
1033 #endif
 1038
 1039 if (logOSR()) {
 1040 dataLog(
 1041 "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
 1042 " succeeded, OSR failed, after a delay of ",
 1043 codeBlock->optimizationDelayCounter(), ".\n");
 1044 }
10341045
10351046 // Count the OSR failure as a speculation failure. If this happens a lot, then
10361047 // reoptimize.
10371048 optimizedCodeBlock->countOSRExit();
10381049
1039 #if ENABLE(JIT_VERBOSE_OSR)
1040  dataLog("Encountered OSR failure ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1041 #endif
1042 
10431050 // We are a lot more conservative about triggering reoptimization after OSR failure than
10441051 // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
10451052 // already, then we really would like to reoptimize immediately. But this case covers

@@DEFINE_STUB_FUNCTION(void, optimize)
10491056 // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
10501057 // reoptimization trigger.
10511058 if (optimizedCodeBlock->shouldReoptimizeNow()) {
1052 #if ENABLE(JIT_VERBOSE_OSR)
1053  dataLog("Triggering reoptimization of ", *codeBlock, " -> ", *codeBlock->replacement(), " (after OSR fail).\n");
1054 #endif
 1059 if (logOSR()) {
 1060 dataLog(
 1061 "Triggering reoptimization of ", *codeBlock, " -> ",
 1062 *codeBlock->replacement(), " (after OSR fail).\n");
 1063 }
10551064 codeBlock->reoptimize();
10561065 return;
10571066 }
150339

Source/JavaScriptCore/runtime/ExecutionHarness.h

@@inline CompilationResult installOptimize
102102 if (numParameters)
103103 *numParameters = codeBlock->numParameters();
104104
105  if (jitCode)
106  codeBlock->vm()->heap.reportExtraMemoryCost(sizeof(*codeBlock) + jitCode->size());
107  else
108  codeBlock->vm()->heap.reportExtraMemoryCost(sizeof(*codeBlock));
 105 // We could be installing optimized code due to worklist flush inside of GC. We don't
 106 // then want to recursively GC.
 107 if (!codeBlock->vm()->heap.isBusy()) {
 108 if (jitCode)
 109 codeBlock->vm()->heap.reportExtraMemoryCost(sizeof(*codeBlock) + jitCode->size());
 110 else
 111 codeBlock->vm()->heap.reportExtraMemoryCost(sizeof(*codeBlock));
 112 }
109113
110114 if (sink != codeBlock) {
111115 // This can happen if we GC and decide that the code is invalid.

@@inline CompilationResult prepareFunction
141145
142146template<typename CodeBlockType>
143147inline CompilationResult replaceWithDeferredOptimizedCode(
144  PassRefPtr<DFG::Plan> plan, RefPtr<CodeBlockType>& sink, RefPtr<JITCode>& jitCode,
 148 PassRefPtr<DFG::Plan> passedPlan, RefPtr<CodeBlockType>& sink, RefPtr<JITCode>& jitCode,
145149 MacroAssemblerCodePtr* jitCodeWithArityCheck, int* numParameters)
146150{
 151 RefPtr<DFG::Plan> plan = passedPlan;
 152 CompilationResult result = DFG::tryFinalizePlan(plan, jitCode, jitCodeWithArityCheck);
 153 if (result == CompilationSuccessful)
 154 plan->codeBlock->alternative()->unlinkIncomingCalls();
147155 return installOptimizedCode(
148  DFG::tryFinalizePlan(plan, jitCode, jitCodeWithArityCheck),
149  sink, static_cast<CodeBlockType*>(plan->codeBlock.get()), jitCode,
 156 result, sink, static_cast<CodeBlockType*>(plan->codeBlock.get()), jitCode,
150157 jitCodeWithArityCheck ? *jitCodeWithArityCheck : MacroAssemblerCodePtr(),
151158 numParameters);
152159}
150339

Source/JavaScriptCore/runtime/Options.h

@@namespace JSC {
8888 v(bool, enableLLVMFastISel, true) \
8989 v(unsigned, llvmOptimizationLevel, 2) \
9090 \
 91 v(bool, enableConcurrentCompilation, false) \
 92 \
9193 v(bool, enableProfiler, false) \
9294 \
9395 v(unsigned, maximumOptimizationCandidateInstructionCount, 10000) \
150339

Source/JavaScriptCore/runtime/StructureInlines.h

@@inline bool Structure::putWillGrowOutOfL
226226
227227ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable()
228228{
229  ASSERT(!globalObject() || !globalObject()->vm().heap.isBusy());
 229 ASSERT(!globalObject() || !globalObject()->vm().heap.isCollecting());
230230 return m_propertyTableUnsafe;
231231}
232232
150339

Source/JavaScriptCore/runtime/VM.cpp

11/*
2  * Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
 2 * Copyright (C) 2008, 2011, 2013 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

3333#include "CodeCache.h"
3434#include "CommonIdentifiers.h"
3535#include "DFGLongLivedState.h"
 36#include "DFGWorklist.h"
3637#include "DebuggerActivation.h"
3738#include "FunctionConstructor.h"
3839#include "GCActivityCallback.h"

@@VM::VM(VMType vmType, HeapType heapType)
253254
254255#if ENABLE(DFG_JIT)
255256 if (canUseJIT())
256  m_dfgState = adoptPtr(new DFG::LongLivedState());
 257 dfgState = adoptPtr(new DFG::LongLivedState());
257258#endif
258259}
259260
260261VM::~VM()
261262{
 263 // Make sure concurrent compilations are done.
 264#if ENABLE(DFG_JIT)
 265 if (worklist)
 266 worklist->completeAllForVM(*this);
 267#endif
 268
262269 // Clear this first to ensure that nobody tries to remove themselves from it.
263270 m_perBytecodeProfiler.clear();
264271
150339

Source/JavaScriptCore/runtime/VM.h

@@namespace JSC {
9797#if ENABLE(DFG_JIT)
9898 namespace DFG {
9999 class LongLivedState;
 100 class Worklist;
100101 }
101102#endif // ENABLE(DFG_JIT)
102103

@@namespace JSC {
207208 Heap heap;
208209
209210#if ENABLE(DFG_JIT)
210  OwnPtr<DFG::LongLivedState> m_dfgState;
 211 OwnPtr<DFG::LongLivedState> dfgState;
 212 RefPtr<DFG::Worklist> worklist;
211213#endif // ENABLE(DFG_JIT)
212214
213215 VMType vmType;
150339

Source/WTF/wtf/ByteSpinLock.h

2929#include <wtf/Assertions.h>
3030#include <wtf/Atomics.h>
3131#include <wtf/Locker.h>
 32#include <wtf/Noncopyable.h>
3233#include <wtf/ThreadingPrimitives.h>
3334
3435namespace WTF {
3536
3637class ByteSpinLock {
 38 WTF_MAKE_NONCOPYABLE(ByteSpinLock);
3739public:
3840 ByteSpinLock()
3941 : m_lock(0)
150339

Source/WTF/wtf/MetaAllocatorHandle.h

11/*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

3131
3232#include <wtf/Assertions.h>
3333#include <wtf/RedBlackTree.h>
34 #include <wtf/RefCounted.h>
 34#include <wtf/ThreadSafeRefCounted.h>
3535#include <wtf/RefPtr.h>
3636
3737namespace WTF {
3838
3939class MetaAllocator;
4040
41 class MetaAllocatorHandle : public RefCounted<MetaAllocatorHandle>, public RedBlackTree<MetaAllocatorHandle, void*>::Node {
 41class MetaAllocatorHandle : public ThreadSafeRefCounted<MetaAllocatorHandle>, public RedBlackTree<MetaAllocatorHandle, void*>::Node {
4242private:
4343 MetaAllocatorHandle(MetaAllocator*, void* start, size_t sizeInBytes, void* ownerUID);
4444
150339