summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-09 12:15:52 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-09 12:16:06 +0100
commitde4f791e30be4e4239b381c11745ffa4d87ddb8b (patch)
tree885e3a5d6670828b454cf676b4d42f78e28b1f0e /Source/JavaScriptCore/dfg
parentb022df48697d40cdabdeafb2c29bb14fe489b6fe (diff)
downloadqtwebkit-de4f791e30be4e4239b381c11745ffa4d87ddb8b.tar.gz
Imported WebKit commit e2c32e2f53e02d388e70b9db88b91d8d9d28fc84 (http://svn.webkit.org/repository/webkit/trunk@133952)
Revert back to an older snapshot that should build on ARM
Diffstat (limited to 'Source/JavaScriptCore/dfg')
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp136
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.h43
-rw-r--r--Source/JavaScriptCore/dfg/DFGArrayMode.cpp241
-rw-r--r--Source/JavaScriptCore/dfg/DFGArrayMode.h29
-rw-r--r--Source/JavaScriptCore/dfg/DFGBasicBlock.h3
-rw-r--r--Source/JavaScriptCore/dfg/DFGBranchDirection.h88
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp39
-rw-r--r--Source/JavaScriptCore/dfg/DFGCCallHelpers.h78
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp6
-rw-r--r--Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h4
-rw-r--r--Source/JavaScriptCore/dfg/DFGFixupPhase.cpp64
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.cpp5
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h12
-rw-r--r--Source/JavaScriptCore/dfg/DFGNode.h67
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp69
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.h8
-rw-r--r--Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp75
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp162
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h46
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp511
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp348
21 files changed, 388 insertions, 1646 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 02e578b29..e518c24a8 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -159,7 +159,7 @@ void AbstractState::initialize(Graph& graph)
}
}
-bool AbstractState::endBasicBlock(MergeMode mergeMode)
+bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDirectionPtr)
{
ASSERT(m_block);
@@ -167,7 +167,6 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode)
block->cfaFoundConstants = m_foundConstants;
block->cfaDidFinish = m_isValid;
- block->cfaBranchDirection = m_branchDirection;
if (!m_isValid) {
reset();
@@ -196,8 +195,12 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode)
ASSERT(mergeMode != DontMerge || !changed);
+ BranchDirection branchDirection = m_branchDirection;
+ if (branchDirectionPtr)
+ *branchDirectionPtr = branchDirection;
+
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
- dataLog(" Branch direction = %s\n", branchDirectionToString(m_branchDirection));
+ dataLog(" Branch direction = %s\n", branchDirectionToString(branchDirection));
#endif
reset();
@@ -205,7 +208,7 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode)
if (mergeMode != MergeToSuccessors)
return changed;
- return mergeToSuccessors(m_graph, block);
+ return mergeToSuccessors(m_graph, block, branchDirection);
}
void AbstractState::reset()
@@ -421,10 +424,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberUnary(node);
- if (isInt32Speculation(forNode(node.child1()).m_type))
- forNode(nodeIndex).set(SpecDoubleReal);
- else
- forNode(nodeIndex).set(SpecDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -448,13 +448,9 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(nodeIndex).set(SpecInt32);
break;
}
- if (Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) {
+ if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
speculateNumberBinary(node);
- if (isRealNumberSpeculation(forNode(node.child1()).m_type)
- && isRealNumberSpeculation(forNode(node.child2()).m_type))
- forNode(nodeIndex).set(SpecDoubleReal);
- else
- forNode(nodeIndex).set(SpecDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
if (node.op() == ValueAdd) {
@@ -526,11 +522,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
speculateNumberBinary(node);
- if (isRealNumberSpeculation(forNode(node.child1()).m_type)
- || isRealNumberSpeculation(forNode(node.child2()).m_type))
- forNode(nodeIndex).set(SpecDoubleReal);
- else
- forNode(nodeIndex).set(SpecDouble);
+ forNode(nodeIndex).set(SpecDouble);
break;
}
@@ -568,7 +560,7 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
}
}
- if (Node::shouldSpeculateIntegerForArithmetic(
+ if (Node::shouldSpeculateInteger(
m_graph[node.child1()], m_graph[node.child2()])
&& node.canSpeculateInteger()) {
speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side.
@@ -588,7 +580,7 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
break;
}
- if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
+ if (m_graph[node.child1()].shouldSpeculateInteger()
&& node.canSpeculateInteger()) {
speculateInt32Unary(node, true);
forNode(nodeIndex).set(SpecInt32);
@@ -613,22 +605,12 @@ bool AbstractState::execute(unsigned indexInBlock)
}
case LogicalNot: {
- // First check if we can fold because the source is a constant.
JSValue childConst = forNode(node.child1()).value();
if (childConst && trySetConstant(nodeIndex, jsBoolean(!childConst.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec())))) {
m_foundConstants = true;
node.setCanExit(false);
break;
}
- // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
- if (isCellSpeculation(forNode(node.child1()).m_type)
- && forNode(node.child1()).m_currentKnownStructure.hasSingleton()
- && !forNode(node.child1()).m_currentKnownStructure.singleton()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))
- && trySetConstant(nodeIndex, jsBoolean(false))) {
- m_foundConstants = true;
- node.setCanExit(false);
- break;
- }
Node& child = m_graph[node.child1()];
if (isBooleanSpeculation(child.prediction()))
speculateBooleanUnary(node);
@@ -696,13 +678,12 @@ bool AbstractState::execute(unsigned indexInBlock)
case CompareGreater:
case CompareGreaterEq:
case CompareEq: {
- bool constantWasSet = false;
-
JSValue leftConst = forNode(node.child1()).value();
JSValue rightConst = forNode(node.child2()).value();
if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) {
double a = leftConst.asNumber();
double b = rightConst.asNumber();
+ bool constantWasSet;
switch (node.op()) {
case CompareLess:
constantWasSet = trySetConstant(nodeIndex, jsBoolean(a < b));
@@ -724,20 +705,11 @@ bool AbstractState::execute(unsigned indexInBlock)
constantWasSet = false;
break;
}
- }
-
- if (!constantWasSet && node.op() == CompareEq) {
- SpeculatedType leftType = forNode(node.child1()).m_type;
- SpeculatedType rightType = forNode(node.child2()).m_type;
- if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType))
- || (isOtherSpeculation(leftType) && isInt32Speculation(rightType)))
- constantWasSet = trySetConstant(nodeIndex, jsBoolean(false));
- }
-
- if (constantWasSet) {
- m_foundConstants = true;
- node.setCanExit(false);
- break;
+ if (constantWasSet) {
+ m_foundConstants = true;
+ node.setCanExit(false);
+ break;
+ }
}
forNode(nodeIndex).set(SpecBoolean);
@@ -870,7 +842,6 @@ bool AbstractState::execute(unsigned indexInBlock)
switch (node.arrayMode().type()) {
case Array::SelectUsingPredictions:
case Array::Unprofiled:
- case Array::Undecided:
ASSERT_NOT_REACHED();
break;
case Array::ForceExit:
@@ -888,22 +859,6 @@ bool AbstractState::execute(unsigned indexInBlock)
forNode(node.child2()).filter(SpecInt32);
forNode(nodeIndex).makeTop();
break;
- case Array::Int32:
- forNode(node.child2()).filter(SpecInt32);
- if (node.arrayMode().isOutOfBounds()) {
- clobberWorld(node.codeOrigin, indexInBlock);
- forNode(nodeIndex).makeTop();
- } else
- forNode(nodeIndex).set(SpecInt32);
- break;
- case Array::Double:
- forNode(node.child2()).filter(SpecInt32);
- if (node.arrayMode().isOutOfBounds()) {
- clobberWorld(node.codeOrigin, indexInBlock);
- forNode(nodeIndex).makeTop();
- } else
- forNode(nodeIndex).set(SpecDoubleReal);
- break;
case Array::Contiguous:
case Array::ArrayStorage:
case Array::SlowPutArrayStorage:
@@ -971,20 +926,6 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::Generic:
clobberWorld(node.codeOrigin, indexInBlock);
break;
- case Array::Int32:
- forNode(child1).filter(SpecCell);
- forNode(child2).filter(SpecInt32);
- forNode(child3).filter(SpecInt32);
- if (node.arrayMode().isOutOfBounds())
- clobberWorld(node.codeOrigin, indexInBlock);
- break;
- case Array::Double:
- forNode(child1).filter(SpecCell);
- forNode(child2).filter(SpecInt32);
- forNode(child3).filter(SpecRealNumber);
- if (node.arrayMode().isOutOfBounds())
- clobberWorld(node.codeOrigin, indexInBlock);
- break;
case Array::Contiguous:
case Array::ArrayStorage:
forNode(child1).filter(SpecCell);
@@ -1077,16 +1018,6 @@ bool AbstractState::execute(unsigned indexInBlock)
case ArrayPush:
node.setCanExit(true);
- switch (node.arrayMode().type()) {
- case Array::Int32:
- forNode(node.child2()).filter(SpecInt32);
- break;
- case Array::Double:
- forNode(node.child2()).filter(SpecRealNumber);
- break;
- default:
- break;
- }
clobberWorld(node.codeOrigin, indexInBlock);
forNode(nodeIndex).set(SpecNumber);
break;
@@ -1112,7 +1043,6 @@ bool AbstractState::execute(unsigned indexInBlock)
break;
case Branch: {
- // First check if we can fold because the source is a constant.
JSValue value = forNode(node.child1()).value();
if (value) {
bool booleanValue = value.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec());
@@ -1123,14 +1053,6 @@ bool AbstractState::execute(unsigned indexInBlock)
node.setCanExit(false);
break;
}
- // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
- if (isCellSpeculation(forNode(node.child1()).m_type)
- && forNode(node.child1()).m_currentKnownStructure.hasSingleton()
- && !forNode(node.child1()).m_currentKnownStructure.singleton()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))) {
- m_branchDirection = TakeTrue;
- node.setCanExit(false);
- break;
- }
// FIXME: The above handles the trivial cases of sparse conditional
// constant propagation, but we can do better:
// 1) If the abstract value does not have a concrete value but describes
@@ -1200,13 +1122,13 @@ bool AbstractState::execute(unsigned indexInBlock)
case NewArray:
node.setCanExit(true);
- forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
m_haveStructures = true;
break;
case NewArrayBuffer:
node.setCanExit(true);
- forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
+ forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
m_haveStructures = true;
break;
@@ -1462,11 +1384,11 @@ bool AbstractState::execute(unsigned indexInBlock)
case Array::String:
forNode(node.child1()).filter(SpecString);
break;
- case Array::Int32:
- case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage:
case Array::SlowPutArrayStorage:
+ // 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.
forNode(node.child1()).filter(SpecCell);
break;
case Array::Arguments:
@@ -1800,7 +1722,7 @@ inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
}
inline bool AbstractState::mergeToSuccessors(
- Graph& graph, BasicBlock* basicBlock)
+ Graph& graph, BasicBlock* basicBlock, BranchDirection branchDirection)
{
Node& terminal = graph[basicBlock->last()];
@@ -1808,7 +1730,7 @@ inline bool AbstractState::mergeToSuccessors(
switch (terminal.op()) {
case Jump: {
- ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
+ ASSERT(branchDirection == InvalidBranchDirection);
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
#endif
@@ -1816,17 +1738,17 @@ inline bool AbstractState::mergeToSuccessors(
}
case Branch: {
- ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection);
+ ASSERT(branchDirection != InvalidBranchDirection);
bool changed = false;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex());
#endif
- if (basicBlock->cfaBranchDirection != TakeFalse)
+ if (branchDirection != TakeFalse)
changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex());
#endif
- if (basicBlock->cfaBranchDirection != TakeTrue)
+ if (branchDirection != TakeTrue)
changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
return changed;
}
@@ -1834,7 +1756,7 @@ inline bool AbstractState::mergeToSuccessors(
case Return:
case Throw:
case ThrowReferenceError:
- ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
+ ASSERT(branchDirection == InvalidBranchDirection);
return false;
default:
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h
index 0e33140c0..ec1a06231 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,7 +31,6 @@
#if ENABLE(DFG_JIT)
#include "DFGAbstractValue.h"
-#include "DFGBranchDirection.h"
#include "DFGGraph.h"
#include "DFGNode.h"
#include <wtf/Vector.h>
@@ -93,6 +92,36 @@ public:
MergeToSuccessors
};
+ enum BranchDirection {
+ // This is not a branch and so there is no branch direction, or
+ // the branch direction has yet to be set.
+ InvalidBranchDirection,
+
+ // The branch takes the true case.
+ TakeTrue,
+
+ // The branch takes the false case.
+ TakeFalse,
+
+ // For all we know, the branch could go either direction, so we
+ // have to assume the worst.
+ TakeBoth
+ };
+
+ static const char* branchDirectionToString(BranchDirection branchDirection)
+ {
+ switch (branchDirection) {
+ case InvalidBranchDirection:
+ return "Invalid";
+ case TakeTrue:
+ return "TakeTrue";
+ case TakeFalse:
+ return "TakeFalse";
+ case TakeBoth:
+ return "TakeBoth";
+ }
+ }
+
AbstractState(Graph&);
~AbstractState();
@@ -145,7 +174,11 @@ public:
// A true return means that you must revisit (at least) the successor
// blocks. This also sets cfaShouldRevisit to true for basic blocks
// that must be visited next.
- bool endBasicBlock(MergeMode);
+ //
+ // If you'd like to know what direction the branch at the end of the
+ // basic block is thought to have taken, you can pass a non-0 pointer
+ // for BranchDirection.
+ bool endBasicBlock(MergeMode, BranchDirection* = 0);
// Reset the AbstractState. This throws away any results, and at this point
// you can safely call beginBasicBlock() on any basic block.
@@ -178,8 +211,8 @@ public:
// successors. Returns true if any of the successors' states changed. Note
// that this is automatically called in endBasicBlock() if MergeMode is
// MergeToSuccessors.
- bool mergeToSuccessors(Graph&, BasicBlock*);
-
+ bool mergeToSuccessors(Graph&, BasicBlock*, BranchDirection);
+
void dump(FILE* out);
private:
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
index 0d15b9a30..699902a16 100644
--- a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
@@ -34,46 +34,19 @@ namespace JSC { namespace DFG {
ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, bool makeSafe)
{
- ArrayModes observed = profile->observedArrayModes();
- switch (observed) {
+ switch (profile->observedArrayModes()) {
case 0:
return ArrayMode(Array::Unprofiled);
case asArrayModes(NonArray):
if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
- return ArrayMode(Array::Undecided, Array::NonArray, Array::OutOfBounds, Array::Convert);
+ return ArrayMode(Array::Contiguous, Array::NonArray, Array::OutOfBounds, Array::Convert); // 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 ArrayMode(Array::SelectUsingPredictions);
-
- case asArrayModes(ArrayWithUndecided):
- if (action == Array::Write)
- return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::Convert);
- return ArrayMode(Array::Generic);
-
- case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided):
- if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
- return ArrayMode(Array::Undecided, Array::PossiblyArray, Array::OutOfBounds, Array::Convert);
- return ArrayMode(Array::SelectUsingPredictions);
-
- case asArrayModes(NonArrayWithInt32):
- return ArrayMode(Array::Int32, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe);
- case asArrayModes(ArrayWithInt32):
- return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(profile, makeSafe);
- case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32):
- return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe);
-
- case asArrayModes(NonArrayWithDouble):
- return ArrayMode(Array::Double, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe);
- case asArrayModes(ArrayWithDouble):
- return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(profile, makeSafe);
- case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble):
- return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe);
-
case asArrayModes(NonArrayWithContiguous):
return ArrayMode(Array::Contiguous, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe);
case asArrayModes(ArrayWithContiguous):
return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(profile, makeSafe);
case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous):
return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe);
-
case asArrayModes(NonArrayWithArrayStorage):
return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe);
case asArrayModes(NonArrayWithSlowPutArrayStorage):
@@ -89,39 +62,36 @@ ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, b
case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe);
-
+ case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
+ return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::Convert).withProfile(profile, makeSafe);
+ case asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
+ return ArrayMode(Array::ArrayStorage, Array::Array, Array::Convert).withProfile(profile, makeSafe);
+ case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage):
+ return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::Convert).withProfile(profile, makeSafe);
+ case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous):
+ if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
+ return ArrayMode(Array::Contiguous, Array::NonArray, Array::OutOfBounds, Array::Convert);
+ return ArrayMode(Array::SelectUsingPredictions);
+ case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage):
+ case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage):
+ if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
+ return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::OutOfBounds, Array::Convert);
+ return ArrayMode(Array::SelectUsingPredictions);
+ case asArrayModes(NonArray) | asArrayModes(NonArrayWithSlowPutArrayStorage):
+ case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage):
+ if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
+ return ArrayMode(Array::SlowPutArrayStorage, Array::NonArray, Array::OutOfBounds, Array::Convert);
+ return ArrayMode(Array::SelectUsingPredictions);
default:
- if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses())
- return ArrayMode(Array::SelectUsingPredictions);
-
- Array::Type type;
- Array::Class arrayClass;
-
- if (shouldUseSlowPutArrayStorage(observed))
- type = Array::SlowPutArrayStorage;
- else if (shouldUseFastArrayStorage(observed))
- type = Array::ArrayStorage;
- else if (shouldUseContiguous(observed))
- type = Array::Contiguous;
- else if (shouldUseDouble(observed))
- type = Array::Double;
- else if (shouldUseInt32(observed))
- type = Array::Int32;
- else
- type = Array::Undecided;
-
- if (observed & (asArrayModes(ArrayWithUndecided) | asArrayModes(ArrayWithInt32) | asArrayModes(ArrayWithDouble) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
- arrayClass = Array::Array;
- else if (observed & (asArrayModes(NonArray) | asArrayModes(NonArrayWithInt32) | asArrayModes(NonArrayWithDouble) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage)))
- arrayClass = Array::NonArray;
- else
- arrayClass = Array::PossiblyArray;
-
- return ArrayMode(type, arrayClass, Array::Convert).withProfile(profile, makeSafe);
+ // We know that this is possibly a kind of array for which, though there is no
+ // useful data in the array profile, we may be able to extract useful data from
+ // the value profiles of the inputs. Hence, we leave it as undecided, and let
+ // the predictions propagator decide later.
+ return ArrayMode(Array::SelectUsingPredictions);
}
}
-ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, SpeculatedType value) const
+ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index) const
{
if (!base || !index) {
// It can be that we had a legitimate arrayMode but no incoming predictions. That'll
@@ -134,85 +104,49 @@ ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, Speculate
if (!isInt32Speculation(index) || !isCellSpeculation(base))
return ArrayMode(Array::Generic);
- switch (type()) {
- case Array::Unprofiled:
+ if (type() == Array::Unprofiled) {
+ // If the indexing type wasn't recorded in the array profile but the values are
+ // base=cell property=int, then we know that this access didn't execute.
return ArrayMode(Array::ForceExit);
-
- case Array::Undecided:
- if (!value)
- return withType(Array::ForceExit);
- if (isInt32Speculation(value))
- return withTypeAndConversion(Array::Int32, Array::Convert);
- if (isNumberSpeculation(value))
- return withTypeAndConversion(Array::Double, Array::Convert);
- return withTypeAndConversion(Array::Contiguous, Array::Convert);
-
- case Array::Int32:
- if (!value || isInt32Speculation(value))
- return *this;
- if (isNumberSpeculation(value))
- return withTypeAndConversion(Array::Double, Array::Convert);
- return withTypeAndConversion(Array::Contiguous, Array::Convert);
-
- case Array::Double:
- if (!value || isNumberSpeculation(value))
- return *this;
- return withTypeAndConversion(Array::Contiguous, Array::Convert);
-
- case Array::SelectUsingPredictions:
- if (isStringSpeculation(base))
- return ArrayMode(Array::String);
-
- if (isArgumentsSpeculation(base))
- return ArrayMode(Array::Arguments);
-
- if (isInt8ArraySpeculation(base))
- return ArrayMode(Array::Int8Array);
-
- if (isInt16ArraySpeculation(base))
- return ArrayMode(Array::Int16Array);
-
- if (isInt32ArraySpeculation(base))
- return ArrayMode(Array::Int32Array);
-
- if (isUint8ArraySpeculation(base))
- return ArrayMode(Array::Uint8Array);
-
- if (isUint8ClampedArraySpeculation(base))
- return ArrayMode(Array::Uint8ClampedArray);
-
- if (isUint16ArraySpeculation(base))
- return ArrayMode(Array::Uint16Array);
-
- if (isUint32ArraySpeculation(base))
- return ArrayMode(Array::Uint32Array);
-
- if (isFloat32ArraySpeculation(base))
- return ArrayMode(Array::Float32Array);
-
- if (isFloat64ArraySpeculation(base))
- return ArrayMode(Array::Float64Array);
-
- return ArrayMode(Array::Generic);
-
- default:
- return *this;
- }
-}
-
-bool ArrayMode::alreadyChecked(AbstractValue& value, IndexingType shape) const
-{
- if (isJSArray()) {
- if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray)))
- return true;
- return value.m_currentKnownStructure.hasSingleton()
- && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape
- && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
}
- if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray)))
- return true;
- return value.m_currentKnownStructure.hasSingleton()
- && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape;
+
+ if (type() != Array::SelectUsingPredictions)
+ return *this;
+
+ if (isStringSpeculation(base))
+ return ArrayMode(Array::String);
+
+ if (isArgumentsSpeculation(base))
+ return ArrayMode(Array::Arguments);
+
+ if (isInt8ArraySpeculation(base))
+ return ArrayMode(Array::Int8Array);
+
+ if (isInt16ArraySpeculation(base))
+ return ArrayMode(Array::Int16Array);
+
+ if (isInt32ArraySpeculation(base))
+ return ArrayMode(Array::Int32Array);
+
+ if (isUint8ArraySpeculation(base))
+ return ArrayMode(Array::Uint8Array);
+
+ if (isUint8ClampedArraySpeculation(base))
+ return ArrayMode(Array::Uint8ClampedArray);
+
+ if (isUint16ArraySpeculation(base))
+ return ArrayMode(Array::Uint16Array);
+
+ if (isUint32ArraySpeculation(base))
+ return ArrayMode(Array::Uint32Array);
+
+ if (isFloat32ArraySpeculation(base))
+ return ArrayMode(Array::Float32Array);
+
+ if (isFloat64ArraySpeculation(base))
+ return ArrayMode(Array::Float64Array);
+
+ return ArrayMode(Array::Generic);
}
bool ArrayMode::alreadyChecked(AbstractValue& value) const
@@ -227,17 +161,31 @@ bool ArrayMode::alreadyChecked(AbstractValue& value) const
case Array::String:
return speculationChecked(value.m_type, SpecString);
- case Array::Int32:
- return alreadyChecked(value, Int32Shape);
-
- case Array::Double:
- return alreadyChecked(value, DoubleShape);
-
case Array::Contiguous:
- return alreadyChecked(value, ContiguousShape);
+ if (isJSArray()) {
+ if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithContiguous)))
+ return true;
+ return value.m_currentKnownStructure.hasSingleton()
+ && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType())
+ && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
+ }
+ if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous)))
+ return true;
+ return value.m_currentKnownStructure.hasSingleton()
+ && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType());
case Array::ArrayStorage:
- return alreadyChecked(value, ArrayStorageShape);
+ if (isJSArray()) {
+ if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage)))
+ return true;
+ return value.m_currentKnownStructure.hasSingleton()
+ && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType())
+ && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
+ }
+ if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage)))
+ return true;
+ return value.m_currentKnownStructure.hasSingleton()
+ && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType());
case Array::SlowPutArrayStorage:
if (isJSArray()) {
@@ -284,7 +232,6 @@ bool ArrayMode::alreadyChecked(AbstractValue& value) const
case Array::SelectUsingPredictions:
case Array::Unprofiled:
- case Array::Undecided:
break;
}
@@ -305,12 +252,6 @@ const char* arrayTypeToString(Array::Type type)
return "ForceExit";
case Array::String:
return "String";
- case Array::Undecided:
- return "Undecided";
- case Array::Int32:
- return "Int32";
- case Array::Double:
- return "Double";
case Array::Contiguous:
return "Contiguous";
case Array::ArrayStorage:
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.h b/Source/JavaScriptCore/dfg/DFGArrayMode.h
index 206d689f2..615965c92 100644
--- a/Source/JavaScriptCore/dfg/DFGArrayMode.h
+++ b/Source/JavaScriptCore/dfg/DFGArrayMode.h
@@ -52,10 +52,7 @@ enum Type {
ForceExit, // Implies that we have no idea how to execute this operation, so we should just give up.
Generic,
String,
-
- Undecided,
- Int32,
- Double,
+
Contiguous,
ArrayStorage,
SlowPutArrayStorage,
@@ -84,6 +81,7 @@ enum Speculation {
ToHole,
OutOfBounds
};
+
enum Conversion {
AsIs,
Convert
@@ -171,17 +169,7 @@ public:
return ArrayMode(type(), myArrayClass, mySpeculation, conversion());
}
- ArrayMode withType(Array::Type type) const
- {
- return ArrayMode(type, arrayClass(), speculation(), conversion());
- }
-
- ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const
- {
- return ArrayMode(type, arrayClass(), speculation(), conversion);
- }
-
- ArrayMode refine(SpeculatedType base, SpeculatedType index, SpeculatedType value = SpecNone) const;
+ ArrayMode refine(SpeculatedType base, SpeculatedType index) const;
bool alreadyChecked(AbstractValue&) const;
@@ -190,8 +178,6 @@ public:
bool usesButterfly() const
{
switch (type()) {
- case Array::Int32:
- case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage:
case Array::SlowPutArrayStorage:
@@ -277,7 +263,6 @@ public:
case Array::Unprofiled:
case Array::ForceExit:
case Array::Generic:
- case Array::Undecided:
return false;
default:
return true;
@@ -292,8 +277,6 @@ public:
case Array::ForceExit:
case Array::Generic:
return false;
- case Array::Int32:
- case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage:
case Array::SlowPutArrayStorage:
@@ -326,10 +309,6 @@ public:
switch (type()) {
case Array::Generic:
return ALL_ARRAY_MODES;
- case Array::Int32:
- return arrayModesWithIndexingShape(Int32Shape);
- case Array::Double:
- return arrayModesWithIndexingShape(DoubleShape);
case Array::Contiguous:
return arrayModesWithIndexingShape(ContiguousShape);
case Array::ArrayStorage:
@@ -375,8 +354,6 @@ private:
}
}
- bool alreadyChecked(AbstractValue&, IndexingType shape) const;
-
union {
struct {
uint8_t type;
diff --git a/Source/JavaScriptCore/dfg/DFGBasicBlock.h b/Source/JavaScriptCore/dfg/DFGBasicBlock.h
index 6f348f2e1..441e2e75e 100644
--- a/Source/JavaScriptCore/dfg/DFGBasicBlock.h
+++ b/Source/JavaScriptCore/dfg/DFGBasicBlock.h
@@ -29,7 +29,6 @@
#if ENABLE(DFG_JIT)
#include "DFGAbstractValue.h"
-#include "DFGBranchDirection.h"
#include "DFGNode.h"
#include "Operands.h"
#include <wtf/OwnPtr.h>
@@ -47,7 +46,6 @@ struct BasicBlock : Vector<NodeIndex, 8> {
, cfaShouldRevisit(false)
, cfaFoundConstants(false)
, cfaDidFinish(true)
- , cfaBranchDirection(InvalidBranchDirection)
#if !ASSERT_DISABLED
, isLinked(false)
#endif
@@ -107,7 +105,6 @@ struct BasicBlock : Vector<NodeIndex, 8> {
bool cfaShouldRevisit;
bool cfaFoundConstants;
bool cfaDidFinish;
- BranchDirection cfaBranchDirection;
#if !ASSERT_DISABLED
bool isLinked;
#endif
diff --git a/Source/JavaScriptCore/dfg/DFGBranchDirection.h b/Source/JavaScriptCore/dfg/DFGBranchDirection.h
deleted file mode 100644
index 8bbe3c635..000000000
--- a/Source/JavaScriptCore/dfg/DFGBranchDirection.h
+++ /dev/null
@@ -1,88 +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 DFGBranchDirection_h
-#define DFGBranchDirection_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
-
-namespace JSC { namespace DFG {
-
-enum BranchDirection {
- // This is not a branch and so there is no branch direction, or
- // the branch direction has yet to be set.
- InvalidBranchDirection,
-
- // The branch takes the true case.
- TakeTrue,
-
- // The branch takes the false case.
- TakeFalse,
-
- // For all we know, the branch could go either direction, so we
- // have to assume the worst.
- TakeBoth
-};
-
-static inline const char* branchDirectionToString(BranchDirection branchDirection)
-{
- switch (branchDirection) {
- case InvalidBranchDirection:
- return "Invalid";
- case TakeTrue:
- return "TakeTrue";
- case TakeFalse:
- return "TakeFalse";
- case TakeBoth:
- return "TakeBoth";
- }
-}
-
-static inline bool isKnownDirection(BranchDirection branchDirection)
-{
- switch (branchDirection) {
- case TakeTrue:
- case TakeFalse:
- return true;
- default:
- return false;
- }
-}
-
-static inline bool branchCondition(BranchDirection branchDirection)
-{
- if (branchDirection == TakeTrue)
- return true;
- ASSERT(branchDirection == TakeFalse);
- return false;
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
-#endif // DFGBranchDirection_h
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 142b8ab95..70aa2b637 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -905,15 +905,10 @@ private:
return getPrediction(m_graph.size(), m_currentProfilingIndex);
}
- ArrayMode getArrayMode(ArrayProfile* profile, Array::Action action)
- {
- profile->computeUpdatedPrediction(m_inlineStackTop->m_codeBlock);
- return ArrayMode::fromObserved(profile, action, false);
- }
-
ArrayMode getArrayMode(ArrayProfile* profile)
{
- return getArrayMode(profile, Array::Read);
+ profile->computeUpdatedPrediction(m_inlineStackTop->m_codeBlock);
+ return ArrayMode::fromObserved(profile, Array::Read, false);
}
ArrayMode getArrayModeAndEmitChecks(ArrayProfile* profile, Array::Action action, NodeIndex base)
@@ -1654,12 +1649,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
return false;
ArrayMode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile);
- if (!arrayMode.isJSArray())
- return false;
switch (arrayMode.type()) {
- case Array::Undecided:
- case Array::Int32:
- case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage: {
NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
@@ -1679,11 +1669,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
return false;
ArrayMode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile);
- if (!arrayMode.isJSArray())
- return false;
switch (arrayMode.type()) {
- case Array::Int32:
- case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage: {
NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(registerOffset + argumentToOperand(0)));
@@ -1768,7 +1754,7 @@ bool ByteCodeParser::handleConstantInternalFunction(
if (argumentCountIncludingThis == 2) {
setIntrinsicResult(
usesResult, resultOperand,
- addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(registerOffset + argumentToOperand(1))));
+ addToGraph(NewArrayWithSize, get(registerOffset + argumentToOperand(1))));
return true;
}
@@ -1776,7 +1762,7 @@ bool ByteCodeParser::handleConstantInternalFunction(
addVarArgChild(get(registerOffset + argumentToOperand(i)));
setIntrinsicResult(
usesResult, resultOperand,
- addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
+ addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0)));
return true;
}
@@ -2136,37 +2122,24 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_new_array: {
int startOperand = currentInstruction[2].u.operand;
int numOperands = currentInstruction[3].u.operand;
- ArrayAllocationProfile* profile = currentInstruction[4].u.arrayAllocationProfile;
for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx)
addVarArgChild(get(operandIdx));
- set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(profile->selectIndexingType()), OpInfo(0)));
+ set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0)));
NEXT_OPCODE(op_new_array);
}
case op_new_array_with_size: {
int lengthOperand = currentInstruction[2].u.operand;
- ArrayAllocationProfile* profile = currentInstruction[3].u.arrayAllocationProfile;
- set(currentInstruction[1].u.operand, addToGraph(NewArrayWithSize, OpInfo(profile->selectIndexingType()), get(lengthOperand)));
+ set(currentInstruction[1].u.operand, addToGraph(NewArrayWithSize, get(lengthOperand)));
NEXT_OPCODE(op_new_array_with_size);
}
case op_new_array_buffer: {
int startConstant = currentInstruction[2].u.operand;
int numConstants = currentInstruction[3].u.operand;
- ArrayAllocationProfile* profile = currentInstruction[4].u.arrayAllocationProfile;
NewArrayBufferData data;
data.startConstant = m_inlineStackTop->m_constantBufferRemap[startConstant];
data.numConstants = numConstants;
- data.indexingType = profile->selectIndexingType();
-
- // If this statement has never executed, we'll have the wrong indexing type in the profile.
- for (int i = 0; i < numConstants; ++i) {
- data.indexingType =
- leastUpperBoundOfIndexingTypeAndValue(
- data.indexingType,
- m_codeBlock->constantBuffer(data.startConstant)[i]);
- }
-
m_graph.m_newArrayBufferData.append(data);
set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(&m_graph.m_newArrayBufferData.last())));
NEXT_OPCODE(op_new_array_buffer);
diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
index 308dde5a6..a2570b7ea 100644
--- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
+++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
@@ -210,15 +210,6 @@ public:
addCallArgument(arg3);
}
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, GPRReg arg3)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- }
-
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
{
resetCallArguments();
@@ -277,16 +268,6 @@ public:
addCallArgument(arg4);
}
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- addCallArgument(arg4);
- }
-
ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
{
resetCallArguments();
@@ -336,23 +317,6 @@ public:
addCallArgument(arg4);
addCallArgument(arg5);
}
-
- ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
- {
- resetCallArguments();
- addCallArgument(GPRInfo::callFrameRegister);
- addCallArgument(arg1);
- addCallArgument(arg2);
- addCallArgument(arg3);
- }
#endif // !NUMBER_OF_ARGUMENT_REGISTERS
// These methods are suitable for any calling convention that provides for
// at least 4 argument registers, e.g. X86_64, ARMv7.
@@ -499,20 +463,6 @@ public:
{
setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
}
-
- ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
- {
- moveDouble(arg1, FPRInfo::argumentFPR0);
- move(arg2, GPRInfo::argumentGPR1);
- move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
- {
- moveDouble(arg3, FPRInfo::argumentFPR0);
- setupStubArguments(arg1, arg2);
- move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
#elif CPU(ARM)
#if CPU(ARM_HARDFP)
ALWAYS_INLINE void setupArguments(FPRReg arg1)
@@ -546,21 +496,6 @@ public:
assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
}
-
- ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
- {
- move(arg2, GPRInfo::argumentGPR3);
- assembler().vmov(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, arg1);
- move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
- {
- setupStubArguments(arg1, arg2);
- move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- assembler().vmov(GPRInfo::argumentGPR3, GPRInfo::nonArgGPR0, arg3);
- poke(GPRInfo::nonArgGPR0);
- }
#endif // CPU(ARM_HARDFP)
#else
#error "DFG JIT not supported on this platform."
@@ -700,13 +635,6 @@ public:
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, GPRReg arg3)
- {
- setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
- move(arg2, GPRInfo::argumentGPR2);
- move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- }
-
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
{
move(arg1, GPRInfo::argumentGPR1);
@@ -795,12 +723,6 @@ public:
setupArgumentsWithExecState(arg1, arg2, arg3);
}
- ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4)
- {
- poke(arg4);
- setupArgumentsWithExecState(arg1, arg2, arg3);
- }
-
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4)
{
poke(arg4);
diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
index e3827d8ad..e0d973992 100644
--- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
@@ -99,8 +99,9 @@ public:
case Branch: {
// Branch on constant -> jettison the not-taken block and merge.
- if (isKnownDirection(block->cfaBranchDirection)) {
- bool condition = branchCondition(block->cfaBranchDirection);
+ if (m_graph[m_graph[block->last()].child1()].hasConstant()) {
+ bool condition =
+ m_graph.valueOfJSConstant(m_graph[block->last()].child1().index()).toBoolean(m_graph.globalObjectFor(m_graph[block->last()].codeOrigin)->globalExec());
BasicBlock* targetBlock = m_graph.m_blocks[
m_graph.successorForCondition(block, condition)].get();
if (targetBlock->m_predecessors.size() == 1) {
@@ -729,7 +730,6 @@ private:
}
firstBlock->valuesAtTail = secondBlock->valuesAtTail;
- firstBlock->cfaBranchDirection = secondBlock->cfaBranchDirection;
m_graph.m_blocks[secondBlockIndex].clear();
}
diff --git a/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h b/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h
index 03713b6c5..46d5f44cb 100644
--- a/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h
+++ b/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h
@@ -61,7 +61,7 @@ protected:
jit->silentSpill(m_plans[i]);
jit->callOperation(m_function, m_resultGPR, m_structure, m_size);
GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
- for (unsigned i = m_plans.size(); i--;)
+ 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);
@@ -106,7 +106,7 @@ protected:
done.link(&jit->m_jit);
jit->callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR);
GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
- for (unsigned i = m_plans.size(); i--;)
+ for (unsigned i = 0; i < m_plans.size(); ++i)
jit->silentFill(m_plans[i], canTrample);
jumpTo(jit);
}
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 621d6e96a..5a76aa8df 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -145,30 +145,7 @@ private:
}
case ArrayPush: {
- // May need to refine the array mode in case the value prediction contravenes
- // the array prediction. For example, we may have evidence showing that the
- // array is in Int32 mode, but the value we're storing is likely to be a double.
- // Then we should turn this into a conversion to Double array followed by the
- // push. On the other hand, we absolutely don't want to refine based on the
- // base prediction. If it has non-cell garbage in it, then we want that to be
- // ignored. That's because ArrayPush can't handle any array modes that aren't
- // array-related - so if refine() turned this into a "Generic" ArrayPush then
- // that would break things.
- node.setArrayMode(
- node.arrayMode().refine(
- m_graph[node.child1()].prediction() & SpecCell,
- SpecInt32,
- m_graph[node.child2()].prediction()));
blessArrayOperation(node.child1(), node.child2(), 2);
-
- Node* nodePtr = &m_graph[m_compileIndex];
- switch (nodePtr->arrayMode().type()) {
- case Array::Double:
- fixDoubleEdge(1);
- break;
- default:
- break;
- }
break;
}
@@ -259,7 +236,7 @@ private:
case ValueAdd: {
if (m_graph.addShouldSpeculateInteger(node))
break;
- if (!Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()]))
+ if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
break;
fixDoubleEdge(0);
fixDoubleEdge(1);
@@ -285,7 +262,7 @@ private:
case ArithMin:
case ArithMax:
case ArithMod: {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
+ if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
&& node.canSpeculateInteger())
break;
fixDoubleEdge(0);
@@ -302,7 +279,7 @@ private:
}
case ArithDiv: {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
+ if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
&& node.canSpeculateInteger()) {
if (isX86())
break;
@@ -330,7 +307,7 @@ private:
}
case ArithAbs: {
- if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
+ if (m_graph[node.child1()].shouldSpeculateInteger()
&& node.canSpeculateInteger())
break;
fixDoubleEdge(0);
@@ -351,17 +328,13 @@ private:
node.setArrayMode(
node.arrayMode().refine(
m_graph[child1].prediction(),
- m_graph[child2].prediction(),
- m_graph[child3].prediction()));
+ m_graph[child2].prediction()));
blessArrayOperation(child1, child2, 3);
Node* nodePtr = &m_graph[m_compileIndex];
switch (nodePtr->arrayMode().modeForPut().type()) {
- case Array::Double:
- fixDoubleEdge(2);
- break;
case Array::Int8Array:
case Array::Int16Array:
case Array::Int32Array:
@@ -382,19 +355,6 @@ private:
break;
}
- case NewArray: {
- for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
- node.setIndexingType(
- leastUpperBoundOfIndexingTypeAndType(
- node.indexingType(), m_graph[m_graph.varArgChild(node, i)].prediction()));
- }
- if (node.indexingType() == ArrayWithDouble) {
- for (unsigned i = m_graph.varArgNumChildren(node); i--;)
- fixDoubleEdge(i);
- }
- break;
- }
-
default:
break;
}
@@ -432,17 +392,15 @@ private:
if (arrayMode.isJSArrayWithOriginalStructure()) {
JSGlobalObject* globalObject = m_graph.baselineCodeBlockFor(codeOrigin)->globalObject();
switch (arrayMode.type()) {
- case Array::Int32:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithInt32);
- break;
- case Array::Double:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithDouble);
- break;
case Array::Contiguous:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous);
+ structure = globalObject->arrayStructure();
+ if (structure->indexingType() != ArrayWithContiguous)
+ structure = 0;
break;
case Array::ArrayStorage:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage);
+ structure = globalObject->arrayStructureWithArrayStorage();
+ if (structure->indexingType() != ArrayWithArrayStorage)
+ structure = 0;
break;
default:
break;
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp
index 38079f020..8e8817f81 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp
@@ -287,11 +287,6 @@ void Graph::dump(const char* prefix, NodeIndex nodeIndex)
dataLog("]");
hasPrinted = true;
}
- if (node.hasIndexingType()) {
- if (hasPrinted)
- dataLog(", ");
- dataLog("%s", indexingTypeToString(node.indexingType()));
- }
if (op == JSConstant) {
dataLog("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
JSValue value = valueOfJSConstant(nodeIndex);
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 4de2e0e26..9fbb2df07 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -220,7 +220,7 @@ public:
if (right.hasConstant())
return addImmediateShouldSpeculateInteger(add, left, right);
- return Node::shouldSpeculateIntegerExpectingDefined(left, right) && add.canSpeculateInteger();
+ return Node::shouldSpeculateInteger(left, right) && add.canSpeculateInteger();
}
bool mulShouldSpeculateInteger(Node& mul)
@@ -235,13 +235,13 @@ public:
if (right.hasConstant())
return mulImmediateShouldSpeculateInteger(mul, left, right);
- return Node::shouldSpeculateIntegerForArithmetic(left, right) && mul.canSpeculateInteger() && !nodeMayOverflow(mul.arithNodeFlags());
+ return Node::shouldSpeculateInteger(left, right) && mul.canSpeculateInteger() && !nodeMayOverflow(mul.arithNodeFlags());
}
bool negateShouldSpeculateInteger(Node& negate)
{
ASSERT(negate.op() == ArithNegate);
- return at(negate.child1()).shouldSpeculateIntegerForArithmetic() && negate.canSpeculateInteger();
+ return at(negate.child1()).shouldSpeculateInteger() && negate.canSpeculateInteger();
}
bool addShouldSpeculateInteger(NodeIndex nodeIndex)
@@ -493,8 +493,6 @@ public:
switch (node.arrayMode().type()) {
case Array::Generic:
return false;
- case Array::Int32:
- case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage:
return !node.arrayMode().isOutOfBounds();
@@ -714,7 +712,7 @@ private:
if (!immediateValue.isNumber())
return false;
- if (!variable.shouldSpeculateIntegerExpectingDefined())
+ if (!variable.shouldSpeculateInteger())
return false;
if (immediateValue.isInt32())
@@ -736,7 +734,7 @@ private:
if (!immediateValue.isInt32())
return false;
- if (!variable.shouldSpeculateIntegerForArithmetic())
+ if (!variable.shouldSpeculateInteger())
return false;
int32_t intImmediate = immediateValue.asInt32();
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index bff7fe65f..e66629ec4 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -62,7 +62,6 @@ struct StructureTransitionData {
struct NewArrayBufferData {
unsigned startConstant;
unsigned numConstants;
- IndexingType indexingType;
};
// This type used in passing an immediate argument to Node constructor;
@@ -434,32 +433,6 @@ struct Node {
return newArrayBufferData()->numConstants;
}
- bool hasIndexingType()
- {
- switch (op()) {
- case NewArray:
- case NewArrayWithSize:
- case NewArrayBuffer:
- return true;
- default:
- return false;
- }
- }
-
- IndexingType indexingType()
- {
- ASSERT(hasIndexingType());
- if (op() == NewArrayBuffer)
- return newArrayBufferData()->indexingType;
- return m_opInfo;
- }
-
- void setIndexingType(IndexingType indexingType)
- {
- ASSERT(hasIndexingType());
- m_opInfo = indexingType;
- }
-
bool hasRegexpIndex()
{
return op() == NewRegexp;
@@ -949,36 +922,16 @@ struct Node {
return isInt32Speculation(prediction());
}
- bool shouldSpeculateIntegerForArithmetic()
- {
- return isInt32SpeculationForArithmetic(prediction());
- }
-
- bool shouldSpeculateIntegerExpectingDefined()
- {
- return isInt32SpeculationExpectingDefined(prediction());
- }
-
bool shouldSpeculateDouble()
{
return isDoubleSpeculation(prediction());
}
- bool shouldSpeculateDoubleForArithmetic()
- {
- return isDoubleSpeculationForArithmetic(prediction());
- }
-
bool shouldSpeculateNumber()
{
return isNumberSpeculation(prediction());
}
- bool shouldSpeculateNumberExpectingDefined()
- {
- return isNumberSpeculationExpectingDefined(prediction());
- }
-
bool shouldSpeculateBoolean()
{
return isBooleanSpeculation(prediction());
@@ -1084,31 +1037,11 @@ struct Node {
return op1.shouldSpeculateInteger() && op2.shouldSpeculateInteger();
}
- static bool shouldSpeculateIntegerForArithmetic(Node& op1, Node& op2)
- {
- return op1.shouldSpeculateIntegerForArithmetic() && op2.shouldSpeculateIntegerForArithmetic();
- }
-
- static bool shouldSpeculateIntegerExpectingDefined(Node& op1, Node& op2)
- {
- return op1.shouldSpeculateIntegerExpectingDefined() && op2.shouldSpeculateIntegerExpectingDefined();
- }
-
- static bool shouldSpeculateDoubleForArithmetic(Node& op1, Node& op2)
- {
- return op1.shouldSpeculateDoubleForArithmetic() && op2.shouldSpeculateDoubleForArithmetic();
- }
-
static bool shouldSpeculateNumber(Node& op1, Node& op2)
{
return op1.shouldSpeculateNumber() && op2.shouldSpeculateNumber();
}
- static bool shouldSpeculateNumberExpectingDefined(Node& op1, Node& op2)
- {
- return op1.shouldSpeculateNumberExpectingDefined() && op2.shouldSpeculateNumberExpectingDefined();
- }
-
static bool shouldSpeculateFinalObject(Node& op1, Node& op2)
{
return op1.shouldSpeculateFinalObject() && op2.shouldSpeculateFinalObject();
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index 8356d22f9..0e45e230c 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -27,9 +27,9 @@
#include "DFGOperations.h"
#include "Arguments.h"
-#include "ButterflyInlines.h"
+#include "ButterflyInlineMethods.h"
#include "CodeBlock.h"
-#include "CopiedSpaceInlines.h"
+#include "CopiedSpaceInlineMethods.h"
#include "DFGOSRExit.h"
#include "DFGRepatch.h"
#include "DFGThunks.h"
@@ -580,40 +580,6 @@ void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec,
array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
}
-void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
-{
- JSGlobalData* globalData = &exec->globalData();
- NativeCallFrameTracer tracer(globalData, exec);
-
- JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
-
- if (index >= 0) {
- array->putByIndexInline(exec, index, jsValue, true);
- return;
- }
-
- PutPropertySlot slot(true);
- array->methodTable()->put(
- array, exec, Identifier::from(exec, index), jsValue, slot);
-}
-
-void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
-{
- JSGlobalData* globalData = &exec->globalData();
- NativeCallFrameTracer tracer(globalData, exec);
-
- JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
-
- if (index >= 0) {
- array->putByIndexInline(exec, index, jsValue, false);
- return;
- }
-
- PutPropertySlot slot(false);
- array->methodTable()->put(
- array, exec, Identifier::from(exec, index), jsValue, slot);
-}
-
EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
{
JSGlobalData* globalData = &exec->globalData();
@@ -623,15 +589,6 @@ EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue
return JSValue::encode(jsNumber(array->length()));
}
-EncodedJSValue DFG_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
-{
- JSGlobalData* globalData = &exec->globalData();
- NativeCallFrameTracer tracer(globalData, exec);
-
- array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
- return JSValue::encode(jsNumber(array->length()));
-}
-
EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
{
JSGlobalData* globalData = &exec->globalData();
@@ -1370,36 +1327,30 @@ char* DFG_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState*
return reinterpret_cast<char*>(result);
}
-char* DFG_OPERATION operationEnsureInt32(ExecState* exec, JSObject* object)
+char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSObject* object)
{
JSGlobalData& globalData = exec->globalData();
NativeCallFrameTracer tracer(&globalData, exec);
- return reinterpret_cast<char*>(object->ensureInt32(globalData));
+ return reinterpret_cast<char*>(object->ensureContiguous(globalData));
}
-char* DFG_OPERATION operationEnsureDouble(ExecState* exec, JSObject* object)
+char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSObject* object)
{
JSGlobalData& globalData = exec->globalData();
NativeCallFrameTracer tracer(&globalData, exec);
-
- return reinterpret_cast<char*>(object->ensureDouble(globalData));
-}
-char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSObject* object)
-{
- JSGlobalData& globalData = exec->globalData();
- NativeCallFrameTracer tracer(&globalData, exec);
-
- return reinterpret_cast<char*>(object->ensureContiguous(globalData));
+ return reinterpret_cast<char*>(object->ensureArrayStorage(globalData));
}
-char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSObject* object)
+char* DFG_OPERATION operationEnsureContiguousOrArrayStorage(ExecState* exec, JSObject* object, int32_t index)
{
JSGlobalData& globalData = exec->globalData();
NativeCallFrameTracer tracer(&globalData, exec);
- return reinterpret_cast<char*>(object->ensureArrayStorage(globalData));
+ 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)
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index b99c214e9..8d2beacec 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -64,7 +64,6 @@ typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EAZ)(ExecState*, JSArray*,
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
-typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EDA)(ExecState*, double, JSArray*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGriJsgI)(ExecState*, ResolveOperation*, JSGlobalObject*, Identifier*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EI)(ExecState*, Identifier*);
typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EIRo)(ExecState*, Identifier*, ResolveOperations*);
@@ -93,7 +92,6 @@ typedef size_t DFG_OPERATION (*S_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*)
typedef size_t DFG_OPERATION (*S_DFGOperation_EJ)(ExecState*, EncodedJSValue);
typedef size_t DFG_OPERATION (*S_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
typedef size_t DFG_OPERATION (*S_DFGOperation_J)(EncodedJSValue);
-typedef void DFG_OPERATION (*V_DFGOperation_EOZD)(ExecState*, JSObject*, int32_t, double);
typedef void DFG_OPERATION (*V_DFGOperation_EOZJ)(ExecState*, JSObject*, int32_t, EncodedJSValue);
typedef void DFG_OPERATION (*V_DFGOperation_EC)(ExecState*, JSCell*);
typedef void DFG_OPERATION (*V_DFGOperation_ECIcf)(ExecState*, JSCell*, InlineCallFrame*);
@@ -150,10 +148,7 @@ void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSVal
void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSObject*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL;
-void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL;
-void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL;
EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
-EncodedJSValue DFG_OPERATION operationArrayPushDouble(ExecState*, double value, 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;
@@ -200,10 +195,9 @@ 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 operationEnsureInt32(ExecState*, JSObject*);
-char* DFG_OPERATION operationEnsureDouble(ExecState*, JSObject*);
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/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index b5fde4eee..3e8ead5c6 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -225,6 +225,24 @@ private:
break;
}
+ case ArithMod: {
+ SpeculatedType left = m_graph[node.child1()].prediction();
+ SpeculatedType right = m_graph[node.child2()].prediction();
+
+ if (left && right) {
+ if (isInt32Speculation(mergeSpeculations(left, right))
+ && nodeCanSpeculateInteger(node.arithNodeFlags()))
+ changed |= mergePrediction(SpecInt32);
+ else
+ changed |= mergePrediction(SpecDouble);
+ }
+
+ flags |= NodeUsedAsValue;
+ changed |= m_graph[node.child1()].mergeFlags(flags);
+ changed |= m_graph[node.child2()].mergeFlags(flags);
+ break;
+ }
+
case UInt32ToNumber: {
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
@@ -240,7 +258,7 @@ private:
SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)) {
if (m_graph.addShouldSpeculateInteger(node))
changed |= mergePrediction(SpecInt32);
else
@@ -315,7 +333,7 @@ private:
SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
@@ -355,7 +373,7 @@ private:
SpeculatedType right = m_graph[node.child2()].prediction();
if (left && right) {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
+ if (isInt32Speculation(mergeSpeculations(left, right))
&& nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(SpecInt32);
else
@@ -364,7 +382,7 @@ private:
// As soon as a multiply happens, we can easily end up in the part
// of the double domain where the point at which you do truncation
- // can change the outcome. So, ArithDiv always checks for overflow
+ // can change the outcome. So, ArithMul always checks for overflow
// no matter what, and always forces its inputs to check as well.
flags |= NodeUsedAsNumber | NodeNeedsNegZero;
@@ -373,24 +391,6 @@ private:
break;
}
- case ArithMod: {
- SpeculatedType left = m_graph[node.child1()].prediction();
- SpeculatedType right = m_graph[node.child2()].prediction();
-
- if (left && right) {
- if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
- && nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(SpecInt32);
- else
- changed |= mergePrediction(SpecDouble);
- }
-
- flags |= NodeUsedAsValue;
- changed |= m_graph[node.child1()].mergeFlags(flags);
- changed |= m_graph[node.child2()].mergeFlags(flags);
- break;
- }
-
case ArithSqrt: {
changed |= setPrediction(SpecDouble);
changed |= m_graph[node.child1()].mergeFlags(flags | NodeUsedAsValue);
@@ -399,11 +399,10 @@ private:
case ArithAbs: {
SpeculatedType child = m_graph[node.child1()].prediction();
- if (isInt32SpeculationForArithmetic(child)
- && nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(SpecInt32);
+ if (nodeCanSpeculateInteger(node.arithNodeFlags()))
+ changed |= mergePrediction(child);
else
- changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
+ changed |= setPrediction(speculatedDoubleTypeForPrediction(child));
flags &= ~NodeNeedsNegZero;
changed |= m_graph[node.child1()].mergeFlags(flags);
@@ -777,7 +776,7 @@ private:
DoubleBallot ballot;
- if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)
+ if (isNumberSpeculation(left) && isNumberSpeculation(right)
&& !m_graph.addShouldSpeculateInteger(node))
ballot = VoteDouble;
else
@@ -815,7 +814,7 @@ private:
DoubleBallot ballot;
if (isNumberSpeculation(left) && isNumberSpeculation(right)
- && !(Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child1()])
+ && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()])
&& node.canSpeculateInteger()))
ballot = VoteDouble;
else
@@ -828,7 +827,7 @@ private:
case ArithAbs:
DoubleBallot ballot;
- if (!(m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
+ if (!(m_graph[node.child1()].shouldSpeculateInteger()
&& node.canSpeculateInteger()))
ballot = VoteDouble;
else
@@ -850,24 +849,6 @@ private:
break;
}
- case PutByVal:
- case PutByValAlias: {
- Edge child1 = m_graph.varArgChild(node, 0);
- Edge child2 = m_graph.varArgChild(node, 1);
- Edge child3 = m_graph.varArgChild(node, 2);
- m_graph.vote(child1, VoteValue);
- m_graph.vote(child2, VoteValue);
- switch (node.arrayMode().type()) {
- case Array::Double:
- m_graph.vote(child3, VoteDouble);
- break;
- default:
- m_graph.vote(child3, VoteValue);
- break;
- }
- break;
- }
-
default:
m_graph.vote(node, VoteValue);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 829bc14ff..6bedd6d68 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -59,7 +59,7 @@ SpeculativeJIT::~SpeculativeJIT()
void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR, GPRReg storageGPR, unsigned numElements)
{
- ASSERT(hasUndecided(structure->indexingType()) || hasInt32(structure->indexingType()) || hasDouble(structure->indexingType()) || hasContiguous(structure->indexingType()));
+ ASSERT(hasContiguous(structure->indexingType()));
GPRTemporary scratch(this);
GPRReg scratchGPR = scratch.gpr();
@@ -67,7 +67,6 @@ void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR,
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);
@@ -80,21 +79,6 @@ void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR,
m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
- if (hasDouble(structure->indexingType()) && numElements < vectorLength) {
-#if USE(JSVALUE64)
- m_jit.move(TrustedImm64(bitwise_cast<int64_t>(QNaN)), scratchGPR);
- for (unsigned i = numElements; i < vectorLength; ++i)
- m_jit.store64(scratchGPR, MacroAssembler::Address(storageGPR, sizeof(double) * i));
-#else
- EncodedValueDescriptor value;
- value.asInt64 = JSValue::encode(JSValue(JSValue::EncodeAsDouble, QNaN));
- for (unsigned i = numElements; i < vectorLength; ++i) {
- m_jit.store32(TrustedImm32(value.asBits.tag), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(TrustedImm32(value.asBits.payload), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- }
-#endif
- }
-
// 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. :-/
@@ -359,31 +343,24 @@ const TypedArrayDescriptor* SpeculativeJIT::typedArrayDescriptor(ArrayMode array
}
}
-JITCompiler::Jump SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, IndexingType shape, bool invert)
-{
- if (arrayMode.isJSArray()) {
- m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
- return m_jit.branch32(
- invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape));
- }
- m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
- return m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape));
-}
-
JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, bool invert)
{
JITCompiler::JumpList result;
switch (arrayMode.type()) {
- case Array::Int32:
- return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, Int32Shape, invert);
-
- case Array::Double:
- return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, DoubleShape, invert);
-
- case Array::Contiguous:
- return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, ContiguousShape, invert);
-
+ case Array::Contiguous: {
+ if (arrayMode.isJSArray()) {
+ m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
+ result.append(
+ m_jit.branch32(
+ invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | ContiguousShape)));
+ break;
+ }
+ m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
+ result.append(
+ m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(ContiguousShape)));
+ break;
+ }
case Array::ArrayStorage:
case Array::SlowPutArrayStorage: {
if (arrayMode.isJSArray()) {
@@ -460,8 +437,6 @@ void SpeculativeJIT::checkArray(Node& node)
case Array::String:
expectedClassInfo = &JSString::s_info;
break;
- case Array::Int32:
- case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage:
case Array::SlowPutArrayStorage: {
@@ -553,30 +528,16 @@ void SpeculativeJIT::arrayify(Node& node, GPRReg baseReg, GPRReg propertyReg)
// If we're allegedly creating contiguous storage and the index is bogus, then
// just don't.
- if (propertyReg != InvalidGPRReg) {
- switch (node.arrayMode().type()) {
- case Array::Int32:
- case Array::Double:
- case Array::Contiguous:
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(
- MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
- break;
- default:
- break;
- }
+ if (node.arrayMode().type() == Array::Contiguous && propertyReg != InvalidGPRReg) {
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branch32(
+ MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
}
// Now call out to create the array storage.
silentSpillAllRegisters(tempGPR);
switch (node.arrayMode().type()) {
- case Array::Int32:
- callOperation(operationEnsureInt32, tempGPR, baseReg);
- break;
- case Array::Double:
- callOperation(operationEnsureDouble, tempGPR, baseReg);
- break;
case Array::Contiguous:
callOperation(operationEnsureContiguous, tempGPR, baseReg);
break;
@@ -1836,85 +1797,6 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
return ValueRecovery();
}
-void SpeculativeJIT::compileDoublePutByVal(Node& node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property)
-{
- Edge child3 = m_jit.graph().varArgChild(node, 2);
- Edge child4 = m_jit.graph().varArgChild(node, 3);
-
- ArrayMode arrayMode = node.arrayMode();
-
- GPRReg baseReg = base.gpr();
- GPRReg propertyReg = property.gpr();
-
- SpeculateDoubleOperand value(this, child3);
-
- FPRReg valueReg = value.fpr();
-
- if (!isRealNumberSpeculation(m_state.forNode(child3).m_type)) {
- // FIXME: We need a way of profiling these, and we need to hoist them into
- // SpeculateDoubleOperand.
- speculationCheck(
- BadType, JSValueRegs(), NoNode,
- m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg));
- }
-
- if (!m_compileOkay)
- return;
-
- StorageOperand storage(this, child4);
- GPRReg storageReg = storage.gpr();
-
- if (node.op() == PutByValAlias) {
- // Store the value to the array.
- GPRReg propertyReg = property.gpr();
- FPRReg valueReg = value.fpr();
- m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
-
- noResult(m_compileIndex);
- return;
- }
-
- GPRTemporary temporary;
- GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
-
- MacroAssembler::JumpList slowCases;
-
- if (arrayMode.isInBounds()) {
- 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 (!arrayMode.isOutOfBounds())
- speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases);
-
- m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
- m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
-
- inBounds.link(&m_jit);
- }
-
- m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
-
- base.use();
- property.use();
- value.use();
- storage.use();
-
- if (arrayMode.isOutOfBounds()) {
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this,
- m_jit.codeBlock()->isStrictMode() ? operationPutDoubleByValBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict,
- NoResult, baseReg, propertyReg, valueReg));
- }
-
- noResult(m_compileIndex, UseChildrenCalledExplicitly);
-}
-
void SpeculativeJIT::compileGetCharCodeAt(Node& node)
{
SpeculateCellOperand string(this, node.child1());
@@ -2881,7 +2763,7 @@ void SpeculativeJIT::compileAdd(Node& node)
return;
}
- if (Node::shouldSpeculateNumberExpectingDefined(at(node.child1()), at(node.child2()))) {
+ if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
SpeculateDoubleOperand op1(this, node.child1());
SpeculateDoubleOperand op2(this, node.child2());
FPRTemporary result(this, op1, op2);
@@ -3119,7 +3001,7 @@ void SpeculativeJIT::compileIntegerArithDivForX86(Node& node)
void SpeculativeJIT::compileArithMod(Node& node)
{
- if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
+ if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))
&& node.canSpeculateInteger()) {
compileSoftModulo(node);
return;
@@ -3454,8 +3336,6 @@ void SpeculativeJIT::compileGetArrayLength(Node& node)
const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode());
switch (node.arrayMode().type()) {
- case Array::Int32:
- case Array::Double:
case Array::Contiguous: {
StorageOperand storage(this, node.child2());
GPRTemporary result(this, storage);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 059d3a6c6..446ea7dbe 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1308,11 +1308,6 @@ public:
m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_DFGOperation_EDA operation, GPRReg result, FPRReg arg1, GPRReg arg2)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2);
- return appendCallWithExceptionCheckSetResult(operation, result);
- }
JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -1458,11 +1453,6 @@ public:
m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallWithExceptionCheck(operation);
}
- JITCompiler::Call callOperation(V_DFGOperation_EOZD operation, GPRReg arg1, GPRReg arg2, FPRReg arg3)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
- return appendCallWithExceptionCheck(operation);
- }
JITCompiler::Call callOperation(V_DFGOperation_EOZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
@@ -1671,21 +1661,11 @@ public:
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier));
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
- JITCompiler::Call callOperation(J_DFGOperation_EDA operation, GPRReg resultTag, GPRReg resultPayload, FPRReg arg1, GPRReg arg2)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2);
- return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
- }
JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2);
return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
}
- JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, TrustedImm32 arg1Tag, GPRReg arg1Payload, GPRReg arg2)
- {
- m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2);
- return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
- }
JITCompiler::Call callOperation(J_DFGOperation_EJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
@@ -1839,21 +1819,11 @@ public:
m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
return appendCallWithExceptionCheck(operation);
}
- JITCompiler::Call callOperation(V_DFGOperation_EOZD operation, GPRReg arg1, GPRReg arg2, FPRReg arg3)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
- return appendCallWithExceptionCheck(operation);
- }
JITCompiler::Call callOperation(V_DFGOperation_EOZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
{
m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
return appendCallWithExceptionCheck(operation);
}
- JITCompiler::Call callOperation(V_DFGOperation_EOZJ operation, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3Tag, GPRReg arg3Payload)
- {
- m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
- return appendCallWithExceptionCheck(operation);
- }
JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet)
{
m_jit.setupArguments(TrustedImmPtr(watchpointSet));
@@ -2300,11 +2270,6 @@ public:
void compileAllocatePropertyStorage(Node&);
void compileReallocatePropertyStorage(Node&);
-#if USE(JSVALUE32_64)
- template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
- void compileContiguousPutByVal(Node&, BaseOperandType&, PropertyOperandType&, ValueOperandType&, GPRReg valuePayloadReg, TagType valueTag);
-#endif
- void compileDoublePutByVal(Node&, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property);
bool putByValWillNeedExtraRegister(ArrayMode arrayMode)
{
return arrayMode.mayStoreToHole();
@@ -2450,7 +2415,6 @@ public:
const TypedArrayDescriptor* typedArrayDescriptor(ArrayMode);
- JITCompiler::Jump jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, ArrayMode, IndexingType, bool invert);
JITCompiler::JumpList jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, ArrayMode, bool invert = false);
void checkArray(Node&);
void arrayify(Node&, GPRReg baseReg, GPRReg propertyReg);
@@ -2991,11 +2955,6 @@ public:
m_gprOrInvalid = m_jit->fillSpeculateInt(index(), m_format);
return m_gprOrInvalid;
}
-
- void use()
- {
- m_jit->use(m_index);
- }
private:
SpeculativeJIT* m_jit;
@@ -3076,11 +3035,6 @@ public:
m_fprOrInvalid = m_jit->fillSpeculateDouble(index());
return m_fprOrInvalid;
}
-
- void use()
- {
- m_jit->use(m_index);
- }
private:
SpeculativeJIT* m_jit;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 694f1452e..65fdf5593 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -2046,69 +2046,6 @@ void SpeculativeJIT::emitBranch(Node& node)
}
}
-template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
-void SpeculativeJIT::compileContiguousPutByVal(Node& node, BaseOperandType& base, PropertyOperandType& property, ValueOperandType& value, GPRReg valuePayloadReg, TagType valueTag)
-{
- Edge child4 = m_jit.graph().varArgChild(node, 3);
-
- ArrayMode arrayMode = node.arrayMode();
-
- GPRReg baseReg = base.gpr();
- GPRReg propertyReg = property.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(valueTag, 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);
- return;
- }
-
- MacroAssembler::JumpList slowCases;
-
- if (arrayMode.isInBounds()) {
- 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 (!arrayMode.isOutOfBounds())
- 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(valueTag, 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)));
-
- base.use();
- property.use();
- value.use();
- storage.use();
-
- if (arrayMode.isOutOfBounds()) {
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this,
- m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
- NoResult, baseReg, propertyReg, valueTag, valuePayloadReg));
- }
-
- noResult(m_compileIndex, UseChildrenCalledExplicitly);
-}
-
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op();
@@ -2429,8 +2366,7 @@ void SpeculativeJIT::compile(Node& node)
break;
case ArithDiv: {
- if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
- && node.canSpeculateInteger()) {
+ if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
#if CPU(X86)
compileIntegerArithDivForX86(node);
#else // CPU(X86) -> so non-X86 code follows
@@ -2457,8 +2393,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ArithAbs: {
- if (at(node.child1()).shouldSpeculateIntegerForArithmetic()
- && node.canSpeculateInteger()) {
+ if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) {
SpeculateIntegerOperand op1(this, node.child1());
GPRTemporary result(this, op1);
GPRTemporary scratch(this);
@@ -2482,8 +2417,7 @@ void SpeculativeJIT::compile(Node& node)
case ArithMin:
case ArithMax: {
- if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
- && node.canSpeculateInteger()) {
+ if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
SpeculateStrictInt32Operand op1(this, node.child1());
SpeculateStrictInt32Operand op2(this, node.child2());
GPRTemporary result(this, op1);
@@ -2633,7 +2567,6 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
break;
}
- case Array::Int32:
case Array::Contiguous: {
if (node.arrayMode().isInBounds()) {
SpeculateStrictInt32Operand property(this, node.child2());
@@ -2647,20 +2580,8 @@ void SpeculativeJIT::compile(Node& node)
speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
- GPRTemporary resultPayload(this);
- if (node.arrayMode().type() == Array::Int32) {
- speculationCheck(
- OutOfBounds, JSValueRegs(), NoNode,
- m_jit.branch32(
- MacroAssembler::Equal,
- MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
- TrustedImm32(JSValue::EmptyValueTag)));
- m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
- integerResult(resultPayload.gpr(), m_compileIndex);
- break;
- }
-
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());
@@ -2700,60 +2621,6 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex);
break;
}
- case Array::Double: {
- if (node.arrayMode().isInBounds()) {
- 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())));
-
- FPRTemporary result(this);
- m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
- doubleResult(result.fpr(), m_compileIndex);
- break;
- }
-
- 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);
- FPRTemporary temp(this);
- GPRReg resultTagReg = resultTag.gpr();
- GPRReg resultPayloadReg = resultPayload.gpr();
- FPRReg tempReg = temp.fpr();
-
- MacroAssembler::JumpList slowCases;
-
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
- m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
- slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
- boxDouble(tempReg, resultTagReg, resultPayloadReg);
-
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this, operationGetByValArrayInt,
- JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
-
- jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex);
- break;
- }
case Array::ArrayStorage:
case Array::SlowPutArrayStorage: {
if (node.arrayMode().isInBounds()) {
@@ -2904,17 +2771,6 @@ void SpeculativeJIT::compile(Node& node)
GPRReg propertyReg = property.gpr();
switch (arrayMode.type()) {
- case Array::Int32: {
- SpeculateIntegerOperand value(this, child3);
-
- GPRReg valuePayloadReg = value.gpr();
-
- if (!m_compileOkay)
- return;
-
- compileContiguousPutByVal(node, base, property, value, valuePayloadReg, TrustedImm32(JSValue::Int32Tag));
- break;
- }
case Array::Contiguous: {
JSValueOperand value(this, child3);
@@ -2928,14 +2784,61 @@ void SpeculativeJIT::compile(Node& node)
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;
+ }
- compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg);
- break;
- }
- case Array::Double: {
- compileDoublePutByVal(node, base, property);
+ MacroAssembler::JumpList slowCases;
+
+ if (arrayMode.isInBounds()) {
+ 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 (!arrayMode.isOutOfBounds())
+ 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)));
+
+ base.use();
+ property.use();
+ value.use();
+ storage.use();
+
+ if (arrayMode.isOutOfBounds()) {
+ addSlowPathGenerator(
+ slowPathCall(
+ slowCases, this,
+ m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
+ NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
+ }
+
+ noResult(m_compileIndex, UseChildrenCalledExplicitly);
break;
}
+
case Array::ArrayStorage:
case Array::SlowPutArrayStorage: {
JSValueOperand value(this, child3);
@@ -3125,47 +3028,24 @@ void SpeculativeJIT::compile(Node& node)
ASSERT(node.arrayMode().isJSArray());
SpeculateCellOperand base(this, node.child1());
+ JSValueOperand value(this, node.child2());
GPRTemporary storageLength(this);
GPRReg baseGPR = base.gpr();
+ GPRReg valueTagGPR = value.tagGPR();
+ GPRReg valuePayloadGPR = value.payloadGPR();
GPRReg storageLengthGPR = storageLength.gpr();
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
+ }
+
StorageOperand storage(this, node.child3());
GPRReg storageGPR = storage.gpr();
switch (node.arrayMode().type()) {
- case Array::Int32: {
- SpeculateIntegerOperand value(this, node.child2());
- GPRReg valuePayloadGPR = value.gpr();
-
- 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(TrustedImm32(JSValue::Int32Tag), 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),
- TrustedImm32(JSValue::Int32Tag), valuePayloadGPR, baseGPR));
-
- jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
- break;
- }
-
case Array::Contiguous: {
- JSValueOperand value(this, node.child2());
- GPRReg valueTagGPR = value.tagGPR();
- GPRReg valuePayloadGPR = value.payloadGPR();
-
- if (Heap::isWriteBarrierEnabled()) {
- GPRTemporary scratch(this);
- writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
- }
-
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)));
@@ -3184,45 +3064,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case Array::Double: {
- SpeculateDoubleOperand value(this, node.child2());
- FPRReg valueFPR = value.fpr();
-
- if (!isRealNumberSpeculation(m_state.forNode(node.child2()).m_type)) {
- // FIXME: We need a way of profiling these, and we need to hoist them into
- // SpeculateDoubleOperand.
- speculationCheck(
- BadType, JSValueRegs(), NoNode,
- m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
- }
-
- 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.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
- 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, operationArrayPushDouble,
- JSValueRegs(storageGPR, storageLengthGPR),
- valueFPR, baseGPR));
-
- jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
- break;
- }
-
case Array::ArrayStorage: {
- JSValueOperand value(this, node.child2());
- GPRReg valueTagGPR = value.tagGPR();
- GPRReg valuePayloadGPR = value.payloadGPR();
-
- if (Heap::isWriteBarrierEnabled()) {
- GPRTemporary scratch(this);
- writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
- }
-
m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
// Refuse to handle bizarre lengths.
@@ -3265,7 +3107,6 @@ void SpeculativeJIT::compile(Node& node)
GPRReg storageGPR = storage.gpr();
switch (node.arrayMode().type()) {
- case Array::Int32:
case Array::Contiguous: {
m_jit.load32(
MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
@@ -3299,44 +3140,6 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case Array::Double: {
- FPRTemporary temp(this);
- FPRReg tempFPR = temp.fpr();
-
- m_jit.load32(
- MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
- MacroAssembler::Jump undefinedCase =
- m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
- m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
- m_jit.store32(
- valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.loadDouble(
- MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight),
- tempFPR);
- MacroAssembler::Jump slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
- JSValue nan = JSValue(JSValue::EncodeAsDouble, QNaN);
- m_jit.store32(
- MacroAssembler::TrustedImm32(nan.u.asBits.tag),
- MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(
- MacroAssembler::TrustedImm32(nan.u.asBits.payload),
- MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- boxDouble(tempFPR, valueTagGPR, valuePayloadGPR);
-
- 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::ArrayStorage: {
GPRTemporary storageLength(this);
GPRReg storageLengthGPR = storageLength.gpr();
@@ -3555,17 +3358,11 @@ void SpeculativeJIT::compile(Node& node)
case NewArray: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime() && !hasArrayStorage(node.indexingType())) {
+ if (!globalObject->isHavingABadTime()) {
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
- Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType());
- ASSERT(structure->indexingType() == node.indexingType());
- ASSERT(
- hasUndecided(structure->indexingType())
- || hasInt32(structure->indexingType())
- || hasDouble(structure->indexingType())
- || hasContiguous(structure->indexingType()));
-
+ ASSERT(hasContiguous(globalObject->arrayStructure()->indexingType()));
+
unsigned numElements = node.numChildren();
GPRTemporary result(this);
@@ -3574,52 +3371,17 @@ void SpeculativeJIT::compile(Node& node)
GPRReg resultGPR = result.gpr();
GPRReg storageGPR = storage.gpr();
- emitAllocateJSArray(structure, resultGPR, storageGPR, numElements);
+ 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.
- ASSERT(!hasUndecided(structure->indexingType()) || !node.numChildren());
-
for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
- Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx];
- switch (node.indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- case ALL_UNDECIDED_INDEXING_TYPES:
- CRASH();
- break;
- case ALL_DOUBLE_INDEXING_TYPES: {
- SpeculateDoubleOperand operand(this, use);
- FPRReg opFPR = operand.fpr();
- if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) {
- // FIXME: We need a way of profiling these, and we need to hoist them into
- // SpeculateDoubleOperand.
- speculationCheck(
- BadType, JSValueRegs(), NoNode,
- m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
- }
-
- m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
- break;
- }
- case ALL_INT32_INDEXING_TYPES: {
- SpeculateIntegerOperand operand(this, use);
- m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(operand.gpr(), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- break;
- }
- case ALL_CONTIGUOUS_INDEXING_TYPES: {
- 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)));
- break;
- }
- default:
- CRASH();
- break;
- }
+ 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
@@ -3637,7 +3399,7 @@ void SpeculativeJIT::compile(Node& node)
flushRegisters();
GPRResult result(this);
callOperation(
- operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
+ operationNewEmptyArray, result.gpr(), globalObject->arrayStructure());
cellResult(result.gpr(), m_compileIndex);
break;
}
@@ -3647,61 +3409,13 @@ void SpeculativeJIT::compile(Node& node)
EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
- // Need to perform the speculations that this node promises to perform. If we're
- // emitting code here and the indexing type is not array storage then there is
- // probably something hilarious going on and we're already failing at all the
- // things, but at least we're going to be sound.
- Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx];
- switch (node.indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- case ALL_UNDECIDED_INDEXING_TYPES:
- CRASH();
- break;
- case ALL_DOUBLE_INDEXING_TYPES: {
- SpeculateDoubleOperand operand(this, use);
- FPRReg opFPR = operand.fpr();
- if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) {
- // FIXME: We need a way of profiling these, and we need to hoist them into
- // SpeculateDoubleOperand.
- speculationCheck(
- BadType, JSValueRegs(), NoNode,
- m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
- }
-
- m_jit.storeDouble(opFPR, reinterpret_cast<char*>(buffer + operandIdx));
- break;
- }
- case ALL_INT32_INDEXING_TYPES: {
- SpeculateIntegerOperand operand(this, use);
- GPRReg opGPR = operand.gpr();
- m_jit.store32(TrustedImm32(JSValue::Int32Tag), reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
- m_jit.store32(opGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
- break;
- }
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
- JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
- GPRReg opTagGPR = operand.tagGPR();
- GPRReg opPayloadGPR = operand.payloadGPR();
-
- m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
- m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
- operand.use();
- break;
- }
- default:
- CRASH();
- break;
- }
- }
-
- switch (node.indexingType()) {
- case ALL_DOUBLE_INDEXING_TYPES:
- case ALL_INT32_INDEXING_TYPES:
- useChildren(node);
- break;
- default:
- break;
+ JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
+ GPRReg opTagGPR = operand.tagGPR();
+ GPRReg opPayloadGPR = operand.payloadGPR();
+ operand.use();
+
+ m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+ m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
}
flushRegisters();
@@ -3717,8 +3431,8 @@ void SpeculativeJIT::compile(Node& node)
GPRResult result(this);
callOperation(
- operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()),
- static_cast<void*>(buffer), node.numChildren());
+ operationNewArray, result.gpr(), globalObject->arrayStructure(),
+ static_cast<void *>(buffer), node.numChildren());
if (scratchSize) {
GPRTemporary scratch(this);
@@ -3757,30 +3471,17 @@ void SpeculativeJIT::compile(Node& node)
emitAllocateBasicStorage(resultGPR, storageGPR));
m_jit.subPtr(scratchGPR, storageGPR);
emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(
- TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), resultGPR, scratchGPR,
+ 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()));
- if (hasDouble(node.indexingType())) {
- JSValue nan = JSValue(JSValue::EncodeAsDouble, QNaN);
-
- m_jit.move(sizeGPR, scratchGPR);
- MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
- MacroAssembler::Label loop = m_jit.label();
- m_jit.sub32(TrustedImm32(1), scratchGPR);
- m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
- m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
- m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
- done.link(&m_jit);
- }
-
addSlowPathGenerator(adoptPtr(
new CallArrayAllocatorWithVariableSizeSlowPathGenerator(
slowCases, this, operationNewArrayWithSize, resultGPR,
- globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()),
- globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
+ globalObject->arrayStructure(),
+ globalObject->arrayStructureWithArrayStorage(),
sizeGPR)));
cellResult(resultGPR, m_compileIndex);
@@ -3791,24 +3492,15 @@ void SpeculativeJIT::compile(Node& node)
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->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), structureGPR);
- MacroAssembler::Jump done = m_jit.jump();
- bigLength.link(&m_jit);
- m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR);
- done.link(&m_jit);
callOperation(
- operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR);
- cellResult(resultGPR, m_compileIndex);
+ operationNewArrayWithSize, result.gpr(), globalObject->arrayStructure(), sizeGPR);
+ cellResult(result.gpr(), m_compileIndex);
break;
}
case NewArrayBuffer: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- IndexingType indexingType = node.indexingType();
- if (!globalObject->isHavingABadTime() && !hasArrayStorage(indexingType)) {
+ if (!globalObject->isHavingABadTime()) {
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
unsigned numElements = node.numConstants();
@@ -3819,25 +3511,12 @@ void SpeculativeJIT::compile(Node& node)
GPRReg resultGPR = result.gpr();
GPRReg storageGPR = storage.gpr();
- emitAllocateJSArray(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), resultGPR, storageGPR, numElements);
+ emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
- if (node.indexingType() == ArrayWithDouble) {
- JSValue* data = m_jit.codeBlock()->constantBuffer(node.startConstant());
- for (unsigned index = 0; index < node.numConstants(); ++index) {
- union {
- int32_t halves[2];
- double value;
- } u;
- u.value = data[index].asNumber();
- m_jit.store32(Imm32(u.halves[0]), MacroAssembler::Address(storageGPR, sizeof(double) * index));
- m_jit.store32(Imm32(u.halves[1]), MacroAssembler::Address(storageGPR, sizeof(double) * index + sizeof(int32_t)));
- }
- } else {
- 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));
- }
+ 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);
@@ -3847,7 +3526,7 @@ void SpeculativeJIT::compile(Node& node)
flushRegisters();
GPRResult result(this);
- callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), node.startConstant(), node.numConstants());
+ callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructure(), node.startConstant(), node.numConstants());
cellResult(result.gpr(), m_compileIndex);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index ecd823e7b..6c066c388 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -2403,8 +2403,7 @@ void SpeculativeJIT::compile(Node& node)
break;
case ArithDiv: {
- if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
- && node.canSpeculateInteger()) {
+ if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
compileIntegerArithDivForX86(node);
break;
}
@@ -2427,8 +2426,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ArithAbs: {
- if (at(node.child1()).shouldSpeculateIntegerForArithmetic()
- && node.canSpeculateInteger()) {
+ if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) {
SpeculateIntegerOperand op1(this, node.child1());
GPRTemporary result(this);
GPRTemporary scratch(this);
@@ -2452,8 +2450,7 @@ void SpeculativeJIT::compile(Node& node)
case ArithMin:
case ArithMax: {
- if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
- && node.canSpeculateInteger()) {
+ if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
SpeculateStrictInt32Operand op1(this, node.child1());
SpeculateStrictInt32Operand op2(this, node.child2());
GPRTemporary result(this, op1);
@@ -2601,7 +2598,6 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(result.gpr(), m_compileIndex);
break;
}
- case Array::Int32:
case Array::Contiguous: {
if (node.arrayMode().isInBounds()) {
SpeculateStrictInt32Operand property(this, node.child2());
@@ -2618,7 +2614,7 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
- jsValueResult(result.gpr(), m_compileIndex, node.arrayMode().type() == Array::Int32 ? DataFormatJSInteger : DataFormatJS);
+ jsValueResult(result.gpr(), m_compileIndex);
break;
}
@@ -2651,60 +2647,6 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(resultReg, m_compileIndex);
break;
}
-
- case Array::Double: {
- if (node.arrayMode().isInBounds()) {
- 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())));
-
- FPRTemporary result(this);
- m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
- doubleResult(result.fpr(), m_compileIndex);
- break;
- }
-
- 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);
- FPRTemporary temp(this);
- GPRReg resultReg = result.gpr();
- FPRReg tempReg = temp.fpr();
-
- MacroAssembler::JumpList slowCases;
-
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
- m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
- slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
- boxDouble(tempReg, resultReg);
-
- addSlowPathGenerator(
- slowPathCall(
- slowCases, this, operationGetByValArrayInt,
- result.gpr(), baseReg, propertyReg));
-
- jsValueResult(resultReg, m_compileIndex);
- break;
- }
-
case Array::ArrayStorage:
case Array::SlowPutArrayStorage: {
if (node.arrayMode().isInBounds()) {
@@ -2847,7 +2789,6 @@ void SpeculativeJIT::compile(Node& node)
GPRReg propertyReg = property.gpr();
switch (arrayMode.type()) {
- case Array::Int32:
case Array::Contiguous: {
JSValueOperand value(this, child3);
@@ -2855,15 +2796,8 @@ void SpeculativeJIT::compile(Node& node)
if (!m_compileOkay)
return;
-
- if (arrayMode.type() == Array::Int32
- && !isInt32Speculation(m_state.forNode(child3).m_type)) {
- speculationCheck(
- BadType, JSValueRegs(valueReg), child3,
- m_jit.branch64(MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
- }
- if (arrayMode.type() == Array::Contiguous && Heap::isWriteBarrierEnabled()) {
+ if (Heap::isWriteBarrierEnabled()) {
GPRTemporary scratch(this);
writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr());
}
@@ -2923,11 +2857,6 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case Array::Double: {
- compileDoublePutByVal(node, base, property);
- break;
- }
-
case Array::ArrayStorage:
case Array::SlowPutArrayStorage: {
JSValueOperand value(this, child3);
@@ -3152,31 +3081,23 @@ void SpeculativeJIT::compile(Node& node)
ASSERT(node.arrayMode().isJSArray());
SpeculateCellOperand base(this, node.child1());
+ JSValueOperand value(this, node.child2());
GPRTemporary storageLength(this);
GPRReg baseGPR = base.gpr();
+ GPRReg valueGPR = value.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
+ if (Heap::isWriteBarrierEnabled()) {
+ GPRTemporary scratch(this);
+ writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
+ }
+
StorageOperand storage(this, node.child3());
GPRReg storageGPR = storage.gpr();
switch (node.arrayMode().type()) {
- case Array::Int32:
case Array::Contiguous: {
- JSValueOperand value(this, node.child2());
- GPRReg valueGPR = value.gpr();
-
- if (node.arrayMode().type() == Array::Int32 && !isInt32Speculation(m_state.forNode(node.child2()).m_type)) {
- speculationCheck(
- BadType, JSValueRegs(valueGPR), node.child2(),
- m_jit.branch64(MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister));
- }
-
- if (node.arrayMode().type() != Array::Int32 && Heap::isWriteBarrierEnabled()) {
- GPRTemporary scratch(this);
- writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
- }
-
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.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
@@ -3193,43 +3114,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case Array::Double: {
- SpeculateDoubleOperand value(this, node.child2());
- FPRReg valueFPR = value.fpr();
-
- if (!isRealNumberSpeculation(m_state.forNode(node.child2()).m_type)) {
- // FIXME: We need a way of profiling these, and we need to hoist them into
- // SpeculateDoubleOperand.
- speculationCheck(
- BadType, JSValueRegs(), NoNode,
- m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
- }
-
- 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.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
- m_jit.add32(TrustedImm32(1), storageLengthGPR);
- m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
-
- addSlowPathGenerator(
- slowPathCall(
- slowPath, this, operationArrayPushDouble, NoResult, storageLengthGPR,
- valueFPR, baseGPR));
-
- jsValueResult(storageLengthGPR, m_compileIndex);
- break;
- }
-
case Array::ArrayStorage: {
- JSValueOperand value(this, node.child2());
- GPRReg valueGPR = value.gpr();
-
- if (Heap::isWriteBarrierEnabled()) {
- GPRTemporary scratch(this);
- writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
- }
-
m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
// Refuse to handle bizarre lengths.
@@ -3267,17 +3152,13 @@ void SpeculativeJIT::compile(Node& node)
StorageOperand storage(this, node.child2());
GPRTemporary value(this);
GPRTemporary storageLength(this);
- FPRTemporary temp(this); // This is kind of lame, since we don't always need it. I'm relying on the fact that we don't have FPR pressure, especially in code that uses pop().
GPRReg baseGPR = base.gpr();
GPRReg storageGPR = storage.gpr();
GPRReg valueGPR = value.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- FPRReg tempFPR = temp.fpr();
switch (node.arrayMode().type()) {
- case Array::Int32:
- case Array::Double:
case Array::Contiguous: {
m_jit.load32(
MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
@@ -3286,27 +3167,14 @@ void SpeculativeJIT::compile(Node& node)
m_jit.sub32(TrustedImm32(1), storageLengthGPR);
m_jit.store32(
storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
- MacroAssembler::Jump slowCase;
- if (node.arrayMode().type() == Array::Double) {
- m_jit.loadDouble(
- MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
- tempFPR);
- // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
- // length and the new length.
- m_jit.store64(
- MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
- slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
- boxDouble(tempFPR, valueGPR);
- } else {
- m_jit.load64(
- MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
- valueGPR);
- // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
- // length and the new length.
- m_jit.store64(
+ m_jit.load64(
+ MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
+ valueGPR);
+ // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
+ // length and the new length.
+ m_jit.store64(
MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
- slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
- }
+ MacroAssembler::Jump slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
addSlowPathGenerator(
slowPathMove(
@@ -3316,7 +3184,6 @@ void SpeculativeJIT::compile(Node& node)
slowPathCall(
slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
- // We can't know for sure that the result is an int because of the slow paths. :-/
jsValueResult(valueGPR, m_compileIndex);
break;
}
@@ -3471,16 +3338,10 @@ void SpeculativeJIT::compile(Node& node)
case NewArray: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime() && !hasArrayStorage(node.indexingType())) {
+ if (!globalObject->isHavingABadTime()) {
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
- Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType());
- ASSERT(structure->indexingType() == node.indexingType());
- ASSERT(
- hasUndecided(structure->indexingType())
- || hasInt32(structure->indexingType())
- || hasDouble(structure->indexingType())
- || hasContiguous(structure->indexingType()));
+ ASSERT(hasContiguous(globalObject->arrayStructure()->indexingType()));
unsigned numElements = node.numChildren();
@@ -3490,50 +3351,15 @@ void SpeculativeJIT::compile(Node& node)
GPRReg resultGPR = result.gpr();
GPRReg storageGPR = storage.gpr();
- emitAllocateJSArray(structure, resultGPR, storageGPR, numElements);
+ 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.
- ASSERT(!hasUndecided(structure->indexingType()) || !node.numChildren());
-
for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
- Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx];
- switch (node.indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- case ALL_UNDECIDED_INDEXING_TYPES:
- CRASH();
- break;
- case ALL_DOUBLE_INDEXING_TYPES: {
- SpeculateDoubleOperand operand(this, use);
- FPRReg opFPR = operand.fpr();
- if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) {
- // FIXME: We need a way of profiling these, and we need to hoist them into
- // SpeculateDoubleOperand.
- speculationCheck(
- BadType, JSValueRegs(), NoNode,
- m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
- }
-
- m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
- break;
- }
- case ALL_INT32_INDEXING_TYPES:
- case ALL_CONTIGUOUS_INDEXING_TYPES: {
- JSValueOperand operand(this, use);
- GPRReg opGPR = operand.gpr();
- if (hasInt32(node.indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) {
- speculationCheck(
- BadType, JSValueRegs(opGPR), use.index(),
- m_jit.branch64(MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister));
- }
- m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx));
- break;
- }
- default:
- CRASH();
- break;
- }
+ JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
+ GPRReg opGPR = operand.gpr();
+ m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx));
}
// Yuck, we should *really* have a way of also returning the storageGPR. But
@@ -3550,7 +3376,7 @@ void SpeculativeJIT::compile(Node& node)
if (!node.numChildren()) {
flushRegisters();
GPRResult result(this);
- callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
+ callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructure());
cellResult(result.gpr(), m_compileIndex);
break;
}
@@ -3560,65 +3386,11 @@ void SpeculativeJIT::compile(Node& node)
EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
- // Need to perform the speculations that this node promises to perform. If we're
- // emitting code here and the indexing type is not array storage then there is
- // probably something hilarious going on and we're already failing at all the
- // things, but at least we're going to be sound.
- Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx];
- switch (node.indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- case ALL_UNDECIDED_INDEXING_TYPES:
- CRASH();
- break;
- case ALL_DOUBLE_INDEXING_TYPES: {
- SpeculateDoubleOperand operand(this, use);
- GPRTemporary scratch(this);
- FPRReg opFPR = operand.fpr();
- GPRReg scratchGPR = scratch.gpr();
- if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) {
- // FIXME: We need a way of profiling these, and we need to hoist them into
- // SpeculateDoubleOperand.
- speculationCheck(
- BadType, JSValueRegs(), NoNode,
- m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
- }
-
- m_jit.boxDouble(opFPR, scratchGPR);
- m_jit.store64(scratchGPR, buffer + operandIdx);
- break;
- }
- case ALL_INT32_INDEXING_TYPES: {
- JSValueOperand operand(this, use);
- GPRReg opGPR = operand.gpr();
- if (hasInt32(node.indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) {
- speculationCheck(
- BadType, JSValueRegs(opGPR), use.index(),
- m_jit.branch64(MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister));
- }
- m_jit.store64(opGPR, buffer + operandIdx);
- break;
- }
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
- JSValueOperand operand(this, use);
- GPRReg opGPR = operand.gpr();
- m_jit.store64(opGPR, buffer + operandIdx);
- operand.use();
- break;
- }
- default:
- CRASH();
- break;
- }
- }
-
- switch (node.indexingType()) {
- case ALL_DOUBLE_INDEXING_TYPES:
- case ALL_INT32_INDEXING_TYPES:
- useChildren(node);
- break;
- default:
- break;
+ JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
+ GPRReg opGPR = operand.gpr();
+ operand.use();
+
+ m_jit.store64(opGPR, buffer + operandIdx);
}
flushRegisters();
@@ -3634,7 +3406,7 @@ void SpeculativeJIT::compile(Node& node)
GPRResult result(this);
callOperation(
- operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()),
+ operationNewArray, result.gpr(), globalObject->arrayStructure(),
static_cast<void*>(buffer), node.numChildren());
if (scratchSize) {
@@ -3650,26 +3422,18 @@ void SpeculativeJIT::compile(Node& node)
case NewArrayWithSize: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- if (!globalObject->isHavingABadTime() && !hasArrayStorage(node.indexingType())) {
+ if (!globalObject->isHavingABadTime()) {
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
SpeculateStrictInt32Operand size(this, node.child1());
GPRTemporary result(this);
GPRTemporary storage(this);
GPRTemporary scratch(this);
- GPRTemporary scratch2;
GPRReg sizeGPR = size.gpr();
GPRReg resultGPR = result.gpr();
GPRReg storageGPR = storage.gpr();
GPRReg scratchGPR = scratch.gpr();
- GPRReg scratch2GPR = InvalidGPRReg;
-
- if (hasDouble(node.indexingType())) {
- GPRTemporary realScratch2(this, size);
- scratch2.adopt(realScratch2);
- scratch2GPR = scratch2.gpr();
- }
MacroAssembler::JumpList slowCases;
slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
@@ -3682,28 +3446,17 @@ void SpeculativeJIT::compile(Node& node)
emitAllocateBasicStorage(resultGPR, storageGPR));
m_jit.subPtr(scratchGPR, storageGPR);
emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(
- TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), resultGPR, scratchGPR,
+ 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()));
- if (hasDouble(node.indexingType())) {
- m_jit.move(TrustedImm64(bitwise_cast<int64_t>(QNaN)), scratchGPR);
- m_jit.move(sizeGPR, scratch2GPR);
- MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratch2GPR);
- MacroAssembler::Label loop = m_jit.label();
- m_jit.sub32(TrustedImm32(1), scratch2GPR);
- m_jit.store64(scratchGPR, MacroAssembler::BaseIndex(storageGPR, scratch2GPR, MacroAssembler::TimesEight));
- m_jit.branchTest32(MacroAssembler::NonZero, scratch2GPR).linkTo(loop, &m_jit);
- done.link(&m_jit);
- }
-
addSlowPathGenerator(adoptPtr(
new CallArrayAllocatorWithVariableSizeSlowPathGenerator(
slowCases, this, operationNewArrayWithSize, resultGPR,
- globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()),
- globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
+ globalObject->arrayStructure(),
+ globalObject->arrayStructureWithArrayStorage(),
sizeGPR)));
cellResult(resultGPR, m_compileIndex);
@@ -3717,10 +3470,10 @@ void SpeculativeJIT::compile(Node& node)
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->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), structureGPR);
+ m_jit.move(TrustedImmPtr(globalObject->arrayStructure()), structureGPR);
MacroAssembler::Jump done = m_jit.jump();
bigLength.link(&m_jit);
- m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR);
+ m_jit.move(TrustedImmPtr(globalObject->arrayStructureWithArrayStorage()), structureGPR);
done.link(&m_jit);
callOperation(operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR);
cellResult(resultGPR, m_compileIndex);
@@ -3767,8 +3520,7 @@ void SpeculativeJIT::compile(Node& node)
case NewArrayBuffer: {
JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
- IndexingType indexingType = node.indexingType();
- if (!globalObject->isHavingABadTime() && !hasArrayStorage(indexingType)) {
+ if (!globalObject->isHavingABadTime()) {
globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
unsigned numElements = node.numConstants();
@@ -3779,23 +3531,13 @@ void SpeculativeJIT::compile(Node& node)
GPRReg resultGPR = result.gpr();
GPRReg storageGPR = storage.gpr();
- emitAllocateJSArray(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), resultGPR, storageGPR, numElements);
+ emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
- ASSERT(indexingType & IsArray);
JSValue* data = m_jit.codeBlock()->constantBuffer(node.startConstant());
- if (indexingType == ArrayWithDouble) {
- for (unsigned index = 0; index < node.numConstants(); ++index) {
- double value = data[index].asNumber();
- m_jit.store64(
- Imm64(bitwise_cast<int64_t>(value)),
- MacroAssembler::Address(storageGPR, sizeof(double) * index));
- }
- } else {
- for (unsigned index = 0; index < node.numConstants(); ++index) {
- m_jit.store64(
- Imm64(JSValue::encode(data[index])),
- MacroAssembler::Address(storageGPR, sizeof(JSValue) * index));
- }
+ for (unsigned index = 0; index < node.numConstants(); ++index) {
+ m_jit.store64(
+ Imm64(JSValue::encode(data[index])),
+ MacroAssembler::Address(storageGPR, sizeof(JSValue) * index));
}
cellResult(resultGPR, m_compileIndex);
@@ -3805,7 +3547,7 @@ void SpeculativeJIT::compile(Node& node)
flushRegisters();
GPRResult result(this);
- callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), node.startConstant(), node.numConstants());
+ callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructure(), node.startConstant(), node.numConstants());
cellResult(result.gpr(), m_compileIndex);
break;