+
+ RefPtr<RegisterID> base = generator.newTemporary();
+ RefPtr<RegisterID> length;
+ RefPtr<RegisterID> enumerator;
+ generator.emitNode(base.get(), m_expr);
+ RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
+ RefPtr<RegisterID> enumeratorIndex;
+
+ int profilerStartOffset = m_statement->startOffset();
+ int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
+
+ enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
+
+ // Indexed property loop.
+ {
+ LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+ RefPtr<Label> loopStart = generator.newLabel();
+ RefPtr<Label> loopEnd = generator.newLabel();
+
+ length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
+ RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+ RefPtr<RegisterID> propertyName = generator.newTemporary();
+
+ generator.emitLabel(loopStart.get());
+ generator.emitLoopHint();
+
+ RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
+ generator.emitJumpIfFalse(result.get(), loopEnd.get());
+ generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
+ generator.emitJumpIfFalse(result.get(), scope->continueTarget());
+
+ generator.emitToIndexString(propertyName.get(), i.get());
+ this->emitLoopHeader(generator, propertyName.get());
+
+ generator.emitProfileControlFlow(profilerStartOffset);
+
+ generator.pushIndexedForInScope(local.get(), i.get());
+ generator.emitNode(dst, m_statement);
+ generator.popIndexedForInScope(local.get());
+
+ generator.emitProfileControlFlow(profilerEndOffset);
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitInc(i.get());
+ generator.emitJump(loopStart.get());
+
+ generator.emitLabel(scope->breakTarget());
+ generator.emitJump(end.get());
+ generator.emitLabel(loopEnd.get());
+ }
+
+ // Structure property loop.
+ {
+ LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+ RefPtr<Label> loopStart = generator.newLabel();
+ RefPtr<Label> loopEnd = generator.newLabel();
+
+ enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+ RefPtr<RegisterID> propertyName = generator.newTemporary();
+ generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+
+ generator.emitLabel(loopStart.get());
+ generator.emitLoopHint();
+
+ RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
+ generator.emitJumpIfTrue(result.get(), loopEnd.get());
+ generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
+ generator.emitJumpIfFalse(result.get(), scope->continueTarget());
+
+ this->emitLoopHeader(generator, propertyName.get());
+
+ generator.emitProfileControlFlow(profilerStartOffset);
+
+ generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
+ generator.emitNode(dst, m_statement);
+ generator.popStructureForInScope(local.get());
+
+ generator.emitProfileControlFlow(profilerEndOffset);
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitInc(enumeratorIndex.get());
+ generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+ generator.emitJump(loopStart.get());
+
+ generator.emitLabel(scope->breakTarget());
+ generator.emitJump(end.get());
+ generator.emitLabel(loopEnd.get());
+ }
+
+ // Generic property loop.
+ {
+ LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+ RefPtr<Label> loopStart = generator.newLabel();
+ RefPtr<Label> loopEnd = generator.newLabel();
+
+ RefPtr<RegisterID> propertyName = generator.newTemporary();
+
+ generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+
+ generator.emitLabel(loopStart.get());
+ generator.emitLoopHint();
+
+ RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
+ generator.emitJumpIfTrue(result.get(), loopEnd.get());
+
+ generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
+ generator.emitJumpIfFalse(result.get(), scope->continueTarget());
+
+ this->emitLoopHeader(generator, propertyName.get());
+
+ generator.emitProfileControlFlow(profilerStartOffset);
+
+ generator.emitNode(dst, m_statement);
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitInc(enumeratorIndex.get());
+ generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+ generator.emitJump(loopStart.get());
+
+ generator.emitLabel(scope->breakTarget());
+ generator.emitJump(end.get());
+ generator.emitLabel(loopEnd.get());
+ }
+
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
+ generator.emitLabel(end.get());
+ generator.emitProfileControlFlow(profilerEndOffset);
+}
+
+void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ this->emitMultiLoopBytecode(generator, dst);