summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-16 14:56:46 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-16 14:57:30 +0200
commitb297e0fa5c217c9467033b7c8b46891a52870120 (patch)
tree43fc14689295e9e64f2719d05aad94e3049f6cd7 /Source/JavaScriptCore/dfg
parent69d517dbfa69903d8593cc1737f0474b21e3251e (diff)
downloadqtwebkit-b297e0fa5c217c9467033b7c8b46891a52870120.tar.gz
Revert "Imported WebKit commit 0dc6cd75e1d4836eaffbb520be96fac4847cc9d2 (http://svn.webkit.org/repository/webkit/trunk@131300)"
This reverts commit 5466563f4b5b6b86523e3f89bb7f77e5b5270c78. Caused OOM issues on some CI machines :(
Diffstat (limited to 'Source/JavaScriptCore/dfg')
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp32
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp24
-rw-r--r--Source/JavaScriptCore/dfg/DFGArrayMode.cpp81
-rw-r--r--Source/JavaScriptCore/dfg/DFGArrayMode.h107
-rw-r--r--Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h33
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeCache.h8
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp140
-rw-r--r--Source/JavaScriptCore/dfg/DFGCCallHelpers.h15
-rw-r--r--Source/JavaScriptCore/dfg/DFGCSEPhase.cpp8
-rw-r--r--Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h128
-rw-r--r--Source/JavaScriptCore/dfg/DFGCapabilities.h4
-rw-r--r--Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp3
-rw-r--r--Source/JavaScriptCore/dfg/DFGFixupPhase.cpp44
-rw-r--r--Source/JavaScriptCore/dfg/DFGGenerationInfo.h6
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h7
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.cpp34
-rw-r--r--Source/JavaScriptCore/dfg/DFGJITCompiler.h2
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSREntry.cpp2
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp88
-rw-r--r--Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp56
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp76
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.h19
-rw-r--r--Source/JavaScriptCore/dfg/DFGRepatch.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp370
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h169
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp579
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp560
-rw-r--r--Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp222
-rw-r--r--Source/JavaScriptCore/dfg/DFGThunks.cpp14
-rw-r--r--Source/JavaScriptCore/dfg/DFGValueSource.cpp12
-rw-r--r--Source/JavaScriptCore/dfg/DFGValueSource.h62
-rw-r--r--Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp4
34 files changed, 900 insertions, 2021 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index da5682f55..db0861c7d 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -859,16 +859,12 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
- case IN_BOUNDS_CONTIGUOUS_MODES:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case SLOW_PUT_ARRAY_STORAGE_MODES:
- case ALL_EFFECTFUL_MODES:
- forNode(node.child1()).filter(SpecCell);
+ case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
forNode(node.child2()).filter(SpecInt32);
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).makeTop();
@@ -912,9 +908,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).set(SpecDouble);
break;
- default:
- ASSERT_NOT_REACHED();
- break;
}
break;
}
@@ -922,7 +915,6 @@ bool AbstractState::execute(unsigned indexInBlock)
case PutByVal:
case PutByValAlias: {
node.setCanExit(true);
- Edge child1 = m_graph.varArgChild(node, 0);
Edge child2 = m_graph.varArgChild(node, 1);
Edge child3 = m_graph.varArgChild(node, 2);
switch (modeForPut(node.arrayMode())) {
@@ -932,17 +924,11 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::Generic:
clobberWorld(node.codeOrigin, indexInBlock);
break;
- case IN_BOUNDS_CONTIGUOUS_MODES:
- case CONTIGUOUS_TO_TAIL_MODES:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
forNode(child2).filter(SpecInt32);
break;
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
- case ARRAY_STORAGE_TO_HOLE_MODES:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case SLOW_PUT_ARRAY_STORAGE_MODES:
- case ALL_EFFECTFUL_MODES:
- forNode(child1).filter(SpecCell);
+ case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
forNode(child2).filter(SpecInt32);
clobberWorld(node.codeOrigin, indexInBlock);
break;
@@ -1124,15 +1110,16 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case NewArrayBuffer:
- node.setCanExit(true);
- forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
- m_haveStructures = true;
+ // Unless we're having a bad time, this node can change its mind about what structure
+ // it uses.
+ node.setCanExit(false);
+ forNode(nodeIndex).set(SpecArray);
break;
case NewArrayWithSize:
node.setCanExit(true);
forNode(node.child1()).filter(SpecInt32);
- forNode(nodeIndex).set(SpecArray);
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
m_haveStructures = true;
break;
@@ -1380,7 +1367,6 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::String:
forNode(node.child1()).filter(SpecString);
break;
- case ALL_CONTIGUOUS_MODES:
case ALL_ARRAY_STORAGE_MODES:
// This doesn't filter anything meaningful right now. We may want to add
// CFA tracking of array mode speculations, but we don't have that, yet.
@@ -1424,11 +1410,9 @@ bool AbstractState::execute(unsigned indexInBlock)
}
case Arrayify: {
switch (node.arrayMode()) {
- case ALL_EFFECTFUL_MODES:
+ case EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES:
node.setCanExit(true);
forNode(node.child1()).filter(SpecCell);
- if (node.child2())
- forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).clear();
clobberStructures(indexInBlock);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h
index ec1a06231..d2bc1a551 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h
@@ -185,7 +185,7 @@ public:
void reset();
// Abstractly executes the given node. The new abstract state is stored into an
- // abstract stack stored in *this. Loads of local variables (that span
+ // abstract register file stored in *this. Loads of local variables (that span
// basic blocks) interrogate the basic block's notion of the state at the head.
// Stores to local variables are handled in endBasicBlock(). This returns true
// if execution should continue past this node. Notably, it will return true
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
index bb61a59e6..513357424 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
@@ -210,7 +210,7 @@ public:
// Make sure that if it's a variable that we think is aliased to
// the arguments, that we know that it might actually not be.
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
data.mergeNonArgumentsAssignment();
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
break;
@@ -228,7 +228,7 @@ public:
break;
}
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
data.mergeArgumentsAssignment();
// This ensures that the variable's uses are in the same context as
// the arguments it is aliasing.
@@ -243,7 +243,7 @@ public:
if (variableAccessData->isCaptured())
break;
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
break;
}
@@ -253,7 +253,7 @@ public:
if (variableAccessData->isCaptured())
break;
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
// If a variable is used in a flush then by definition it escapes.
@@ -266,7 +266,7 @@ public:
if (variableAccessData->isCaptured())
break;
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
data.mergeNonArgumentsAssignment();
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
break;
@@ -350,7 +350,7 @@ public:
}
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
if (data.isValid())
continue;
@@ -369,7 +369,7 @@ public:
dataLog("Captured");
else {
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
bool first = true;
if (data.callContextIsValid()) {
if (!first)
@@ -441,7 +441,7 @@ public:
// things. Note also that the SetLocal should become dead as soon as
// we replace all uses of this variable with GetMyArgumentsLength and
// GetMyArgumentByVal.
- ASSERT(m_argumentsAliasing.find(variableAccessData)->value.isValid());
+ ASSERT(m_argumentsAliasing.find(variableAccessData)->second.isValid());
changed |= variableAccessData->mergeIsArgumentsAlias(true);
break;
}
@@ -685,7 +685,7 @@ private:
if (variableAccessData->isCaptured())
break;
- ArgumentsAliasingData& data = m_argumentsAliasing.find(variableAccessData)->value;
+ ArgumentsAliasingData& data = m_argumentsAliasing.find(variableAccessData)->second;
data.escapes = true;
break;
}
@@ -734,7 +734,7 @@ private:
if (variableAccessData->isCaptured())
return;
- ArgumentsAliasingData& data = m_argumentsAliasing.find(variableAccessData)->value;
+ ArgumentsAliasingData& data = m_argumentsAliasing.find(variableAccessData)->second;
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
}
@@ -756,7 +756,7 @@ private:
if (variableAccessData->isCaptured())
break;
ArgumentsAliasingData& data =
- m_argumentsAliasing.find(variableAccessData)->value;
+ m_argumentsAliasing.find(variableAccessData)->second;
if (!data.isValid())
break;
@@ -792,7 +792,7 @@ private:
&& !m_createsArguments.contains(child.codeOrigin.inlineCallFrame);
bool isAliasedArgumentsRegister =
!variableAccessData->isCaptured()
- && m_argumentsAliasing.find(variableAccessData)->value.isValid()
+ && m_argumentsAliasing.find(variableAccessData)->second.isValid()
&& !m_createsArguments.contains(child.codeOrigin.inlineCallFrame);
if (!isDeadArgumentsRegister && !isAliasedArgumentsRegister)
break;
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
index 3985d769c..12c9640c8 100644
--- a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
@@ -39,14 +39,8 @@ Array::Mode fromObserved(ArrayProfile* profile, Array::Action action, bool makeS
return Array::Unprofiled;
case asArrayModes(NonArray):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
- return Array::ToContiguous; // FIXME: we don't know whether to go to contiguous or array storage. We're making a static guess here. In future we should use exit profiling for this.
+ return Array::BlankToArrayStorage; // FIXME: we don't know whether to go to slow put mode, or not. This is a decent guess.
return Array::Undecided;
- case asArrayModes(NonArrayWithContiguous):
- return makeSafe ? Array::ContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::ContiguousToTail : Array::Contiguous);
- case asArrayModes(ArrayWithContiguous):
- return makeSafe ? Array::ArrayWithContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::ArrayWithContiguousToTail : Array::ArrayWithContiguous);
- case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous):
- return makeSafe ? Array::PossiblyArrayWithContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::PossiblyArrayWithContiguousToTail : Array::PossiblyArrayWithContiguous);
case asArrayModes(NonArrayWithArrayStorage):
return makeSafe ? Array::ArrayStorageOutOfBounds : (profile->mayStoreToHole() ? Array::ArrayStorageToHole : Array::ArrayStorage);
case asArrayModes(NonArrayWithSlowPutArrayStorage):
@@ -62,25 +56,14 @@ Array::Mode fromObserved(ArrayProfile* profile, Array::Action action, bool makeS
case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
return Array::PossiblyArrayWithSlowPutArrayStorage;
- case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
- return Array::ToArrayStorage;
- case asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
- return Array::ArrayToArrayStorage;
- case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
- return Array::PossiblyArrayToArrayStorage;
- case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous):
- if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
- return Array::ToContiguous;
- return Array::Undecided;
- case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
- return Array::ToArrayStorage;
+ return Array::BlankToArrayStorage;
return Array::Undecided;
case asArrayModes(NonArray) | asArrayModes(NonArrayWithSlowPutArrayStorage):
case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
- return Array::ToSlowPutArrayStorage;
+ return Array::BlankToSlowPutArrayStorage;
return Array::Undecided;
default:
// We know that this is possibly a kind of array for which, though there is no
@@ -161,22 +144,6 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode)
case Array::String:
return isStringSpeculation(value.m_type);
- case Array::Contiguous:
- case Array::ContiguousToTail:
- case Array::ContiguousOutOfBounds:
- case Array::PossiblyArrayWithContiguous:
- case Array::PossiblyArrayWithContiguousToTail:
- case Array::PossiblyArrayWithContiguousOutOfBounds:
- return value.m_currentKnownStructure.hasSingleton()
- && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType());
-
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousToTail:
- case Array::ArrayWithContiguousOutOfBounds:
- return value.m_currentKnownStructure.hasSingleton()
- && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType())
- && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
-
case Array::ArrayStorage:
case Array::ArrayStorageToHole:
case Array::ArrayStorageOutOfBounds:
@@ -184,26 +151,26 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode)
case Array::PossiblyArrayWithArrayStorageToHole:
case Array::PossiblyArrayWithArrayStorageOutOfBounds:
return value.m_currentKnownStructure.hasSingleton()
- && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType());
+ && (value.m_currentKnownStructure.singleton()->indexingType() & HasArrayStorage);
case Array::SlowPutArrayStorage:
case Array::PossiblyArrayWithSlowPutArrayStorage:
return value.m_currentKnownStructure.hasSingleton()
- && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType());
+ && (value.m_currentKnownStructure.singleton()->indexingType() & (HasArrayStorage | HasSlowPutArrayStorage));
case Array::ArrayWithArrayStorage:
case Array::ArrayWithArrayStorageToHole:
case Array::ArrayWithArrayStorageOutOfBounds:
return value.m_currentKnownStructure.hasSingleton()
- && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType())
+ && (value.m_currentKnownStructure.singleton()->indexingType() & HasArrayStorage)
&& (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
case Array::ArrayWithSlowPutArrayStorage:
return value.m_currentKnownStructure.hasSingleton()
- && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType())
+ && (value.m_currentKnownStructure.singleton()->indexingType() & (HasArrayStorage | HasSlowPutArrayStorage))
&& (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
- case ALL_EFFECTFUL_MODES:
+ case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
return false;
case Array::Arguments:
@@ -258,24 +225,6 @@ const char* modeToString(Array::Mode mode)
return "ForceExit";
case Array::String:
return "String";
- case Array::Contiguous:
- return "Contiguous";
- case Array::ContiguousToTail:
- return "ContiguousToTail";
- case Array::ContiguousOutOfBounds:
- return "ContiguousOutOfBounds";
- case Array::ArrayWithContiguous:
- return "ArrayWithContiguous";
- case Array::ArrayWithContiguousToTail:
- return "ArrayWithContiguousToTail";
- case Array::ArrayWithContiguousOutOfBounds:
- return "ArrayWithContiguousOutOfBounds";
- case Array::PossiblyArrayWithContiguous:
- return "PossiblyArrayWithContiguous";
- case Array::PossiblyArrayWithContiguousToTail:
- return "PossiblyArrayWithContiguousToTail";
- case Array::PossiblyArrayWithContiguousOutOfBounds:
- return "PossiblyArrayWithContiguousOutOfBounds";
case Array::ArrayStorage:
return "ArrayStorage";
case Array::ArrayStorageToHole:
@@ -300,16 +249,10 @@ const char* modeToString(Array::Mode mode)
return "PossiblyArrayWithSlowPutArrayStorage";
case Array::PossiblyArrayWithArrayStorageOutOfBounds:
return "PossiblyArrayWithArrayStorageOutOfBounds";
- case Array::ToContiguous:
- return "ToContiguous";
- case Array::ToArrayStorage:
- return "ToArrayStorage";
- case Array::ToSlowPutArrayStorage:
- return "ToSlowPutArrayStorage";
- case Array::ArrayToArrayStorage:
- return "ArrayToArrayStorage";
- case Array::PossiblyArrayToArrayStorage:
- return "PossiblyArrayToArrayStorage";
+ case Array::BlankToArrayStorage:
+ return "BlankToArrayStorage";
+ case Array::BlankToSlowPutArrayStorage:
+ return "BlankToSlowPutArrayStorage";
case Array::Arguments:
return "Arguments";
case Array::Int8Array:
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.h b/Source/JavaScriptCore/dfg/DFGArrayMode.h
index a666bb83f..d4be9c0eb 100644
--- a/Source/JavaScriptCore/dfg/DFGArrayMode.h
+++ b/Source/JavaScriptCore/dfg/DFGArrayMode.h
@@ -54,15 +54,6 @@ enum Mode {
String,
// Modes of conventional indexed storage where the check is non side-effecting.
- Contiguous,
- ContiguousToTail,
- ContiguousOutOfBounds,
- ArrayWithContiguous,
- ArrayWithContiguousToTail,
- ArrayWithContiguousOutOfBounds,
- PossiblyArrayWithContiguous,
- PossiblyArrayWithContiguousToTail,
- PossiblyArrayWithContiguousOutOfBounds,
ArrayStorage,
ArrayStorageToHole,
SlowPutArrayStorage,
@@ -77,11 +68,8 @@ enum Mode {
PossiblyArrayWithArrayStorageOutOfBounds,
// Modes of conventional indexed storage where the check is side-effecting.
- ToContiguous,
- ToArrayStorage,
- ArrayToArrayStorage,
- PossiblyArrayToArrayStorage,
- ToSlowPutArrayStorage,
+ BlankToArrayStorage,
+ BlankToSlowPutArrayStorage,
Arguments,
Int8Array,
@@ -101,32 +89,6 @@ enum Mode {
// have the word "ArrayStorage" in them.
// First: helpers for non-side-effecting checks.
-#define NON_ARRAY_CONTIGUOUS_MODES \
- Array::Contiguous: \
- case Array::ContiguousToTail: \
- case Array::ContiguousOutOfBounds: \
- case Array::PossiblyArrayWithContiguous: \
- case Array::PossiblyArrayWithContiguousToTail: \
- case Array::PossiblyArrayWithContiguousOutOfBounds
-#define ARRAY_WITH_CONTIGUOUS_MODES \
- Array::ArrayWithContiguous: \
- case Array::ArrayWithContiguousToTail: \
- case Array::ArrayWithContiguousOutOfBounds
-#define ALL_CONTIGUOUS_MODES \
- NON_ARRAY_CONTIGUOUS_MODES: \
- case ARRAY_WITH_CONTIGUOUS_MODES
-#define IN_BOUNDS_CONTIGUOUS_MODES \
- Array::Contiguous: \
- case Array::ArrayWithContiguous: \
- case Array::PossiblyArrayWithContiguous
-#define CONTIGUOUS_TO_TAIL_MODES \
- Array::ContiguousToTail: \
- case Array::ArrayWithContiguousToTail: \
- case Array::PossiblyArrayWithContiguousToTail
-#define OUT_OF_BOUNDS_CONTIGUOUS_MODES \
- Array::ContiguousOutOfBounds: \
- case Array::ArrayWithContiguousOutOfBounds: \
- case Array::PossiblyArrayWithContiguousOutOfBounds
#define NON_ARRAY_ARRAY_STORAGE_MODES \
Array::ArrayStorage: \
case Array::ArrayStorageToHole: \
@@ -144,43 +106,33 @@ enum Mode {
#define ALL_ARRAY_STORAGE_MODES \
NON_ARRAY_ARRAY_STORAGE_MODES: \
case ARRAY_WITH_ARRAY_STORAGE_MODES
-#define IN_BOUNDS_ARRAY_STORAGE_MODES \
- Array::ArrayStorage: \
- case Array::ArrayWithArrayStorage: \
- case Array::PossiblyArrayWithArrayStorage
#define ARRAY_STORAGE_TO_HOLE_MODES \
Array::ArrayStorageToHole: \
case Array::ArrayWithArrayStorageToHole: \
case Array::PossiblyArrayWithArrayStorageToHole
+#define IN_BOUNDS_ARRAY_STORAGE_MODES \
+ ARRAY_STORAGE_TO_HOLE_MODES: \
+ case Array::ArrayStorage: \
+ case Array::ArrayWithArrayStorage: \
+ case Array::PossiblyArrayWithArrayStorage
#define SLOW_PUT_ARRAY_STORAGE_MODES \
Array::SlowPutArrayStorage: \
case Array::ArrayWithSlowPutArrayStorage: \
case Array::PossiblyArrayWithSlowPutArrayStorage
#define OUT_OF_BOUNDS_ARRAY_STORAGE_MODES \
- Array::ArrayStorageOutOfBounds: \
+ SLOW_PUT_ARRAY_STORAGE_MODES: \
+ case Array::ArrayStorageOutOfBounds: \
case Array::ArrayWithArrayStorageOutOfBounds: \
case Array::PossiblyArrayWithArrayStorageOutOfBounds
// Next: helpers for side-effecting checks.
-#define NON_ARRAY_EFFECTFUL_MODES \
- Array::ToContiguous: \
- case Array::ToArrayStorage: \
- case Array::ToSlowPutArrayStorage: \
- case Array::PossiblyArrayToArrayStorage
-#define ARRAY_EFFECTFUL_MODES \
- Array::ArrayToArrayStorage
-#define ALL_EFFECTFUL_CONTIGUOUS_MODES \
- Array::ToContiguous
-#define ALL_EFFECTFUL_ARRAY_STORAGE_MODES \
- Array::ToArrayStorage: \
- case Array::ToSlowPutArrayStorage: \
- case Array::ArrayToArrayStorage: \
- case Array::PossiblyArrayToArrayStorage
-#define SLOW_PUT_EFFECTFUL_ARRAY_STORAGE_MODES \
- Array::ToSlowPutArrayStorage
-#define ALL_EFFECTFUL_MODES \
- ALL_EFFECTFUL_CONTIGUOUS_MODES: \
- case ALL_EFFECTFUL_ARRAY_STORAGE_MODES
+#define EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES \
+ Array::BlankToArrayStorage: \
+ case Array::BlankToSlowPutArrayStorage
+#define ALL_EFFECTFUL_ARRAY_STORAGE_MODES \
+ EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES
+#define SLOW_PUT_EFFECTFUL_ARRAY_STORAGE_MODES \
+ Array::BlankToSlowPutArrayStorage
Array::Mode fromObserved(ArrayProfile*, Array::Action, bool makeSafe);
@@ -193,9 +145,8 @@ const char* modeToString(Array::Mode);
inline bool modeUsesButterfly(Array::Mode arrayMode)
{
switch (arrayMode) {
- case ALL_CONTIGUOUS_MODES:
case ALL_ARRAY_STORAGE_MODES:
- case ALL_EFFECTFUL_MODES:
+ case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
return true;
default:
return false;
@@ -205,9 +156,7 @@ inline bool modeUsesButterfly(Array::Mode arrayMode)
inline bool modeIsJSArray(Array::Mode arrayMode)
{
switch (arrayMode) {
- case ARRAY_WITH_CONTIGUOUS_MODES:
case ARRAY_WITH_ARRAY_STORAGE_MODES:
- case ARRAY_EFFECTFUL_MODES:
return true;
default:
return false;
@@ -217,9 +166,6 @@ inline bool modeIsJSArray(Array::Mode arrayMode)
inline bool isInBoundsAccess(Array::Mode arrayMode)
{
switch (arrayMode) {
- case IN_BOUNDS_CONTIGUOUS_MODES:
- case CONTIGUOUS_TO_TAIL_MODES:
- case ARRAY_STORAGE_TO_HOLE_MODES:
case IN_BOUNDS_ARRAY_STORAGE_MODES:
return true;
default:
@@ -238,24 +184,11 @@ inline bool isSlowPutAccess(Array::Mode arrayMode)
}
}
-inline bool mayStoreToTail(Array::Mode arrayMode)
-{
- switch (arrayMode) {
- case CONTIGUOUS_TO_TAIL_MODES:
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES:
- return true;
- default:
- return false;
- }
-}
-
inline bool mayStoreToHole(Array::Mode arrayMode)
{
switch (arrayMode) {
case ARRAY_STORAGE_TO_HOLE_MODES:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case SLOW_PUT_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
return true;
default:
@@ -316,9 +249,7 @@ inline bool modeSupportsLength(Array::Mode mode)
case Array::Unprofiled:
case Array::ForceExit:
case Array::Generic:
- case NON_ARRAY_CONTIGUOUS_MODES:
case NON_ARRAY_ARRAY_STORAGE_MODES:
- case NON_ARRAY_EFFECTFUL_MODES:
return false;
default:
return true;
@@ -328,7 +259,7 @@ inline bool modeSupportsLength(Array::Mode mode)
inline bool benefitsFromStructureCheck(Array::Mode mode)
{
switch (mode) {
- case ALL_EFFECTFUL_MODES:
+ case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
case Array::Undecided:
case Array::Unprofiled:
case Array::ForceExit:
@@ -342,7 +273,7 @@ inline bool benefitsFromStructureCheck(Array::Mode mode)
inline bool isEffectful(Array::Mode mode)
{
switch (mode) {
- case ALL_EFFECTFUL_MODES:
+ case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
return true;
default:
return false;
diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp
index a19b723d8..7799ee505 100644
--- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp
@@ -30,6 +30,8 @@
namespace JSC { namespace DFG {
+const double AssemblyHelpers::twoToThe32 = (double)0x100000000ull;
+
ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin)
{
if (!codeOrigin.inlineCallFrame)
@@ -47,9 +49,9 @@ Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock*
HashMap<CodeBlock*, Vector<BytecodeAndMachineOffset> >::AddResult result = m_decodedCodeMaps.add(codeBlock, Vector<BytecodeAndMachineOffset>());
if (result.isNewEntry)
- codeBlock->jitCodeMap()->decode(result.iterator->value);
+ codeBlock->jitCodeMap()->decode(result.iterator->second);
- return result.iterator->value;
+ return result.iterator->second;
}
#if ENABLE(SAMPLING_FLAGS)
diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
index 5d338fa57..a2003c5bf 100644
--- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
@@ -93,16 +93,16 @@ public:
}
#endif
- void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, GPRReg to)
+ void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, GPRReg to)
{
loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to);
}
- void emitPutToCallFrameHeader(GPRReg from, JSStack::CallFrameHeaderEntry entry)
+ void emitPutToCallFrameHeader(GPRReg from, RegisterFile::CallFrameHeaderEntry entry)
{
storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
}
- void emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry)
+ void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
{
storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
}
@@ -243,14 +243,33 @@ public:
}
#endif
-#if USE(JSVALUE32_64)
+#if USE(JSVALUE32_64) && CPU(X86)
void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
{
- moveDoubleToInts(fpr, payloadGPR, tagGPR);
+ movePackedToInt32(fpr, payloadGPR);
+ rshiftPacked(TrustedImm32(32), fpr);
+ movePackedToInt32(fpr, tagGPR);
}
void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
{
- moveIntsToDouble(payloadGPR, tagGPR, fpr, scratchFPR);
+ jitAssertIsJSDouble(tagGPR);
+ moveInt32ToPacked(payloadGPR, fpr);
+ moveInt32ToPacked(tagGPR, scratchFPR);
+ lshiftPacked(TrustedImm32(32), scratchFPR);
+ orPacked(scratchFPR, fpr);
+ }
+#endif
+
+#if USE(JSVALUE32_64) && CPU(ARM)
+ void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
+ {
+ m_assembler.vmov(payloadGPR, tagGPR, fpr);
+ }
+ void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
+ {
+ jitAssertIsJSDouble(tagGPR);
+ UNUSED_PARAM(scratchFPR);
+ m_assembler.vmov(fpr, payloadGPR, tagGPR);
}
#endif
@@ -345,6 +364,8 @@ public:
Vector<BytecodeAndMachineOffset>& decodedCodeMapFor(CodeBlock*);
+ static const double twoToThe32;
+
protected:
JSGlobalData* m_globalData;
CodeBlock* m_codeBlock;
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeCache.h b/Source/JavaScriptCore/dfg/DFGByteCodeCache.h
index 6b9056e54..ab88e99e5 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeCache.h
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeCache.h
@@ -132,10 +132,10 @@ public:
Map::iterator begin = m_map.begin();
Map::iterator end = m_map.end();
for (Map::iterator iter = begin; iter != end; ++iter) {
- if (!iter->value.codeBlock)
+ if (!iter->second.codeBlock)
continue;
- if (iter->value.owned) {
- delete iter->value.codeBlock;
+ if (iter->second.owned) {
+ delete iter->second.codeBlock;
continue;
}
}
@@ -145,7 +145,7 @@ public:
{
Map::iterator iter = m_map.find(key);
if (iter != m_map.end())
- return iter->value.codeBlock;
+ return iter->second.codeBlock;
ByteCodeCacheValue value;
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index dc668d93e..6d5f68200 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -43,76 +43,6 @@
namespace JSC { namespace DFG {
-class ConstantBufferKey {
-public:
- ConstantBufferKey()
- : m_codeBlock(0)
- , m_index(0)
- {
- }
-
- ConstantBufferKey(WTF::HashTableDeletedValueType)
- : m_codeBlock(0)
- , m_index(1)
- {
- }
-
- ConstantBufferKey(CodeBlock* codeBlock, unsigned index)
- : m_codeBlock(codeBlock)
- , m_index(index)
- {
- }
-
- bool operator==(const ConstantBufferKey& other) const
- {
- return m_codeBlock == other.m_codeBlock
- && m_index == other.m_index;
- }
-
- unsigned hash() const
- {
- return WTF::PtrHash<CodeBlock*>::hash(m_codeBlock) ^ m_index;
- }
-
- bool isHashTableDeletedValue() const
- {
- return !m_codeBlock && m_index;
- }
-
- CodeBlock* codeBlock() const { return m_codeBlock; }
- unsigned index() const { return m_index; }
-
-private:
- CodeBlock* m_codeBlock;
- unsigned m_index;
-};
-
-struct ConstantBufferKeyHash {
- static unsigned hash(const ConstantBufferKey& key) { return key.hash(); }
- static bool equal(const ConstantBufferKey& a, const ConstantBufferKey& b)
- {
- return a == b;
- }
-
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-} } // namespace JSC::DFG
-
-namespace WTF {
-
-template<typename T> struct DefaultHash;
-template<> struct DefaultHash<JSC::DFG::ConstantBufferKey> {
- typedef JSC::DFG::ConstantBufferKeyHash Hash;
-};
-
-template<typename T> struct HashTraits;
-template<> struct HashTraits<JSC::DFG::ConstantBufferKey> : SimpleClassHashTraits<JSC::DFG::ConstantBufferKey> { };
-
-} // namespace WTF
-
-namespace JSC { namespace DFG {
-
// === ByteCodeParser ===
//
// This class is used to compile the dataflow graph from a CodeBlock.
@@ -212,7 +142,7 @@ private:
return getJSConstant(constant);
}
- if (operand == JSStack::Callee)
+ if (operand == RegisterFile::Callee)
return getCallee();
// Is this an argument?
@@ -297,10 +227,7 @@ private:
if (nodePtr->op() == GetLocal)
nodeIndex = nodePtr->child1().index();
- NodeIndex newGetLocal = injectLazyOperandSpeculation(
- addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
- m_currentBlock->variablesAtTail.local(operand) = newGetLocal;
- return newGetLocal;
+ return injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
}
if (nodePtr->op() == GetLocal)
@@ -439,11 +366,11 @@ private:
InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame;
if (!inlineCallFrame)
break;
- if (operand >= static_cast<int>(inlineCallFrame->stackOffset - JSStack::CallFrameHeaderSize))
+ if (operand >= static_cast<int>(inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize))
continue;
if (operand == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset())
continue;
- if (operand < static_cast<int>(inlineCallFrame->stackOffset - JSStack::CallFrameHeaderSize - inlineCallFrame->arguments.size()))
+ if (operand < static_cast<int>(inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize - inlineCallFrame->arguments.size()))
continue;
int argument = operandToArgument(operand - inlineCallFrame->stackOffset);
return stack->m_argumentPositions[argument];
@@ -742,9 +669,9 @@ private:
{
HashMap<JSCell*, NodeIndex>::AddResult result = m_cellConstantNodes.add(cell, NoNode);
if (result.isNewEntry)
- result.iterator->value = addToGraph(WeakJSConstant, OpInfo(cell));
+ result.iterator->second = addToGraph(WeakJSConstant, OpInfo(cell));
- return result.iterator->value;
+ return result.iterator->second;
}
CodeOrigin currentCodeOrigin()
@@ -831,8 +758,8 @@ private:
addVarArgChild(get(currentInstruction[1].u.operand));
int argCount = currentInstruction[2].u.operand;
- if (JSStack::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
- m_parameterSlots = JSStack::CallFrameHeaderSize + argCount;
+ if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
+ m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
int registerOffset = currentInstruction[3].u.operand;
int dummyThisArgument = op == Call ? 0 : 1;
@@ -1122,8 +1049,6 @@ private:
Vector<PhiStackEntry, 16> m_argumentPhiStack;
Vector<PhiStackEntry, 16> m_localPhiStack;
- HashMap<ConstantBufferKey, unsigned> m_constantBufferCache;
-
struct InlineStackEntry {
ByteCodeParser* m_byteCodeParser;
@@ -1142,7 +1067,6 @@ private:
// direct, caller).
Vector<unsigned> m_identifierRemap;
Vector<unsigned> m_constantRemap;
- Vector<unsigned> m_constantBufferRemap;
// Blocks introduced by this code block, which need successor linking.
// May include up to one basic block that includes the continuation after
@@ -1215,7 +1139,7 @@ private:
return result;
}
- if (operand == JSStack::Callee)
+ if (operand == RegisterFile::Callee)
return m_calleeVR;
return operand + m_inlineCallFrame->stackOffset;
@@ -1437,14 +1361,14 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
// FIXME: Don't flush constants!
- int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - JSStack::CallFrameHeaderSize;
+ int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize;
// Make sure that the area used by the call frame is reserved.
- for (int arg = inlineCallFrameStart + JSStack::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;)
+ for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;)
m_preservedVars.set(arg);
// Make sure that we have enough locals.
- unsigned newNumLocals = inlineCallFrameStart + JSStack::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
+ unsigned newNumLocals = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
if (newNumLocals > m_numLocals) {
m_numLocals = newNumLocals;
for (size_t i = 0; i < m_graph.m_blocks.size(); ++i)
@@ -1647,8 +1571,6 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
case Array::ArrayWithArrayStorageToHole:
ASSERT_NOT_REACHED();
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds:
case Array::ArrayWithArrayStorage:
case Array::ArrayWithArrayStorageOutOfBounds: {
NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
@@ -1672,8 +1594,6 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
case Array::ArrayWithArrayStorageToHole:
ASSERT_NOT_REACHED();
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds:
case Array::ArrayWithArrayStorage:
case Array::ArrayWithArrayStorageOutOfBounds: {
NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)));
@@ -1948,7 +1868,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_create_this: {
- set(currentInstruction[1].u.operand, addToGraph(CreateThis, get(JSStack::Callee)));
+ set(currentInstruction[1].u.operand, addToGraph(CreateThis, get(RegisterFile::Callee)));
NEXT_OPCODE(op_create_this);
}
@@ -1969,7 +1889,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_new_array_buffer: {
int startConstant = currentInstruction[2].u.operand;
int numConstants = currentInstruction[3].u.operand;
- set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(m_inlineStackTop->m_constantBufferRemap[startConstant]), OpInfo(numConstants)));
+ set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(startConstant), OpInfo(numConstants)));
NEXT_OPCODE(op_new_array_buffer);
}
@@ -2833,8 +2753,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
addToGraph(CheckArgumentsNotCreated);
unsigned argCount = m_inlineStackTop->m_inlineCallFrame->arguments.size();
- if (JSStack::CallFrameHeaderSize + argCount > m_parameterSlots)
- m_parameterSlots = JSStack::CallFrameHeaderSize + argCount;
+ if (RegisterFile::CallFrameHeaderSize + argCount > m_parameterSlots)
+ m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
addVarArgChild(get(currentInstruction[1].u.operand)); // callee
addVarArgChild(get(currentInstruction[2].u.operand)); // this
@@ -2855,10 +2775,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// Statically speculate for now. It makes sense to let speculate-only jneq_ptr
// support simmer for a while before making it more general, since it's
// already gnarly enough as it is.
- ASSERT(pointerIsFunction(currentInstruction[2].u.specialPointer));
addToGraph(
- CheckFunction,
- OpInfo(actualPointerFor(m_inlineStackTop->m_codeBlock, currentInstruction[2].u.specialPointer)),
+ CheckFunction, OpInfo(currentInstruction[2].u.jsCell.get()),
get(currentInstruction[1].u.operand));
addToGraph(Jump, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_ptr)));
LAST_OPCODE(op_jneq_ptr);
@@ -3287,7 +3205,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
InlineCallFrame inlineCallFrame;
inlineCallFrame.executable.set(*byteCodeParser->m_globalData, byteCodeParser->m_codeBlock->ownerExecutable(), codeBlock->ownerExecutable());
- inlineCallFrame.stackOffset = inlineCallFrameStart + JSStack::CallFrameHeaderSize;
+ inlineCallFrame.stackOffset = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize;
inlineCallFrame.callee.set(*byteCodeParser->m_globalData, byteCodeParser->m_codeBlock->ownerExecutable(), callee);
inlineCallFrame.caller = byteCodeParser->currentCodeOrigin();
inlineCallFrame.arguments.resize(argumentCountIncludingThis); // Set the number of arguments including this, but don't configure the value recoveries, yet.
@@ -3324,14 +3242,13 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
m_identifierRemap.resize(codeBlock->numberOfIdentifiers());
m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
- m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers());
for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) {
StringImpl* rep = codeBlock->identifier(i).impl();
IdentifierMap::AddResult result = byteCodeParser->m_identifierMap.add(rep, byteCodeParser->m_codeBlock->numberOfIdentifiers());
if (result.isNewEntry)
byteCodeParser->m_codeBlock->addIdentifier(Identifier(byteCodeParser->m_globalData, rep));
- m_identifierRemap[i] = result.iterator->value;
+ m_identifierRemap[i] = result.iterator->second;
}
for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) {
JSValue value = codeBlock->getConstant(i + FirstConstantRegisterIndex);
@@ -3349,24 +3266,10 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
byteCodeParser->m_codeBlock->addConstant(value);
byteCodeParser->m_constants.append(ConstantRecord());
}
- m_constantRemap[i] = result.iterator->value;
+ m_constantRemap[i] = result.iterator->second;
}
for (unsigned i = 0; i < codeBlock->numberOfGlobalResolveInfos(); ++i)
byteCodeParser->m_codeBlock->addGlobalResolveInfo(std::numeric_limits<unsigned>::max());
- for (unsigned i = 0; i < codeBlock->numberOfConstantBuffers(); ++i) {
- // If we inline the same code block multiple times, we don't want to needlessly
- // duplicate its constant buffers.
- HashMap<ConstantBufferKey, unsigned>::iterator iter =
- byteCodeParser->m_constantBufferCache.find(ConstantBufferKey(codeBlock, i));
- if (iter != byteCodeParser->m_constantBufferCache.end()) {
- m_constantBufferRemap[i] = iter->value;
- continue;
- }
- Vector<JSValue>& buffer = codeBlock->constantBufferAsVector(i);
- unsigned newIndex = byteCodeParser->m_codeBlock->addConstantBuffer(buffer);
- m_constantBufferRemap[i] = newIndex;
- byteCodeParser->m_constantBufferCache.add(ConstantBufferKey(codeBlock, i), newIndex);
- }
m_callsiteBlockHeadNeedsLinking = true;
} else {
@@ -3382,14 +3285,11 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
m_identifierRemap.resize(codeBlock->numberOfIdentifiers());
m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
- m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers());
for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i)
m_identifierRemap[i] = i;
for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i)
m_constantRemap[i] = i + FirstConstantRegisterIndex;
- for (size_t i = 0; i < codeBlock->numberOfConstantBuffers(); ++i)
- m_constantBufferRemap[i] = i;
m_callsiteBlockHeadNeedsLinking = false;
}
diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
index 4a6024305..5cd0baab2 100644
--- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
@@ -184,14 +184,6 @@ public:
addCallArgument(arg2);
}
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImm32 arg2)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- }
-
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
resetCallArguments();
@@ -601,13 +593,6 @@ public:
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
- ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImm32 arg2)
- {
- move(arg1, GPRInfo::argumentGPR1);
- move(arg2, GPRInfo::argumentGPR2);
- move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
setupStubArguments(arg1, arg2, arg3);
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index 1b08bc6b0..cea2f3c48 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -177,7 +177,6 @@ private:
if (!m_graph.byValIsPure(node))
return NoNode;
switch (node.arrayMode()) {
- case CONTIGUOUS_TO_TAIL_MODES:
case ARRAY_STORAGE_TO_HOLE_MODES:
return NoNode;
default:
@@ -360,6 +359,9 @@ private:
// for a structure change or a put to property storage to affect
// the GetByVal.
break;
+ case ArrayPush:
+ // A push cannot affect previously existing elements in the array.
+ break;
default:
if (m_graph.clobbersWorld(index))
return NoNode;
@@ -1220,7 +1222,9 @@ private:
case PutByVal: {
Edge child1 = m_graph.varArgChild(node, 0);
Edge child2 = m_graph.varArgChild(node, 1);
- if (canCSEStorage(node.arrayMode())) {
+ if (isActionableMutableArraySpeculation(m_graph[child1].prediction())
+ && m_graph[child2].shouldSpeculateInteger()
+ && !m_graph[child1].shouldSpeculateArguments()) {
NodeIndex nodeIndex = getByValLoadElimination(child1.index(), child2.index());
if (nodeIndex == NoNode)
break;
diff --git a/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h b/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h
deleted file mode 100644
index 46d5f44cb..000000000
--- a/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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 DFGCallArrayAllocatorSlowPathGenerator_h
-#define DFGCallArrayAllocatorSlowPathGenerator_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGCommon.h"
-#include "DFGSlowPathGenerator.h"
-#include "DFGSpeculativeJIT.h"
-#include <wtf/Vector.h>
-
-namespace JSC { namespace DFG {
-
-class CallArrayAllocatorSlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> {
-public:
- CallArrayAllocatorSlowPathGenerator(
- MacroAssembler::JumpList from, SpeculativeJIT* jit, P_DFGOperation_EStZ function,
- GPRReg resultGPR, GPRReg storageGPR, Structure* structure, size_t size)
- : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
- , m_function(function)
- , m_resultGPR(resultGPR)
- , m_storageGPR(storageGPR)
- , m_structure(structure)
- , m_size(size)
- {
- ASSERT(size < static_cast<size_t>(std::numeric_limits<int32_t>::max()));
- jit->silentSpillAllRegistersImpl(false, m_plans, resultGPR);
- }
-
-protected:
- void generateInternal(SpeculativeJIT* jit)
- {
- linkFrom(jit);
- for (unsigned i = 0; i < m_plans.size(); ++i)
- jit->silentSpill(m_plans[i]);
- jit->callOperation(m_function, m_resultGPR, m_structure, m_size);
- GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
- for (unsigned i = 0; i < m_plans.size(); ++i)
- jit->silentFill(m_plans[i], canTrample);
- jit->m_jit.loadPtr(MacroAssembler::Address(m_resultGPR, JSObject::butterflyOffset()), m_storageGPR);
- jumpTo(jit);
- }
-
-private:
- P_DFGOperation_EStZ m_function;
- GPRReg m_resultGPR;
- GPRReg m_storageGPR;
- Structure* m_structure;
- size_t m_size;
- Vector<SilentRegisterSavePlan, 2> m_plans;
-};
-
-class CallArrayAllocatorWithVariableSizeSlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> {
-public:
- CallArrayAllocatorWithVariableSizeSlowPathGenerator(
- MacroAssembler::JumpList from, SpeculativeJIT* jit, P_DFGOperation_EStZ function,
- GPRReg resultGPR, Structure* contiguousStructure, Structure* arrayStorageStructure, GPRReg sizeGPR)
- : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
- , m_function(function)
- , m_resultGPR(resultGPR)
- , m_contiguousStructure(contiguousStructure)
- , m_arrayStorageStructure(arrayStorageStructure)
- , m_sizeGPR(sizeGPR)
- {
- jit->silentSpillAllRegistersImpl(false, m_plans, resultGPR);
- }
-
-protected:
- void generateInternal(SpeculativeJIT* jit)
- {
- linkFrom(jit);
- for (unsigned i = 0; i < m_plans.size(); ++i)
- jit->silentSpill(m_plans[i]);
- GPRReg scratchGPR = AssemblyHelpers::selectScratchGPR(m_sizeGPR);
- MacroAssembler::Jump bigLength = jit->m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_SPARSE_ARRAY_INDEX));
- jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
- MacroAssembler::Jump done = jit->m_jit.jump();
- bigLength.link(&jit->m_jit);
- jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageStructure), scratchGPR);
- done.link(&jit->m_jit);
- jit->callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR);
- GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
- for (unsigned i = 0; i < m_plans.size(); ++i)
- jit->silentFill(m_plans[i], canTrample);
- jumpTo(jit);
- }
-
-private:
- P_DFGOperation_EStZ m_function;
- GPRReg m_resultGPR;
- Structure* m_contiguousStructure;
- Structure* m_arrayStorageStructure;
- GPRReg m_sizeGPR;
- Vector<SilentRegisterSavePlan, 2> m_plans;
-};
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
-#endif // DFGCallArrayAllocatorSlowPathGenerator_h
-
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h
index e1760699a..bccde7ca7 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.h
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h
@@ -201,6 +201,10 @@ inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction
case op_resolve:
case op_resolve_base:
+ // Constant buffers aren't copied correctly. This is easy to fix, but for
+ // now we just disable inlining for functions that use them.
+ case op_new_array_buffer:
+
// Inlining doesn't correctly remap regular expression operands.
case op_new_regexp:
diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
index 8a261ad2b..dfb62cbc4 100644
--- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
@@ -179,8 +179,7 @@ private:
block->variablesAtTail.operand(node.local()) = previousLocalAccess;
else {
ASSERT(m_graph[tailNodeIndex].op() == Flush
- || m_graph[tailNodeIndex].op() == SetLocal
- || node.variableAccessData()->isCaptured());
+ || m_graph[tailNodeIndex].op() == SetLocal);
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index be5811772..aa2d5dff4 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -116,7 +116,7 @@ private:
m_graph.deref(m_compileIndex);
nodePtr->setArrayMode(arrayMode);
- NodeIndex storage = checkArray(arrayMode, nodePtr->codeOrigin, nodePtr->child1().index(), NoNode, lengthNeedsStorage, nodePtr->shouldGenerate());
+ NodeIndex storage = checkArray(arrayMode, nodePtr->codeOrigin, nodePtr->child1().index(), lengthNeedsStorage, nodePtr->shouldGenerate());
if (storage == NoNode)
break;
@@ -137,17 +137,17 @@ private:
m_graph[node.child1()].prediction(),
m_graph[node.child2()].prediction()));
- blessArrayOperation(node.child1(), node.child2(), 2);
+ blessArrayOperation(node.child1(), 2);
break;
}
case ArrayPush: {
- blessArrayOperation(node.child1(), node.child2(), 2);
+ blessArrayOperation(node.child1(), 2);
break;
}
case ArrayPop: {
- blessArrayOperation(node.child1(), node.child2(), 1);
+ blessArrayOperation(node.child1(), 1);
}
case ValueToInt32: {
@@ -327,7 +327,7 @@ private:
m_graph[child1].prediction(),
m_graph[child2].prediction()));
- blessArrayOperation(child1, child2, 3);
+ blessArrayOperation(child1, 3);
Node* nodePtr = &m_graph[m_compileIndex];
@@ -375,28 +375,25 @@ private:
return nodeIndex;
}
- NodeIndex checkArray(Array::Mode arrayMode, CodeOrigin codeOrigin, NodeIndex array, NodeIndex index, bool (*storageCheck)(Array::Mode) = canCSEStorage, bool shouldGenerate = true)
+ NodeIndex checkArray(Array::Mode arrayMode, CodeOrigin codeOrigin, NodeIndex array, bool (*storageCheck)(Array::Mode) = canCSEStorage, bool shouldGenerate = true)
{
ASSERT(modeIsSpecific(arrayMode));
m_graph.ref(array);
if (isEffectful(arrayMode)) {
- if (index != NoNode)
- m_graph.ref(index);
- Node arrayify(Arrayify, codeOrigin, OpInfo(arrayMode), array, index);
+ Node arrayify(Arrayify, codeOrigin, OpInfo(arrayMode), array);
arrayify.ref(); // Once because it's used as a butterfly.
arrayify.ref(); // And twice because it's must-generate.
NodeIndex arrayifyIndex = m_graph.size();
m_graph.append(arrayify);
m_insertionSet.append(m_indexInBlock, arrayifyIndex);
+ ASSERT(storageCheck == canCSEStorage);
ASSERT(shouldGenerate);
ASSERT(canCSEStorage(arrayMode));
ASSERT(modeUsesButterfly(arrayMode));
-
- if (!storageCheck(arrayMode))
- return NoNode;
+
return arrayifyIndex;
}
@@ -418,15 +415,14 @@ private:
return addNode(Node(GetIndexedPropertyStorage, codeOrigin, OpInfo(arrayMode), array), shouldGenerate);
}
- void blessArrayOperation(Edge base, Edge index, unsigned storageChildIdx)
+ void blessArrayOperation(Edge base, unsigned storageChildIdx)
{
if (m_graph.m_fixpointState > BeforeFixpoint)
return;
Node* nodePtr = &m_graph[m_compileIndex];
- switch (nodePtr->arrayMode()) {
- case Array::ForceExit: {
+ if (nodePtr->arrayMode() == Array::ForceExit) {
Node forceExit(ForceOSRExit, nodePtr->codeOrigin);
forceExit.ref();
NodeIndex forceExitIndex = m_graph.size();
@@ -434,23 +430,15 @@ private:
m_insertionSet.append(m_indexInBlock, forceExitIndex);
return;
}
-
- case Array::Undecided:
- case Array::Unprofiled:
- ASSERT_NOT_REACHED();
+
+ if (!modeIsSpecific(nodePtr->arrayMode()))
return;
- case Array::Generic:
+ NodeIndex storage = checkArray(nodePtr->arrayMode(), nodePtr->codeOrigin, base.index());
+ if (storage == NoNode)
return;
- default: {
- NodeIndex storage = checkArray(nodePtr->arrayMode(), nodePtr->codeOrigin, base.index(), index.indexUnchecked());
- if (storage == NoNode)
- return;
-
- m_graph.child(m_graph[m_compileIndex], storageChildIdx) = Edge(storage);
- return;
- } }
+ m_graph.child(m_graph[m_compileIndex], storageChildIdx) = Edge(storage);
}
void fixIntEdge(Edge& edge)
diff --git a/Source/JavaScriptCore/dfg/DFGGenerationInfo.h b/Source/JavaScriptCore/dfg/DFGGenerationInfo.h
index 227433e0e..905c5c5fb 100644
--- a/Source/JavaScriptCore/dfg/DFGGenerationInfo.h
+++ b/Source/JavaScriptCore/dfg/DFGGenerationInfo.h
@@ -201,7 +201,7 @@ public:
// Get the format of the value in machine registers (or 'none').
DataFormat registerFormat() { return m_registerFormat; }
- // Get the format of the value as it is spilled in the JSStack (or 'none').
+ // Get the format of the value as it is spilled in the RegisterFile (or 'none').
DataFormat spillFormat() { return m_spillFormat; }
bool isJSFormat(DataFormat expectedFormat)
@@ -255,11 +255,11 @@ public:
// This should only be called on values that are currently in a register.
ASSERT(m_registerFormat != DataFormatNone);
// Constants do not need spilling, nor do values that have already been
- // spilled to the JSStack.
+ // spilled to the RegisterFile.
return !m_canFill;
}
- // Called when a VirtualRegister is being spilled to the JSStack for the first time.
+ // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
void spill(VariableEventStream& stream, VirtualRegister virtualRegister, DataFormat spillFormat)
{
// We shouldn't be spill values that don't need spilling.
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 212c8bbd2..b02c9991c 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -36,8 +36,8 @@
#include "DFGBasicBlock.h"
#include "DFGDominators.h"
#include "DFGNode.h"
-#include "JSStack.h"
#include "MethodOfGettingAValueProfile.h"
+#include "RegisterFile.h"
#include <wtf/BitVector.h>
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
@@ -479,11 +479,8 @@ public:
{
switch (node.arrayMode()) {
case Array::Generic:
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
- case ARRAY_STORAGE_TO_HOLE_MODES:
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case SLOW_PUT_ARRAY_STORAGE_MODES:
- case ALL_EFFECTFUL_MODES:
+ case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
return false;
case Array::String:
return node.op() == GetByVal;
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
index c7f941a7a..ae28fad3f 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
@@ -68,14 +68,14 @@ void JITCompiler::compileEntry()
{
// This code currently matches the old JIT. In the function header we need to
// pop the return address (since we do not allow any recursion on the machine
- // stack), and perform a fast stack check.
+ // stack), and perform a fast register file check.
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=56292
- // We'll need to convert the remaining cti_ style calls (specifically the stack
+ // We'll need to convert the remaining cti_ style calls (specifically the register file
// check) which will be dependent on stack layout. (We'd need to account for this in
// both normal return code and when jumping to an exception handler).
preserveReturnAddressAfterCall(GPRInfo::regT2);
- emitPutToCallFrameHeader(GPRInfo::regT2, JSStack::ReturnPC);
- emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
+ emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC);
+ emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
}
void JITCompiler::compileBody(SpeculativeJIT& speculative)
@@ -256,12 +256,12 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
// If we needed to perform an arity check we will already have moved the return address,
// so enter after this.
Label fromArityCheck(this);
- // Plant a check that sufficient space is available in the JSStack.
+ // Plant a check that sufficient space is available in the RegisterFile.
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
addPtr(TrustedImm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1);
- Jump stackCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->stack().addressOfEnd()), GPRInfo::regT1);
- // Return here after stack check.
- Label fromStackCheck = label();
+ Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), GPRInfo::regT1);
+ // Return here after register file check.
+ Label fromRegisterFileCheck = label();
// === Function body code generation ===
@@ -271,21 +271,21 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
// === Function footer code generation ===
//
- // Generate code to perform the slow stack check (if the fast one in
+ // Generate code to perform the slow register file check (if the fast one in
// the function header fails), and generate the entry point with arity check.
//
- // Generate the stack check; if the fast check in the function head fails,
+ // Generate the register file check; if the fast check in the function head fails,
// we need to call out to a helper function to check whether more space is available.
// FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
- stackCheck.link(this);
+ registerFileCheck.link(this);
move(stackPointerRegister, GPRInfo::argumentGPR0);
poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
CallBeginToken token;
beginCall(CodeOrigin(0), token);
- Call callStackCheck = call();
- notifyCall(callStackCheck, CodeOrigin(0), token);
- jump(fromStackCheck);
+ Call callRegisterFileCheck = call();
+ notifyCall(callRegisterFileCheck, CodeOrigin(0), token);
+ jump(fromRegisterFileCheck);
// The fast entry point into a function does not check the correct number of arguments
// have been passed to the call (we only use the fast entry point where we can statically
@@ -295,7 +295,7 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
Label arityCheck = label();
compileEntry();
- load32(AssemblyHelpers::payloadFor((VirtualRegister)JSStack::ArgumentCount), GPRInfo::regT1);
+ load32(AssemblyHelpers::payloadFor((VirtualRegister)RegisterFile::ArgumentCount), GPRInfo::regT1);
branch32(AboveOrEqual, GPRInfo::regT1, TrustedImm32(m_codeBlock->numParameters())).linkTo(fromArityCheck, this);
move(stackPointerRegister, GPRInfo::argumentGPR0);
poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
@@ -322,8 +322,8 @@ bool JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
link(linkBuffer);
speculative.linkOSREntries(linkBuffer);
- // FIXME: switch the stack check & arity check over to DFGOpertaion style calls, not JIT stubs.
- linkBuffer.link(callStackCheck, cti_stack_check);
+ // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs.
+ linkBuffer.link(callRegisterFileCheck, cti_register_file_check);
linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
if (m_disassembler)
diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
index c73934832..7ff399f78 100644
--- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h
+++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h
@@ -297,7 +297,7 @@ public:
void beginCall(CodeOrigin codeOrigin, CallBeginToken& token)
{
unsigned index = m_exceptionChecks.size();
- store32(TrustedImm32(index), tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
+ store32(TrustedImm32(index), tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
token.set(codeOrigin, index);
}
diff --git a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
index b838c4fb4..9a7bc96cc 100644
--- a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
@@ -136,7 +136,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
// it seems silly: you'd be diverting the program to error handling when it
// would have otherwise just kept running albeit less quickly.
- if (!globalData->interpreter->stack().grow(&exec->registers()[codeBlock->m_numCalleeRegisters])) {
+ if (!globalData->interpreter->registerFile().grow(&exec->registers()[codeBlock->m_numCalleeRegisters])) {
#if ENABLE(JIT_VERBOSE_OSR)
dataLog(" OSR failed because stack growth failed.\n");
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
index cb13dcc50..8c8e2f949 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
@@ -125,9 +125,9 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
// Int32s, have no FPRs, and have no constants. If there are constants, we
// expect most of them to be jsUndefined(); if that's true then we handle that
// specially to minimize code size and execution time.
- bool haveUnboxedInt32InJSStack = false;
- bool haveUnboxedCellInJSStack = false;
- bool haveUnboxedBooleanInJSStack = false;
+ bool haveUnboxedInt32InRegisterFile = false;
+ bool haveUnboxedCellInRegisterFile = false;
+ bool haveUnboxedBooleanInRegisterFile = false;
bool haveUInt32s = false;
bool haveFPRs = false;
bool haveConstants = false;
@@ -137,10 +137,10 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
- case Int32DisplacedInJSStack:
- case CellDisplacedInJSStack:
- case BooleanDisplacedInJSStack:
+ case DisplacedInRegisterFile:
+ case Int32DisplacedInRegisterFile:
+ case CellDisplacedInRegisterFile:
+ case BooleanDisplacedInRegisterFile:
numberOfDisplacedVirtualRegisters++;
ASSERT((int)recovery.virtualRegister() >= 0);
@@ -174,16 +174,16 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
haveUInt32s = true;
break;
- case AlreadyInJSStackAsUnboxedInt32:
- haveUnboxedInt32InJSStack = true;
+ case AlreadyInRegisterFileAsUnboxedInt32:
+ haveUnboxedInt32InRegisterFile = true;
break;
- case AlreadyInJSStackAsUnboxedCell:
- haveUnboxedCellInJSStack = true;
+ case AlreadyInRegisterFileAsUnboxedCell:
+ haveUnboxedCellInRegisterFile = true;
break;
- case AlreadyInJSStackAsUnboxedBoolean:
- haveUnboxedBooleanInJSStack = true;
+ case AlreadyInRegisterFileAsUnboxedBoolean:
+ haveUnboxedBooleanInRegisterFile = true;
break;
case InFPR:
@@ -214,19 +214,19 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
// 5) Perform all reboxing of integers and cells, except for those in registers.
- if (haveUnboxedInt32InJSStack || haveUnboxedCellInJSStack || haveUnboxedBooleanInJSStack) {
+ if (haveUnboxedInt32InRegisterFile || haveUnboxedCellInRegisterFile || haveUnboxedBooleanInRegisterFile) {
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case AlreadyInJSStackAsUnboxedInt32:
+ case AlreadyInRegisterFileAsUnboxedInt32:
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(operands.operandForIndex(index))));
break;
- case AlreadyInJSStackAsUnboxedCell:
+ case AlreadyInRegisterFileAsUnboxedCell:
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(operands.operandForIndex(index))));
break;
- case AlreadyInJSStackAsUnboxedBoolean:
+ case AlreadyInRegisterFileAsUnboxedBoolean:
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(operands.operandForIndex(index))));
break;
@@ -327,7 +327,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
}
}
- // 7) Dump all doubles into the stack, or to the scratch storage if the
+ // 7) Dump all doubles into the register file, or to the scratch storage if the
// destination virtual register is poisoned.
if (haveFPRs) {
for (size_t index = 0; index < operands.size(); ++index) {
@@ -360,19 +360,19 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
+ case DisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
break;
- case Int32DisplacedInJSStack:
+ case Int32DisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), GPRInfo::toRegister(displacementIndex++));
break;
- case CellDisplacedInJSStack:
+ case CellDisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::CellTag), GPRInfo::toRegister(displacementIndex++));
break;
- case BooleanDisplacedInJSStack:
+ case BooleanDisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), GPRInfo::toRegister(displacementIndex++));
break;
@@ -385,10 +385,10 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
- case Int32DisplacedInJSStack:
- case CellDisplacedInJSStack:
- case BooleanDisplacedInJSStack:
+ case DisplacedInRegisterFile:
+ case Int32DisplacedInRegisterFile:
+ case CellDisplacedInRegisterFile:
+ case BooleanDisplacedInRegisterFile:
m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::payloadFor((VirtualRegister)operands.operandForIndex(index)));
m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::tagFor((VirtualRegister)operands.operandForIndex(index)));
break;
@@ -418,16 +418,16 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
+ case DisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::regT1);
m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
m_jit.store32(GPRInfo::regT1, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
scratchIndex++;
break;
- case Int32DisplacedInJSStack:
- case CellDisplacedInJSStack:
- case BooleanDisplacedInJSStack:
+ case Int32DisplacedInRegisterFile:
+ case CellDisplacedInRegisterFile:
+ case BooleanDisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
break;
@@ -440,24 +440,24 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
+ case DisplacedInRegisterFile:
m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)operands.operandForIndex(index)));
m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)operands.operandForIndex(index)));
scratchIndex++;
break;
- case Int32DisplacedInJSStack:
+ case Int32DisplacedInRegisterFile:
m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor((VirtualRegister)operands.operandForIndex(index)));
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)operands.operandForIndex(index)));
break;
- case CellDisplacedInJSStack:
+ case CellDisplacedInRegisterFile:
m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)operands.operandForIndex(index)));
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)operands.operandForIndex(index)));
break;
- case BooleanDisplacedInJSStack:
+ case BooleanDisplacedInRegisterFile:
m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), AssemblyHelpers::tagFor((VirtualRegister)operands.operandForIndex(index)));
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)operands.operandForIndex(index)));
@@ -575,7 +575,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
// 13) Reify inlined call frames.
ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)JSStack::CodeBlock));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
@@ -597,15 +597,15 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
} else
callerFrameGPR = GPRInfo::callFrameRegister;
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CodeBlock)));
- m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain)));
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee->scope()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain)));
- m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CallerFrame)));
- m_jit.storePtr(callerFrameGPR, AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CallerFrame)));
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ReturnPC)));
- m_jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount)));
- m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee)));
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CodeBlock)));
+ m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee->scope()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain)));
+ m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame)));
+ m_jit.storePtr(callerFrameGPR, AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ReturnPC)));
+ m_jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ArgumentCount)));
+ m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
}
// 14) Create arguments if necessary and place them into the appropriate aliased
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
index 968e56f1a..fcaf0a4bc 100644
--- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
@@ -133,9 +133,9 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case Int32DisplacedInJSStack:
- case DoubleDisplacedInJSStack:
- case DisplacedInJSStack:
+ case Int32DisplacedInRegisterFile:
+ case DoubleDisplacedInRegisterFile:
+ case DisplacedInRegisterFile:
numberOfDisplacedVirtualRegisters++;
ASSERT((int)recovery.virtualRegister() >= 0);
@@ -164,11 +164,11 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
break;
case UnboxedInt32InGPR:
- case AlreadyInJSStackAsUnboxedInt32:
+ case AlreadyInRegisterFileAsUnboxedInt32:
haveUnboxedInt32s = true;
break;
- case AlreadyInJSStackAsUnboxedDouble:
+ case AlreadyInRegisterFileAsUnboxedDouble:
haveUnboxedDoubles = true;
break;
@@ -233,7 +233,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
m_jit.orPtr(GPRInfo::tagTypeNumberRegister, recovery.gpr());
break;
- case AlreadyInJSStackAsUnboxedInt32:
+ case AlreadyInRegisterFileAsUnboxedInt32:
m_jit.store32(AssemblyHelpers::TrustedImm32(static_cast<uint32_t>(TagTypeNumber >> 32)), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(operands.operandForIndex(index))));
break;
@@ -321,7 +321,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
m_jit.boxDouble(fpr, gpr);
}
- // 8) Dump all doubles into the stack, or to the scratch storage if
+ // 8) Dump all doubles into the register file, or to the scratch storage if
// the destination virtual register is poisoned.
for (size_t index = 0; index < operands.size(); ++index) {
@@ -340,11 +340,11 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
// At this point all GPRs and FPRs are available for scratch use.
- // 9) Box all unboxed doubles in the stack.
+ // 9) Box all unboxed doubles in the register file.
if (haveUnboxedDoubles) {
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
- if (recovery.technique() != AlreadyInJSStackAsUnboxedDouble)
+ if (recovery.technique() != AlreadyInRegisterFileAsUnboxedDouble)
continue;
m_jit.loadDouble(AssemblyHelpers::addressFor((VirtualRegister)operands.operandForIndex(index)), FPRInfo::fpRegT0);
m_jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
@@ -367,18 +367,18 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
+ case DisplacedInRegisterFile:
m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
break;
- case Int32DisplacedInJSStack: {
+ case Int32DisplacedInRegisterFile: {
GPRReg gpr = GPRInfo::toRegister(displacementIndex++);
m_jit.load32(AssemblyHelpers::addressFor(recovery.virtualRegister()), gpr);
m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
break;
}
- case DoubleDisplacedInJSStack: {
+ case DoubleDisplacedInRegisterFile: {
GPRReg gpr = GPRInfo::toRegister(displacementIndex++);
m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), gpr);
m_jit.subPtr(GPRInfo::tagTypeNumberRegister, gpr);
@@ -394,9 +394,9 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
- case Int32DisplacedInJSStack:
- case DoubleDisplacedInJSStack:
+ case DisplacedInRegisterFile:
+ case Int32DisplacedInRegisterFile:
+ case DoubleDisplacedInRegisterFile:
m_jit.storePtr(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::addressFor((VirtualRegister)operands.operandForIndex(index)));
break;
@@ -427,19 +427,19 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
+ case DisplacedInRegisterFile:
m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
break;
- case Int32DisplacedInJSStack: {
+ case Int32DisplacedInRegisterFile: {
m_jit.load32(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.orPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
break;
}
- case DoubleDisplacedInJSStack: {
+ case DoubleDisplacedInRegisterFile: {
m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.subPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
@@ -455,9 +455,9 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
- case DisplacedInJSStack:
- case Int32DisplacedInJSStack:
- case DoubleDisplacedInJSStack:
+ case DisplacedInRegisterFile:
+ case Int32DisplacedInRegisterFile:
+ case DoubleDisplacedInRegisterFile:
m_jit.loadPtr(scratchDataBuffer + scratchIndex++, GPRInfo::regT0);
m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor((VirtualRegister)operands.operandForIndex(index)));
break;
@@ -553,7 +553,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
// 14) Reify inlined call frames.
ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)JSStack::CodeBlock));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
@@ -575,12 +575,12 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
} else
callerFrameGPR = GPRInfo::callFrameRegister;
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CodeBlock)));
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee->scope()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain)));
- m_jit.storePtr(callerFrameGPR, AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CallerFrame)));
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ReturnPC)));
- m_jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount)));
- m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::Callee)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CodeBlock)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee->scope()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain)));
+ m_jit.storePtr(callerFrameGPR, AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ReturnPC)));
+ m_jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ArgumentCount)));
+ m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
}
// 15) Create arguments if necessary and place them into the appropriate aliased
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index db736feeb..eaa0f47f7 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -49,7 +49,7 @@
#if ENABLE(DFG_JIT)
-#if COMPILER(GCC) && CPU(X86_64)
+#if CPU(X86_64)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
asm( \
@@ -64,7 +64,7 @@
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8)
-#elif COMPILER(GCC) && CPU(X86)
+#elif CPU(X86)
#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, offset) \
asm( \
@@ -556,7 +556,9 @@ void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSO
NativeCallFrameTracer tracer(globalData, exec);
if (index >= 0) {
- array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
+ // We should only get here if index is outside the existing vector.
+ ASSERT(!array->canSetIndexQuickly(index));
+ array->methodTable()->putByIndex(array, exec, index, JSValue::decode(encodedValue), true);
return;
}
@@ -571,7 +573,9 @@ void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec,
NativeCallFrameTracer tracer(globalData, exec);
if (index >= 0) {
- array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
+ // We should only get here if index is outside the existing vector.
+ ASSERT(!array->canSetIndexQuickly(index));
+ array->methodTable()->putByIndex(array, exec, index, JSValue::decode(encodedValue), false);
return;
}
@@ -597,16 +601,6 @@ EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
return JSValue::encode(array->pop(exec));
}
-EncodedJSValue DFG_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
-{
- JSGlobalData* globalData = &exec->globalData();
- NativeCallFrameTracer tracer(globalData, exec);
-
- array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
-
- return JSValue::encode(array->pop(exec));
-}
-
EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
{
JSGlobalData& globalData = exec->globalData();
@@ -1106,35 +1100,29 @@ EncodedJSValue DFG_OPERATION operationStrCat(ExecState* exec, void* buffer, size
return JSValue::encode(jsString(exec, static_cast<Register*>(buffer), size));
}
-char* DFG_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, 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 bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
+
+ return JSValue::encode(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
}
-char* DFG_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
+EncodedJSValue DFG_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
{
- JSGlobalData* globalData = &exec->globalData();
- NativeCallFrameTracer tracer(globalData, exec);
-
- return bitwise_cast<char*>(JSArray::create(*globalData, arrayStructure));
+ return JSValue::encode(JSArray::create(exec->globalData(), arrayStructure));
}
-char* DFG_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
+EncodedJSValue DFG_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
{
- JSGlobalData* globalData = &exec->globalData();
- NativeCallFrameTracer tracer(globalData, exec);
-
- return bitwise_cast<char*>(JSArray::create(*globalData, arrayStructure, size));
+ return JSValue::encode(JSArray::create(exec->globalData(), arrayStructure, size));
}
-char* DFG_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
+EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState* exec, size_t start, size_t size)
{
JSGlobalData& globalData = exec->globalData();
NativeCallFrameTracer tracer(&globalData, exec);
- return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
+ return JSValue::encode(constructArray(exec, exec->codeBlock()->constantBuffer(start), size));
}
EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
@@ -1321,14 +1309,6 @@ char* DFG_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState*
return reinterpret_cast<char*>(result);
}
-char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSObject* object)
-{
- JSGlobalData& globalData = exec->globalData();
- NativeCallFrameTracer tracer(&globalData, exec);
-
- return reinterpret_cast<char*>(object->ensureContiguous(globalData));
-}
-
char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSObject* object)
{
JSGlobalData& globalData = exec->globalData();
@@ -1337,16 +1317,6 @@ char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSObject* objec
return reinterpret_cast<char*>(object->ensureArrayStorage(globalData));
}
-char* DFG_OPERATION operationEnsureContiguousOrArrayStorage(ExecState* exec, JSObject* object, int32_t index)
-{
- JSGlobalData& globalData = exec->globalData();
- NativeCallFrameTracer tracer(&globalData, exec);
-
- if (static_cast<unsigned>(index) >= MIN_SPARSE_ARRAY_INDEX)
- return reinterpret_cast<char*>(object->ensureArrayStorage(globalData));
- return reinterpret_cast<char*>(object->ensureIndexedStorage(globalData));
-}
-
double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b)
{
return fmod(a, b);
@@ -1455,9 +1425,11 @@ extern "C" void DFG_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock)
#endif // ENABLE(DFG_JIT)
+#if COMPILER(GCC)
+
namespace JSC {
-#if COMPILER(GCC) && CPU(X86_64)
+#if CPU(X86_64)
asm (
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
HIDE_SYMBOL(getHostCallReturnValue) "\n"
@@ -1466,7 +1438,7 @@ SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov %r13, %rdi\n"
"jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC) && CPU(X86)
+#elif CPU(X86)
asm (
".text" "\n" \
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
@@ -1476,7 +1448,7 @@ SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov %edi, 4(%esp)\n"
"jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC) && CPU(ARM_THUMB2)
+#elif CPU(ARM_THUMB2)
asm (
".text" "\n"
".align 2" "\n"
@@ -1489,7 +1461,7 @@ SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
"mov r0, r5" "\n"
"b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
+#elif CPU(ARM_TRADITIONAL)
asm (
".text" "\n"
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
@@ -1511,4 +1483,6 @@ extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWi
} // namespace JSC
+#endif // COMPILER(GCC)
+
#endif // ENABLE(JIT)
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index b6530b755..3b947ecbf 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -77,6 +77,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);
@@ -107,13 +110,8 @@ typedef void DFG_OPERATION (*V_DFGOperation_W)(WatchpointSet*);
typedef char* DFG_OPERATION (*P_DFGOperation_E)(ExecState*);
typedef char* DFG_OPERATION (*P_DFGOperation_EO)(ExecState*, JSObject*);
typedef char* DFG_OPERATION (*P_DFGOperation_EOS)(ExecState*, JSObject*, size_t);
-typedef char* DFG_OPERATION (*P_DFGOperation_EOZ)(ExecState*, JSObject*, int32_t);
typedef char* DFG_OPERATION (*P_DFGOperation_EPS)(ExecState*, void*, size_t);
typedef char* DFG_OPERATION (*P_DFGOperation_ES)(ExecState*, size_t);
-typedef char* DFG_OPERATION (*P_DFGOperation_ESt)(ExecState*, Structure*);
-typedef char* DFG_OPERATION (*P_DFGOperation_EStPS)(ExecState*, Structure*, void*, size_t);
-typedef char* DFG_OPERATION (*P_DFGOperation_EStSS)(ExecState*, Structure*, size_t, size_t);
-typedef char* DFG_OPERATION (*P_DFGOperation_EStZ)(ExecState*, Structure*, int32_t);
// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
JSCell* DFG_OPERATION operationNewObject(ExecState*) WTF_INTERNAL;
@@ -137,10 +135,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;
-char* DFG_OPERATION operationNewArray(ExecState*, Structure*, void*, size_t) WTF_INTERNAL;
-char* DFG_OPERATION operationNewArrayBuffer(ExecState*, Structure*, size_t, size_t) WTF_INTERNAL;
-char* DFG_OPERATION operationNewEmptyArray(ExecState*, Structure*) WTF_INTERNAL;
-char* DFG_OPERATION operationNewArrayWithSize(ExecState*, Structure*, int32_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;
@@ -150,7 +148,6 @@ void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSObject
void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL;
-EncodedJSValue DFG_OPERATION operationArrayPopAndRecoverLength(ExecState*, JSArray*) WTF_INTERNAL;
EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*) WTF_INTERNAL;
@@ -195,9 +192,7 @@ char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecStat
char* DFG_OPERATION operationAllocatePropertyStorage(ExecState*, size_t newSize) WTF_INTERNAL;
char* DFG_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState*, JSObject*) WTF_INTERNAL;
char* DFG_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState*, JSObject*, size_t newSize) WTF_INTERNAL;
-char* DFG_OPERATION operationEnsureContiguous(ExecState*, JSObject*);
char* DFG_OPERATION operationEnsureArrayStorage(ExecState*, JSObject*);
-char* DFG_OPERATION operationEnsureContiguousOrArrayStorage(ExecState*, JSObject*, int32_t);
// This method is used to lookup an exception hander, keyed by faultLocation, which is
// the return location from one of the calls out to one of the helper operations above.
diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
index 6fb185c12..b05537fdf 100644
--- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp
+++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp
@@ -256,7 +256,7 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSCell::structureOffset()), scratchGPR);
stubJit.load8(MacroAssembler::Address(scratchGPR, Structure::indexingTypeOffset()), scratchGPR);
failureCases.append(stubJit.branchTest32(MacroAssembler::Zero, scratchGPR, MacroAssembler::TrustedImm32(IsArray)));
- failureCases.append(stubJit.branchTest32(MacroAssembler::Zero, scratchGPR, MacroAssembler::TrustedImm32(IndexingShapeMask)));
+ failureCases.append(stubJit.branchTest32(MacroAssembler::Zero, scratchGPR, MacroAssembler::TrustedImm32(HasArrayStorage)));
stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
stubJit.load32(MacroAssembler::Address(scratchGPR, ArrayStorage::lengthOffset()), scratchGPR);
@@ -448,7 +448,7 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi
// right now!
stubJit.store32(
MacroAssembler::TrustedImm32(exec->codeOriginIndexForDFG()),
- CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
+ CCallHelpers::tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
operationCall = stubJit.call();
#if USE(JSVALUE64)
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 850d5aa74..05b1e741e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -29,7 +29,6 @@
#if ENABLE(DFG_JIT)
#include "Arguments.h"
-#include "DFGCallArrayAllocatorSlowPathGenerator.h"
#include "DFGSlowPathGenerator.h"
#include "LinkBuffer.h"
@@ -57,37 +56,6 @@ SpeculativeJIT::~SpeculativeJIT()
WTF::deleteAllValues(m_slowPathGenerators);
}
-void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR, GPRReg storageGPR, unsigned numElements)
-{
- ASSERT(hasContiguous(structure->indexingType()));
-
- GPRTemporary scratch(this);
- GPRReg scratchGPR = scratch.gpr();
-
- unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements);
-
- JITCompiler::JumpList slowCases;
- slowCases.append(
- emitAllocateBasicStorage(TrustedImm32(vectorLength * sizeof(JSValue) + sizeof(IndexingHeader)), storageGPR));
- m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR);
- emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(
- TrustedImmPtr(structure), resultGPR, scratchGPR,
- storageGPR, sizeof(JSArray), slowCases);
-
- // I'm assuming that two 32-bit stores are better than a 64-bit store.
- // I have no idea if that's true. And it probably doesn't matter anyway.
- m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-
- // I want a slow path that also loads out the storage pointer, and that's
- // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
- // of work for a very small piece of functionality. :-/
- addSlowPathGenerator(adoptPtr(
- new CallArrayAllocatorSlowPathGenerator(
- slowCases, this, operationNewArrayWithSize, resultGPR, storageGPR,
- structure, numElements)));
-}
-
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail)
{
if (!m_compileOkay)
@@ -102,7 +70,7 @@ void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource
speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail);
}
-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, const MacroAssembler::JumpList& jumpsToFail)
+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail)
{
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
@@ -110,7 +78,7 @@ void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource
speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]);
}
-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail)
{
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail);
@@ -222,7 +190,7 @@ void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValu
convertLastOSRExitToForward(valueRecovery);
}
-void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
+void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
{
ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
@@ -327,66 +295,6 @@ const TypedArrayDescriptor* SpeculativeJIT::typedArrayDescriptor(Array::Mode arr
}
}
-JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, Array::Mode arrayMode)
-{
- JITCompiler::JumpList result;
-
- switch (arrayMode) {
- case NON_ARRAY_CONTIGUOUS_MODES: {
- m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
- result.append(
- m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(ContiguousShape)));
- break;
- }
- case ARRAY_WITH_CONTIGUOUS_MODES: {
- m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
- result.append(
- m_jit.branch32(
- MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | ContiguousShape)));
- break;
- }
- case NON_ARRAY_ARRAY_STORAGE_MODES: {
- m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
- if (isSlowPutAccess(arrayMode)) {
- m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
- result.append(
- m_jit.branch32(
- MacroAssembler::Above, tempGPR,
- TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
- } else {
- result.append(
- m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(ArrayStorageShape)));
- }
- break;
- }
- case Array::ArrayWithArrayStorage:
- case Array::ArrayWithArrayStorageToHole:
- case Array::ArrayWithArrayStorageOutOfBounds: {
- m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
- result.append(
- m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(ArrayStorageShape)));
- break;
- }
- case Array::ArrayWithSlowPutArrayStorage: {
- result.append(
- m_jit.branchTest32(
- MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)));
- m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
- m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
- result.append(
- m_jit.branch32(
- MacroAssembler::Above, tempGPR,
- TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
- break;
- }
- default:
- CRASH();
- break;
- }
-
- return result;
-}
-
void SpeculativeJIT::checkArray(Node& node)
{
ASSERT(modeIsSpecific(node.arrayMode()));
@@ -407,18 +315,39 @@ void SpeculativeJIT::checkArray(Node& node)
case Array::String:
expectedClassInfo = &JSString::s_info;
break;
- case NON_ARRAY_CONTIGUOUS_MODES:
- case ARRAY_WITH_CONTIGUOUS_MODES:
- case NON_ARRAY_ARRAY_STORAGE_MODES:
+ case NON_ARRAY_ARRAY_STORAGE_MODES: {
+ GPRTemporary temp(this);
+ m_jit.loadPtr(
+ MacroAssembler::Address(baseReg, JSCell::structureOffset()), temp.gpr());
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branchTest8(
+ MacroAssembler::Zero,
+ MacroAssembler::Address(temp.gpr(), Structure::indexingTypeOffset()),
+ MacroAssembler::TrustedImm32(
+ isSlowPutAccess(node.arrayMode()) ? (HasArrayStorage | HasSlowPutArrayStorage) : HasArrayStorage)));
+
+ noResult(m_compileIndex);
+ return;
+ }
case ARRAY_WITH_ARRAY_STORAGE_MODES: {
GPRTemporary temp(this);
GPRReg tempGPR = temp.gpr();
m_jit.loadPtr(
MacroAssembler::Address(baseReg, JSCell::structureOffset()), tempGPR);
m_jit.load8(MacroAssembler::Address(tempGPR, Structure::indexingTypeOffset()), tempGPR);
+ // FIXME: This can be turned into a single branch. But we currently have no evidence
+ // that doing so would be profitable, nor do I feel comfortable with the present test
+ // coverage for this code path.
speculationCheck(
Uncountable, JSValueRegs(), NoNode,
- jumpSlowForUnwantedArrayMode(tempGPR, node.arrayMode()));
+ m_jit.branchTest32(
+ MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)));
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branchTest32(
+ MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(
+ isSlowPutAccess(node.arrayMode()) ? (HasArrayStorage | HasSlowPutArrayStorage) : HasArrayStorage)));
noResult(m_compileIndex);
return;
@@ -455,122 +384,78 @@ void SpeculativeJIT::checkArray(Node& node)
noResult(m_compileIndex);
}
-void SpeculativeJIT::arrayify(Node& node, GPRReg baseReg, GPRReg propertyReg)
+void SpeculativeJIT::arrayify(Node& node)
{
- Array::Mode desiredArrayMode;
+ ASSERT(modeIsSpecific(node.arrayMode()));
+ ASSERT(!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode()));
- switch (node.arrayMode()) {
- case Array::ToContiguous:
- desiredArrayMode = Array::Contiguous;
- break;
- case Array::ToArrayStorage:
- desiredArrayMode = Array::ArrayStorage;
- break;
- case Array::ToSlowPutArrayStorage:
- desiredArrayMode = Array::SlowPutArrayStorage;
- break;
- case Array::ArrayToArrayStorage:
- desiredArrayMode = Array::ArrayWithArrayStorage;
- break;
- case Array::PossiblyArrayToArrayStorage:
- desiredArrayMode = Array::PossiblyArrayWithArrayStorage;
- break;
- default:
- CRASH();
- desiredArrayMode = Array::Undecided;
- break;
- }
+ SpeculateCellOperand base(this, node.child1());
+ GPRReg baseReg = base.gpr();
- GPRTemporary structure(this);
- GPRTemporary temp(this);
- GPRReg structureGPR = structure.gpr();
- GPRReg tempGPR = temp.gpr();
+ switch (node.arrayMode()) {
+ case EFFECTFUL_NON_ARRAY_ARRAY_STORAGE_MODES: {
+ GPRTemporary structure(this);
+ GPRTemporary temp(this);
+ GPRReg structureGPR = structure.gpr();
+ GPRReg tempGPR = temp.gpr();
- m_jit.loadPtr(
- MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
-
- m_jit.load8(
- MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()), tempGPR);
+ m_jit.loadPtr(
+ MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
- // We can skip all that comes next if we already have array storage.
- MacroAssembler::JumpList slowCases =
- jumpSlowForUnwantedArrayMode(tempGPR, desiredArrayMode);
+ // We can skip all that comes next if we already have array storage.
+ IndexingType desiredIndexingTypeMask =
+ isSlowPutAccess(node.arrayMode()) ? (HasArrayStorage | HasSlowPutArrayStorage) : HasArrayStorage;
+ MacroAssembler::Jump slowCase = m_jit.branchTest8(
+ MacroAssembler::Zero,
+ MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()),
+ MacroAssembler::TrustedImm32(desiredIndexingTypeMask));
- m_jit.loadPtr(
- MacroAssembler::Address(baseReg, JSObject::butterflyOffset()), tempGPR);
+ m_jit.loadPtr(
+ MacroAssembler::Address(baseReg, JSObject::butterflyOffset()), tempGPR);
- MacroAssembler::Jump done = m_jit.jump();
+ MacroAssembler::Jump done = m_jit.jump();
- slowCases.link(&m_jit);
-
- // If we're allegedly creating contiguous storage and the index is bogus, then
- // just don't.
- if (node.arrayMode() == Array::ToContiguous && propertyReg != InvalidGPRReg) {
+ slowCase.link(&m_jit);
+
+ // Next check that the object does not intercept indexed accesses. If it does,
+ // then this mode won't work.
speculationCheck(
Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(
- MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
- }
-
- // Next check that the object does not intercept indexed accesses. If it does,
- // then this mode won't work.
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branchTest8(
- MacroAssembler::NonZero,
- MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()),
- MacroAssembler::TrustedImm32(InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero)));
+ m_jit.branchTest8(
+ MacroAssembler::NonZero,
+ MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()),
+ MacroAssembler::TrustedImm32(InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero)));
- // Now call out to create the array storage.
- silentSpillAllRegisters(tempGPR);
- switch (node.arrayMode()) {
- case ALL_EFFECTFUL_CONTIGUOUS_MODES:
- callOperation(operationEnsureContiguous, tempGPR, baseReg);
- break;
- case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
+ // Now call out to create the array storage.
+ silentSpillAllRegisters(tempGPR);
callOperation(operationEnsureArrayStorage, tempGPR, baseReg);
+ silentFillAllRegisters(tempGPR);
+
+ // Alas, we need to reload the structure because silent spilling does not save
+ // temporaries. Nor would it be useful for it to do so. Either way we're talking
+ // about a load.
+ m_jit.loadPtr(
+ MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
+
+ // Finally, check that we have the kind of array storage that we wanted to get.
+ // Note that this is a backwards speculation check, which will result in the
+ // bytecode operation corresponding to this arrayification being reexecuted.
+ // That's fine, since arrayification is not user-visible.
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branchTest8(
+ MacroAssembler::Zero,
+ MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()),
+ MacroAssembler::TrustedImm32(desiredIndexingTypeMask)));
+
+ done.link(&m_jit);
+ storageResult(tempGPR, m_compileIndex);
break;
+ }
default:
- CRASH();
+ ASSERT_NOT_REACHED();
break;
}
- silentFillAllRegisters(tempGPR);
-
- // Alas, we need to reload the structure because silent spilling does not save
- // temporaries. Nor would it be useful for it to do so. Either way we're talking
- // about a load.
- m_jit.loadPtr(
- MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
-
- // Finally, check that we have the kind of array storage that we wanted to get.
- // Note that this is a backwards speculation check, which will result in the
- // bytecode operation corresponding to this arrayification being reexecuted.
- // That's fine, since arrayification is not user-visible.
- m_jit.load8(
- MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()), structureGPR);
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- jumpSlowForUnwantedArrayMode(structureGPR, desiredArrayMode));
-
- done.link(&m_jit);
- storageResult(tempGPR, m_compileIndex);
-}
-
-void SpeculativeJIT::arrayify(Node& node)
-{
- ASSERT(modeIsSpecific(node.arrayMode()));
- ASSERT(!modeAlreadyChecked(m_state.forNode(node.child1()), node.arrayMode()));
-
- SpeculateCellOperand base(this, node.child1());
-
- if (!node.child2()) {
- arrayify(node, base.gpr(), InvalidGPRReg);
- return;
- }
-
- SpeculateIntegerOperand property(this, node.child2());
-
- arrayify(node, base.gpr(), property.gpr());
}
GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
@@ -1482,7 +1367,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
for (size_t i = 0; i < m_arguments.size(); ++i) {
- ValueSource valueSource = ValueSource(ValueInJSStack);
+ ValueSource valueSource = ValueSource(ValueInRegisterFile);
m_arguments[i] = valueSource;
m_stream->appendAndLog(VariableEvent::setLocal(argumentToOperand(i), valueSource.dataFormat()));
}
@@ -1499,11 +1384,11 @@ void SpeculativeJIT::compile(BasicBlock& block)
else if (at(nodeIndex).variableAccessData()->isArgumentsAlias())
valueSource = ValueSource(ArgumentsSource);
else if (at(nodeIndex).variableAccessData()->isCaptured())
- valueSource = ValueSource(ValueInJSStack);
+ valueSource = ValueSource(ValueInRegisterFile);
else if (!at(nodeIndex).refCount())
valueSource = ValueSource(SourceIsDead);
else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
- valueSource = ValueSource(DoubleInJSStack);
+ valueSource = ValueSource(DoubleInRegisterFile);
else
valueSource = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->argumentAwarePrediction());
m_variables[i] = valueSource;
@@ -1555,25 +1440,25 @@ void SpeculativeJIT::compile(BasicBlock& block)
for (int i = 0; i < argumentCountIncludingThis; ++i) {
ValueRecovery recovery;
if (codeBlock->isCaptured(argumentToOperand(i)))
- recovery = ValueRecovery::alreadyInJSStack();
+ recovery = ValueRecovery::alreadyInRegisterFile();
else {
ArgumentPosition& argumentPosition =
m_jit.graph().m_argumentPositions[argumentPositionStart + i];
ValueSource valueSource;
if (argumentPosition.shouldUseDoubleFormat())
- valueSource = ValueSource(DoubleInJSStack);
+ valueSource = ValueSource(DoubleInRegisterFile);
else if (isInt32Speculation(argumentPosition.prediction()))
- valueSource = ValueSource(Int32InJSStack);
+ valueSource = ValueSource(Int32InRegisterFile);
else if (isCellSpeculation(argumentPosition.prediction()))
- valueSource = ValueSource(CellInJSStack);
+ valueSource = ValueSource(CellInRegisterFile);
else if (isBooleanSpeculation(argumentPosition.prediction()))
- valueSource = ValueSource(BooleanInJSStack);
+ valueSource = ValueSource(BooleanInRegisterFile);
else
- valueSource = ValueSource(ValueInJSStack);
+ valueSource = ValueSource(ValueInRegisterFile);
recovery = computeValueRecoveryFor(valueSource);
}
// The recovery should refer either to something that has already been
- // stored into the stack at the right place, or to a constant,
+ // stored into the register file at the right place, or to a constant,
// since the Arguments code isn't smart enough to handle anything else.
// The exception is the this argument, which we don't really need to be
// able to recover.
@@ -1665,9 +1550,9 @@ void SpeculativeJIT::checkArgumentTypes()
m_codeOriginForOSR = CodeOrigin(0);
for (size_t i = 0; i < m_arguments.size(); ++i)
- m_arguments[i] = ValueSource(ValueInJSStack);
+ m_arguments[i] = ValueSource(ValueInRegisterFile);
for (size_t i = 0; i < m_variables.size(); ++i)
- m_variables[i] = ValueSource(ValueInJSStack);
+ m_variables[i] = ValueSource(ValueInRegisterFile);
for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
NodeIndex nodeIndex = m_jit.graph().m_arguments[i];
@@ -1764,7 +1649,7 @@ void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
{
- if (valueSource.isInJSStack())
+ if (valueSource.isInRegisterFile())
return valueSource.valueRecovery();
ASSERT(valueSource.kind() == HaveNode);
@@ -2057,17 +1942,16 @@ void SpeculativeJIT::compileUInt32ToNumber(Node& node)
}
IntegerOperand op1(this, node.child1());
- GPRTemporary result(this); // For the benefit of OSR exit, force these to be in different registers. In reality the OSR exit compiler could find cases where you have uint32(%r1) followed by int32(%r1) and then use different registers, but that seems like too much effort.
-
- m_jit.move(op1.gpr(), result.gpr());
+ GPRTemporary result(this, op1);
// Test the operand is positive. This is a very special speculation check - we actually
// use roll-forward speculation here, where if this fails, we jump to the baseline
// instruction that follows us, rather than the one we're executing right now. We have
// to do this because by this point, the original values necessary to compile whatever
// operation the UInt32ToNumber originated from might be dead.
- forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(result.gpr()));
+ forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(op1.gpr()));
+ m_jit.move(op1.gpr(), result.gpr());
integerResult(result.gpr(), m_compileIndex, op1.format());
}
@@ -2256,7 +2140,7 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor&
m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
break;
default:
- CRASH();
+ ASSERT_NOT_REACHED();
}
if (elementSize < 4 || signedness == SignedTypedArray) {
integerResult(resultReg, m_compileIndex);
@@ -2366,7 +2250,7 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor&
m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
break;
default:
- CRASH();
+ ASSERT_NOT_REACHED();
}
if (node.op() == PutByVal)
outOfBounds.link(&m_jit);
@@ -3321,23 +3205,12 @@ void SpeculativeJIT::compileGetArrayLength(Node& node)
const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode());
switch (node.arrayMode()) {
- case ARRAY_WITH_CONTIGUOUS_MODES: {
- StorageOperand storage(this, node.child2());
- GPRTemporary result(this, storage);
- GPRReg storageReg = storage.gpr();
- GPRReg resultReg = result.gpr();
- m_jit.load32(MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()), resultReg);
-
- integerResult(resultReg, m_compileIndex);
- break;
- }
- case ARRAY_WITH_ARRAY_STORAGE_MODES:
- case ARRAY_EFFECTFUL_MODES: {
+ case ARRAY_WITH_ARRAY_STORAGE_MODES: {
StorageOperand storage(this, node.child2());
GPRTemporary result(this, storage);
GPRReg storageReg = storage.gpr();
GPRReg resultReg = result.gpr();
- m_jit.load32(MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()), resultReg);
+ m_jit.load32(MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()), resultReg);
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, MacroAssembler::TrustedImm32(0)));
@@ -3455,11 +3328,14 @@ void SpeculativeJIT::compileAllocatePropertyStorage(Node& node)
ASSERT(!node.structureTransitionData().previousStructure->outOfLineCapacity());
ASSERT(initialOutOfLineCapacity == node.structureTransitionData().newStructure->outOfLineCapacity());
-
- JITCompiler::Jump slowPath =
- emitAllocateBasicStorage(
- TrustedImm32(initialOutOfLineCapacity * sizeof(JSValue)), scratchGPR);
-
+ size_t newSize = initialOutOfLineCapacity * sizeof(JSValue);
+ CopiedAllocator* copiedAllocator = &m_jit.globalData()->heap.storageAllocator();
+
+ m_jit.loadPtr(&copiedAllocator->m_currentRemaining, scratchGPR);
+ JITCompiler::Jump slowPath = m_jit.branchSubPtr(JITCompiler::Signed, JITCompiler::TrustedImm32(newSize), scratchGPR);
+ m_jit.storePtr(scratchGPR, &copiedAllocator->m_currentRemaining);
+ m_jit.negPtr(scratchGPR);
+ m_jit.addPtr(JITCompiler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR);
m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR);
addSlowPathGenerator(
@@ -3500,9 +3376,15 @@ void SpeculativeJIT::compileReallocatePropertyStorage(Node& node)
GPRReg scratchGPR1 = scratch1.gpr();
GPRReg scratchGPR2 = scratch2.gpr();
- JITCompiler::Jump slowPath =
- emitAllocateBasicStorage(TrustedImm32(newSize), scratchGPR2);
-
+ JITCompiler::Jump slowPath;
+
+ CopiedAllocator* copiedAllocator = &m_jit.globalData()->heap.storageAllocator();
+
+ m_jit.loadPtr(&copiedAllocator->m_currentRemaining, scratchGPR2);
+ slowPath = m_jit.branchSubPtr(JITCompiler::Signed, JITCompiler::TrustedImm32(newSize), scratchGPR2);
+ m_jit.storePtr(scratchGPR2, &copiedAllocator->m_currentRemaining);
+ m_jit.negPtr(scratchGPR2);
+ m_jit.addPtr(JITCompiler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR2);
m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR2);
addSlowPathGenerator(
@@ -3517,16 +3399,6 @@ void SpeculativeJIT::compileReallocatePropertyStorage(Node& node)
storageResult(scratchGPR2, m_compileIndex);
}
-GPRReg SpeculativeJIT::temporaryRegisterForPutByVal(GPRTemporary& temporary, Array::Mode arrayMode)
-{
- if (!putByValWillNeedExtraRegister(arrayMode))
- return InvalidGPRReg;
-
- GPRTemporary realTemporary(this);
- temporary.adopt(realTemporary);
- return temporary.gpr();
-}
-
} } // namespace JSC::DFG
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 90b6d483a..15314b2f2 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -42,7 +42,6 @@
namespace JSC { namespace DFG {
-class GPRTemporary;
class JSValueOperand;
class SlowPathGenerator;
class SpeculativeJIT;
@@ -326,7 +325,7 @@ public:
// These methods are used when generating 'unexpected'
// calls out from JIT code to C++ helper routines -
// they spill all live values to the appropriate
- // slots in the JSStack without changing any state
+ // slots in the RegisterFile without changing any state
// in the GenerationInfo.
SilentRegisterSavePlan silentSavePlanForGPR(VirtualRegister spillMe, GPRReg source)
{
@@ -705,7 +704,7 @@ public:
}
#endif
- // Spill a VirtualRegister to the JSStack.
+ // Spill a VirtualRegister to the RegisterFile.
void spill(VirtualRegister spillMe)
{
GenerationInfo& info = m_generationInfo[spillMe];
@@ -715,7 +714,7 @@ public:
return;
#endif
// Check the GenerationInfo to see if this value need writing
- // to the JSStack - if not, mark it as spilled & return.
+ // to the RegisterFile - if not, mark it as spilled & return.
if (!info.needsSpill()) {
info.setSpilled(*m_stream, spillMe);
return;
@@ -830,7 +829,7 @@ public:
return &m_jit.codeBlock()->identifier(index);
}
- // Spill all VirtualRegisters back to the JSStack.
+ // Spill all VirtualRegisters back to the RegisterFile.
void flushRegisters()
{
for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
@@ -1167,11 +1166,6 @@ public:
m_jit.setupArgumentsWithExecState(object, TrustedImmPtr(size));
return appendCallWithExceptionCheckSetResult(operation, result);
}
- JITCompiler::Call callOperation(P_DFGOperation_EOZ operation, GPRReg result, GPRReg object, int32_t size)
- {
- m_jit.setupArgumentsWithExecState(object, TrustedImmPtr(size));
- return appendCallWithExceptionCheckSetResult(operation, result);
- }
JITCompiler::Call callOperation(P_DFGOperation_EPS operation, GPRReg result, GPRReg old, size_t size)
{
m_jit.setupArgumentsWithExecState(old, TrustedImmPtr(size));
@@ -1219,36 +1213,21 @@ public:
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallWithExceptionCheckSetResult(operation, result);
}
- JITCompiler::Call callOperation(P_DFGOperation_ESt operation, GPRReg result, Structure* structure)
+ JITCompiler::Call callOperation(J_DFGOperation_ESt operation, GPRReg result, Structure* structure)
{
m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
return appendCallWithExceptionCheckSetResult(operation, result);
}
- JITCompiler::Call callOperation(P_DFGOperation_EStZ operation, GPRReg result, Structure* structure, GPRReg arg2)
+ 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(P_DFGOperation_EStZ operation, GPRReg result, Structure* structure, size_t arg2)
- {
- m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(arg2));
- return appendCallWithExceptionCheckSetResult(operation, result);
- }
- JITCompiler::Call callOperation(P_DFGOperation_EStZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2);
- return appendCallWithExceptionCheckSetResult(operation, result);
- }
- JITCompiler::Call callOperation(P_DFGOperation_EStPS operation, GPRReg result, Structure* structure, void* pointer, size_t size)
+ 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(P_DFGOperation_EStSS operation, GPRReg result, Structure* structure, size_t index, size_t size)
- {
- m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(index), 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));
@@ -1489,11 +1468,6 @@ public:
m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(arg2));
return appendCallWithExceptionCheckSetResult(operation, result);
}
- JITCompiler::Call callOperation(P_DFGOperation_EOZ operation, GPRReg result, GPRReg arg1, int32_t arg2)
- {
- m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(arg2));
- return appendCallWithExceptionCheckSetResult(operation, result);
- }
JITCompiler::Call callOperation(P_DFGOperation_EPS operation, GPRReg result, GPRReg old, size_t size)
{
m_jit.setupArgumentsWithExecState(old, TrustedImmPtr(size));
@@ -1552,35 +1526,20 @@ public:
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
- JITCompiler::Call callOperation(P_DFGOperation_ESt operation, GPRReg result, Structure* structure)
+ JITCompiler::Call callOperation(J_DFGOperation_ESt operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure)
{
m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
- return appendCallWithExceptionCheckSetResult(operation, result);
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
- JITCompiler::Call callOperation(P_DFGOperation_EStZ operation, GPRReg result, Structure* structure, GPRReg arg2)
+ JITCompiler::Call callOperation(J_DFGOperation_EStI operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2);
- return appendCallWithExceptionCheckSetResult(operation, result);
- }
- JITCompiler::Call callOperation(P_DFGOperation_EStZ operation, GPRReg result, Structure* structure, size_t arg2)
- {
- m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImm32(arg2));
- return appendCallWithExceptionCheckSetResult(operation, result);
- }
- JITCompiler::Call callOperation(P_DFGOperation_EStZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2);
- return appendCallWithExceptionCheckSetResult(operation, result);
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
- JITCompiler::Call callOperation(P_DFGOperation_EStPS operation, GPRReg result, Structure* structure, void* pointer, size_t size)
+ 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, result);
- }
- JITCompiler::Call callOperation(P_DFGOperation_EStSS operation, GPRReg result, Structure* structure, size_t index, size_t size)
- {
- m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(index), TrustedImmPtr(size));
- return appendCallWithExceptionCheckSetResult(operation, result);
+ return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
{
@@ -2190,48 +2149,6 @@ public:
void compileAllocatePropertyStorage(Node&);
void compileReallocatePropertyStorage(Node&);
-#if USE(JSVALUE64)
- MacroAssembler::JumpList compileContiguousGetByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultReg);
- MacroAssembler::JumpList compileArrayStorageGetByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultReg);
-#else
- MacroAssembler::JumpList compileContiguousGetByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultTagReg, GPRReg resultPayloadReg);
- MacroAssembler::JumpList compileArrayStorageGetByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultTagReg, GPRReg resultPayloadReg);
-#endif
-
- bool putByValWillNeedExtraRegister(Array::Mode arrayMode)
- {
- switch (arrayMode) {
- // For ArrayStorage, we need an extra reg for stores to holes except if
- // we're in SlowPut mode.
- case ARRAY_STORAGE_TO_HOLE_MODES:
- case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case ALL_EFFECTFUL_ARRAY_STORAGE_MODES:
- return true;
-
- // For Contiguous, we need an extra reg for any access that may store
- // to the tail.
- case CONTIGUOUS_TO_TAIL_MODES:
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES:
- return true;
-
- default:
- return false;
- }
- }
- GPRReg temporaryRegisterForPutByVal(GPRTemporary&, Array::Mode);
- GPRReg temporaryRegisterForPutByVal(GPRTemporary& temporary, Node& node)
- {
- return temporaryRegisterForPutByVal(temporary, node.arrayMode());
- }
-#if USE(JSVALUE64)
- MacroAssembler::JumpList compileContiguousPutByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueReg, GPRReg tempReg);
- MacroAssembler::JumpList compileArrayStoragePutByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueReg, GPRReg tempReg);
-#else
- MacroAssembler::JumpList compileContiguousPutByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueTagReg, GPRReg valuePayloadReg);
- MacroAssembler::JumpList compileArrayStoragePutByVal(Node&, GPRReg baseReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueTagReg, GPRReg valuePayloadReg);
-#endif
-
void compileGetCharCodeAt(Node&);
void compileGetByValOnString(Node&);
@@ -2253,6 +2170,14 @@ public:
#endif
void compileArithMod(Node&);
void compileSoftModulo(Node&);
+ enum TypedArraySignedness {
+ SignedTypedArray,
+ UnsignedTypedArray
+ };
+ enum TypedArrayRounding {
+ TruncateRounding,
+ ClampRounding
+ };
void compileGetIndexedPropertyStorage(Node&);
void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySignedness);
void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySignedness, TypedArrayRounding = TruncateRounding);
@@ -2261,43 +2186,17 @@ public:
void compileNewFunctionNoCheck(Node&);
void compileNewFunctionExpression(Node&);
bool compileRegExpExec(Node&);
-
- // size can be an immediate or a register, and must be in bytes. If size is a register,
- // it must be a different register than resultGPR. Emits code that place a pointer to
- // the end of the allocation. The returned jump is the jump to the slow path.
- template<typename SizeType>
- MacroAssembler::Jump emitAllocateBasicStorage(SizeType size, GPRReg resultGPR)
- {
- CopiedAllocator* copiedAllocator = &m_jit.globalData()->heap.storageAllocator();
-
- m_jit.loadPtr(&copiedAllocator->m_currentRemaining, resultGPR);
- MacroAssembler::Jump slowPath = m_jit.branchSubPtr(JITCompiler::Signed, size, resultGPR);
-#if 0
- MacroAssembler::Jump done = m_jit.jump();
- slowPath1.link(&m_jit);
- m_jit.breakpoint();
- MacroAssembler::Jump slowPath = m_jit.jump();
- done.link(&m_jit);
-#endif
- m_jit.storePtr(resultGPR, &copiedAllocator->m_currentRemaining);
- m_jit.negPtr(resultGPR);
- m_jit.addPtr(JITCompiler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), resultGPR);
-
- return slowPath;
- }
-
+
// It is NOT okay for the structure and the scratch register to be the same thing because if they are then the Structure will
// get clobbered.
- template <typename ClassType, MarkedBlock::DestructorType destructorType, typename StructureType, typename StorageType>
- void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, StorageType storage, size_t size, MacroAssembler::JumpList& slowPath)
+ template <typename ClassType, bool destructor, typename StructureType>
+ void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
{
MarkedAllocator* allocator = 0;
- if (destructorType == MarkedBlock::Normal)
- allocator = &m_jit.globalData()->heap.allocatorForObjectWithNormalDestructor(size);
- else if (destructorType == MarkedBlock::ImmortalStructure)
- allocator = &m_jit.globalData()->heap.allocatorForObjectWithImmortalStructureDestructor(size);
+ if (destructor)
+ allocator = &m_jit.globalData()->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
else
- allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(size);
+ allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
m_jit.loadPtr(&allocator->m_freeList.head, resultGPR);
slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
@@ -2311,16 +2210,14 @@ public:
m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSCell::structureOffset()));
// Initialize the object's property storage pointer.
- m_jit.storePtr(storage, MacroAssembler::Address(resultGPR, JSObject::butterflyOffset()));
+ m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::butterflyOffset()));
}
template<typename T>
void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
{
- return emitAllocateBasicJSObject<JSFinalObject, MarkedBlock::None>(structure, resultGPR, scratchGPR, TrustedImmPtr(0), JSFinalObject::allocationSize(INLINE_STORAGE_CAPACITY), slowPath);
+ return emitAllocateBasicJSObject<JSFinalObject, false>(structure, resultGPR, scratchGPR, slowPath);
}
-
- void emitAllocateJSArray(Structure*, GPRReg resultGPR, GPRReg storageGPR, unsigned numElements);
#if USE(JSVALUE64)
JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);
@@ -2332,8 +2229,8 @@ public:
void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail);
void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail);
// Add a set of speculation checks without additional recovery.
- void speculationCheck(ExitKind, JSValueSource, NodeIndex, const MacroAssembler::JumpList& jumpsToFail);
- void speculationCheck(ExitKind, JSValueSource, Edge, const MacroAssembler::JumpList& jumpsToFail);
+ void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::JumpList& jumpsToFail);
+ void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::JumpList& jumpsToFail);
// Add a speculation check with additional recovery.
void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
@@ -2354,7 +2251,7 @@ public:
// Note: not specifying the valueRecovery argument (leaving it as ValueRecovery()) implies
// that you've ensured that there exists a MovHint prior to your use of forwardSpeculationCheck().
void forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& = ValueRecovery());
- void forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& = ValueRecovery());
+ void forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& = ValueRecovery());
void speculationCheckWithConditionalDirection(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, bool isForward);
// Called when we statically determine that a speculation will fail.
void terminateSpeculativeExecution(ExitKind, JSValueRegs, NodeIndex);
@@ -2367,9 +2264,7 @@ public:
const TypedArrayDescriptor* typedArrayDescriptor(Array::Mode);
- JITCompiler::JumpList jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, Array::Mode arrayMode);
void checkArray(Node&);
- void arrayify(Node&, GPRReg baseReg, GPRReg propertyReg);
void arrayify(Node&);
template<bool strict>
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 0396f8696..70709b52f 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
* Copyright (C) 2011 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,6 @@
#if ENABLE(DFG_JIT)
-#include "DFGCallArrayAllocatorSlowPathGenerator.h"
#include "DFGSlowPathGenerator.h"
#include "JSActivation.h"
@@ -1016,10 +1015,10 @@ void SpeculativeJIT::emitCall(Node& node)
// receiver (method call). subsequent children are the arguments.
int numPassedArgs = node.numChildren() - 1;
- m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(JSStack::ArgumentCount));
- m_jit.storePtr(GPRInfo::callFrameRegister, callFramePayloadSlot(JSStack::CallerFrame));
- m_jit.store32(calleePayloadGPR, callFramePayloadSlot(JSStack::Callee));
- m_jit.store32(calleeTagGPR, callFrameTagSlot(JSStack::Callee));
+ m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(RegisterFile::ArgumentCount));
+ m_jit.storePtr(GPRInfo::callFrameRegister, callFramePayloadSlot(RegisterFile::CallerFrame));
+ m_jit.store32(calleePayloadGPR, callFramePayloadSlot(RegisterFile::Callee));
+ m_jit.store32(calleeTagGPR, callFrameTagSlot(RegisterFile::Callee));
for (int i = 0; i < numPassedArgs; i++) {
Edge argEdge = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i];
@@ -1050,8 +1049,8 @@ void SpeculativeJIT::emitCall(Node& node)
slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, calleeTagGPR, TrustedImm32(JSValue::CellTag)));
m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultPayloadGPR);
- m_jit.storePtr(resultPayloadGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
- m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+ m_jit.storePtr(resultPayloadGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+ m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
JITCompiler::Call fastCall = m_jit.nearCall();
@@ -2046,113 +2045,6 @@ void SpeculativeJIT::emitBranch(Node& node)
}
}
-MacroAssembler::JumpList SpeculativeJIT::compileContiguousGetByVal(Node&, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultTagReg, GPRReg resultPayloadReg)
-{
- MacroAssembler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
- m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
- m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
- slowCases.append(m_jit.branch32(MacroAssembler::Equal, resultTagReg, TrustedImm32(JSValue::EmptyValueTag)));
-
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileArrayStorageGetByVal(Node&, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultTagReg, GPRReg resultPayloadReg)
-{
- MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
-
- m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
- m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
- MacroAssembler::Jump hole = m_jit.branch32(MacroAssembler::Equal, resultTagReg, TrustedImm32(JSValue::EmptyValueTag));
-
- MacroAssembler::JumpList slowCases;
- slowCases.append(outOfBounds);
- slowCases.append(hole);
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileContiguousPutByVal(Node& node, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueTagReg, GPRReg valuePayloadReg)
-{
- Array::Mode arrayMode = node.arrayMode();
-
- MacroAssembler::JumpList slowCases;
-
- if (!mayStoreToTail(arrayMode)) {
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
- } else {
- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
-
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength())));
-
- if (isInBoundsAccess(arrayMode))
- speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases);
-
- m_jit.add32(TrustedImm32(1), propertyReg);
- m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
- m_jit.sub32(TrustedImm32(1), propertyReg);
-
- inBounds.link(&m_jit);
- }
-
- m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
-
- if (isInBoundsAccess(arrayMode))
- return MacroAssembler::JumpList();
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileArrayStoragePutByVal(Node& node, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueTagReg, GPRReg valuePayloadReg)
-{
- Array::Mode arrayMode = node.arrayMode();
-
- MacroAssembler::JumpList slowCases;
-
- MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
- if (isInBoundsAccess(arrayMode))
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
- else
- slowCases.append(beyondArrayBounds);
-
- // Check if we're writing to a hole; if so increment m_numValuesInVector.
- if (!mayStoreToHole(arrayMode)) {
- // This is uncountable because if we take this exit, then the baseline JIT
- // will immediately count the hole store. So there is no need for exit
- // profiling.
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(MacroAssembler::Equal, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)));
- } else {
- MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
- if (isSlowPutAccess(arrayMode)) {
- // This is sort of strange. If we wanted to optimize this code path, we would invert
- // the above branch. But it's simply not worth it since this only happens if we're
- // already having a bad time.
- slowCases.append(m_jit.jump());
- } else {
- m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
-
- // If we're writing to a hole we might be growing the array;
- MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
- m_jit.add32(TrustedImm32(1), propertyReg);
- m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
- m_jit.sub32(TrustedImm32(1), propertyReg);
-
- lengthDoesNotNeedUpdate.link(&m_jit);
- }
- notHoleValue.link(&m_jit);
- }
-
- // Store the value to the array.
- m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
-
- return slowCases;
-}
-
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op();
@@ -2269,7 +2161,7 @@ void SpeculativeJIT::compile(Node& node)
// SetLocal doubles as a hint as to where a node will be stored and
// as a speculation point. So before we speculate make sure that we
// know where the child of this node needs to go in the virtual
- // stack.
+ // register file.
compileMovHint(node);
// As far as OSR is concerned, we're on the bytecode index corresponding
@@ -2298,7 +2190,7 @@ void SpeculativeJIT::compile(Node& node)
// this SetLocal should not have executed. But for op_post_inc, it's just
// fine, because this SetLocal's local (i.e. the LHS in a x = y++
// statement) would be dead anyway - so the fact that DFG would have
- // already made the assignment, and baked it into the stack during
+ // already made the assignment, and baked it into the register file during
// OSR exit, would not be visible to the old JIT in any way.
m_codeOriginForOSR = nextNode->codeOrigin;
@@ -2308,9 +2200,9 @@ void SpeculativeJIT::compile(Node& node)
m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
// Indicate that it's no longer necessary to retrieve the value of
- // this bytecode variable from registers or other locations in the stack,
+ // this bytecode variable from registers or other locations in the register file,
// but that it is stored as a double.
- recordSetLocal(node.local(), ValueSource(DoubleInJSStack));
+ recordSetLocal(node.local(), ValueSource(DoubleInRegisterFile));
break;
}
SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
@@ -2318,14 +2210,14 @@ void SpeculativeJIT::compile(Node& node)
DoubleOperand value(this, node.child1());
m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(DoubleInJSStack));
+ recordSetLocal(node.local(), ValueSource(DoubleInRegisterFile));
break;
}
if (isInt32Speculation(predictedType)) {
SpeculateIntegerOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(Int32InJSStack));
+ recordSetLocal(node.local(), ValueSource(Int32InRegisterFile));
break;
}
if (isCellSpeculation(predictedType)) {
@@ -2333,14 +2225,14 @@ void SpeculativeJIT::compile(Node& node)
GPRReg cellGPR = cell.gpr();
m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(CellInJSStack));
+ recordSetLocal(node.local(), ValueSource(CellInRegisterFile));
break;
}
if (isBooleanSpeculation(predictedType)) {
SpeculateBooleanOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(BooleanInJSStack));
+ recordSetLocal(node.local(), ValueSource(BooleanInRegisterFile));
break;
}
}
@@ -2348,7 +2240,7 @@ void SpeculativeJIT::compile(Node& node)
m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node.local()));
m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(ValueInJSStack));
+ recordSetLocal(node.local(), ValueSource(ValueInRegisterFile));
// If we're storing an arguments object that has been optimized away,
// our variable event stream for OSR exit now reflects the optimized
@@ -2673,55 +2565,6 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
break;
}
- case IN_BOUNDS_CONTIGUOUS_MODES: {
- SpeculateStrictInt32Operand property(this, node.child2());
- StorageOperand storage(this, node.child3());
-
- GPRReg propertyReg = property.gpr();
- GPRReg storageReg = storage.gpr();
-
- if (!m_compileOkay)
- return;
-
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
- GPRTemporary resultTag(this);
- GPRTemporary resultPayload(this);
- m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
- m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
- jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
- break;
- }
- case CONTIGUOUS_TO_TAIL_MODES:
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES: {
- SpeculateCellOperand base(this, node.child1());
- SpeculateStrictInt32Operand property(this, node.child2());
- StorageOperand storage(this, node.child3());
-
- GPRReg baseReg = base.gpr();
- GPRReg propertyReg = property.gpr();
- GPRReg storageReg = storage.gpr();
-
- if (!m_compileOkay)
- return;
-
- GPRTemporary resultTag(this);
- GPRTemporary resultPayload(this);
- GPRReg resultTagReg = resultTag.gpr();
- GPRReg resultPayloadReg = resultPayload.gpr();
-
- MacroAssembler::JumpList slowCases =
- compileContiguousGetByVal(node, baseReg, propertyReg, storageReg, resultTagReg, resultPayloadReg);
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this, operationGetByValArrayInt,
- JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
-
- jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex);
- break;
- }
case IN_BOUNDS_ARRAY_STORAGE_MODES: {
SpeculateStrictInt32Operand property(this, node.child2());
StorageOperand storage(this, node.child3());
@@ -2744,7 +2587,6 @@ void SpeculativeJIT::compile(Node& node)
break;
}
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case SLOW_PUT_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES: {
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
@@ -2872,55 +2714,6 @@ void SpeculativeJIT::compile(Node& node)
GPRReg propertyReg = property.gpr();
switch (arrayMode) {
- case ALL_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES: {
- JSValueOperand value(this, child3);
-
- GPRReg valueTagReg = value.tagGPR();
- GPRReg valuePayloadReg = value.payloadGPR();
-
- if (!m_compileOkay)
- return;
-
- if (Heap::isWriteBarrierEnabled()) {
- GPRTemporary scratch(this);
- writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratch.gpr());
- }
-
- StorageOperand storage(this, child4);
- GPRReg storageReg = storage.gpr();
-
- if (node.op() == PutByValAlias) {
- // Store the value to the array.
- GPRReg propertyReg = property.gpr();
- m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
-
- noResult(m_compileIndex);
- break;
- }
-
- MacroAssembler::JumpList slowCases =
- compileContiguousPutByVal(
- node, baseReg, propertyReg, storageReg, valueTagReg, valuePayloadReg);
-
- base.use();
- property.use();
- value.use();
- storage.use();
-
- if (!slowCases.empty()) {
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this,
- m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
- NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
- }
-
- noResult(m_compileIndex, UseChildrenCalledExplicitly);
- break;
- }
-
case ALL_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES: {
JSValueOperand value(this, child3);
@@ -2950,23 +2743,61 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- MacroAssembler::JumpList slowCases =
- compileArrayStoragePutByVal(
- node, baseReg, propertyReg, storageReg, valueTagReg, valuePayloadReg);
+ MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
+ if (isInBoundsAccess(node.arrayMode()))
+ speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
+
+ // Check if we're writing to a hole; if so increment m_numValuesInVector.
+ MacroAssembler::Jump isHoleValue;
+ if (!mayStoreToHole(arrayMode)) {
+ // This is uncountable because if we take this exit, then the baseline JIT
+ // will immediately count the hole store. So there is no need for exit
+ // profiling.
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branch32(MacroAssembler::Equal, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)));
+ } else {
+ MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
+ if (isSlowPutAccess(arrayMode)) {
+ // This is sort of strange. If we wanted to optimize this code path, we would invert
+ // the above branch. But it's simply not worth it since this only happens if we're
+ // already having a bad time.
+ isHoleValue = m_jit.jump();
+ } else {
+ m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+
+ // If we're writing to a hole we might be growing the array;
+ MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
+ m_jit.add32(TrustedImm32(1), propertyReg);
+ m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
+ m_jit.sub32(TrustedImm32(1), propertyReg);
+
+ lengthDoesNotNeedUpdate.link(&m_jit);
+ }
+ notHoleValue.link(&m_jit);
+ }
base.use();
property.use();
value.use();
storage.use();
-
- if (!slowCases.empty()) {
+
+ // Store the value to the array.
+ m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+
+ if (!isInBoundsAccess(arrayMode)) {
+ MacroAssembler::JumpList slowCases;
+ slowCases.append(beyondArrayBounds);
+ if (isSlowPutAccess(arrayMode))
+ slowCases.append(isHoleValue);
addSlowPathGenerator(
slowPathCall(
slowCases, this,
m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
}
-
+
noResult(m_compileIndex, UseChildrenCalledExplicitly);
break;
}
@@ -3088,55 +2919,25 @@ void SpeculativeJIT::compile(Node& node)
StorageOperand storage(this, node.child3());
GPRReg storageGPR = storage.gpr();
+
+ m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
- switch (node.arrayMode()) {
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds: {
- m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
- m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
-
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationArrayPush,
- JSValueRegs(storageGPR, storageLengthGPR),
- valueTagGPR, valuePayloadGPR, baseGPR));
-
- jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
- break;
- }
-
- case Array::ArrayWithArrayStorage:
- case Array::ArrayWithArrayStorageOutOfBounds: {
- m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
-
- // Refuse to handle bizarre lengths.
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
+ // Refuse to handle bizarre lengths.
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
- m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+ m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
- m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
- m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
+ m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+ m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
- addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR), valueTagGPR, valuePayloadGPR, baseGPR));
+ addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR), valueTagGPR, valuePayloadGPR, baseGPR));
- jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
- break;
- }
-
- default:
- CRASH();
- break;
- }
+ jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
break;
}
@@ -3147,88 +2948,46 @@ void SpeculativeJIT::compile(Node& node)
StorageOperand storage(this, node.child2());
GPRTemporary valueTag(this);
GPRTemporary valuePayload(this);
+ GPRTemporary storageLength(this);
GPRReg baseGPR = base.gpr();
GPRReg valueTagGPR = valueTag.gpr();
GPRReg valuePayloadGPR = valuePayload.gpr();
GPRReg storageGPR = storage.gpr();
+ GPRReg storageLengthGPR = storageLength.gpr();
- switch (node.arrayMode()) {
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds: {
- m_jit.load32(
- MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valueTagGPR);
- MacroAssembler::Jump undefinedCase =
- m_jit.branchTest32(MacroAssembler::Zero, valueTagGPR);
- m_jit.sub32(TrustedImm32(1), valueTagGPR);
- m_jit.store32(
- valueTagGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.load32(
- MacroAssembler::BaseIndex(storageGPR, valueTagGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
- valuePayloadGPR);
- m_jit.load32(
- MacroAssembler::BaseIndex(storageGPR, valueTagGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
- valueTagGPR);
- MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
-
- addSlowPathGenerator(
- slowPathMove(
- undefinedCase, this,
- MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
- MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
- addSlowPathGenerator(
- slowPathCall(
- slowCase, this, operationArrayPopAndRecoverLength,
- JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
-
- jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex);
- break;
- }
-
- case Array::ArrayWithArrayStorage:
- case Array::ArrayWithArrayStorageOutOfBounds: {
- GPRTemporary storageLength(this);
- GPRReg storageLengthGPR = storageLength.gpr();
-
- m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
+ m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
- JITCompiler::JumpList setUndefinedCases;
- setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
+ JITCompiler::JumpList setUndefinedCases;
+ setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
- m_jit.sub32(TrustedImm32(1), storageLengthGPR);
+ m_jit.sub32(TrustedImm32(1), storageLengthGPR);
- MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
+ MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
- m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
- m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
+ m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
+ m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
- setUndefinedCases.append(m_jit.branch32(MacroAssembler::Equal, TrustedImm32(JSValue::EmptyValueTag), valueTagGPR));
+ setUndefinedCases.append(m_jit.branch32(MacroAssembler::Equal, TrustedImm32(JSValue::EmptyValueTag), valueTagGPR));
- m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+ m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+ m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
- addSlowPathGenerator(
- slowPathMove(
- setUndefinedCases, this,
- MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
- MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
+ addSlowPathGenerator(
+ slowPathMove(
+ setUndefinedCases, this,
+ MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
+ MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
- addSlowPathGenerator(
- slowPathCall(
- slowCase, this, operationArrayPop,
- JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
+ addSlowPathGenerator(
+ slowPathCall(
+ slowCase, this, operationArrayPop,
+ JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
- jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex);
- break;
- }
-
- default:
- CRASH();
- break;
- }
+ jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex);
break;
}
@@ -3292,9 +3051,9 @@ void SpeculativeJIT::compile(Node& node)
}
// Grab the return address.
- m_jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT2);
+ m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT2);
// Restore our caller's "r".
- m_jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
+ m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
// Return.
m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT2);
m_jit.ret();
@@ -3404,48 +3163,16 @@ void SpeculativeJIT::compile(Node& node)
case NewArray: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime()) {
+ if (!globalObject->isHavingABadTime())
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
-
- ASSERT(hasContiguous(globalObject->arrayStructure()->indexingType()));
-
- unsigned numElements = node.numChildren();
-
- GPRTemporary result(this);
- GPRTemporary storage(this);
-
- GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
-
- emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
-
- // At this point, one way or another, resultGPR and storageGPR have pointers to
- // the JSArray and the Butterfly, respectively.
-
- 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();
- m_jit.store32(opTagGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(opPayloadGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- }
-
- // Yuck, we should *really* have a way of also returning the storageGPR. But
- // that's the least of what's wrong with this code. We really shouldn't be
- // allocating the array after having computed - and probably spilled to the
- // stack - all of the things that will go into the array. The solution to that
- // bigger problem will also likely fix the redundancy in reloading the storage
- // pointer that we currently have.
-
- cellResult(resultGPR, m_compileIndex);
- break;
- }
if (!node.numChildren()) {
flushRegisters();
GPRResult result(this);
+ GPRResult2 resultTagIgnored(this);
callOperation(
- operationNewEmptyArray, result.gpr(), globalObject->arrayStructure());
+ operationNewEmptyArray, resultTagIgnored.gpr(), result.gpr(),
+ globalObject->arrayStructure());
cellResult(result.gpr(), m_compileIndex);
break;
}
@@ -3474,10 +3201,11 @@ void SpeculativeJIT::compile(Node& node)
m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
}
- GPRResult result(this);
+ GPRResult resultPayload(this);
+ GPRResult2 resultTag(this);
callOperation(
- operationNewArray, result.gpr(), globalObject->arrayStructure(),
+ operationNewArray, resultTag.gpr(), resultPayload.gpr(), globalObject->arrayStructure(),
static_cast<void *>(buffer), node.numChildren());
if (scratchSize) {
@@ -3487,94 +3215,37 @@ void SpeculativeJIT::compile(Node& node)
m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
}
- cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
+ // 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 NewArrayWithSize: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime()) {
+ if (!globalObject->isHavingABadTime())
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
-
- SpeculateStrictInt32Operand size(this, node.child1());
- GPRTemporary result(this);
- GPRTemporary storage(this);
- GPRTemporary scratch(this);
-
- GPRReg sizeGPR = size.gpr();
- GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
- GPRReg scratchGPR = scratch.gpr();
-
- MacroAssembler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
-
- ASSERT((1 << 3) == sizeof(JSValue));
- m_jit.move(sizeGPR, scratchGPR);
- m_jit.lshift32(TrustedImm32(3), scratchGPR);
- m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
- slowCases.append(
- emitAllocateBasicStorage(resultGPR, storageGPR));
- m_jit.subPtr(scratchGPR, storageGPR);
- emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(
- TrustedImmPtr(globalObject->arrayStructure()), resultGPR, scratchGPR,
- storageGPR, sizeof(JSArray), slowCases);
-
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-
- addSlowPathGenerator(adoptPtr(
- new CallArrayAllocatorWithVariableSizeSlowPathGenerator(
- slowCases, this, operationNewArrayWithSize, resultGPR,
- globalObject->arrayStructure(),
- globalObject->arrayStructureWithArrayStorage(),
- sizeGPR)));
-
- cellResult(resultGPR, m_compileIndex);
- break;
- }
SpeculateStrictInt32Operand size(this, node.child1());
GPRReg sizeGPR = size.gpr();
flushRegisters();
GPRResult result(this);
+ GPRResult2 resultTagIgnored(this);
callOperation(
- operationNewArrayWithSize, result.gpr(), globalObject->arrayStructure(), sizeGPR);
+ operationNewArrayWithSize, resultTagIgnored.gpr(), result.gpr(),
+ globalObject->arrayStructure(), sizeGPR);
cellResult(result.gpr(), m_compileIndex);
break;
}
case NewArrayBuffer: {
- JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime()) {
- globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
-
- unsigned numElements = node.numConstants();
-
- GPRTemporary result(this);
- GPRTemporary storage(this);
-
- GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
-
- emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
-
- int32_t* data = bitwise_cast<int32_t*>(m_jit.codeBlock()->constantBuffer(node.startConstant()));
- for (unsigned index = 0; index < node.numConstants() * 2; ++index) {
- m_jit.store32(
- Imm32(data[index]), MacroAssembler::Address(storageGPR, sizeof(int32_t) * index));
- }
-
- cellResult(resultGPR, m_compileIndex);
- break;
- }
-
flushRegisters();
- GPRResult result(this);
+ GPRResult resultPayload(this);
+ GPRResult2 resultTag(this);
- callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructure(), node.startConstant(), node.numConstants());
+ callOperation(operationNewArrayBuffer, resultTag.gpr(), resultPayload.gpr(), node.startConstant(), node.numConstants());
- cellResult(result.gpr(), m_compileIndex);
+ // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
+ cellResult(resultPayload.gpr(), m_compileIndex);
break;
}
@@ -3695,7 +3366,7 @@ void SpeculativeJIT::compile(Node& node)
case GetCallee: {
GPRTemporary result(this);
- m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(JSStack::Callee)), result.gpr());
+ m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr());
cellResult(result.gpr(), m_compileIndex);
break;
}
@@ -3704,7 +3375,7 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(JSStack::ScopeChain)), resultGPR);
+ m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::ScopeChain)), resultGPR);
bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
int skip = node.scopeChainDepth();
ASSERT(skip || !checkTopLevel);
@@ -4333,14 +4004,14 @@ void SpeculativeJIT::compile(Node& node)
m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::butterflyOffset()), resultPayloadGPR);
m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR);
#if DFG_ENABLE(JIT_ASSERT)
- JITCompiler::Jump isOutOfLine = m_jit.branch32(JITCompiler::GreaterThanOrEqual, resolveInfoGPR, TrustedImm32(firstOutOfLineOffset));
+ JITCompiler::Jump isOutOfLine = m_jit.branch32(JITCompiler::GreaterThanOrEqual, resolveInfoGPR, TrustedImm32(inlineStorageCapacity));
m_jit.breakpoint();
isOutOfLine.link(&m_jit);
#endif
m_jit.neg32(resolveInfoGPR);
m_jit.signExtend32ToPtr(resolveInfoGPR, resolveInfoGPR);
- m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) + (firstOutOfLineOffset - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultTagGPR);
- m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) + (firstOutOfLineOffset - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultPayloadGPR);
+ m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) + (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultTagGPR);
+ m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) + (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultPayloadGPR);
addSlowPathGenerator(
slowPathCall(
@@ -4490,7 +4161,7 @@ void SpeculativeJIT::compile(Node& node)
}
ASSERT(!node.codeOrigin.inlineCallFrame);
- m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR);
+ m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultGPR);
m_jit.sub32(TrustedImm32(1), resultGPR);
integerResult(resultGPR, m_compileIndex);
break;
@@ -4512,7 +4183,7 @@ void SpeculativeJIT::compile(Node& node)
Imm32(node.codeOrigin.inlineCallFrame->arguments.size() - 1),
resultPayloadGPR);
} else {
- m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultPayloadGPR);
+ m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultPayloadGPR);
m_jit.sub32(TrustedImm32(1), resultPayloadGPR);
}
m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
@@ -4565,7 +4236,7 @@ void SpeculativeJIT::compile(Node& node)
m_jit.branch32(
JITCompiler::AboveOrEqual,
resultPayloadGPR,
- JITCompiler::payloadFor(JSStack::ArgumentCount)));
+ JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
}
JITCompiler::JumpList slowArgument;
@@ -4642,7 +4313,7 @@ void SpeculativeJIT::compile(Node& node)
m_jit.branch32(
JITCompiler::AboveOrEqual,
resultPayloadGPR,
- JITCompiler::payloadFor(JSStack::ArgumentCount)));
+ JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
}
JITCompiler::JumpList slowArgument;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 0928dfa58..d7cec27c1 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -29,7 +29,6 @@
#if ENABLE(DFG_JIT)
#include "Arguments.h"
-#include "DFGCallArrayAllocatorSlowPathGenerator.h"
#include "DFGSlowPathGenerator.h"
namespace JSC { namespace DFG {
@@ -73,7 +72,7 @@ GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat
}
// Since we statically know that we're filling an integer, and values
- // in the JSStack are boxed, this must be DataFormatJSInteger.
+ // in the RegisterFile are boxed, this must be DataFormatJSInteger.
// We will check this with a jitAssert below.
info.fillJSValue(*m_stream, gpr, DataFormatJSInteger);
unlock(gpr);
@@ -1006,9 +1005,9 @@ void SpeculativeJIT::emitCall(Node& node)
// arguments.
int numPassedArgs = node.numChildren() - 1;
- m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(JSStack::ArgumentCount));
- m_jit.storePtr(GPRInfo::callFrameRegister, callFrameSlot(JSStack::CallerFrame));
- m_jit.storePtr(calleeGPR, callFrameSlot(JSStack::Callee));
+ m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(RegisterFile::ArgumentCount));
+ m_jit.storePtr(GPRInfo::callFrameRegister, callFrameSlot(RegisterFile::CallerFrame));
+ m_jit.storePtr(calleeGPR, callFrameSlot(RegisterFile::Callee));
for (int i = 0; i < numPassedArgs; i++) {
Edge argEdge = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i];
@@ -1034,7 +1033,7 @@ void SpeculativeJIT::emitCall(Node& node)
slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultGPR);
- m_jit.storePtr(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain));
+ m_jit.storePtr(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain));
CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
JITCompiler::Call fastCall = m_jit.nearCall();
@@ -2110,111 +2109,10 @@ void SpeculativeJIT::emitBranch(Node& node)
}
}
-MacroAssembler::JumpList SpeculativeJIT::compileContiguousGetByVal(Node&, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultReg)
-{
- MacroAssembler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
- m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr), resultReg);
- slowCases.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultReg));
-
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileArrayStorageGetByVal(Node&, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultReg)
-{
- MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
-
- m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
- MacroAssembler::Jump hole = m_jit.branchTestPtr(MacroAssembler::Zero, resultReg);
-
- MacroAssembler::JumpList slowCases;
- slowCases.append(outOfBounds);
- slowCases.append(hole);
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileContiguousPutByVal(Node& node, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueReg, GPRReg tempReg)
-{
- Array::Mode arrayMode = node.arrayMode();
-
- MacroAssembler::JumpList slowCases;
-
- if (!mayStoreToTail(arrayMode)) {
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
- } else {
- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
-
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength())));
-
- if (isInBoundsAccess(arrayMode))
- speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases);
-
- m_jit.add32(TrustedImm32(1), propertyReg, tempReg);
- m_jit.store32(tempReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
-
- inBounds.link(&m_jit);
- }
-
- m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr));
-
- if (isInBoundsAccess(arrayMode))
- return MacroAssembler::JumpList();
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileArrayStoragePutByVal(Node& node, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueReg, GPRReg tempReg)
-{
- Array::Mode arrayMode = node.arrayMode();
-
- MacroAssembler::JumpList slowCases;
-
- MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
- if (isInBoundsAccess(arrayMode))
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
- else
- slowCases.append(beyondArrayBounds);
-
- // Check if we're writing to a hole; if so increment m_numValuesInVector.
- if (!mayStoreToHole(arrayMode)) {
- // This is uncountable because if we take this exit, then the baseline JIT
- // will immediately count the hole store. So there is no need for exit
- // profiling.
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branchTestPtr(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
- } else {
- MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
- if (isSlowPutAccess(arrayMode)) {
- // This is sort of strange. If we wanted to optimize this code path, we would invert
- // the above branch. But it's simply not worth it since this only happens if we're
- // already having a bad time.
- slowCases.append(m_jit.jump());
- } else {
- m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
-
- // If we're writing to a hole we might be growing the array;
- MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
- m_jit.add32(TrustedImm32(1), propertyReg, tempReg);
- m_jit.store32(tempReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
-
- lengthDoesNotNeedUpdate.link(&m_jit);
- }
- notHoleValue.link(&m_jit);
- }
-
- // Store the value to the array.
- m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
-
- return slowCases;
-}
-
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op();
-
+
switch (op) {
case JSConstant:
initConstantInfo(m_compileIndex);
@@ -2304,7 +2202,7 @@ void SpeculativeJIT::compile(Node& node)
// SetLocal doubles as a hint as to where a node will be stored and
// as a speculation point. So before we speculate make sure that we
// know where the child of this node needs to go in the virtual
- // stack.
+ // register file.
compileMovHint(node);
// As far as OSR is concerned, we're on the bytecode index corresponding
@@ -2333,7 +2231,7 @@ void SpeculativeJIT::compile(Node& node)
// this SetLocal should not have executed. But for op_post_inc, it's just
// fine, because this SetLocal's local (i.e. the LHS in a x = y++
// statement) would be dead anyway - so the fact that DFG would have
- // already made the assignment, and baked it into the stack during
+ // already made the assignment, and baked it into the register file during
// OSR exit, would not be visible to the old JIT in any way.
m_codeOriginForOSR = nextNode->codeOrigin;
@@ -2343,9 +2241,9 @@ void SpeculativeJIT::compile(Node& node)
m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
// Indicate that it's no longer necessary to retrieve the value of
- // this bytecode variable from registers or other locations in the stack,
+ // this bytecode variable from registers or other locations in the register file,
// but that it is stored as a double.
- recordSetLocal(node.local(), ValueSource(DoubleInJSStack));
+ recordSetLocal(node.local(), ValueSource(DoubleInRegisterFile));
break;
}
@@ -2354,7 +2252,7 @@ void SpeculativeJIT::compile(Node& node)
SpeculateIntegerOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(Int32InJSStack));
+ recordSetLocal(node.local(), ValueSource(Int32InRegisterFile));
break;
}
if (isCellSpeculation(predictedType)) {
@@ -2362,14 +2260,14 @@ void SpeculativeJIT::compile(Node& node)
GPRReg cellGPR = cell.gpr();
m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(CellInJSStack));
+ recordSetLocal(node.local(), ValueSource(CellInRegisterFile));
break;
}
if (isBooleanSpeculation(predictedType)) {
SpeculateBooleanOperand boolean(this, node.child1());
m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(BooleanInJSStack));
+ recordSetLocal(node.local(), ValueSource(BooleanInRegisterFile));
break;
}
}
@@ -2378,7 +2276,7 @@ void SpeculativeJIT::compile(Node& node)
m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
- recordSetLocal(node.local(), ValueSource(ValueInJSStack));
+ recordSetLocal(node.local(), ValueSource(ValueInRegisterFile));
// If we're storing an arguments object that has been optimized away,
// our variable event stream for OSR exit now reflects the optimized
@@ -2697,51 +2595,6 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(result.gpr(), m_compileIndex);
break;
}
- case IN_BOUNDS_CONTIGUOUS_MODES: {
- SpeculateStrictInt32Operand property(this, node.child2());
- StorageOperand storage(this, node.child3());
-
- GPRReg propertyReg = property.gpr();
- GPRReg storageReg = storage.gpr();
-
- if (!m_compileOkay)
- return;
-
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
- GPRTemporary result(this);
- m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr), result.gpr());
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
- jsValueResult(result.gpr(), m_compileIndex);
- break;
- }
- case CONTIGUOUS_TO_TAIL_MODES:
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES: {
- SpeculateCellOperand base(this, node.child1());
- SpeculateStrictInt32Operand property(this, node.child2());
- StorageOperand storage(this, node.child3());
-
- GPRReg baseReg = base.gpr();
- GPRReg propertyReg = property.gpr();
- GPRReg storageReg = storage.gpr();
-
- if (!m_compileOkay)
- return;
-
- GPRTemporary result(this);
- GPRReg resultReg = result.gpr();
-
- MacroAssembler::JumpList slowCases =
- compileContiguousGetByVal(node, baseReg, propertyReg, storageReg, resultReg);
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this, operationGetByValArrayInt,
- result.gpr(), baseReg, propertyReg));
-
- jsValueResult(resultReg, m_compileIndex);
- break;
- }
case IN_BOUNDS_ARRAY_STORAGE_MODES: {
SpeculateStrictInt32Operand property(this, node.child2());
StorageOperand storage(this, node.child3());
@@ -2762,7 +2615,6 @@ void SpeculativeJIT::compile(Node& node)
break;
}
case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case SLOW_PUT_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES: {
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
@@ -2775,17 +2627,21 @@ void SpeculativeJIT::compile(Node& node)
if (!m_compileOkay)
return;
- GPRTemporary result(this);
- GPRReg resultReg = result.gpr();
+ MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
- MacroAssembler::JumpList slowCases =
- compileArrayStorageGetByVal(node, baseReg, propertyReg, storageReg, resultReg);
+ GPRTemporary result(this);
+ m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
+ MacroAssembler::Jump hole = m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr());
+
+ MacroAssembler::JumpList slowCases;
+ slowCases.append(outOfBounds);
+ slowCases.append(hole);
addSlowPathGenerator(
slowPathCall(
slowCases, this, operationGetByValArrayInt,
result.gpr(), baseReg, propertyReg));
- jsValueResult(resultReg, m_compileIndex);
+ jsValueResult(result.gpr(), m_compileIndex);
break;
}
case Array::String:
@@ -2879,57 +2735,6 @@ void SpeculativeJIT::compile(Node& node)
GPRReg propertyReg = property.gpr();
switch (arrayMode) {
- case ALL_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES: {
- JSValueOperand value(this, child3);
-
- GPRReg valueReg = value.gpr();
-
- if (!m_compileOkay)
- return;
-
- if (Heap::isWriteBarrierEnabled()) {
- GPRTemporary scratch(this);
- writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr());
- }
-
- StorageOperand storage(this, child4);
- GPRReg storageReg = storage.gpr();
-
- if (node.op() == PutByValAlias) {
- // Store the value to the array.
- GPRReg propertyReg = property.gpr();
- GPRReg valueReg = value.gpr();
- m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr));
-
- noResult(m_compileIndex);
- break;
- }
-
- GPRTemporary temporary;
- GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
-
- MacroAssembler::JumpList slowCases =
- compileContiguousPutByVal(
- node, baseReg, propertyReg, storageReg, valueReg, temporaryReg);
-
- base.use();
- property.use();
- value.use();
- storage.use();
-
- if (!slowCases.empty()) {
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this,
- m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
- NoResult, baseReg, propertyReg, valueReg));
- }
-
- noResult(m_compileIndex, UseChildrenCalledExplicitly);
- break;
- }
-
case ALL_ARRAY_STORAGE_MODES:
case ALL_EFFECTFUL_ARRAY_STORAGE_MODES: {
JSValueOperand value(this, child3);
@@ -2957,19 +2762,53 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- GPRTemporary temporary;
- GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
-
- MacroAssembler::JumpList slowCases =
- compileArrayStoragePutByVal(
- node, baseReg, propertyReg, storageReg, valueReg, temporaryReg);
-
+ MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
+ if (isInBoundsAccess(arrayMode))
+ speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
+
+ // Check if we're writing to a hole; if so increment m_numValuesInVector.
+ MacroAssembler::Jump isHoleValue;
+ if (!mayStoreToHole(arrayMode)) {
+ // This is uncountable because if we take this exit, then the baseline JIT
+ // will immediately count the hole store. So there is no need for exit
+ // profiling.
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branchTestPtr(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
+ } else {
+ MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+ if (isSlowPutAccess(arrayMode)) {
+ // This is sort of strange. If we wanted to optimize this code path, we would invert
+ // the above branch. But it's simply not worth it since this only happens if we're
+ // already having a bad time.
+ isHoleValue = m_jit.jump();
+ } else {
+ m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+
+ // If we're writing to a hole we might be growing the array;
+ MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
+ m_jit.add32(TrustedImm32(1), propertyReg);
+ m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
+ m_jit.sub32(TrustedImm32(1), propertyReg);
+
+ lengthDoesNotNeedUpdate.link(&m_jit);
+ }
+ notHoleValue.link(&m_jit);
+ }
+
base.use();
property.use();
value.use();
storage.use();
-
- if (!slowCases.empty()) {
+
+ // Store the value to the array.
+ m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+
+ if (!isInBoundsAccess(arrayMode)) {
+ MacroAssembler::JumpList slowCases;
+ slowCases.append(beyondArrayBounds);
+ if (isSlowPutAccess(arrayMode))
+ slowCases.append(isHoleValue);
addSlowPathGenerator(
slowPathCall(
slowCases, this,
@@ -3134,54 +2973,26 @@ void SpeculativeJIT::compile(Node& node)
StorageOperand storage(this, node.child3());
GPRReg storageGPR = storage.gpr();
- switch (node.arrayMode()) {
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds: {
- m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
- m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr));
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
-
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
- valueGPR, baseGPR));
-
- jsValueResult(storageLengthGPR, m_compileIndex);
- break;
- }
-
- case Array::ArrayWithArrayStorage:
- case Array::ArrayWithArrayStorageOutOfBounds: {
- m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
+ m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
- // Refuse to handle bizarre lengths.
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
+ // Refuse to handle bizarre lengths.
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
- MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
+ MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
- m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+ m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
- m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
- m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
+ m_jit.add32(TrustedImm32(1), storageLengthGPR);
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
+ m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+ m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
- valueGPR, baseGPR));
+ addSlowPathGenerator(
+ slowPathCall(
+ slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
+ valueGPR, baseGPR));
- jsValueResult(storageLengthGPR, m_compileIndex);
- break;
- }
-
- default:
- CRASH();
- break;
- }
+ jsValueResult(storageLengthGPR, m_compileIndex);
break;
}
@@ -3191,77 +3002,41 @@ void SpeculativeJIT::compile(Node& node)
SpeculateCellOperand base(this, node.child1());
StorageOperand storage(this, node.child2());
GPRTemporary value(this);
+ GPRTemporary storageLength(this);
GPRReg baseGPR = base.gpr();
GPRReg storageGPR = storage.gpr();
GPRReg valueGPR = value.gpr();
+ GPRReg storageLengthGPR = storageLength.gpr();
- switch (node.arrayMode()) {
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds: {
- m_jit.load32(
- MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valueGPR);
- MacroAssembler::Jump undefinedCase =
- m_jit.branchTest32(MacroAssembler::Zero, valueGPR);
- m_jit.sub32(TrustedImm32(1), valueGPR);
- m_jit.store32(
- valueGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.loadPtr(
- MacroAssembler::BaseIndex(storageGPR, valueGPR, MacroAssembler::ScalePtr),
- valueGPR);
- MacroAssembler::Jump slowCase = m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
-
- addSlowPathGenerator(
- slowPathMove(
- undefinedCase, this,
- MacroAssembler::TrustedImmPtr(JSValue::encode(jsUndefined())), valueGPR));
- addSlowPathGenerator(
- slowPathCall(
- slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
-
- jsValueResult(valueGPR, m_compileIndex);
- break;
- }
-
- case Array::ArrayWithArrayStorage:
- case Array::ArrayWithArrayStorageOutOfBounds: {
- GPRTemporary storageLength(this);
- GPRReg storageLengthGPR = storageLength.gpr();
- m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
+ m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
- JITCompiler::Jump undefinedCase =
- m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
+ JITCompiler::JumpList setUndefinedCases;
+ setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
- m_jit.sub32(TrustedImm32(1), storageLengthGPR);
+ m_jit.sub32(TrustedImm32(1), storageLengthGPR);
- JITCompiler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
+ MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
- m_jit.loadPtr(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
- slowCases.append(m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR));
+ m_jit.loadPtr(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
+ m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
+
+ setUndefinedCases.append(m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR));
- m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
- m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+ m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+ m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
- addSlowPathGenerator(
- slowPathMove(
- undefinedCase, this,
- MacroAssembler::TrustedImmPtr(JSValue::encode(jsUndefined())), valueGPR));
+ addSlowPathGenerator(
+ slowPathMove(
+ setUndefinedCases, this,
+ MacroAssembler::TrustedImmPtr(JSValue::encode(jsUndefined())), valueGPR));
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this, operationArrayPop, valueGPR, baseGPR));
+ addSlowPathGenerator(
+ slowPathCall(
+ slowCase, this, operationArrayPop, valueGPR, baseGPR));
- jsValueResult(valueGPR, m_compileIndex);
- break;
- }
-
- default:
- CRASH();
- break;
- }
+ jsValueResult(valueGPR, m_compileIndex);
break;
}
@@ -3312,9 +3087,9 @@ void SpeculativeJIT::compile(Node& node)
m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
// Grab the return address.
- m_jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
+ m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
// Restore our caller's "r".
- m_jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
+ m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
// Return.
m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
m_jit.ret();
@@ -3376,40 +3151,8 @@ void SpeculativeJIT::compile(Node& node)
case NewArray: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime()) {
+ if (!globalObject->isHavingABadTime())
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
-
- ASSERT(hasContiguous(globalObject->arrayStructure()->indexingType()));
-
- unsigned numElements = node.numChildren();
-
- GPRTemporary result(this);
- GPRTemporary storage(this);
-
- GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
-
- emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
-
- // At this point, one way or another, resultGPR and storageGPR have pointers to
- // the JSArray and the Butterfly, respectively.
-
- for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
- JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
- GPRReg opGPR = operand.gpr();
- m_jit.storePtr(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx));
- }
-
- // Yuck, we should *really* have a way of also returning the storageGPR. But
- // that's the least of what's wrong with this code. We really shouldn't be
- // allocating the array after having computed - and probably spilled to the
- // stack - all of the things that will go into the array. The solution to that
- // bigger problem will also likely fix the redundancy in reloading the storage
- // pointer that we currently have.
-
- cellResult(resultGPR, m_compileIndex);
- break;
- }
if (!node.numChildren()) {
flushRegisters();
@@ -3460,61 +3203,15 @@ void SpeculativeJIT::compile(Node& node)
case NewArrayWithSize: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime()) {
+ if (!globalObject->isHavingABadTime())
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
-
- SpeculateStrictInt32Operand size(this, node.child1());
- GPRTemporary result(this);
- GPRTemporary storage(this);
- GPRTemporary scratch(this);
-
- GPRReg sizeGPR = size.gpr();
- GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
- GPRReg scratchGPR = scratch.gpr();
-
- MacroAssembler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
-
- ASSERT((1 << 3) == sizeof(JSValue));
- m_jit.move(sizeGPR, scratchGPR);
- m_jit.lshift32(TrustedImm32(3), scratchGPR);
- m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
- slowCases.append(
- emitAllocateBasicStorage(resultGPR, storageGPR));
- m_jit.subPtr(scratchGPR, storageGPR);
- emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(
- TrustedImmPtr(globalObject->arrayStructure()), resultGPR, scratchGPR,
- storageGPR, sizeof(JSArray), slowCases);
-
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-
- addSlowPathGenerator(adoptPtr(
- new CallArrayAllocatorWithVariableSizeSlowPathGenerator(
- slowCases, this, operationNewArrayWithSize, resultGPR,
- globalObject->arrayStructure(),
- globalObject->arrayStructureWithArrayStorage(),
- sizeGPR)));
-
- cellResult(resultGPR, m_compileIndex);
- break;
- }
SpeculateStrictInt32Operand size(this, node.child1());
GPRReg sizeGPR = size.gpr();
flushRegisters();
GPRResult result(this);
- GPRReg resultGPR = result.gpr();
- GPRReg structureGPR = selectScratchGPR(sizeGPR);
- MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX));
- m_jit.move(TrustedImmPtr(globalObject->arrayStructure()), structureGPR);
- MacroAssembler::Jump done = m_jit.jump();
- bigLength.link(&m_jit);
- m_jit.move(TrustedImmPtr(globalObject->arrayStructureWithArrayStorage()), structureGPR);
- done.link(&m_jit);
- callOperation(operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR);
- cellResult(resultGPR, m_compileIndex);
+ callOperation(operationNewArrayWithSize, result.gpr(), globalObject->arrayStructure(), sizeGPR);
+ cellResult(result.gpr(), m_compileIndex);
break;
}
@@ -3557,35 +3254,10 @@ void SpeculativeJIT::compile(Node& node)
}
case NewArrayBuffer: {
- JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime()) {
- globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
-
- unsigned numElements = node.numConstants();
-
- GPRTemporary result(this);
- GPRTemporary storage(this);
-
- GPRReg resultGPR = result.gpr();
- GPRReg storageGPR = storage.gpr();
-
- emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
-
- JSValue* data = m_jit.codeBlock()->constantBuffer(node.startConstant());
- for (unsigned index = 0; index < node.numConstants(); ++index) {
- m_jit.storePtr(
- ImmPtr(bitwise_cast<void*>(JSValue::encode(data[index]))),
- MacroAssembler::Address(storageGPR, sizeof(JSValue) * index));
- }
-
- cellResult(resultGPR, m_compileIndex);
- break;
- }
-
flushRegisters();
GPRResult result(this);
- callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructure(), node.startConstant(), node.numConstants());
+ callOperation(operationNewArrayBuffer, result.gpr(), node.startConstant(), node.numConstants());
cellResult(result.gpr(), m_compileIndex);
break;
@@ -3703,7 +3375,7 @@ void SpeculativeJIT::compile(Node& node)
case GetCallee: {
GPRTemporary result(this);
- m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(JSStack::Callee)), result.gpr());
+ m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr());
cellResult(result.gpr(), m_compileIndex);
break;
}
@@ -3712,7 +3384,7 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(JSStack::ScopeChain)), resultGPR);
+ m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::ScopeChain)), resultGPR);
bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
int skip = node.scopeChainDepth();
ASSERT(skip || !checkTopLevel);
@@ -4301,14 +3973,14 @@ void SpeculativeJIT::compile(Node& node)
// Fast case
m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR);
#if DFG_ENABLE(JIT_ASSERT)
- JITCompiler::Jump isOutOfLine = m_jit.branch32(JITCompiler::GreaterThanOrEqual, resolveInfoGPR, TrustedImm32(firstOutOfLineOffset));
+ JITCompiler::Jump isOutOfLine = m_jit.branch32(JITCompiler::GreaterThanOrEqual, resolveInfoGPR, TrustedImm32(inlineStorageCapacity));
m_jit.breakpoint();
isOutOfLine.link(&m_jit);
#endif
m_jit.neg32(resolveInfoGPR);
m_jit.signExtend32ToPtr(resolveInfoGPR, resolveInfoGPR);
m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::butterflyOffset()), resultGPR);
- m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr, (firstOutOfLineOffset - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultGPR);
+ m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr, (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultGPR);
addSlowPathGenerator(
slowPathCall(
@@ -4434,7 +4106,7 @@ void SpeculativeJIT::compile(Node& node)
}
ASSERT(!node.codeOrigin.inlineCallFrame);
- m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR);
+ m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultGPR);
m_jit.sub32(TrustedImm32(1), resultGPR);
integerResult(resultGPR, m_compileIndex);
break;
@@ -4457,7 +4129,7 @@ void SpeculativeJIT::compile(Node& node)
jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1)))),
resultGPR);
} else {
- m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR);
+ m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultGPR);
m_jit.sub32(TrustedImm32(1), resultGPR);
m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
}
@@ -4506,7 +4178,7 @@ void SpeculativeJIT::compile(Node& node)
m_jit.branch32(
JITCompiler::AboveOrEqual,
resultGPR,
- JITCompiler::payloadFor(JSStack::ArgumentCount)));
+ JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
}
JITCompiler::JumpList slowArgument;
@@ -4571,7 +4243,7 @@ void SpeculativeJIT::compile(Node& node)
m_jit.branch32(
JITCompiler::AboveOrEqual,
resultGPR,
- JITCompiler::payloadFor(JSStack::ArgumentCount)));
+ JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
}
JITCompiler::JumpList slowArgument;
diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
index 2e44af2d7..5b0b22963 100644
--- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
@@ -122,18 +122,12 @@ public:
if (!subNode.shouldGenerate())
continue;
switch (subNode.op()) {
- case CheckStructure: {
- if (subNode.child1().index() != source)
- break;
-
- noticeStructureCheck(variable, subNode.structureSet());
- break;
- }
+ case CheckStructure:
case StructureTransitionWatchpoint: {
if (subNode.child1().index() != source)
break;
- noticeStructureCheck(variable, subNode.structure());
+ noticeStructureCheck(variable, subNode.structureSet());
break;
}
default:
@@ -168,7 +162,7 @@ public:
dataLog("Zeroing the structure to hoist for %s because the ratio is %lf.\n",
m_graph.nameOfVariableAccessData(variable), variable->voteRatio());
#endif
- iter->value.m_structure = 0;
+ iter->second.m_structure = 0;
}
// Disable structure check hoisting for variables that cross the OSR entry that
@@ -193,7 +187,7 @@ public:
HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
if (iter == m_map.end())
continue;
- if (!iter->value.m_structure)
+ if (!iter->second.m_structure)
continue;
JSValue value = m_graph.m_mustHandleValues[i];
if (!value || !value.isCell()) {
@@ -201,34 +195,162 @@ public:
dataLog("Zeroing the structure to hoist for %s because the OSR entry value is not a cell: %s.\n",
m_graph.nameOfVariableAccessData(variable), value.description());
#endif
- iter->value.m_structure = 0;
+ iter->second.m_structure = 0;
continue;
}
- if (value.asCell()->structure() != iter->value.m_structure) {
+ if (value.asCell()->structure() != iter->second.m_structure) {
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog("Zeroing the structure to hoist for %s because the OSR entry value has structure %p and we wanted %p.\n",
- m_graph.nameOfVariableAccessData(variable), value.asCell()->structure(), iter->value.m_structure);
+ m_graph.nameOfVariableAccessData(variable), value.asCell()->structure(), iter->second.m_structure);
#endif
- iter->value.m_structure = 0;
+ iter->second.m_structure = 0;
continue;
}
}
}
+ // Identify the set of variables that are live across a structure clobber.
+
+ Operands<VariableAccessData*> live(
+ m_graph.m_blocks[0]->variablesAtTail.numberOfArguments(),
+ m_graph.m_blocks[0]->variablesAtTail.numberOfLocals());
+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ if (!block)
+ continue;
+ ASSERT(live.numberOfArguments() == block->variablesAtTail.numberOfArguments());
+ ASSERT(live.numberOfLocals() == block->variablesAtTail.numberOfLocals());
+ for (unsigned i = live.size(); i--;) {
+ NodeIndex indexAtTail = block->variablesAtTail[i];
+ VariableAccessData* variable;
+ if (indexAtTail == NoNode)
+ variable = 0;
+ else
+ variable = m_graph[indexAtTail].variableAccessData();
+ live[i] = variable;
+ }
+ for (unsigned indexInBlock = block->size(); indexInBlock--;) {
+ NodeIndex nodeIndex = block->at(indexInBlock);
+ Node& node = m_graph[nodeIndex];
+ if (!node.shouldGenerate())
+ continue;
+ switch (node.op()) {
+ case GetLocal:
+ case Flush:
+ // This is a birth.
+ live.operand(node.local()) = node.variableAccessData();
+ break;
+
+ case SetLocal:
+ case SetArgument:
+ ASSERT(live.operand(node.local())); // Must be live.
+ ASSERT(live.operand(node.local()) == node.variableAccessData()); // Must have the variable we expected.
+ // This is a death.
+ live.operand(node.local()) = 0;
+ break;
+
+ // Use the CFA's notion of what clobbers the world.
+ case ValueAdd:
+ if (m_graph.addShouldSpeculateInteger(node))
+ break;
+ if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
+ break;
+ clobber(live);
+ break;
+
+ case CompareLess:
+ case CompareLessEq:
+ case CompareGreater:
+ case CompareGreaterEq:
+ case CompareEq: {
+ Node& left = m_graph[node.child1()];
+ Node& right = m_graph[node.child2()];
+ if (Node::shouldSpeculateInteger(left, right))
+ break;
+ if (Node::shouldSpeculateNumber(left, right))
+ break;
+ if (node.op() == CompareEq) {
+ if ((m_graph.isConstant(node.child1().index())
+ && m_graph.valueOfJSConstant(node.child1().index()).isNull())
+ || (m_graph.isConstant(node.child2().index())
+ && m_graph.valueOfJSConstant(node.child2().index()).isNull()))
+ break;
+
+ if (Node::shouldSpeculateFinalObject(left, right))
+ break;
+ if (Node::shouldSpeculateArray(left, right))
+ break;
+ if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther())
+ break;
+ if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther())
+ break;
+ if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther())
+ break;
+ if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther())
+ break;
+ }
+ clobber(live);
+ break;
+ }
+
+ case GetByVal:
+ case PutByVal:
+ case PutByValAlias:
+ if (m_graph.byValIsPure(node))
+ break;
+ clobber(live);
+ break;
+
+ case GetMyArgumentsLengthSafe:
+ case GetMyArgumentByValSafe:
+ case GetById:
+ case GetByIdFlush:
+ case PutStructure:
+ case PhantomPutStructure:
+ case PutById:
+ case PutByIdDirect:
+ case Call:
+ case Construct:
+ case Resolve:
+ case ResolveBase:
+ case ResolveBaseStrictPut:
+ case ResolveGlobal:
+ case ArrayPush:
+ case ArrayPop:
+ case Arrayify:
+ clobber(live);
+ break;
+
+ default:
+ ASSERT(node.op() != Phi);
+ break;
+ }
+ }
+ }
+
bool changed = false;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
for (HashMap<VariableAccessData*, CheckData>::iterator it = m_map.begin();
it != m_map.end(); ++it) {
- if (!it->value.m_structure) {
- dataLog("Not hoisting checks for %s because of heuristics.\n", m_graph.nameOfVariableAccessData(it->key));
+ if (!it->second.m_structure) {
+ dataLog("Not hoisting checks for %s because of heuristics.\n", m_graph.nameOfVariableAccessData(it->first));
+ continue;
+ }
+ if (it->second.m_isClobbered && !it->second.m_structure->transitionWatchpointSetIsStillValid()) {
+ dataLog("Not hoisting checks for %s because the structure is clobbered and has an invalid watchpoint set.\n", m_graph.nameOfVariableAccessData(it->first));
continue;
}
- dataLog("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->key));
+ dataLog("Hoisting checks for %s\n", m_graph.nameOfVariableAccessData(it->first));
}
#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- // Place CheckStructure's at SetLocal sites.
+ // Make changes:
+ // 1) If a variable's live range does not span a clobber, then inject structure
+ // checks before the SetLocal.
+ // 2) If a variable's live range spans a clobber but is watchpointable, then
+ // inject structure checks before the SetLocal and replace all other structure
+ // checks on that variable with structure transition watchpoints.
InsertionSet<NodeIndex> insertionSet;
for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
@@ -254,7 +376,9 @@ public:
HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
if (iter == m_map.end())
break;
- if (!iter->value.m_structure)
+ if (!iter->second.m_structure)
+ break;
+ if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid())
break;
node.ref();
@@ -268,7 +392,7 @@ public:
m_graph.append(getLocal);
insertionSet.append(indexInBlock + 1, getLocalIndex);
- Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), getLocalIndex);
+ Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->second.m_structure)), getLocalIndex);
checkStructure.ref();
NodeIndex checkStructureIndex = m_graph.size();
m_graph.append(checkStructure);
@@ -288,7 +412,9 @@ public:
HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
if (iter == m_map.end())
break;
- if (!iter->value.m_structure)
+ if (!iter->second.m_structure)
+ break;
+ if (iter->second.m_isClobbered && !iter->second.m_structure->transitionWatchpointSetIsStillValid())
break;
// First insert a dead SetLocal to tell OSR that the child's value should
@@ -305,7 +431,7 @@ public:
m_graph[child1].ref();
// Use a ForwardCheckStructure to indicate that we should exit to the
// next bytecode instruction rather than reexecuting the current one.
- Node checkStructure(ForwardCheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), child1);
+ Node checkStructure(ForwardCheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(iter->second.m_structure)), child1);
checkStructure.ref();
NodeIndex checkStructureIndex = m_graph.size();
m_graph.append(checkStructure);
@@ -314,6 +440,28 @@ public:
break;
}
+ case CheckStructure: {
+ Node& child = m_graph[node.child1()];
+ if (child.op() != GetLocal)
+ break;
+ HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(child.variableAccessData());
+ if (iter == m_map.end())
+ break;
+ if (!iter->second.m_structure)
+ break;
+ if (!iter->second.m_isClobbered) {
+ node.setOpAndDefaultFlags(Phantom);
+ ASSERT(node.refCount() == 1);
+ break;
+ }
+ if (!iter->second.m_structure->transitionWatchpointSetIsStillValid())
+ break;
+ ASSERT(iter->second.m_structure == node.structureSet().singletonStructure());
+ node.convertToStructureTransitionWatchpoint();
+ changed = true;
+ break;
+ }
+
default:
break;
}
@@ -328,12 +476,12 @@ private:
void noticeStructureCheck(VariableAccessData* variable, Structure* structure)
{
HashMap<VariableAccessData*, CheckData>::AddResult result =
- m_map.add(variable, CheckData(structure));
+ m_map.add(variable, CheckData(structure, false));
if (result.isNewEntry)
return;
- if (result.iterator->value.m_structure == structure)
+ if (result.iterator->second.m_structure == structure)
return;
- result.iterator->value.m_structure = 0;
+ result.iterator->second.m_structure = 0;
}
void noticeStructureCheck(VariableAccessData* variable, const StructureSet& set)
@@ -345,16 +493,38 @@ private:
noticeStructureCheck(variable, set.singletonStructure());
}
+ void noticeClobber(VariableAccessData* variable)
+ {
+ HashMap<VariableAccessData*, CheckData>::iterator iter =
+ m_map.find(variable);
+ if (iter == m_map.end())
+ return;
+ iter->second.m_isClobbered = true;
+ }
+
+ void clobber(const Operands<VariableAccessData*>& live)
+ {
+ for (size_t i = live.size(); i--;) {
+ VariableAccessData* variable = live[i];
+ if (!variable)
+ continue;
+ noticeClobber(variable);
+ }
+ }
+
struct CheckData {
Structure* m_structure;
+ bool m_isClobbered;
CheckData()
: m_structure(0)
+ , m_isClobbered(false)
{
}
- CheckData(Structure* structure)
+ CheckData(Structure* structure, bool isClobbered)
: m_structure(structure)
+ , m_isClobbered(isClobbered)
{
}
};
diff --git a/Source/JavaScriptCore/dfg/DFGThunks.cpp b/Source/JavaScriptCore/dfg/DFGThunks.cpp
index 25fcad10a..546aec256 100644
--- a/Source/JavaScriptCore/dfg/DFGThunks.cpp
+++ b/Source/JavaScriptCore/dfg/DFGThunks.cpp
@@ -113,7 +113,7 @@ MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(JSGlobalData* glob
jit.loadPtr(
CCallHelpers::Address(
GPRInfo::callFrameRegister,
- static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::CallerFrame),
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::CallerFrame),
GPRInfo::callFrameRegister);
jit.peek(GPRInfo::nonPreservedNonReturnGPR, JITSTACKFRAME_ARGS_INDEX);
jit.setupArgumentsWithExecState(GPRInfo::nonPreservedNonReturnGPR);
@@ -136,7 +136,7 @@ static void slowPathFor(
GPRInfo::nonArgGPR2,
CCallHelpers::Address(
GPRInfo::callFrameRegister,
- static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ReturnPC));
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC));
jit.storePtr(GPRInfo::callFrameRegister, &globalData->topCallFrame);
jit.poke(GPRInfo::nonPreservedNonReturnGPR, JITSTACKFRAME_ARGS_INDEX);
jit.setupArgumentsExecState();
@@ -151,13 +151,13 @@ static void slowPathFor(
jit.loadPtr(
CCallHelpers::Address(
GPRInfo::callFrameRegister,
- static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ReturnPC),
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC),
GPRInfo::nonPreservedNonReturnGPR);
jit.storePtr(
CCallHelpers::TrustedImmPtr(0),
CCallHelpers::Address(
GPRInfo::callFrameRegister,
- static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ReturnPC));
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ReturnPC));
emitPointerValidation(jit, GPRInfo::nonPreservedNonReturnGPR);
jit.restoreReturnAddressBeforeReturn(GPRInfo::nonPreservedNonReturnGPR);
emitPointerValidation(jit, GPRInfo::returnValueGPR);
@@ -249,19 +249,19 @@ static MacroAssemblerCodeRef virtualForThunkGenerator(
GPRInfo::nonArgGPR1,
CCallHelpers::Address(
GPRInfo::callFrameRegister,
- static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain));
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain));
#else
jit.storePtr(
GPRInfo::nonArgGPR1,
CCallHelpers::Address(
GPRInfo::callFrameRegister,
- static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain +
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain +
OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
jit.store32(
CCallHelpers::TrustedImm32(JSValue::CellTag),
CCallHelpers::Address(
GPRInfo::callFrameRegister,
- static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain +
+ static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain +
OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGValueSource.cpp b/Source/JavaScriptCore/dfg/DFGValueSource.cpp
index d59e4842f..25d43ee6b 100644
--- a/Source/JavaScriptCore/dfg/DFGValueSource.cpp
+++ b/Source/JavaScriptCore/dfg/DFGValueSource.cpp
@@ -39,19 +39,19 @@ void ValueSource::dump(FILE* out) const
case SourceIsDead:
fprintf(out, "IsDead");
break;
- case ValueInJSStack:
- fprintf(out, "InStack");
+ case ValueInRegisterFile:
+ fprintf(out, "InRegFile");
break;
- case Int32InJSStack:
+ case Int32InRegisterFile:
fprintf(out, "Int32");
break;
- case CellInJSStack:
+ case CellInRegisterFile:
fprintf(out, "Cell");
break;
- case BooleanInJSStack:
+ case BooleanInRegisterFile:
fprintf(out, "Bool");
break;
- case DoubleInJSStack:
+ case DoubleInRegisterFile:
fprintf(out, "Double");
break;
case ArgumentsSource:
diff --git a/Source/JavaScriptCore/dfg/DFGValueSource.h b/Source/JavaScriptCore/dfg/DFGValueSource.h
index 8a4c66b37..f776137d0 100644
--- a/Source/JavaScriptCore/dfg/DFGValueSource.h
+++ b/Source/JavaScriptCore/dfg/DFGValueSource.h
@@ -39,11 +39,11 @@ namespace JSC { namespace DFG {
enum ValueSourceKind {
SourceNotSet,
- ValueInJSStack,
- Int32InJSStack,
- CellInJSStack,
- BooleanInJSStack,
- DoubleInJSStack,
+ ValueInRegisterFile,
+ Int32InRegisterFile,
+ CellInRegisterFile,
+ BooleanInRegisterFile,
+ DoubleInRegisterFile,
ArgumentsSource,
SourceIsDead,
HaveNode
@@ -53,35 +53,35 @@ static inline ValueSourceKind dataFormatToValueSourceKind(DataFormat dataFormat)
{
switch (dataFormat) {
case DataFormatInteger:
- return Int32InJSStack;
+ return Int32InRegisterFile;
case DataFormatDouble:
- return DoubleInJSStack;
+ return DoubleInRegisterFile;
case DataFormatBoolean:
- return BooleanInJSStack;
+ return BooleanInRegisterFile;
case DataFormatCell:
- return CellInJSStack;
+ return CellInRegisterFile;
case DataFormatDead:
return SourceIsDead;
case DataFormatArguments:
return ArgumentsSource;
default:
ASSERT(dataFormat & DataFormatJS);
- return ValueInJSStack;
+ return ValueInRegisterFile;
}
}
static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind)
{
switch (kind) {
- case ValueInJSStack:
+ case ValueInRegisterFile:
return DataFormatJS;
- case Int32InJSStack:
+ case Int32InRegisterFile:
return DataFormatInteger;
- case CellInJSStack:
+ case CellInRegisterFile:
return DataFormatCell;
- case BooleanInJSStack:
+ case BooleanInRegisterFile:
return DataFormatBoolean;
- case DoubleInJSStack:
+ case DoubleInRegisterFile:
return DataFormatDouble;
case ArgumentsSource:
return DataFormatArguments;
@@ -92,7 +92,7 @@ static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind)
}
}
-static inline bool isInJSStack(ValueSourceKind kind)
+static inline bool isInRegisterFile(ValueSourceKind kind)
{
DataFormat format = valueSourceKindToDataFormat(kind);
return format != DataFormatNone && format < DataFormatOSRMarker;
@@ -129,12 +129,12 @@ public:
static ValueSource forSpeculation(SpeculatedType prediction)
{
if (isInt32Speculation(prediction))
- return ValueSource(Int32InJSStack);
+ return ValueSource(Int32InRegisterFile);
if (isArraySpeculation(prediction) || isCellSpeculation(prediction))
- return ValueSource(CellInJSStack);
+ return ValueSource(CellInRegisterFile);
if (isBooleanSpeculation(prediction))
- return ValueSource(BooleanInJSStack);
- return ValueSource(ValueInJSStack);
+ return ValueSource(BooleanInRegisterFile);
+ return ValueSource(ValueInRegisterFile);
}
static ValueSource forDataFormat(DataFormat dataFormat)
@@ -152,7 +152,7 @@ public:
return kindFromNodeIndex(m_nodeIndex);
}
- bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); }
+ bool isInRegisterFile() const { return JSC::DFG::isInRegisterFile(kind()); }
bool isTriviallyRecoverable() const { return JSC::DFG::isTriviallyRecoverable(kind()); }
DataFormat dataFormat() const
@@ -164,20 +164,20 @@ public:
{
ASSERT(isTriviallyRecoverable());
switch (kind()) {
- case ValueInJSStack:
- return ValueRecovery::alreadyInJSStack();
+ case ValueInRegisterFile:
+ return ValueRecovery::alreadyInRegisterFile();
- case Int32InJSStack:
- return ValueRecovery::alreadyInJSStackAsUnboxedInt32();
+ case Int32InRegisterFile:
+ return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
- case CellInJSStack:
- return ValueRecovery::alreadyInJSStackAsUnboxedCell();
+ case CellInRegisterFile:
+ return ValueRecovery::alreadyInRegisterFileAsUnboxedCell();
- case BooleanInJSStack:
- return ValueRecovery::alreadyInJSStackAsUnboxedBoolean();
+ case BooleanInRegisterFile:
+ return ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean();
- case DoubleInJSStack:
- return ValueRecovery::alreadyInJSStackAsUnboxedDouble();
+ case DoubleInRegisterFile:
+ return ValueRecovery::alreadyInRegisterFileAsUnboxedDouble();
case SourceIsDead:
return ValueRecovery::constant(jsUndefined());
diff --git a/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp b/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
index fa36ccdb5..a1152bc2b 100644
--- a/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
+++ b/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
@@ -93,7 +93,7 @@ void VariableEventStream::reconstruct(
if (!index) {
valueRecoveries = Operands<ValueRecovery>(codeBlock->numParameters(), numVariables);
for (size_t i = 0; i < valueRecoveries.size(); ++i)
- valueRecoveries[i] = ValueRecovery::alreadyInJSStack();
+ valueRecoveries[i] = ValueRecovery::alreadyInRegisterFile();
return;
}
@@ -280,7 +280,7 @@ void VariableEventStream::reconstruct(
}
valueRecoveries[i] =
- ValueRecovery::displacedInJSStack(static_cast<VirtualRegister>(info->u.virtualReg), info->format);
+ ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(info->u.virtualReg), info->format);
}
}