Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (172400 => 172401)
--- trunk/Source/_javascript_Core/ChangeLog 2014-08-11 18:47:34 UTC (rev 172400)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-08-11 18:59:44 UTC (rev 172401)
@@ -1,3 +1,26 @@
+2014-08-11 Mark Hahnenberg <mhahnenb...@apple.com>
+
+ for-in optimization should also make sure the base matches the object being iterated
+ https://bugs.webkit.org/show_bug.cgi?id=135782
+
+ Reviewed by Geoffrey Garen.
+
+ If we access a different base object with the same index, we shouldn't try to randomly
+ load from that object's backing store.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitGetByVal):
+ (JSC::BytecodeGenerator::pushIndexedForInScope):
+ (JSC::BytecodeGenerator::pushStructureForInScope):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::ForInContext::ForInContext):
+ (JSC::ForInContext::base):
+ (JSC::StructureForInContext::StructureForInContext):
+ (JSC::IndexedForInContext::IndexedForInContext):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ForInNode::emitMultiLoopBytecode):
+ * tests/stress/for-in-tests.js:
+
2014-08-11 Brent Fulgham <bfulg...@apple.com>
[Win] Unreviewed gardening.
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (172400 => 172401)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2014-08-11 18:47:34 UTC (rev 172400)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2014-08-11 18:59:44 UTC (rev 172401)
@@ -1445,6 +1445,9 @@
{
for (size_t i = m_forInContextStack.size(); i > 0; i--) {
ForInContext* context = m_forInContextStack[i - 1].get();
+ if (context->base() != base)
+ continue;
+
if (context->local() != property)
continue;
@@ -2620,11 +2623,11 @@
return dst;
}
-void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
+void BytecodeGenerator::pushIndexedForInScope(RegisterID* baseRegister, RegisterID* localRegister, RegisterID* indexRegister)
{
if (!localRegister)
return;
- m_forInContextStack.append(std::make_unique<IndexedForInContext>(localRegister, indexRegister));
+ m_forInContextStack.append(std::make_unique<IndexedForInContext>(baseRegister, localRegister, indexRegister));
}
void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
@@ -2634,11 +2637,11 @@
m_forInContextStack.removeLast();
}
-void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
+void BytecodeGenerator::pushStructureForInScope(RegisterID* baseRegister, RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
{
if (!localRegister)
return;
- m_forInContextStack.append(std::make_unique<StructureForInContext>(localRegister, indexRegister, propertyRegister, enumeratorRegister));
+ m_forInContextStack.append(std::make_unique<StructureForInContext>(baseRegister, localRegister, indexRegister, propertyRegister, enumeratorRegister));
}
void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (172400 => 172401)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2014-08-11 18:47:34 UTC (rev 172400)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2014-08-11 18:59:44 UTC (rev 172401)
@@ -99,8 +99,9 @@
class ForInContext {
public:
- ForInContext(RegisterID* localRegister)
- : m_localRegister(localRegister)
+ ForInContext(RegisterID* baseRegister, RegisterID* localRegister)
+ : m_baseRegister(baseRegister)
+ , m_localRegister(localRegister)
, m_isValid(true)
{
}
@@ -118,17 +119,19 @@
};
virtual ForInContextType type() const = 0;
+ RegisterID* base() const { return m_baseRegister.get(); }
RegisterID* local() const { return m_localRegister.get(); }
private:
+ RefPtr<RegisterID> m_baseRegister;
RefPtr<RegisterID> m_localRegister;
bool m_isValid;
};
class StructureForInContext : public ForInContext {
public:
- StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
- : ForInContext(localRegister)
+ StructureForInContext(RegisterID* baseRegister, RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
+ : ForInContext(baseRegister, localRegister)
, m_indexRegister(indexRegister)
, m_propertyRegister(propertyRegister)
, m_enumeratorRegister(enumeratorRegister)
@@ -152,8 +155,8 @@
class IndexedForInContext : public ForInContext {
public:
- IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
- : ForInContext(localRegister)
+ IndexedForInContext(RegisterID* baseRegister, RegisterID* localRegister, RegisterID* indexRegister)
+ : ForInContext(baseRegister, localRegister)
, m_indexRegister(indexRegister)
{
}
@@ -525,9 +528,9 @@
void pushFinallyContext(StatementNode* finallyBlock);
void popFinallyContext();
- void pushIndexedForInScope(RegisterID* local, RegisterID* index);
+ void pushIndexedForInScope(RegisterID* base, RegisterID* local, RegisterID* index);
void popIndexedForInScope(RegisterID* local);
- void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
+ void pushStructureForInScope(RegisterID* base, RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
void popStructureForInScope(RegisterID* local);
void invalidateForInContextForLocal(RegisterID* local);
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (172400 => 172401)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2014-08-11 18:47:34 UTC (rev 172400)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2014-08-11 18:59:44 UTC (rev 172401)
@@ -2044,7 +2044,7 @@
generator.emitToIndexString(propertyName.get(), i.get());
this->emitLoopHeader(generator, propertyName.get());
- generator.pushIndexedForInScope(local.get(), i.get());
+ generator.pushIndexedForInScope(base.get(), local.get(), i.get());
generator.emitNode(dst, m_statement);
generator.popIndexedForInScope(local.get());
@@ -2078,7 +2078,7 @@
this->emitLoopHeader(generator, propertyName.get());
- generator.pushStructureForInScope(local.get(), i.get(), propertyName.get(), structureEnumerator.get());
+ generator.pushStructureForInScope(base.get(), local.get(), i.get(), propertyName.get(), structureEnumerator.get());
generator.emitNode(dst, m_statement);
generator.popStructureForInScope(local.get());
Modified: trunk/Source/_javascript_Core/tests/stress/for-in-tests.js (172400 => 172401)
--- trunk/Source/_javascript_Core/tests/stress/for-in-tests.js 2014-08-11 18:47:34 UTC (rev 172400)
+++ trunk/Source/_javascript_Core/tests/stress/for-in-tests.js 2014-08-11 18:59:44 UTC (rev 172401)
@@ -75,3 +75,26 @@
}
foo(null);
})();
+(function() {
+ var foo = function(a, b) {
+ for (var p in a) {
+ var f1 = a[p];
+ var f2 = b[p];
+ if (f1 === f2)
+ continue;
+ a[p] = b[p];
+ }
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ var o1 = {};
+ var o2 = {};
+ o2.x = 42;
+ o2.y = 53;
+ foo(o1, o2);
+ if (o1.x !== o2.x)
+ throw new Error("bad result: " + o1.x + "!==" + o2.x);
+ if (o1.y !== o2.y)
+ throw new Error("bad result: " + o1.y + "!==" + o2.y);
+ }
+})();