REGRESSION (172175-172177): Change in for...in processing causes properties added in loop to be enumerated
https://bugs.webkit.org/show_bug.cgi?id=142856

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Refactored the way the for .. in enumeration over objects is done.  We used to make three C++ calls to
get info for three loops to iterate over indexed properties, structure properties and other properties,
respectively.  We still have the three loops, but now we make one C++ call to get all the info needed
for all loops before we exectue any enumeration.

The JSPropertyEnumerator has a count of the indexed properties and a list of named properties.
The named properties are one list, with structured properties in the range [0,m_endStructurePropertyIndex)
and the generic properties in the range [m_endStructurePropertyIndex, m_endGenericPropertyIndex);

Eliminated the bytecodes op_get_structure_property_enumerator, op_get_generic_property_enumerator and
op_next_enumerator_pname.
Added the bytecodes op_get_property_enumerator, op_enumerator_structure_pname and op_enumerator_generic_pname.
The bytecodes op_enumerator_structure_pname and op_enumerator_generic_pname are similar except for what
end value we stop iterating on.

Made corresponding node changes to the DFG and FTL for the bytecode changes.

* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitGetPropertyEnumerator):
(JSC::BytecodeGenerator::emitEnumeratorStructurePropertyName):
(JSC::BytecodeGenerator::emitEnumeratorGenericPropertyName):
(JSC::BytecodeGenerator::emitGetStructurePropertyEnumerator): Deleted.
(JSC::BytecodeGenerator::emitGetGenericPropertyEnumerator): Deleted.
(JSC::BytecodeGenerator::emitNextEnumeratorPropertyName): Deleted.
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ForInNode::emitMultiLoopBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileGetEnumerableLength):
(JSC::FTL::LowerDFGToLLVM::compileGetPropertyEnumerator):
(JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorStructurePname):
(JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorGenericPname):
(JSC::FTL::LowerDFGToLLVM::compileGetStructurePropertyEnumerator): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileGetGenericPropertyEnumerator): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorPname): Deleted.
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_enumerator_structure_pname):
(JSC::JIT::emit_op_enumerator_generic_pname):
(JSC::JIT::emit_op_get_property_enumerator):
(JSC::JIT::emit_op_next_enumerator_pname): Deleted.
(JSC::JIT::emit_op_get_structure_property_enumerator): Deleted.
(JSC::JIT::emit_op_get_generic_property_enumerator): Deleted.
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_enumerator_structure_pname):
(JSC::JIT::emit_op_enumerator_generic_pname):
(JSC::JIT::emit_op_next_enumerator_pname): Deleted.
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* llint/LowLevelInterpreter.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* runtime/JSPropertyNameEnumerator.cpp:
(JSC::JSPropertyNameEnumerator::create):
(JSC::JSPropertyNameEnumerator::finishCreation):
* runtime/JSPropertyNameEnumerator.h:
(JSC::JSPropertyNameEnumerator::indexedLength):
(JSC::JSPropertyNameEnumerator::endStructurePropertyIndex):
(JSC::JSPropertyNameEnumerator::endGenericPropertyIndex):
(JSC::JSPropertyNameEnumerator::indexedLengthOffset):
(JSC::JSPropertyNameEnumerator::endStructurePropertyIndexOffset):
(JSC::JSPropertyNameEnumerator::endGenericPropertyIndexOffset):
(JSC::JSPropertyNameEnumerator::cachedInlineCapacityOffset):
(JSC::propertyNameEnumerator):
(JSC::JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset): Deleted.
(JSC::structurePropertyNameEnumerator): Deleted.
(JSC::genericPropertyNameEnumerator): Deleted.
* runtime/Structure.cpp:
(JSC::Structure::setCachedPropertyNameEnumerator):
(JSC::Structure::cachedPropertyNameEnumerator):
(JSC::Structure::canCachePropertyNameEnumerator):
(JSC::Structure::setCachedStructurePropertyNameEnumerator): Deleted.
(JSC::Structure::cachedStructurePropertyNameEnumerator): Deleted.
(JSC::Structure::setCachedGenericPropertyNameEnumerator): Deleted.
(JSC::Structure::cachedGenericPropertyNameEnumerator): Deleted.
(JSC::Structure::canCacheStructurePropertyNameEnumerator): Deleted.
(JSC::Structure::canCacheGenericPropertyNameEnumerator): Deleted.
* runtime/Structure.h:
* runtime/StructureRareData.cpp:
(JSC::StructureRareData::visitChildren):
(JSC::StructureRareData::cachedPropertyNameEnumerator):
(JSC::StructureRareData::setCachedPropertyNameEnumerator):
(JSC::StructureRareData::cachedStructurePropertyNameEnumerator): Deleted.
(JSC::StructureRareData::setCachedStructurePropertyNameEnumerator): Deleted.
(JSC::StructureRareData::cachedGenericPropertyNameEnumerator): Deleted.
(JSC::StructureRareData::setCachedGenericPropertyNameEnumerator): Deleted.
* runtime/StructureRareData.h:
* tests/stress/for-in-delete-during-iteration.js:

LayoutTests:

New tests and rebased one test.

* js/for-in-modify-in-loop-expected.txt: Added.
* js/for-in-modify-in-loop.html: Added.
* js/script-tests/for-in-modify-in-loop.js: Added.
(haveSameProperties):
(each):
(testAdd):
(testAddDelete):
* http/tests/security/cross-frame-access-enumeration-expected.txt: Rebased.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@181891 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index e3542d1..3769378 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -1966,15 +1966,15 @@
         forNode(node).makeHeapTop();
         break;
     }
-    case GetStructurePropertyEnumerator: {
+    case GetPropertyEnumerator: {
         forNode(node).setType(SpecCell);
         break;
     }
-    case GetGenericPropertyEnumerator: {
-        forNode(node).setType(SpecCell);
+    case GetEnumeratorStructurePname: {
+        forNode(node).setType(SpecString | SpecOther);
         break;
     }
-    case GetEnumeratorPname: {
+    case GetEnumeratorGenericPname: {
         forNode(node).setType(SpecString | SpecOther);
         break;
     }
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 4387cf9..151f162 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -3770,28 +3770,26 @@
             NEXT_OPCODE(op_get_direct_pname);
         }
 
-        case op_get_structure_property_enumerator: {
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetStructurePropertyEnumerator, 
+        case op_get_property_enumerator: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetPropertyEnumerator, 
+                get(VirtualRegister(currentInstruction[2].u.operand))));
+            NEXT_OPCODE(op_get_property_enumerator);
+        }
+
+        case op_enumerator_structure_pname: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorStructurePname,
                 get(VirtualRegister(currentInstruction[2].u.operand)),
                 get(VirtualRegister(currentInstruction[3].u.operand))));
-            NEXT_OPCODE(op_get_structure_property_enumerator);
+            NEXT_OPCODE(op_enumerator_structure_pname);
         }
 
-        case op_get_generic_property_enumerator: {
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetGenericPropertyEnumerator, 
-                get(VirtualRegister(currentInstruction[2].u.operand)),
-                get(VirtualRegister(currentInstruction[3].u.operand)),
-                get(VirtualRegister(currentInstruction[4].u.operand))));
-            NEXT_OPCODE(op_get_generic_property_enumerator);
-        }
-
-        case op_next_enumerator_pname: {
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorPname, 
+        case op_enumerator_generic_pname: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorGenericPname,
                 get(VirtualRegister(currentInstruction[2].u.operand)),
                 get(VirtualRegister(currentInstruction[3].u.operand))));
-            NEXT_OPCODE(op_next_enumerator_pname);
+            NEXT_OPCODE(op_enumerator_generic_pname);
         }
-
+            
         case op_to_index_string: {
             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToIndexString, 
                 get(VirtualRegister(currentInstruction[2].u.operand))));
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
index a476572..f54b223 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
@@ -202,9 +202,9 @@
     case op_has_structure_property:
     case op_has_indexed_property:
     case op_get_direct_pname:
-    case op_get_structure_property_enumerator:
-    case op_get_generic_property_enumerator:
-    case op_next_enumerator_pname:
+    case op_get_property_enumerator:
+    case op_enumerator_structure_pname:
+    case op_enumerator_generic_pname:
     case op_to_index_string:
     case op_new_func:
     case op_new_func_exp:
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index 625e2213..a695607 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -162,8 +162,7 @@
     case HasGenericProperty:
     case HasStructureProperty:
     case GetEnumerableLength:
-    case GetStructurePropertyEnumerator:
-    case GetGenericPropertyEnumerator: {
+    case GetPropertyEnumerator: {
         read(Heap);
         write(SideState);
         return;
@@ -178,7 +177,8 @@
     }
 
     case ToIndexString:
-    case GetEnumeratorPname: {
+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname: {
         def(PureValue(node));
         return;
     }
diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
index 8f70a18..375ac75 100644
--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
@@ -231,9 +231,9 @@
     case NewFunctionExpression:
     case NewTypedArray:
     case ThrowReferenceError:
-    case GetStructurePropertyEnumerator:
-    case GetGenericPropertyEnumerator:
-    case GetEnumeratorPname:
+    case GetPropertyEnumerator:
+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname:
     case ToIndexString:
     case MaterializeNewObject:
         return true;
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index b36fd91..191925a 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -1091,7 +1091,7 @@
             break;
         }
         case HasGenericProperty: {
-            fixEdge<StringUse>(node->child2());
+            fixEdge<CellUse>(node->child2());
             break;
         }
         case HasStructureProperty: {
@@ -1123,18 +1123,16 @@
             fixEdge<KnownCellUse>(enumerator);
             break;
         }
-        case GetStructurePropertyEnumerator: {
+        case GetPropertyEnumerator: {
             fixEdge<CellUse>(node->child1());
+            break;
+        }
+        case GetEnumeratorStructurePname: {
+            fixEdge<KnownCellUse>(node->child1());
             fixEdge<KnownInt32Use>(node->child2());
             break;
         }
-        case GetGenericPropertyEnumerator: {
-            fixEdge<CellUse>(node->child1());
-            fixEdge<KnownInt32Use>(node->child2());
-            fixEdge<KnownCellUse>(node->child3());
-            break;
-        }
-        case GetEnumeratorPname: {
+        case GetEnumeratorGenericPname: {
             fixEdge<KnownCellUse>(node->child1());
             fixEdge<KnownInt32Use>(node->child2());
             break;
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 339ce62..7b09dd7 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -322,9 +322,9 @@
     macro(HasStructureProperty, NodeResultBoolean) \
     macro(HasGenericProperty, NodeResultBoolean) \
     macro(GetDirectPname, NodeMustGenerate | NodeHasVarArgs | NodeResultJS) \
-    macro(GetStructurePropertyEnumerator, NodeMustGenerate | NodeResultJS) \
-    macro(GetGenericPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
-    macro(GetEnumeratorPname, NodeMustGenerate | NodeResultJS) \
+    macro(GetPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
+    macro(GetEnumeratorStructurePname, NodeMustGenerate | NodeResultJS) \
+    macro(GetEnumeratorGenericPname, NodeMustGenerate | NodeResultJS) \
     macro(ToIndexString, NodeResultJS)
 
 // This enum generates a monotonically increasing id for all Node types,
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index de7fbd8..5a6271f 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -583,12 +583,15 @@
             changed |= setPrediction(SpecBoolean);
             break;
         }
-        case GetStructurePropertyEnumerator:
-        case GetGenericPropertyEnumerator: {
+        case GetPropertyEnumerator: {
             changed |= setPrediction(SpecCell);
             break;
         }
-        case GetEnumeratorPname: {
+        case GetEnumeratorStructurePname: {
+            changed |= setPrediction(SpecCell | SpecOther);
+            break;
+        }
+        case GetEnumeratorGenericPname: {
             changed |= setPrediction(SpecCell | SpecOther);
             break;
         }
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index f5dbfcb..b1e1e9e 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -272,9 +272,9 @@
     case HasStructureProperty:
     case HasIndexedProperty:
     case GetDirectPname:
-    case GetStructurePropertyEnumerator:
-    case GetGenericPropertyEnumerator:
-    case GetEnumeratorPname:
+    case GetPropertyEnumerator:
+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname:
     case ToIndexString:
     case PhantomNewObject:
     case PutHint:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 44e8b26..b624de4 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -4715,12 +4715,11 @@
     }
 
     case GetEnumerableLength: {
-        SpeculateCellOperand base(this, node->child1());
+        SpeculateCellOperand enumerator(this, node->child1());
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
 
-        flushRegisters();
-        callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
+        m_jit.load32(MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::indexedLengthOffset()), resultGPR);
         int32Result(resultGPR, node);
         break;
     }
@@ -4912,30 +4911,18 @@
         jsValueResult(resultTagGPR, resultPayloadGPR, node);
         break;
     }
-    case GetStructurePropertyEnumerator: {
+    case GetPropertyEnumerator: {
         SpeculateCellOperand base(this, node->child1());
-        SpeculateInt32Operand length(this, node->child2());
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
 
         flushRegisters();
-        callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
+        callOperation(operationGetPropertyEnumerator, resultGPR, base.gpr());
         cellResult(resultGPR, node);
         break;
     }
-    case GetGenericPropertyEnumerator: {
-        SpeculateCellOperand base(this, node->child1());
-        SpeculateInt32Operand length(this, node->child2());
-        SpeculateCellOperand enumerator(this, node->child3());
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-
-        flushRegisters();
-        callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
-        cellResult(resultGPR, node);
-        break;
-    }
-    case GetEnumeratorPname: {
+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname: {
         SpeculateCellOperand enumerator(this, node->child1());
         SpeculateInt32Operand index(this, node->child2());
         GPRTemporary scratch(this);
@@ -4948,8 +4935,10 @@
         GPRReg resultTagGPR = resultTag.gpr();
         GPRReg resultPayloadGPR = resultPayload.gpr();
 
-        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, 
-            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
+        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, indexGPR,
+            MacroAssembler::Address(enumeratorGPR, (op == GetEnumeratorStructurePname)
+                ? JSPropertyNameEnumerator::endStructurePropertyIndexOffset()
+                : JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
 
         m_jit.move(MacroAssembler::TrustedImm32(JSValue::NullTag), resultTagGPR);
         m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 17b7eed..96e05c0 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -4772,12 +4772,11 @@
     }
 
     case GetEnumerableLength: {
-        SpeculateCellOperand base(this, node->child1());
+        SpeculateCellOperand enumerator(this, node->child1());
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
 
-        flushRegisters();
-        callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
+        m_jit.load32(MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::indexedLengthOffset()), resultGPR);
         int32Result(resultGPR, node);
         break;
     }
@@ -4948,30 +4947,18 @@
         jsValueResult(resultGPR, node);
         break;
     }
-    case GetStructurePropertyEnumerator: {
+    case GetPropertyEnumerator: {
         SpeculateCellOperand base(this, node->child1());
-        SpeculateInt32Operand length(this, node->child2());
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
 
         flushRegisters();
-        callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
+        callOperation(operationGetPropertyEnumerator, resultGPR, base.gpr());
         cellResult(resultGPR, node);
         break;
     }
-    case GetGenericPropertyEnumerator: {
-        SpeculateCellOperand base(this, node->child1());
-        SpeculateInt32Operand length(this, node->child2());
-        SpeculateCellOperand enumerator(this, node->child3());
-        GPRFlushedCallResult result(this);
-        GPRReg resultGPR = result.gpr();
-
-        flushRegisters();
-        callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
-        cellResult(resultGPR, node);
-        break;
-    }
-    case GetEnumeratorPname: {
+    case GetEnumeratorStructurePname:
+    case GetEnumeratorGenericPname: {
         SpeculateCellOperand enumerator(this, node->child1());
         SpeculateStrictInt32Operand index(this, node->child2());
         GPRTemporary scratch1(this);
@@ -4982,8 +4969,10 @@
         GPRReg scratch1GPR = scratch1.gpr();
         GPRReg resultGPR = result.gpr();
 
-        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, 
-            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
+        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, indexGPR,
+            MacroAssembler::Address(enumeratorGPR, (op == GetEnumeratorStructurePname)
+                ? JSPropertyNameEnumerator::endStructurePropertyIndexOffset()
+                : JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
 
         m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsNull())), resultGPR);