summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-09 09:42:44 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-09 09:42:44 +0100
commita59391482883479a9b28a6f1ace6d1ebd08a7ecd (patch)
treefa539db054a20a67bff2fc891c33b0f4ec632916 /Source/JavaScriptCore/bytecode
parentcfd86b747d32ac22246a1aa908eaa720c63a88c1 (diff)
downloadqtwebkit-a59391482883479a9b28a6f1ace6d1ebd08a7ecd.tar.gz
Imported WebKit commit 7bcdfab9a40db7d16b4b95bb77d78b8a59c9e701 (http://svn.webkit.org/repository/webkit/trunk@134025)
New snapshot with numerious build fixes, including MSVC 2012 and ARM Thumb-2.
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
-rw-r--r--Source/JavaScriptCore/bytecode/ArrayAllocationProfile.cpp40
-rw-r--r--Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h80
-rw-r--r--Source/JavaScriptCore/bytecode/ArrayProfile.cpp7
-rw-r--r--Source/JavaScriptCore/bytecode/ArrayProfile.h48
-rw-r--r--Source/JavaScriptCore/bytecode/ByValInfo.h8
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp52
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h12
-rw-r--r--Source/JavaScriptCore/bytecode/DFGExitProfile.h2
-rw-r--r--Source/JavaScriptCore/bytecode/Instruction.h5
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h6
-rw-r--r--Source/JavaScriptCore/bytecode/SpeculatedType.h26
-rw-r--r--Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp19
-rw-r--r--Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h11
13 files changed, 284 insertions, 32 deletions
diff --git a/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.cpp b/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.cpp
new file mode 100644
index 000000000..aa682da86
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ArrayAllocationProfile.h"
+
+namespace JSC {
+
+void ArrayAllocationProfile::updateIndexingType()
+{
+ if (!m_lastArray)
+ return;
+ m_currentIndexingType = leastUpperBoundOfIndexingTypes(m_currentIndexingType, m_lastArray->structure()->indexingType());
+ m_lastArray = 0;
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h b/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h
new file mode 100644
index 000000000..a1647fad4
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ArrayAllocationProfile_h
+#define ArrayAllocationProfile_h
+
+#include "IndexingType.h"
+#include "JSArray.h"
+
+namespace JSC {
+
+class ArrayAllocationProfile {
+public:
+ ArrayAllocationProfile()
+ : m_currentIndexingType(ArrayWithUndecided)
+ , m_lastArray(0)
+ {
+ }
+
+ IndexingType selectIndexingType()
+ {
+ if (m_lastArray && UNLIKELY(m_lastArray->structure()->indexingType() != m_currentIndexingType))
+ updateIndexingType();
+ return m_currentIndexingType;
+ }
+
+ JSArray* updateLastAllocation(JSArray* lastArray)
+ {
+ m_lastArray = lastArray;
+ return lastArray;
+ }
+
+ JS_EXPORT_PRIVATE void updateIndexingType();
+
+ static IndexingType selectIndexingTypeFor(ArrayAllocationProfile* profile)
+ {
+ if (!profile)
+ return ArrayWithUndecided;
+ return profile->selectIndexingType();
+ }
+
+ static JSArray* updateLastAllocationFor(ArrayAllocationProfile* profile, JSArray* lastArray)
+ {
+ if (profile)
+ profile->updateLastAllocation(lastArray);
+ return lastArray;
+ }
+
+private:
+
+ IndexingType m_currentIndexingType;
+ JSArray* m_lastArray;
+};
+
+} // namespace JSC
+
+#endif // ArrayAllocationProfile_h
+
diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.cpp b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp
index 5a87380fd..51baf332f 100644
--- a/Source/JavaScriptCore/bytecode/ArrayProfile.cpp
+++ b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp
@@ -65,6 +65,13 @@ const char* arrayModesToString(ArrayModes arrayModes)
return result;
}
+ArrayModes ArrayProfile::updatedObservedArrayModes() const
+{
+ if (m_lastSeenStructure)
+ return m_observedArrayModes | arrayModeFromStructure(m_lastSeenStructure);
+ return m_observedArrayModes;
+}
+
void ArrayProfile::computeUpdatedPrediction(CodeBlock* codeBlock, OperationInProgress operation)
{
if (m_lastSeenStructure) {
diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.h b/Source/JavaScriptCore/bytecode/ArrayProfile.h
index 376684fc1..5116cd36f 100644
--- a/Source/JavaScriptCore/bytecode/ArrayProfile.h
+++ b/Source/JavaScriptCore/bytecode/ArrayProfile.h
@@ -45,15 +45,20 @@ typedef unsigned ArrayModes;
#define ALL_NON_ARRAY_ARRAY_MODES \
(asArrayModes(NonArray) \
- | asArrayModes(NonArrayWithContiguous) \
- | asArrayModes(NonArrayWithArrayStorage) \
- | asArrayModes(NonArrayWithSlowPutArrayStorage))
+ | asArrayModes(NonArrayWithInt32) \
+ | asArrayModes(NonArrayWithDouble) \
+ | asArrayModes(NonArrayWithContiguous) \
+ | asArrayModes(NonArrayWithArrayStorage) \
+ | asArrayModes(NonArrayWithSlowPutArrayStorage))
#define ALL_ARRAY_ARRAY_MODES \
(asArrayModes(ArrayClass) \
- | asArrayModes(ArrayWithContiguous) \
- | asArrayModes(ArrayWithArrayStorage) \
- | asArrayModes(ArrayWithSlowPutArrayStorage))
+ | asArrayModes(ArrayWithUndecided) \
+ | asArrayModes(ArrayWithInt32) \
+ | asArrayModes(ArrayWithDouble) \
+ | asArrayModes(ArrayWithContiguous) \
+ | asArrayModes(ArrayWithArrayStorage) \
+ | asArrayModes(ArrayWithSlowPutArrayStorage))
#define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES)
@@ -79,6 +84,36 @@ inline bool arrayModesAlreadyChecked(ArrayModes proven, ArrayModes expected)
return (expected | proven) == expected;
}
+inline bool arrayModesInclude(ArrayModes arrayModes, IndexingType shape)
+{
+ return !!(arrayModes & (asArrayModes(NonArray | shape) | asArrayModes(ArrayClass | shape)));
+}
+
+inline bool shouldUseSlowPutArrayStorage(ArrayModes arrayModes)
+{
+ return arrayModesInclude(arrayModes, SlowPutArrayStorageShape);
+}
+
+inline bool shouldUseFastArrayStorage(ArrayModes arrayModes)
+{
+ return arrayModesInclude(arrayModes, ArrayStorageShape);
+}
+
+inline bool shouldUseContiguous(ArrayModes arrayModes)
+{
+ return arrayModesInclude(arrayModes, ContiguousShape);
+}
+
+inline bool shouldUseDouble(ArrayModes arrayModes)
+{
+ return arrayModesInclude(arrayModes, DoubleShape);
+}
+
+inline bool shouldUseInt32(ArrayModes arrayModes)
+{
+ return arrayModesInclude(arrayModes, Int32Shape);
+}
+
class ArrayProfile {
public:
ArrayProfile()
@@ -128,6 +163,7 @@ public:
return !structureIsPolymorphic() && m_expectedStructure;
}
ArrayModes observedArrayModes() const { return m_observedArrayModes; }
+ ArrayModes updatedObservedArrayModes() const; // Computes the observed array modes without updating the profile.
bool mayInterceptIndexedAccesses() const { return m_mayInterceptIndexedAccesses; }
bool mayStoreToHole() const { return m_mayStoreToHole; }
diff --git a/Source/JavaScriptCore/bytecode/ByValInfo.h b/Source/JavaScriptCore/bytecode/ByValInfo.h
index 8cba4463d..3f79967df 100644
--- a/Source/JavaScriptCore/bytecode/ByValInfo.h
+++ b/Source/JavaScriptCore/bytecode/ByValInfo.h
@@ -39,6 +39,8 @@
namespace JSC {
enum JITArrayMode {
+ JITInt32,
+ JITDouble,
JITContiguous,
JITArrayStorage,
JITInt8Array,
@@ -55,6 +57,8 @@ enum JITArrayMode {
inline bool isOptimizableIndexingType(IndexingType indexingType)
{
switch (indexingType) {
+ case ALL_INT32_INDEXING_TYPES:
+ case ALL_DOUBLE_INDEXING_TYPES:
case ALL_CONTIGUOUS_INDEXING_TYPES:
case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES:
return true;
@@ -77,6 +81,10 @@ inline bool hasOptimizableIndexing(Structure* structure)
inline JITArrayMode jitArrayModeForIndexingType(IndexingType indexingType)
{
switch (indexingType) {
+ case ALL_INT32_INDEXING_TYPES:
+ return JITInt32;
+ case ALL_DOUBLE_INDEXING_TYPES:
+ return JITDouble;
case ALL_CONTIGUOUS_INDEXING_TYPES:
return JITContiguous;
case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES:
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index ceae3fcb2..83833c6ec 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -44,7 +44,7 @@
#include "JSValue.h"
#include "LowLevelInterpreter.h"
#include "RepatchBuffer.h"
-#include "SlotVisitorInlineMethods.h"
+#include "SlotVisitorInlines.h"
#include <stdio.h>
#include <wtf/StringExtras.h>
#include <wtf/UnusedParam.h>
@@ -654,6 +654,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int argc = (++it)->u.operand;
dataLog("[%4d] new_array\t %s, %s, %d", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc);
dumpBytecodeCommentAndNewLine(location);
+ ++it; // Skip array allocation profile.
break;
}
case op_new_array_with_size: {
@@ -661,6 +662,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int length = (++it)->u.operand;
dataLog("[%4d] new_array_with_size\t %s, %s", location, registerName(exec, dst).data(), registerName(exec, length).data());
dumpBytecodeCommentAndNewLine(location);
+ ++it; // Skip array allocation profile.
break;
}
case op_new_array_buffer: {
@@ -669,6 +671,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
int argc = (++it)->u.operand;
dataLog("[%4d] new_array_buffer\t %s, %d, %d", location, registerName(exec, dst).data(), argv, argc);
dumpBytecodeCommentAndNewLine(location);
+ ++it; // Skip array allocation profile.
break;
}
case op_new_regexp: {
@@ -1746,6 +1749,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
#if ENABLE(DFG_JIT)
if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
m_arrayProfiles.grow(size);
+ if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles())
+ m_arrayAllocationProfiles.grow(size);
if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
m_valueProfiles.grow(size);
#endif
@@ -1800,19 +1805,32 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
break;
}
+ case op_new_array:
+ case op_new_array_buffer:
+ case op_new_array_with_size: {
+ int arrayAllocationProfileIndex = pc[i + opLength - 1].u.operand;
+ instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
+ break;
+ }
+#endif
+
case op_call:
case op_call_eval: {
+#if ENABLE(DFG_JIT)
int arrayProfileIndex = pc[i + opLength - 1].u.operand;
m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
- // fallthrough
- }
#endif
#if ENABLE(LLINT)
- case op_construct:
instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand];
+#endif
break;
+ }
+ case op_construct:
+#if ENABLE(LLINT)
+ instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand];
#endif
+ break;
case op_get_by_id_out_of_line:
case op_get_by_id_self:
case op_get_by_id_proto:
@@ -2787,18 +2805,28 @@ void CodeBlock::updateAllPredictionsAndCountLiveness(
#if ENABLE(DFG_JIT)
m_lazyOperandValueProfiles.computeUpdatedPredictions(operation);
#endif
-
- // Don't count the array profiles towards statistics, since each array profile
- // site also has a value profile site - so we already know whether or not it's
- // live.
+}
+
+void CodeBlock::updateAllValueProfilePredictions(OperationInProgress operation)
+{
+ unsigned ignoredValue1, ignoredValue2;
+ updateAllPredictionsAndCountLiveness(operation, ignoredValue1, ignoredValue2);
+}
+
+void CodeBlock::updateAllArrayPredictions(OperationInProgress operation)
+{
for (unsigned i = m_arrayProfiles.size(); i--;)
m_arrayProfiles[i].computeUpdatedPrediction(this, operation);
+
+ // Don't count these either, for similar reasons.
+ for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
+ m_arrayAllocationProfiles[i].updateIndexingType();
}
void CodeBlock::updateAllPredictions(OperationInProgress operation)
{
- unsigned ignoredValue1, ignoredValue2;
- updateAllPredictionsAndCountLiveness(operation, ignoredValue1, ignoredValue2);
+ updateAllValueProfilePredictions(operation);
+ updateAllArrayPredictions(operation);
}
bool CodeBlock::shouldOptimizeNow()
@@ -2814,12 +2842,14 @@ bool CodeBlock::shouldOptimizeNow()
if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay())
return true;
+ updateAllArrayPredictions();
+
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());
+ dataLog("Profile hotness: %lf (%u / %u), %lf (%u / %u)\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(), numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles());
#endif
if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate())
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index a28064940..0199935bb 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -755,6 +755,13 @@ namespace JSC {
}
ArrayProfile* getArrayProfile(unsigned bytecodeOffset);
ArrayProfile* getOrAddArrayProfile(unsigned bytecodeOffset);
+
+ unsigned numberOfArrayAllocationProfiles() const { return m_arrayAllocationProfiles.size(); }
+ ArrayAllocationProfile* addArrayAllocationProfile()
+ {
+ m_arrayAllocationProfiles.append(ArrayAllocationProfile());
+ return &m_arrayAllocationProfiles.last();
+ }
#endif
// Exception handling support
@@ -1145,9 +1152,13 @@ namespace JSC {
#if ENABLE(VALUE_PROFILER)
bool shouldOptimizeNow();
+ void updateAllValueProfilePredictions(OperationInProgress = NoOperation);
+ void updateAllArrayPredictions(OperationInProgress = NoOperation);
void updateAllPredictions(OperationInProgress = NoOperation);
#else
bool shouldOptimizeNow() { return false; }
+ void updateAllValueProfilePredictions(OperationInProgress = NoOperation) { }
+ void updateAllArrayPredictions(OperationInProgress = NoOperation) { }
void updateAllPredictions(OperationInProgress = NoOperation) { }
#endif
@@ -1330,6 +1341,7 @@ namespace JSC {
SegmentedVector<ValueProfile, 8> m_valueProfiles;
SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
SegmentedVector<RareCaseProfile, 8> m_specialFastCaseProfiles;
+ SegmentedVector<ArrayAllocationProfile, 8> m_arrayAllocationProfiles;
ArrayProfileVector m_arrayProfiles;
unsigned m_executionEntryCount;
#endif
diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.h b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
index 60d313ad4..7132adfd4 100644
--- a/Source/JavaScriptCore/bytecode/DFGExitProfile.h
+++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
@@ -58,6 +58,8 @@ inline const char* exitKindToString(ExitKind kind)
return "BadCache";
case BadWeakConstantCache:
return "BadWeakConstantCache";
+ case BadIndexingType:
+ return "BadIndexingType";
case Overflow:
return "Overflow";
case NegativeZero:
diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h
index 9fcf509f6..50b80e03c 100644
--- a/Source/JavaScriptCore/bytecode/Instruction.h
+++ b/Source/JavaScriptCore/bytecode/Instruction.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -47,6 +47,7 @@ namespace JSC {
// curently actually use PolymorphicAccessStructureLists, which we should). Anyway, this seems like the best
// solution for now - will need to something smarter if/when we actually want mixed-mode operation.
+ class ArrayAllocationProfile;
class ArrayProfile;
class JSCell;
class Structure;
@@ -193,6 +194,7 @@ namespace JSC {
Instruction(ValueProfile* profile) { u.profile = profile; }
Instruction(ArrayProfile* profile) { u.arrayProfile = profile; }
+ Instruction(ArrayAllocationProfile* profile) { u.arrayAllocationProfile = profile; }
Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; }
@@ -212,6 +214,7 @@ namespace JSC {
LLIntCallLinkInfo* callLinkInfo;
ValueProfile* profile;
ArrayProfile* arrayProfile;
+ ArrayAllocationProfile* arrayAllocationProfile;
void* pointer;
bool* predicatePointer;
} u;
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index 8979d0b7b..38d314d78 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -48,9 +48,9 @@ namespace JSC {
macro(op_convert_this, 3) \
\
macro(op_new_object, 2) \
- macro(op_new_array, 4) \
- macro(op_new_array_with_size, 3) \
- macro(op_new_array_buffer, 4) \
+ macro(op_new_array, 5) \
+ macro(op_new_array_with_size, 4) \
+ macro(op_new_array_buffer, 5) \
macro(op_new_regexp, 3) \
macro(op_mov, 3) \
\
diff --git a/Source/JavaScriptCore/bytecode/SpeculatedType.h b/Source/JavaScriptCore/bytecode/SpeculatedType.h
index 09ba9fdfa..656bc79ee 100644
--- a/Source/JavaScriptCore/bytecode/SpeculatedType.h
+++ b/Source/JavaScriptCore/bytecode/SpeculatedType.h
@@ -61,6 +61,7 @@ static const SpeculatedType SpecInt32 = 0x00800000; // It's definite
static const SpeculatedType SpecDoubleReal = 0x01000000; // It's definitely a non-NaN double.
static const SpeculatedType SpecDoubleNaN = 0x02000000; // It's definitely a NaN.
static const SpeculatedType SpecDouble = 0x03000000; // It's either a non-NaN or a NaN double.
+static const SpeculatedType SpecRealNumber = 0x01800000; // It's either an Int32 or a DoubleReal.
static const SpeculatedType SpecNumber = 0x03800000; // It's either an Int32 or a Double.
static const SpeculatedType SpecBoolean = 0x04000000; // It's definitely a Boolean.
static const SpeculatedType SpecOther = 0x08000000; // It's definitely none of the above.
@@ -228,6 +229,16 @@ inline bool isInt32Speculation(SpeculatedType value)
return value == SpecInt32;
}
+inline bool isInt32SpeculationForArithmetic(SpeculatedType value)
+{
+ return !(value & SpecDouble);
+}
+
+inline bool isInt32SpeculationExpectingDefined(SpeculatedType value)
+{
+ return isInt32Speculation(value & ~SpecOther);
+}
+
inline bool isDoubleRealSpeculation(SpeculatedType value)
{
return value == SpecDoubleReal;
@@ -238,11 +249,26 @@ inline bool isDoubleSpeculation(SpeculatedType value)
return !!value && (value & SpecDouble) == value;
}
+inline bool isDoubleSpeculationForArithmetic(SpeculatedType value)
+{
+ return !!(value & SpecDouble);
+}
+
+inline bool isRealNumberSpeculation(SpeculatedType value)
+{
+ return !!(value & SpecRealNumber) && !(value & ~SpecRealNumber);
+}
+
inline bool isNumberSpeculation(SpeculatedType value)
{
return !!(value & SpecNumber) && !(value & ~SpecNumber);
}
+inline bool isNumberSpeculationExpectingDefined(SpeculatedType value)
+{
+ return isNumberSpeculation(value & ~SpecOther);
+}
+
inline bool isBooleanSpeculation(SpeculatedType value)
{
return value == SpecBoolean;
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
index 8aa48404a..e98d4de0a 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
@@ -80,8 +80,6 @@ void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visito
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
Base::visitChildren(thisObject, visitor);
- visitor.append(&thisObject->m_codeBlockForCall);
- visitor.append(&thisObject->m_codeBlockForConstruct);
visitor.append(&thisObject->m_nameValue);
visitor.append(&thisObject->m_symbolTableForCall);
visitor.append(&thisObject->m_symbolTableForConstruct);
@@ -112,12 +110,16 @@ UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(JSGlobalData
{
switch (specializationKind) {
case CodeForCall:
- if (m_codeBlockForCall)
- return m_codeBlockForCall.get();
+ if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get()) {
+ globalData.codeCache()->usedFunctionCode(globalData, codeBlock);
+ return codeBlock;
+ }
break;
case CodeForConstruct:
- if (m_codeBlockForConstruct)
- return m_codeBlockForConstruct.get();
+ if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get()) {
+ globalData.codeCache()->usedFunctionCode(globalData, codeBlock);
+ return codeBlock;
+ }
break;
}
@@ -128,11 +130,11 @@ UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(JSGlobalData
switch (specializationKind) {
case CodeForCall:
- m_codeBlockForCall.set(globalData, this, result);
+ m_codeBlockForCall = PassWeak<UnlinkedFunctionCodeBlock>(result);
m_symbolTableForCall.set(globalData, this, result->symbolTable());
break;
case CodeForConstruct:
- m_codeBlockForConstruct.set(globalData, this, result);
+ m_codeBlockForConstruct = PassWeak<UnlinkedFunctionCodeBlock>(result);
m_symbolTableForConstruct.set(globalData, this, result->symbolTable());
break;
}
@@ -171,6 +173,7 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(JSGlobalData* globalData, Structure* struct
, m_resolveOperationCount(0)
, m_putToBaseOperationCount(1)
, m_arrayProfileCount(0)
+ , m_arrayAllocationProfileCount(0)
, m_valueProfileCount(0)
, m_llintCallLinkInfoCount(0)
#if ENABLE(BYTECODE_COMMENTS)
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
index bf3f5fdff..23937d773 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
@@ -36,6 +36,7 @@
#include "Nodes.h"
#include "RegExp.h"
#include "SpecialPointer.h"
+#include "Weak.h"
#include <wtf/RefCountedArray.h>
#include <wtf/Vector.h>
@@ -56,6 +57,7 @@ class UnlinkedFunctionCodeBlock;
typedef unsigned UnlinkedValueProfile;
typedef unsigned UnlinkedArrayProfile;
+typedef unsigned UnlinkedArrayAllocationProfile;
typedef unsigned UnlinkedLLIntCallLinkInfo;
struct ExecutableInfo {
@@ -107,7 +109,7 @@ public:
FunctionExecutable* link(JSGlobalData&, const SourceCode&, size_t lineOffset, size_t sourceOffset);
- void clearCode()
+ void clearCodeForRecompilation()
{
m_symbolTableForCall.clear();
m_symbolTableForConstruct.clear();
@@ -135,8 +137,8 @@ public:
private:
UnlinkedFunctionExecutable(JSGlobalData*, Structure*, const SourceCode&, FunctionBodyNode*);
- WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
- WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
+ Weak<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
+ Weak<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
unsigned m_numCapturedVariables : 29;
bool m_forceUsesArguments : 1;
@@ -392,6 +394,8 @@ public:
UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
+ UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
+ unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
unsigned numberOfValueProfiles() { return m_valueProfileCount; }
@@ -518,6 +522,7 @@ private:
unsigned m_resolveOperationCount;
unsigned m_putToBaseOperationCount;
unsigned m_arrayProfileCount;
+ unsigned m_arrayAllocationProfileCount;
unsigned m_valueProfileCount;
unsigned m_llintCallLinkInfoCount;