summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp310
1 files changed, 137 insertions, 173 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index f11fd1663..6c066c388 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -2111,107 +2111,6 @@ void SpeculativeJIT::emitBranch(Node& node)
}
}
-MacroAssembler::JumpList SpeculativeJIT::compileContiguousGetByVal(Node&, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultReg)
-{
- MacroAssembler::JumpList slowCases;
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
-
- m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
- slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
-
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileArrayStorageGetByVal(Node&, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg resultReg)
-{
- MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
-
- m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
- MacroAssembler::Jump hole = m_jit.branchTest64(MacroAssembler::Zero, resultReg);
-
- MacroAssembler::JumpList slowCases;
- slowCases.append(outOfBounds);
- slowCases.append(hole);
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileContiguousPutByVal(Node& node, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueReg, GPRReg tempReg)
-{
- Array::Mode arrayMode = node.arrayMode();
-
- MacroAssembler::JumpList slowCases;
-
- if (!mayStoreToTail(arrayMode)) {
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
- } else {
- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
-
- slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength())));
-
- if (isInBoundsAccess(arrayMode))
- speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases);
-
- m_jit.add32(TrustedImm32(1), propertyReg, tempReg);
- m_jit.store32(tempReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
-
- inBounds.link(&m_jit);
- }
-
- m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
-
- if (isInBoundsAccess(arrayMode))
- return MacroAssembler::JumpList();
- return slowCases;
-}
-
-MacroAssembler::JumpList SpeculativeJIT::compileArrayStoragePutByVal(Node& node, GPRReg, GPRReg propertyReg, GPRReg storageReg, GPRReg valueReg, GPRReg tempReg)
-{
- Array::Mode arrayMode = node.arrayMode();
-
- MacroAssembler::JumpList slowCases;
-
- MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
- if (isInBoundsAccess(arrayMode))
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
- else
- slowCases.append(beyondArrayBounds);
-
- // Check if we're writing to a hole; if so increment m_numValuesInVector.
- if (!mayStoreToHole(arrayMode)) {
- // This is uncountable because if we take this exit, then the baseline JIT
- // will immediately count the hole store. So there is no need for exit
- // profiling.
- speculationCheck(
- Uncountable, JSValueRegs(), NoNode,
- m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
- } else {
- MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
- if (isSlowPutAccess(arrayMode)) {
- // This is sort of strange. If we wanted to optimize this code path, we would invert
- // the above branch. But it's simply not worth it since this only happens if we're
- // already having a bad time.
- slowCases.append(m_jit.jump());
- } else {
- m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
-
- // If we're writing to a hole we might be growing the array;
- MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
- m_jit.add32(TrustedImm32(1), propertyReg, tempReg);
- m_jit.store32(tempReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
-
- lengthDoesNotNeedUpdate.link(&m_jit);
- }
- notHoleValue.link(&m_jit);
- }
-
- // Store the value to the array.
- m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
-
- return slowCases;
-}
-
void SpeculativeJIT::compile(Node& node)
{
NodeType op = node.op();
@@ -2673,13 +2572,14 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case Arrayify: {
+ case Arrayify:
+ case ArrayifyToStructure: {
arrayify(node);
break;
}
case GetByVal: {
- switch (node.arrayMode()) {
+ switch (node.arrayMode().type()) {
case Array::SelectUsingPredictions:
case Array::ForceExit:
ASSERT_NOT_REACHED();
@@ -2698,27 +2598,26 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(result.gpr(), m_compileIndex);
break;
}
- case IN_BOUNDS_CONTIGUOUS_MODES: {
- SpeculateStrictInt32Operand property(this, node.child2());
- StorageOperand storage(this, node.child3());
-
- GPRReg propertyReg = property.gpr();
- GPRReg storageReg = storage.gpr();
-
- if (!m_compileOkay)
- return;
-
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+ case Array::Contiguous: {
+ 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())));
+
+ 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);
+ break;
+ }
- 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);
- break;
- }
- case CONTIGUOUS_TO_TAIL_MODES:
- case OUT_OF_BOUNDS_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES: {
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
StorageOperand storage(this, node.child3());
@@ -2733,8 +2632,13 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultReg = result.gpr();
- MacroAssembler::JumpList slowCases =
- compileContiguousGetByVal(node, baseReg, propertyReg, storageReg, resultReg);
+ MacroAssembler::JumpList slowCases;
+
+ slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
+
+ m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
+ slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
+
addSlowPathGenerator(
slowPathCall(
slowCases, this, operationGetByValArrayInt,
@@ -2743,28 +2647,28 @@ void SpeculativeJIT::compile(Node& node)
jsValueResult(resultReg, m_compileIndex);
break;
}
- case IN_BOUNDS_ARRAY_STORAGE_MODES: {
- SpeculateStrictInt32Operand property(this, node.child2());
- StorageOperand storage(this, node.child3());
+ case Array::ArrayStorage:
+ case Array::SlowPutArrayStorage: {
+ if (node.arrayMode().isInBounds()) {
+ SpeculateStrictInt32Operand property(this, node.child2());
+ StorageOperand storage(this, node.child3());
- GPRReg propertyReg = property.gpr();
- GPRReg storageReg = storage.gpr();
+ GPRReg propertyReg = property.gpr();
+ GPRReg storageReg = storage.gpr();
- if (!m_compileOkay)
- return;
+ if (!m_compileOkay)
+ return;
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
+ speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
- GPRTemporary result(this);
- m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
- speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
+ GPRTemporary result(this);
+ m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
+ speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
- jsValueResult(result.gpr(), m_compileIndex);
- break;
- }
- case OUT_OF_BOUNDS_ARRAY_STORAGE_MODES:
- case SLOW_PUT_ARRAY_STORAGE_MODES:
- case ALL_EFFECTFUL_ARRAY_STORAGE_MODES: {
+ jsValueResult(result.gpr(), m_compileIndex);
+ break;
+ }
+
SpeculateCellOperand base(this, node.child1());
SpeculateStrictInt32Operand property(this, node.child2());
StorageOperand storage(this, node.child3());
@@ -2779,8 +2683,13 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary result(this);
GPRReg resultReg = result.gpr();
- MacroAssembler::JumpList slowCases =
- compileArrayStorageGetByVal(node, baseReg, propertyReg, storageReg, resultReg);
+ MacroAssembler::JumpList slowCases;
+
+ slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
+
+ m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
+ slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
+
addSlowPathGenerator(
slowPathCall(
slowCases, this, operationGetByValArrayInt,
@@ -2836,10 +2745,10 @@ void SpeculativeJIT::compile(Node& node)
Edge child3 = m_jit.graph().varArgChild(node, 2);
Edge child4 = m_jit.graph().varArgChild(node, 3);
- Array::Mode arrayMode = modeForPut(node.arrayMode());
+ ArrayMode arrayMode = node.arrayMode().modeForPut();
bool alreadyHandled = false;
- switch (arrayMode) {
+ switch (arrayMode.type()) {
case Array::SelectUsingPredictions:
case Array::ForceExit:
ASSERT_NOT_REACHED();
@@ -2879,9 +2788,8 @@ void SpeculativeJIT::compile(Node& node)
GPRReg baseReg = base.gpr();
GPRReg propertyReg = property.gpr();
- switch (arrayMode) {
- case ALL_CONTIGUOUS_MODES:
- case ALL_EFFECTFUL_CONTIGUOUS_MODES: {
+ switch (arrayMode.type()) {
+ case Array::Contiguous: {
JSValueOperand value(this, child3);
GPRReg valueReg = value.gpr();
@@ -2910,16 +2818,34 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary temporary;
GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
- MacroAssembler::JumpList slowCases =
- compileContiguousPutByVal(
- node, baseReg, propertyReg, storageReg, valueReg, temporaryReg);
+ 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.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
base.use();
property.use();
value.use();
storage.use();
- if (!slowCases.empty()) {
+ if (arrayMode.isOutOfBounds()) {
addSlowPathGenerator(
slowPathCall(
slowCases, this,
@@ -2931,8 +2857,8 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case ALL_ARRAY_STORAGE_MODES:
- case ALL_EFFECTFUL_ARRAY_STORAGE_MODES: {
+ case Array::ArrayStorage:
+ case Array::SlowPutArrayStorage: {
JSValueOperand value(this, child3);
GPRReg valueReg = value.gpr();
@@ -2961,9 +2887,44 @@ void SpeculativeJIT::compile(Node& node)
GPRTemporary temporary;
GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
- MacroAssembler::JumpList slowCases =
- compileArrayStoragePutByVal(
- node, baseReg, propertyReg, storageReg, valueReg, temporaryReg);
+ MacroAssembler::JumpList slowCases;
+
+ MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
+ if (!arrayMode.isOutOfBounds())
+ speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
+ else
+ slowCases.append(beyondArrayBounds);
+
+ // Check if we're writing to a hole; if so increment m_numValuesInVector.
+ if (arrayMode.isInBounds()) {
+ // This is uncountable because if we take this exit, then the baseline JIT
+ // will immediately count the hole store. So there is no need for exit
+ // profiling.
+ speculationCheck(
+ Uncountable, JSValueRegs(), NoNode,
+ m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
+ } else {
+ MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+ if (arrayMode.isSlowPut()) {
+ // This is sort of strange. If we wanted to optimize this code path, we would invert
+ // the above branch. But it's simply not worth it since this only happens if we're
+ // already having a bad time.
+ slowCases.append(m_jit.jump());
+ } else {
+ m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
+
+ // If we're writing to a hole we might be growing the array;
+ MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
+ m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
+ m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
+
+ lengthDoesNotNeedUpdate.link(&m_jit);
+ }
+ notHoleValue.link(&m_jit);
+ }
+
+ // Store the value to the array.
+ m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
base.use();
property.use();
@@ -3117,7 +3078,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ArrayPush: {
- ASSERT(modeIsJSArray(node.arrayMode()));
+ ASSERT(node.arrayMode().isJSArray());
SpeculateCellOperand base(this, node.child1());
JSValueOperand value(this, node.child2());
@@ -3135,9 +3096,8 @@ void SpeculativeJIT::compile(Node& node)
StorageOperand storage(this, node.child3());
GPRReg storageGPR = storage.gpr();
- switch (node.arrayMode()) {
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds: {
+ switch (node.arrayMode().type()) {
+ case Array::Contiguous: {
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));
@@ -3154,8 +3114,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case Array::ArrayWithArrayStorage:
- case Array::ArrayWithArrayStorageOutOfBounds: {
+ case Array::ArrayStorage: {
m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
// Refuse to handle bizarre lengths.
@@ -3187,7 +3146,7 @@ void SpeculativeJIT::compile(Node& node)
}
case ArrayPop: {
- ASSERT(modeIsJSArray(node.arrayMode()));
+ ASSERT(node.arrayMode().isJSArray());
SpeculateCellOperand base(this, node.child1());
StorageOperand storage(this, node.child2());
@@ -3199,9 +3158,8 @@ void SpeculativeJIT::compile(Node& node)
GPRReg valueGPR = value.gpr();
GPRReg storageLengthGPR = storageLength.gpr();
- switch (node.arrayMode()) {
- case Array::ArrayWithContiguous:
- case Array::ArrayWithContiguousOutOfBounds: {
+ switch (node.arrayMode().type()) {
+ case Array::Contiguous: {
m_jit.load32(
MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
MacroAssembler::Jump undefinedCase =
@@ -3230,8 +3188,7 @@ void SpeculativeJIT::compile(Node& node)
break;
}
- case Array::ArrayWithArrayStorage:
- case Array::ArrayWithArrayStorageOutOfBounds: {
+ case Array::ArrayStorage: {
m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
JITCompiler::Jump undefinedCase =
@@ -3873,9 +3830,15 @@ void SpeculativeJIT::compile(Node& node)
ASSERT(node.structureSet().size());
+ ExitKind exitKind;
+ if (m_jit.graph()[node.child1()].op() == WeakJSConstant)
+ exitKind = BadWeakConstantCache;
+ else
+ exitKind = BadCache;
+
if (node.structureSet().size() == 1) {
speculationCheckWithConditionalDirection(
- BadCache, JSValueRegs(base.gpr()), NoNode,
+ exitKind, JSValueRegs(base.gpr()), NoNode,
m_jit.branchWeakPtr(
JITCompiler::NotEqual,
JITCompiler::Address(base.gpr(), JSCell::structureOffset()),
@@ -3892,7 +3855,7 @@ void SpeculativeJIT::compile(Node& node)
done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node.structureSet()[i]));
speculationCheckWithConditionalDirection(
- BadCache, JSValueRegs(base.gpr()), NoNode,
+ exitKind, JSValueRegs(base.gpr()), NoNode,
m_jit.branchWeakPtr(
JITCompiler::NotEqual, structure.gpr(), node.structureSet().last()),
node.op() == ForwardCheckStructure);
@@ -3916,7 +3879,8 @@ void SpeculativeJIT::compile(Node& node)
m_jit.addWeakReference(node.structure());
node.structure()->addTransitionWatchpoint(
speculationWatchpointWithConditionalDirection(
- BadCache, node.op() == ForwardStructureTransitionWatchpoint));
+ m_jit.graph()[node.child1()].op() == WeakJSConstant ? BadWeakConstantCache : BadCache,
+ node.op() == ForwardStructureTransitionWatchpoint));
#if !ASSERT_DISABLED
SpeculateCellOperand op1(this, node.child1());