summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/API/JSBase.h2
-rw-r--r--Source/JavaScriptCore/ChangeLog232
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.pri6
-rwxr-xr-xSource/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def1
-rw-r--r--Source/JavaScriptCore/PlatformBlackBerry.cmake1
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp71
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h11
-rw-r--r--Source/JavaScriptCore/bytecode/ExecutionCounter.cpp21
-rw-r--r--Source/JavaScriptCore/bytecode/ExecutionCounter.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp12
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp12
-rw-r--r--Source/JavaScriptCore/dfg/DFGCCallHelpers.h25
-rw-r--r--Source/JavaScriptCore/dfg/DFGCSEPhase.cpp11
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h31
-rw-r--r--Source/JavaScriptCore/dfg/DFGNodeType.h5
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp18
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.h7
-rw-r--r--Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp28
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h30
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp95
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp79
-rw-r--r--Source/JavaScriptCore/heap/IncrementalSweeper.cpp1
-rw-r--r--Source/JavaScriptCore/heap/MachineStackMarker.cpp14
-rw-r--r--Source/JavaScriptCore/heap/MachineStackMarker.h4
-rw-r--r--Source/JavaScriptCore/heap/MarkedBlock.h2
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.cpp6
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h37
-rw-r--r--Source/JavaScriptCore/runtime/JSExportMacros.h4
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h41
-rw-r--r--Source/JavaScriptCore/runtime/MemoryStatistics.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Options.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/Options.h6
-rw-r--r--Source/JavaScriptCore/runtime/WeakRandom.h3
-rw-r--r--Source/JavaScriptCore/wscript2
38 files changed, 663 insertions, 199 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/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 9304ce075..686fac171 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,33 +1,223 @@
-2012-06-19 Joel Dillon <joel.dillon@codethink.co.uk> Jocelyn Turcotte <jocelyn.turcotte@nokia.com>
+2012-06-26 Geoffrey Garen <ggaren@apple.com>
- [Qt][Win] Fix broken QtWebKit5.lib linking
- https://bugs.webkit.org/show_bug.cgi?id=88321
+ Reduced (but did not eliminate) use of "berzerker GC"
+ https://bugs.webkit.org/show_bug.cgi?id=89237
+
+ Reviewed by Gavin Barraclough.
+
+ (PART 2)
+
+ This part turns off "berzerker GC" and turns on incremental shrinking.
+
+ * heap/IncrementalSweeper.cpp:
+ (JSC::IncrementalSweeper::doSweep): Free or shrink after sweeping to
+ maintain the behavior we used to get from the occasional berzerker GC,
+ which would run all finalizers and then free or shrink all blocks
+ synchronously.
+
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::needsSweeping): Sweep zapped blocks, too. It's always
+ safe to sweep a zapped block (that's the point of zapping), and it's
+ sometimes profitable. For example, consider this case: Block A does some
+ allocation (transitioning Block A from Marked to FreeListed), then GC
+ happens (transitioning Block A to Zapped), then all objects in Block A
+ are free, then the incremental sweeper visits Block A. If we skipped
+ Zapped blocks, we'd skip Block A, even though it would be profitable to
+ run its destructors and free its memory.
+
+ * runtime/GCActivityCallback.cpp:
+ (JSC::DefaultGCActivityCallback::doWork): Don't sweep eagerly; we'll do
+ this incrementally.
+
+2012-06-26 Filip Pizlo <fpizlo@apple.com>
+
+ DFG PutByValAlias is too aggressive
+ https://bugs.webkit.org/show_bug.cgi?id=90026
+ <rdar://problem/11751830>
+
+ Reviewed by Gavin Barraclough.
+
+ For CSE on normal arrays, we now treat PutByVal as impure. This does not appear to affect
+ performance by much.
+
+ For CSE on typed arrays, we fix PutByValAlias by making GetByVal speculate that the access
+ is within bounds. This also has the effect of making our out-of-bounds handling consistent
+ with WebCore.
+
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::byValIsPure):
+ (JSC::DFG::Graph::clobbersWorld):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
+
+2012-06-26 Yong Li <yoli@rim.com>
+
+ [BlackBerry] Add JSC statistics into about:memory
+ https://bugs.webkit.org/show_bug.cgi?id=89779
+
+ Reviewed by Rob Buis.
+
+ Fix non-JIT build on BlackBerry broken by r121196.
+
+ * runtime/MemoryStatistics.cpp:
+ (JSC::globalMemoryStatistics):
+
+2012-06-25 Filip Pizlo <fpizlo@apple.com>
+
+ DFG::operationNewArray is unnecessarily slow, and may use the wrong array
+ prototype when inlined
+ https://bugs.webkit.org/show_bug.cgi?id=89821
+
+ Reviewed by Geoffrey Garen.
+
+ Fixes all array allocations to use the right structure, and hence the right prototype. Adds
+ inlining of new Array(...) with a non-zero number of arguments. Optimizes allocations of
+ empty arrays.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+ * dfg/DFGCCallHelpers.h:
+ (JSC::DFG::CCallHelpers::setupArgumentsWithExecState):
+ (CCallHelpers):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * runtime/JSArray.h:
+ (JSC):
+ (JSC::constructArray):
+ * runtime/JSGlobalObject.h:
+ (JSC):
+ (JSC::constructArray):
- Reviewed by NOBODY (OOPS!).
+2012-06-26 Filip Pizlo <fpizlo@apple.com>
- Also update the Wx build to use the new define.
+ New fast/js/dfg-store-unexpected-value-into-argument-and-osr-exit.html fails on 32 bit
+ https://bugs.webkit.org/show_bug.cgi?id=89953
- * API/JSBase.h:
- * runtime/JSExportMacros.h:
- * wscript:
+ Reviewed by Zoltan Herczeg.
+
+ DFG 32-bit JIT was confused about the difference between a predicted type and a
+ proven type. This is easy to get confused about, since a local that is predicted int32
+ almost always means that the local must be an int32 since speculations are hoisted to
+ stores to locals. But that is less likely to be the case for arguments, where there is
+ an additional least-upper-bounding step: any store to an argument with a weird type
+ may force the argument to be any type.
+
+ This patch basically duplicates the functionality in DFGSpeculativeJIT64.cpp for
+ GetLocal: the decision of whether to load a local as an int32 (or as an array, or as
+ a boolean) is made based on the AbstractValue::m_type, which is a type proof, rather
+ than the VariableAccessData::prediction(), which is a predicted type.
-2012-06-13 Patrick Gansterer <paroga@webkit.org>
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
- [WIN] Remove dependency on pthread from MachineStackMarker
- https://bugs.webkit.org/show_bug.cgi?id=68429
+2012-06-25 Filip Pizlo <fpizlo@apple.com>
- Reviewed by NOBODY (OOPS!).
+ JSC should try to make profiling deterministic because otherwise reproducing failures is
+ nearly impossible
+ https://bugs.webkit.org/show_bug.cgi?id=89940
- Implement pthread TLS functionality with native windows functions.
+ Rubber stamped by Gavin Barraclough.
+
+ This rolls out the part of http://trac.webkit.org/changeset/121215 that introduced randomness
+ into the system. Now, instead of randomizing the tier-up threshold, we always set it to an
+ artificially low (and statically predetermined!) value. This gives most of the benefit of
+ threshold randomization without actually making the system behave completely differently on
+ each invocation.
- * 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:
+ * bytecode/ExecutionCounter.cpp:
+ (JSC::ExecutionCounter::setThreshold):
+ * runtime/Options.cpp:
+ (Options):
+ (JSC::Options::initializeOptions):
+ * runtime/Options.h:
+ (Options):
+
+2012-06-22 Filip Pizlo <fpizlo@apple.com>
+
+ Value profiling should use tier-up threshold randomization to get more coverage
+ https://bugs.webkit.org/show_bug.cgi?id=89802
+
+ Reviewed by Gavin Barraclough.
+
+ This patch causes both LLInt and Baseline JIT code to take the OSR slow path several
+ times before actually doing OSR. If we take the OSR slow path before the execution
+ count threshold is reached, then we just call CodeBlock::updateAllPredictions() to
+ compute the current latest least-upper-bound SpecType of all values seen in each
+ ValueProfile.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::stronglyVisitStrongReferences):
+ (JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
+ (JSC):
+ (JSC::CodeBlock::updateAllPredictions):
+ (JSC::CodeBlock::shouldOptimizeNow):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::llintExecuteCounter):
+ (JSC::CodeBlock::jitExecuteCounter):
+ (CodeBlock):
+ (JSC::CodeBlock::updateAllPredictions):
+ * bytecode/ExecutionCounter.cpp:
+ (JSC::ExecutionCounter::setThreshold):
+ (JSC::ExecutionCounter::status):
+ (JSC):
+ * bytecode/ExecutionCounter.h:
+ (JSC::ExecutionCounter::count):
+ (ExecutionCounter):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::jitCompileAndSetHeuristics):
+ (JSC::LLInt::entryOSR):
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::JSGlobalObject):
+ (JSC):
+ * runtime/JSGlobalObject.h:
+ (JSGlobalObject):
+ (JSC::JSGlobalObject::weakRandomInteger):
+ * runtime/Options.cpp:
+ (Options):
+ (JSC::Options::initializeOptions):
+ * runtime/Options.h:
+ (Options):
+ * runtime/WeakRandom.h:
+ (WeakRandom):
+ (JSC::WeakRandom::seedUnsafe):
+
+2012-06-25 Yong Li <yoli@rim.com>
+
+ [BlackBerry] Add JSC statistics into about:memory
+ https://bugs.webkit.org/show_bug.cgi?id=89779
+
+ Reviewed by Rob Buis.
+
+ Add MemoryStatistics.cpp into build, and fill JITBytes for BlackBerry port.
+
+ * PlatformBlackBerry.cmake:
+ * runtime/MemoryStatistics.cpp:
+ (JSC::globalMemoryStatistics):
2012-06-23 Sheriff Bot <webkit.review.bot@gmail.com>
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 c48ef49c6..6a8a89372 100755
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -9,6 +9,7 @@ EXPORTS
??0DropAllLocks@JSLock@JSC@@QAE@W4JSLockBehavior@2@@Z
??0DynamicGlobalObjectScope@JSC@@QAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@@Z
??0InternalFunction@JSC@@IAE@PAVJSGlobalObject@1@PAVStructure@1@@Z
+ ??0JSGlobalObject@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@PBUGlobalObjectMethodTable@1@@Z
??0JSLock@JSC@@QAE@PAVExecState@1@@Z
??0MD5@WTF@@QAE@XZ
??0Mutex@WTF@@QAE@XZ
diff --git a/Source/JavaScriptCore/PlatformBlackBerry.cmake b/Source/JavaScriptCore/PlatformBlackBerry.cmake
index cc3cfead3..f9352cd4f 100644
--- a/Source/JavaScriptCore/PlatformBlackBerry.cmake
+++ b/Source/JavaScriptCore/PlatformBlackBerry.cmake
@@ -8,6 +8,7 @@ LIST(REMOVE_ITEM JavaScriptCore_SOURCES
LIST(APPEND JavaScriptCore_SOURCES
runtime/GCActivityCallbackBlackBerry.cpp
+ runtime/MemoryStatistics.cpp
)
INSTALL(FILES "wtf/Forward.h" DESTINATION usr/include/browser/webkit/wtf)
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index bcbb51f63..e0a4da71d 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -2104,26 +2104,7 @@ void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
}
#endif
-#if ENABLE(DFG_JIT)
- if (hasCodeOrigins()) {
- // Make sure that executables that we have inlined don't die.
- // FIXME: If they would have otherwise died, we should probably trigger recompilation.
- for (size_t i = 0; i < inlineCallFrames().size(); ++i) {
- InlineCallFrame& inlineCallFrame = inlineCallFrames()[i];
- visitor.append(&inlineCallFrame.executable);
- visitor.append(&inlineCallFrame.callee);
- }
- }
-
- m_lazyOperandValueProfiles.computeUpdatedPredictions(Collection);
-#endif
-
-#if ENABLE(VALUE_PROFILER)
- for (unsigned profileIndex = 0; profileIndex < numberOfArgumentValueProfiles(); ++profileIndex)
- valueProfileForArgument(profileIndex)->computeUpdatedPrediction(Collection);
- for (unsigned profileIndex = 0; profileIndex < numberOfValueProfiles(); ++profileIndex)
- valueProfile(profileIndex)->computeUpdatedPrediction(Collection);
-#endif
+ updateAllPredictions(Collection);
}
void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor)
@@ -2574,21 +2555,11 @@ bool FunctionCodeBlock::jitCompileImpl(ExecState* exec)
#endif
#if ENABLE(VALUE_PROFILER)
-bool CodeBlock::shouldOptimizeNow()
+void CodeBlock::updateAllPredictionsAndCountLiveness(
+ OperationInProgress operation, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
{
-#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("Considering optimizing %p...\n", this);
-#endif
-
-#if ENABLE(VERBOSE_VALUE_PROFILE)
- dumpValueProfiles();
-#endif
-
- if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay)
- return true;
-
- unsigned numberOfLiveNonArgumentValueProfiles = 0;
- unsigned numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
+ numberOfLiveNonArgumentValueProfiles = 0;
+ numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
ValueProfile* profile = getFromAllValueProfiles(i);
unsigned numSamples = profile->totalNumberOfSamples();
@@ -2596,13 +2567,41 @@ bool CodeBlock::shouldOptimizeNow()
numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
numberOfSamplesInProfiles += numSamples;
if (profile->m_bytecodeOffset < 0) {
- profile->computeUpdatedPrediction();
+ profile->computeUpdatedPrediction(operation);
continue;
}
if (profile->numberOfSamples() || profile->m_prediction != SpecNone)
numberOfLiveNonArgumentValueProfiles++;
- profile->computeUpdatedPrediction();
+ profile->computeUpdatedPrediction(operation);
}
+
+#if ENABLE(DFG_JIT)
+ m_lazyOperandValueProfiles.computeUpdatedPredictions(operation);
+#endif
+}
+
+void CodeBlock::updateAllPredictions(OperationInProgress operation)
+{
+ unsigned ignoredValue1, ignoredValue2;
+ updateAllPredictionsAndCountLiveness(operation, ignoredValue1, ignoredValue2);
+}
+
+bool CodeBlock::shouldOptimizeNow()
+{
+#if ENABLE(JIT_VERBOSE_OSR)
+ dataLog("Considering optimizing %p...\n", this);
+#endif
+
+#if ENABLE(VERBOSE_VALUE_PROFILE)
+ dumpValueProfiles();
+#endif
+
+ if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay)
+ return true;
+
+ unsigned numberOfLiveNonArgumentValueProfiles;
+ unsigned numberOfSamplesInProfiles;
+ updateAllPredictionsAndCountLiveness(NoOperation, numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles);
#if ENABLE(JIT_VERBOSE_OSR)
dataLog("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles());
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index b73dcb2b6..4e4fee2b7 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -913,9 +913,9 @@ namespace JSC {
m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITSoon, this);
}
- int32_t llintExecuteCounter() const
+ const ExecutionCounter& llintExecuteCounter() const
{
- return m_llintExecuteCounter.m_counter;
+ return m_llintExecuteCounter;
}
// Functions for controlling when tiered compilation kicks in. This
@@ -971,7 +971,7 @@ namespace JSC {
static ptrdiff_t offsetOfJITExecutionActiveThreshold() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_activeThreshold); }
static ptrdiff_t offsetOfJITExecutionTotalCount() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_totalCount); }
- int32_t jitExecuteCounter() const { return m_jitExecuteCounter.m_counter; }
+ const ExecutionCounter& jitExecuteCounter() const { return m_jitExecuteCounter; }
unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; }
@@ -1100,8 +1100,10 @@ namespace JSC {
#if ENABLE(VALUE_PROFILER)
bool shouldOptimizeNow();
+ void updateAllPredictions(OperationInProgress = NoOperation);
#else
bool shouldOptimizeNow() { return false; }
+ void updateAllPredictions(OperationInProgress = NoOperation) { }
#endif
#if ENABLE(JIT)
@@ -1134,6 +1136,9 @@ namespace JSC {
#else
void tallyFrequentExitSites() { }
#endif
+#if ENABLE(VALUE_PROFILER)
+ void updateAllPredictionsAndCountLiveness(OperationInProgress, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
+#endif
void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&);
diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp
index ea335005e..1f2e8260a 100644
--- a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp
+++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp
@@ -28,6 +28,7 @@
#include "CodeBlock.h"
#include "ExecutableAllocator.h"
+#include <wtf/StringExtras.h>
namespace JSC {
@@ -125,7 +126,7 @@ bool ExecutionCounter::setThreshold(CodeBlock* codeBlock)
ASSERT(!hasCrossedThreshold(codeBlock));
// Compute the true total count.
- double trueTotalCount = static_cast<double>(m_totalCount) + m_counter;
+ double trueTotalCount = count();
// Correct the threshold for current memory usage.
double threshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock);
@@ -143,9 +144,14 @@ bool ExecutionCounter::setThreshold(CodeBlock* codeBlock)
return true;
}
- if (threshold > std::numeric_limits<int32_t>::max())
- threshold = std::numeric_limits<int32_t>::max();
-
+ int32_t maxThreshold;
+ if (Options::randomizeExecutionCountsBetweenCheckpoints)
+ maxThreshold = codeBlock->globalObject()->weakRandomInteger() % Options::maximumExecutionCountsBetweenCheckpoints;
+ else
+ maxThreshold = Options::maximumExecutionCountsBetweenCheckpoints;
+ if (threshold > maxThreshold)
+ threshold = maxThreshold;
+
m_counter = static_cast<int32_t>(-threshold);
m_totalCount = trueTotalCount + threshold;
@@ -160,5 +166,12 @@ void ExecutionCounter::reset()
m_activeThreshold = 0;
}
+const char* ExecutionCounter::status() const
+{
+ static char result[80];
+ snprintf(result, sizeof(result), "%lf/%lf, %d", count(), static_cast<double>(m_activeThreshold), m_counter);
+ return result;
+}
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.h b/Source/JavaScriptCore/bytecode/ExecutionCounter.h
index d2ffbb649..1c0d23f0f 100644
--- a/Source/JavaScriptCore/bytecode/ExecutionCounter.h
+++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.h
@@ -38,6 +38,8 @@ public:
bool checkIfThresholdCrossedAndSet(CodeBlock*);
void setNewThreshold(int32_t threshold, CodeBlock*);
void deferIndefinitely();
+ double count() const { return static_cast<double>(m_totalCount) + m_counter; }
+ const char* status() const;
static double applyMemoryUsageHeuristics(int32_t value, CodeBlock*);
static int32_t applyMemoryUsageHeuristicsAndConvertToInt(int32_t value, CodeBlock*);
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 94e96853d..c2d49f7ee 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -1141,13 +1141,19 @@ bool AbstractState::execute(unsigned indexInBlock)
case NewArray:
case NewArrayBuffer:
node.setCanExit(false);
- forNode(nodeIndex).set(m_codeBlock->globalObject()->arrayStructure());
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
+ m_haveStructures = true;
+ break;
+
+ case NewArrayWithSize:
+ speculateInt32Unary(node);
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
m_haveStructures = true;
break;
case NewRegexp:
node.setCanExit(false);
- forNode(nodeIndex).set(m_codeBlock->globalObject()->regExpStructure());
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->regExpStructure());
m_haveStructures = true;
break;
@@ -1392,7 +1398,7 @@ bool AbstractState::execute(unsigned indexInBlock)
case StructureTransitionWatchpoint: {
// FIXME: Turn CheckStructure into StructureTransitionWatchpoint when possible!
AbstractValue& value = forNode(node.child1());
- ASSERT(isCellSpeculation(value.m_type));
+ ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad.
value.filter(node.structure());
node.setCanExit(true);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 75611972e..cdb0b639a 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -1606,15 +1606,19 @@ bool ByteCodeParser::handleConstantInternalFunction(
// 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;
+ if (argumentCountIncludingThis == 2) {
+ setIntrinsicResult(
+ usesResult, resultOperand,
+ addToGraph(NewArrayWithSize, get(registerOffset + argumentToOperand(1))));
+ return true;
+ }
+ for (int i = 1; i < argumentCountIncludingThis; ++i)
+ addVarArgChild(get(registerOffset + argumentToOperand(i)));
setIntrinsicResult(
usesResult, resultOperand,
addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0)));
diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
index 4cacd45c1..b60290870 100644
--- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
@@ -160,6 +160,14 @@ public:
addCallArgument(arg2);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
{
resetCallArguments();
@@ -203,6 +211,15 @@ public:
addCallArgument(arg3);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
+ {
+ resetCallArguments();
+ addCallArgument(GPRInfo::callFrameRegister);
+ addCallArgument(arg1);
+ addCallArgument(arg2);
+ addCallArgument(arg3);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
{
resetCallArguments();
@@ -597,6 +614,14 @@ public:
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
+ {
+ move(arg1, GPRInfo::argumentGPR1);
+ move(arg2, GPRInfo::argumentGPR2);
+ move(arg3, GPRInfo::argumentGPR3);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, TrustedImm32 arg3)
{
move(arg1, GPRInfo::argumentGPR1);
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index a362e6e97..be0012f56 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -1080,10 +1080,15 @@ private:
break;
case PutByVal:
- if (m_graph.byValIsPure(node)
- && !m_graph[node.child1()].shouldSpeculateArguments()
- && getByValLoadElimination(node.child1().index(), node.child2().index()) != NoNode)
+ if (isActionableMutableArraySpeculation(m_graph[node.child1()].prediction())
+ && m_graph[node.child2()].shouldSpeculateInteger()
+ && !m_graph[node.child1()].shouldSpeculateArguments()) {
+ NodeIndex nodeIndex = getByValLoadElimination(
+ node.child1().index(), node.child2().index());
+ if (nodeIndex == NoNode)
+ break;
node.setOp(PutByValAlias);
+ }
break;
case CheckStructure:
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 9e4a28fc3..a9080d117 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -463,10 +463,31 @@ public:
bool byValIsPure(Node& node)
{
- return at(node.child2()).shouldSpeculateInteger()
- && ((node.op() == PutByVal || node.op() == PutByValAlias)
- ? isActionableMutableArraySpeculation(at(node.child1()).prediction())
- : isActionableArraySpeculation(at(node.child1()).prediction()));
+ if (!at(node.child2()).shouldSpeculateInteger())
+ return false;
+ SpeculatedType prediction = at(node.child1()).prediction();
+ switch (node.op()) {
+ case PutByVal:
+ if (!isActionableMutableArraySpeculation(prediction))
+ return false;
+ if (isArraySpeculation(prediction))
+ return false;
+ return true;
+
+ case PutByValAlias:
+ if (!isActionableMutableArraySpeculation(prediction))
+ return false;
+ return true;
+
+ case GetByVal:
+ if (!isActionableArraySpeculation(prediction))
+ return false;
+ return true;
+
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
}
bool clobbersWorld(Node& node)
@@ -484,6 +505,8 @@ public:
case CompareEq:
return !isPredictedNumerical(node);
case GetByVal:
+ case PutByVal:
+ case PutByValAlias:
return !byValIsPure(node);
default:
ASSERT_NOT_REACHED();
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 4671f6b6c..8c2f96222 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -111,8 +111,8 @@ namespace JSC { namespace DFG {
/* Since a put to 'length' may invalidate optimizations here, */\
/* this must be the directly subsequent property put. */\
macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
- macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
- macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
+ macro(PutByVal, NodeMustGenerate | NodeMightClobber) \
+ macro(PutByValAlias, NodeMustGenerate | NodeMightClobber) \
macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
@@ -184,6 +184,7 @@ namespace JSC { namespace DFG {
/* Allocations. */\
macro(NewObject, NodeResultJS) \
macro(NewArray, NodeResultJS | NodeHasVarArgs) \
+ macro(NewArrayWithSize, NodeResultJS) \
macro(NewArrayBuffer, NodeResultJS) \
macro(NewRegexp, NodeResultJS) \
\
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index b056a3c6d..11362f432 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -1005,12 +1005,22 @@ EncodedJSValue DFG_OPERATION operationStrCat(ExecState* exec, void* buffer, size
return JSValue::encode(jsString(exec, static_cast<Register*>(buffer), size));
}
-EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* buffer, size_t size)
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
{
JSGlobalData* globalData = &exec->globalData();
NativeCallFrameTracer tracer(globalData, exec);
- return JSValue::encode(constructArray(exec, static_cast<JSValue*>(buffer), size));
+ return JSValue::encode(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
+}
+
+EncodedJSValue DFG_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
+{
+ return JSValue::encode(JSArray::create(exec->globalData(), arrayStructure));
+}
+
+EncodedJSValue DFG_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
+{
+ return JSValue::encode(JSArray::create(exec->globalData(), arrayStructure, size));
}
EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState* exec, size_t start, size_t size)
@@ -1238,12 +1248,12 @@ void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void*
SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
CodeBlock* codeBlock = debugInfo->codeBlock;
CodeBlock* alternative = codeBlock->alternative();
- dataLog("Speculation failure in %p at @%u with executeCounter = %d, "
+ dataLog("Speculation failure in %p at @%u with executeCounter = %s, "
"reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, "
"success/fail %u/(%u+%u)\n",
codeBlock,
debugInfo->nodeIndex,
- alternative ? alternative->jitExecuteCounter() : 0,
+ alternative ? alternative->jitExecuteCounter().status() : 0,
alternative ? alternative->reoptimizationRetryCounter() : 0,
alternative ? alternative->optimizationDelayCounter() : 0,
codeBlock->speculativeSuccessCounter(),
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index 7477ab2fc..3c85ee761 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -76,6 +76,9 @@ typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EP)(ExecState*, void*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, void*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESt)(ExecState*, Structure*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EStI)(ExecState*, Structure*, int32_t);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EStPS)(ExecState*, Structure*, void*, size_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZ)(ExecState*, int32_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZIcfZ)(ExecState*, int32_t, InlineCallFrame*, int32_t);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZZ)(ExecState*, int32_t, int32_t);
@@ -124,8 +127,10 @@ EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifie
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;
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, Structure*, void*, size_t) WTF_INTERNAL;
EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewEmptyArray(ExecState*, Structure*) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationNewArrayWithSize(ExecState*, Structure*, int32_t) WTF_INTERNAL;
EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL;
void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index bcb79a96a..0bd81ec44 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -535,6 +535,12 @@ private:
break;
}
+ case NewArrayWithSize: {
+ changed |= setPrediction(SpecArray);
+ changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+ break;
+ }
+
case NewArrayBuffer: {
changed |= setPrediction(SpecArray);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index d9a79f13a..0c0f3260f 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -986,13 +986,8 @@ void SpeculativeJIT::compile(BasicBlock& block)
m_jit.jitAssertHasValidCallFrame();
ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
- for (size_t i = 0; i < m_arguments.size(); ++i) {
- NodeIndex nodeIndex = block.variablesAtHead.argument(i);
- if (nodeIndex == NoNode || m_jit.codeBlock()->argumentIsCaptured(i))
- m_arguments[i] = ValueSource(ValueInRegisterFile);
- else
- m_arguments[i] = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->prediction());
- }
+ for (size_t i = 0; i < m_arguments.size(); ++i)
+ m_arguments[i] = ValueSource(ValueInRegisterFile);
m_state.reset();
m_state.beginBasicBlock(&block);
@@ -2005,10 +2000,10 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor&
return;
}
- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
- m_jit.xorPtr(resultReg, resultReg);
- MacroAssembler::Jump outOfBounds = m_jit.jump();
- inBounds.link(&m_jit);
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branch32(
+ MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)));
switch (elementSize) {
case 1:
if (signedness == SignedTypedArray)
@@ -2028,7 +2023,6 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor&
default:
ASSERT_NOT_REACHED();
}
- outOfBounds.link(&m_jit);
if (elementSize < 4 || signedness == SignedTypedArray) {
integerResult(resultReg, m_compileIndex);
return;
@@ -2167,11 +2161,10 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor
FPRTemporary result(this);
FPRReg resultReg = result.fpr();
ASSERT(speculationRequirements != NoTypedArraySpecCheck);
- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
- static const double zero = 0;
- m_jit.loadDouble(&zero, resultReg);
- MacroAssembler::Jump outOfBounds = m_jit.jump();
- inBounds.link(&m_jit);
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branch32(
+ MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)));
switch (elementSize) {
case 4:
m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
@@ -2188,7 +2181,6 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor
default:
ASSERT_NOT_REACHED();
}
- outOfBounds.link(&m_jit);
doubleResult(resultReg, m_compileIndex);
}
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 6c6948b90..67a22b767 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1244,6 +1244,21 @@ public:
m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_DFGOperation_ESt operation, GPRReg result, Structure* structure)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
+ return appendCallWithExceptionCheckSetResult(operation, result);
+ }
+ JITCompiler::Call callOperation(J_DFGOperation_EStI operation, GPRReg result, Structure* structure, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2);
+ return appendCallWithExceptionCheckSetResult(operation, result);
+ }
+ JITCompiler::Call callOperation(J_DFGOperation_EStPS operation, GPRReg result, Structure* structure, void* pointer, size_t size)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(pointer), TrustedImmPtr(size));
+ return appendCallWithExceptionCheckSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg result, void* pointer, size_t size)
{
m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
@@ -1502,6 +1517,21 @@ public:
m_jit.setupArgumentsWithExecState(arg1);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
+ JITCompiler::Call callOperation(J_DFGOperation_ESt operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+ }
+ JITCompiler::Call callOperation(J_DFGOperation_EStI operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2);
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+ }
+ JITCompiler::Call callOperation(J_DFGOperation_EStPS operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure, void* pointer, size_t size)
+ {
+ m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(pointer), TrustedImmPtr(size));
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+ }
JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
{
m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 21d94e9e8..05609baa8 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -1891,7 +1891,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isInt32Speculation(prediction)) {
+ if (isInt32Speculation(value.m_type)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1903,7 +1903,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isArraySpeculation(prediction)) {
+ if (isArraySpeculation(value.m_type)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -1915,7 +1915,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- if (isBooleanSpeculation(prediction)) {
+ if (isBooleanSpeculation(value.m_type)) {
GPRTemporary result(this);
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
@@ -2975,25 +2975,60 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case StrCat:
- case NewArray: {
- // We really don't want to grow the register file just to do a StrCat or NewArray.
- // Say we have 50 functions on the stack that all have a StrCat in them that has
- // upwards of 10 operands. In the DFG this would mean that each one gets
- // some random virtual register, and then to do the StrCat we'd need a second
- // span of 10 operands just to have somewhere to copy the 10 operands to, where
- // they'd be contiguous and we could easily tell the C code how to find them.
- // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
- // way, those 50 functions will share the same scratchBuffer for offloading their
- // StrCat operands. It's about as good as we can do, unless we start doing
- // virtual register coalescing to ensure that operands to StrCat get spilled
- // in exactly the place where StrCat wants them, or else have the StrCat
- // refer to those operands' SetLocal instructions to force them to spill in
- // the right place. Basically, any way you cut it, the current approach
- // probably has the best balance of performance and sensibility in the sense
- // that it does not increase the complexity of the DFG JIT just to make StrCat
- // fast and pretty.
+ case StrCat: {
+ size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
+ ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
+ EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
+
+ for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
+ JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
+ GPRReg opTagGPR = operand.tagGPR();
+ GPRReg opPayloadGPR = operand.payloadGPR();
+ operand.use();
+
+ m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+ m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ }
+
+ flushRegisters();
+ if (scratchSize) {
+ GPRTemporary scratch(this);
+
+ // Tell GC mark phase how much of the scratch buffer is active during call.
+ m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
+ }
+
+ GPRResult resultPayload(this);
+ GPRResult2 resultTag(this);
+
+ callOperation(operationStrCat, resultTag.gpr(), resultPayload.gpr(), static_cast<void *>(buffer), node.numChildren());
+
+ if (scratchSize) {
+ GPRTemporary scratch(this);
+
+ m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
+ }
+
+ // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
+ cellResult(resultPayload.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ case NewArray: {
+ if (!node.numChildren()) {
+ flushRegisters();
+ GPRResult result(this);
+ GPRResult2 resultTagIgnored(this);
+ callOperation(
+ operationNewEmptyArray, resultTagIgnored.gpr(), result.gpr(),
+ m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure());
+ cellResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
@@ -3021,7 +3056,10 @@ void SpeculativeJIT::compile(Node& node)
GPRResult resultPayload(this);
GPRResult2 resultTag(this);
- callOperation(op == StrCat ? operationStrCat : operationNewArray, resultTag.gpr(), resultPayload.gpr(), static_cast<void *>(buffer), node.numChildren());
+ callOperation(
+ operationNewArray, resultTag.gpr(), resultPayload.gpr(),
+ m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(),
+ static_cast<void *>(buffer), node.numChildren());
if (scratchSize) {
GPRTemporary scratch(this);
@@ -3035,6 +3073,19 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ case NewArrayWithSize: {
+ SpeculateStrictInt32Operand size(this, node.child1());
+ GPRReg sizeGPR = size.gpr();
+ flushRegisters();
+ GPRResult result(this);
+ GPRResult2 resultTagIgnored(this);
+ callOperation(
+ operationNewArrayWithSize, resultTagIgnored.gpr(), result.gpr(),
+ m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), sizeGPR);
+ cellResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
case NewArrayBuffer: {
flushRegisters();
GPRResult resultPayload(this);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index a6c283584..215f8013d 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -3035,25 +3035,68 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case StrCat:
case NewArray: {
- // We really don't want to grow the register file just to do a StrCat or NewArray.
- // Say we have 50 functions on the stack that all have a StrCat in them that has
- // upwards of 10 operands. In the DFG this would mean that each one gets
- // some random virtual register, and then to do the StrCat we'd need a second
- // span of 10 operands just to have somewhere to copy the 10 operands to, where
- // they'd be contiguous and we could easily tell the C code how to find them.
- // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
- // way, those 50 functions will share the same scratchBuffer for offloading their
- // StrCat operands. It's about as good as we can do, unless we start doing
- // virtual register coalescing to ensure that operands to StrCat get spilled
- // in exactly the place where StrCat wants them, or else have the StrCat
- // refer to those operands' SetLocal instructions to force them to spill in
- // the right place. Basically, any way you cut it, the current approach
- // probably has the best balance of performance and sensibility in the sense
- // that it does not increase the complexity of the DFG JIT just to make StrCat
- // fast and pretty.
+ if (!node.numChildren()) {
+ flushRegisters();
+ GPRResult result(this);
+ callOperation(
+ operationNewEmptyArray, result.gpr(),
+ m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure());
+ cellResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
+ size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
+ ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
+ EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
+
+ for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
+ JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
+ GPRReg opGPR = operand.gpr();
+ operand.use();
+
+ m_jit.storePtr(opGPR, buffer + operandIdx);
+ }
+
+ flushRegisters();
+
+ if (scratchSize) {
+ GPRTemporary scratch(this);
+ // Tell GC mark phase how much of the scratch buffer is active during call.
+ m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
+ }
+
+ GPRResult result(this);
+
+ callOperation(
+ operationNewArray, result.gpr(),
+ m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(),
+ static_cast<void*>(buffer), node.numChildren());
+
+ if (scratchSize) {
+ GPRTemporary scratch(this);
+
+ m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
+ }
+
+ cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
+ break;
+ }
+
+ case NewArrayWithSize: {
+ SpeculateStrictInt32Operand size(this, node.child1());
+ GPRReg sizeGPR = size.gpr();
+ flushRegisters();
+ GPRResult result(this);
+ callOperation(operationNewArrayWithSize, result.gpr(), m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), sizeGPR);
+ cellResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
+ case StrCat: {
size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
@@ -3078,7 +3121,7 @@ void SpeculativeJIT::compile(Node& node)
GPRResult result(this);
- callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), static_cast<void *>(buffer), node.numChildren());
+ callOperation(operationStrCat, result.gpr(), static_cast<void *>(buffer), node.numChildren());
if (scratchSize) {
GPRTemporary scratch(this);
diff --git a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
index 165bfeaff..848377346 100644
--- a/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
+++ b/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
@@ -78,6 +78,7 @@ void IncrementalSweeper::doSweep(double sweepBeginTime)
continue;
block->sweep();
+ m_globalData->heap.objectSpace().freeOrShrinkBlock(block);
CFTimeInterval elapsedTime = WTF::monotonicallyIncreasingTime() - sweepBeginTime;
if (elapsedTime < sweepTimeSlice)
diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp
index 8e0c57b6a..7eb57479b 100644
--- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp
+++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp
@@ -141,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;) {
@@ -179,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/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h
index eb1cb681b..c3c43752b 100644
--- a/Source/JavaScriptCore/heap/MarkedBlock.h
+++ b/Source/JavaScriptCore/heap/MarkedBlock.h
@@ -408,7 +408,7 @@ namespace JSC {
inline bool MarkedBlock::needsSweeping()
{
- return m_state == Marked;
+ return m_state == Marked || m_state == Zapped;
}
#if ENABLE(GGC)
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index b0ff4a0c7..6b8082886 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -1928,11 +1928,13 @@ DEFINE_STUB_FUNCTION(void, optimize)
unsigned bytecodeIndex = stackFrame.args[0].int32();
#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+ dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %s, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter().status(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
#endif
- if (!codeBlock->checkIfOptimizationThresholdReached())
+ if (!codeBlock->checkIfOptimizationThresholdReached()) {
+ codeBlock->updateAllPredictions();
return;
+ }
if (codeBlock->hasOptimizedReplacement()) {
#if ENABLE(JIT_VERBOSE_OSR)
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index ca3eb1eb0..a7698be37 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -264,6 +264,8 @@ inline bool shouldJIT(ExecState* exec)
// Returns true if we should try to OSR.
inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
{
+ codeBlock->updateAllPredictions();
+
if (!codeBlock->checkIfJITThresholdReached()) {
#if ENABLE(JIT_VERBOSE_OSR)
dataLog(" JIT threshold should be lifted.\n");
@@ -300,7 +302,8 @@ enum EntryKind { Prologue, ArityCheck };
static SlowPathReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind)
{
#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered %s with executeCounter = %d\n", codeBlock, name, codeBlock->llintExecuteCounter());
+ dataLog("%p: Entered %s with executeCounter = %s\n", codeBlock, name,
+ codeBlock->llintExecuteCounter().status());
#endif
if (!shouldJIT(exec)) {
@@ -346,7 +349,8 @@ LLINT_SLOW_PATH_DECL(loop_osr)
CodeBlock* codeBlock = exec->codeBlock();
#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered loop_osr with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
+ dataLog("%p: Entered loop_osr with executeCounter = %s\n", codeBlock,
+ codeBlock->llintExecuteCounter().status());
#endif
if (!shouldJIT(exec)) {
@@ -376,7 +380,8 @@ LLINT_SLOW_PATH_DECL(replace)
CodeBlock* codeBlock = exec->codeBlock();
#if ENABLE(JIT_VERBOSE_OSR)
- dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
+ dataLog("%p: Entered replace with executeCounter = %s\n", codeBlock,
+ codeBlock->llintExecuteCounter().status());
#endif
if (shouldJIT(exec))
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
index 794d1545e..c2fca8c01 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
@@ -75,7 +75,7 @@ void DefaultGCActivityCallback::doWork()
return;
}
#endif
- heap->collectAllGarbage();
+ heap->collect(Heap::DoNotSweep);
}
void DefaultGCActivityCallback::scheduleTimer(double newDelay)
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index c1a3a632b..52c591324 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -380,7 +380,42 @@ namespace JSC {
return size;
}
+
+ inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const ArgList& values)
+ {
+ JSGlobalData& globalData = exec->globalData();
+ unsigned length = values.size();
+ JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
+
+ // FIXME: we should probably throw an out of memory error here, but
+ // when making this change we should check that all clients of this
+ // function will correctly handle an exception being thrown from here.
+ if (!array)
+ CRASH();
+
+ for (unsigned i = 0; i < length; ++i)
+ array->initializeIndex(globalData, i, values.at(i));
+ array->completeInitialization(length);
+ return array;
+ }
- } // namespace JSC
+ inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const JSValue* values, unsigned length)
+ {
+ JSGlobalData& globalData = exec->globalData();
+ JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
+
+ // FIXME: we should probably throw an out of memory error here, but
+ // when making this change we should check that all clients of this
+ // function will correctly handle an exception being thrown from here.
+ if (!array)
+ CRASH();
+
+ for (unsigned i = 0; i < length; ++i)
+ array->initializeIndex(globalData, i, values[i]);
+ array->completeInitialization(length);
+ return array;
+ }
+
+} // namespace JSC
#endif // JSArray_h
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 d38570dfb..d19db4fd8 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -112,6 +112,15 @@ template <typename T> static inline void visitIfNeeded(SlotVisitor& visitor, Wri
visitor.append(v);
}
+JSGlobalObject::JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable)
+ : JSSegmentedVariableObject(globalData, structure, &m_symbolTable)
+ , m_globalScopeChain()
+ , m_weakRandom(Options::forceWeakRandomSeed ? Options::forcedWeakRandomSeed : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
+ , m_evalEnabled(true)
+ , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
+{
+}
+
JSGlobalObject::~JSGlobalObject()
{
ASSERT(JSLock::currentThreadIsHoldingLock());
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 2396142b1..1dcfc63cc 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -175,14 +175,7 @@ namespace JSC {
static JS_EXPORTDATA const ClassInfo s_info;
protected:
- explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable = 0)
- : JSSegmentedVariableObject(globalData, structure, &m_symbolTable)
- , m_globalScopeChain()
- , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
- , m_evalEnabled(true)
- , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
- {
- }
+ JS_EXPORT_PRIVATE explicit JSGlobalObject(JSGlobalData&, Structure*, const GlobalObjectMethodTable* = 0);
void finishCreation(JSGlobalData& globalData)
{
@@ -328,6 +321,7 @@ namespace JSC {
}
double weakRandomNumber() { return m_weakRandom.get(); }
+ unsigned weakRandomInteger() { return m_weakRandom.getUint32(); }
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSSegmentedVariableObject::StructureFlags;
@@ -451,23 +445,10 @@ namespace JSC {
{
return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength);
}
-
+
inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values)
{
- JSGlobalData& globalData = exec->globalData();
- unsigned length = values.size();
- JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length);
-
- // FIXME: we should probably throw an out of memory error here, but
- // when making this change we should check that all clients of this
- // function will correctly handle an exception being thrown from here.
- if (!array)
- CRASH();
-
- for (unsigned i = 0; i < length; ++i)
- array->initializeIndex(globalData, i, values.at(i));
- array->completeInitialization(length);
- return array;
+ return constructArray(exec, globalObject->arrayStructure(), values);
}
inline JSArray* constructArray(ExecState* exec, const ArgList& values)
@@ -477,19 +458,7 @@ namespace JSC {
inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const JSValue* values, unsigned length)
{
- JSGlobalData& globalData = exec->globalData();
- JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length);
-
- // FIXME: we should probably throw an out of memory error here, but
- // when making this change we should check that all clients of this
- // function will correctly handle an exception being thrown from here.
- if (!array)
- CRASH();
-
- for (unsigned i = 0; i < length; ++i)
- array->initializeIndex(globalData, i, values[i]);
- array->completeInitialization(length);
- return array;
+ return constructArray(exec, globalObject->arrayStructure(), values, length);
}
inline JSArray* constructArray(ExecState* exec, const JSValue* values, unsigned length)
diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.cpp b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp
index 86101f559..14b1c7d06 100644
--- a/Source/JavaScriptCore/runtime/MemoryStatistics.cpp
+++ b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp
@@ -37,7 +37,7 @@ GlobalMemoryStatistics globalMemoryStatistics()
GlobalMemoryStatistics stats;
stats.stackBytes = RegisterFile::committedByteCount();
-#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED) || (PLATFORM(BLACKBERRY) && ENABLE(JIT))
stats.JITBytes = ExecutableAllocator::committedByteCount();
#else
stats.JITBytes = 0;
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index 7b6da6536..894ca8cc0 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -67,6 +67,9 @@ int32_t thresholdForOptimizeSoon;
int32_t executionCounterIncrementForLoop;
int32_t executionCounterIncrementForReturn;
+bool randomizeExecutionCountsBetweenCheckpoints;
+int32_t maximumExecutionCountsBetweenCheckpoints;
+
unsigned desiredSpeculativeSuccessFailRatio;
double likelyToTakeSlowCaseThreshold;
@@ -95,6 +98,9 @@ unsigned gcMarkStackSegmentSize;
unsigned numberOfGCMarkers;
unsigned opaqueRootMergeThreshold;
+bool forceWeakRandomSeed;
+unsigned forcedWeakRandomSeed;
+
#if ENABLE(RUN_TIME_HEURISTICS)
static bool parse(const char* string, bool& value)
{
@@ -184,6 +190,9 @@ void initializeOptions()
SET(executionCounterIncrementForLoop, 1);
SET(executionCounterIncrementForReturn, 15);
+
+ SET(randomizeExecutionCountsBetweenCheckpoints, false);
+ SET(maximumExecutionCountsBetweenCheckpoints, 1000);
SET(desiredSpeculativeSuccessFailRatio, 6);
@@ -227,6 +236,9 @@ void initializeOptions()
ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) > 0);
ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max()));
+
+ SET(forceWeakRandomSeed, false);
+ SET(forcedWeakRandomSeed, 0);
}
} } // namespace JSC::Options
diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h
index 0adb59e9b..1bce5b944 100644
--- a/Source/JavaScriptCore/runtime/Options.h
+++ b/Source/JavaScriptCore/runtime/Options.h
@@ -53,6 +53,9 @@ extern int32_t thresholdForOptimizeNextInvocation;
extern int32_t executionCounterIncrementForLoop;
extern int32_t executionCounterIncrementForReturn;
+extern bool randomizeExecutionCountsBetweenCheckpoints;
+extern int32_t maximumExecutionCountsBetweenCheckpoints;
+
extern unsigned desiredSpeculativeSuccessFailRatio;
extern double likelyToTakeSlowCaseThreshold;
@@ -81,6 +84,9 @@ extern unsigned gcMarkStackSegmentSize;
JS_EXPORTDATA extern unsigned numberOfGCMarkers;
JS_EXPORTDATA extern unsigned opaqueRootMergeThreshold;
+extern bool forceWeakRandomSeed;
+extern unsigned forcedWeakRandomSeed;
+
void initializeOptions();
} } // namespace JSC::Options
diff --git a/Source/JavaScriptCore/runtime/WeakRandom.h b/Source/JavaScriptCore/runtime/WeakRandom.h
index 6083980d2..3cd1016d3 100644
--- a/Source/JavaScriptCore/runtime/WeakRandom.h
+++ b/Source/JavaScriptCore/runtime/WeakRandom.h
@@ -62,6 +62,9 @@ public:
, m_high(seed)
{
}
+
+ // Returns the seed provided that you've never called get() or getUint32().
+ unsigned seedUnsafe() const { return m_high; }
double get()
{
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 = '',