Diff
Modified: trunk/LayoutTests/ChangeLog (181890 => 181891)
--- trunk/LayoutTests/ChangeLog 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/LayoutTests/ChangeLog 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1,3 +1,21 @@
+2015-03-24 Michael Saboff <msab...@apple.com>
+
+ 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.
+
+ 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.
+
2015-03-24 Saam Barati <saambara...@gmail.com>
Improve error messages in JSC
Modified: trunk/LayoutTests/http/tests/security/cross-frame-access-enumeration-expected.txt (181890 => 181891)
--- trunk/LayoutTests/http/tests/security/cross-frame-access-enumeration-expected.txt 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/LayoutTests/http/tests/security/cross-frame-access-enumeration-expected.txt 2015-03-24 10:05:21 UTC (rev 181891)
@@ -9,6 +9,7 @@
CONSOLE MESSAGE: line 82: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 29: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 29: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 29: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 102: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
CONSOLE MESSAGE: line 109: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
This tests that variable names can't be enumerated cross domain (see http://bugs.webkit.org/show_bug.cgi?id=16387)
Added: trunk/LayoutTests/js/for-in-modify-in-loop-expected.txt (0 => 181891)
--- trunk/LayoutTests/js/for-in-modify-in-loop-expected.txt (rev 0)
+++ trunk/LayoutTests/js/for-in-modify-in-loop-expected.txt 2015-03-24 10:05:21 UTC (rev 181891)
@@ -0,0 +1,12 @@
+Check for ... in will properly enumerate elements added or deleted during the loop
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 }) is true
+PASS haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 }) is true
+PASS haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 }) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/for-in-modify-in-loop.html (0 => 181891)
--- trunk/LayoutTests/js/for-in-modify-in-loop.html (rev 0)
+++ trunk/LayoutTests/js/for-in-modify-in-loop.html 2015-03-24 10:05:21 UTC (rev 181891)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/script-tests/for-in-modify-in-loop.js (0 => 181891)
--- trunk/LayoutTests/js/script-tests/for-in-modify-in-loop.js (rev 0)
+++ trunk/LayoutTests/js/script-tests/for-in-modify-in-loop.js 2015-03-24 10:05:21 UTC (rev 181891)
@@ -0,0 +1,97 @@
+description("Check for ... in will properly enumerate elements added or deleted during the loop");
+
+function haveSameProperties(a, b) {
+ var p;
+
+ for (p in a) {
+ if (!b.hasOwnProperty(p))
+ return false;
+ }
+
+ for (p in b) {
+ if (!a.hasOwnProperty(p))
+ return false;
+ }
+
+ return true;
+}
+
+function each(o, callback) {
+ var result = {};
+
+ for (var property in o) {
+ callback(property, o);
+ if (result.hasOwnProperty(property))
+ throw "Duplicate property \"" + property + "\" enumerated";
+ result[property] = 1;
+ }
+
+ return result;
+}
+
+function testAdd()
+{
+ var obj = { a : "First" };
+ obj["m"] = "Second";
+ obj["z"] = "Third";
+
+ var elementsToAdd = [ "c", "t", "k" ];
+ var addIndex = 0;
+
+ var result = {};
+
+ return each(obj, function(p, o) {
+ if (addIndex < elementsToAdd.length)
+ o[elementsToAdd[addIndex++]] = "Added #" + addIndex;
+ });
+}
+
+function testDelete()
+{
+ var obj = { a : "First" };
+ obj["b"] = "Second";
+ obj["c"] = "Third";
+ obj["d"] = "Fourth";
+
+ var elementsToDelete = [ "c" ];
+ var deleteIndex = 0;
+
+ return each(obj, function(p, o) {
+ if (deleteIndex < elementsToDelete.length)
+ delete o[elementsToDelete[deleteIndex++]];
+ });
+}
+
+function testAddDelete()
+{
+ var obj = { a : "First", b : "Second", c : "Third", j : "Fourth", z : "Fifth", lastOne : "The End" };
+
+ elementsToAdd = [ "d", "p" ];
+ elementsToDelete = [ "z", "lastOne", "c" ];
+ var loopIndex = 0;
+
+ return each(obj, function(p, o) {
+ if (loopIndex++ == 1) {
+ for (var i = 0; i < elementsToAdd.length; i++)
+ o[elementsToAdd[i]] = "Added #" + i;
+ for (var i = 0; i < elementsToDelete.length; i++)
+ delete o[elementsToDelete[i]];
+ }
+ });
+}
+
+shouldBeTrue("haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 })");
+shouldBeTrue("haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 })");
+shouldBeTrue("haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 })");
+
+for (var i = 0; i < 10000; i++) {
+ if (!haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 }))
+ shouldBeTrue("haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 })");
+
+ if (!haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 }))
+ shouldBeTrue("haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 })");
+
+ if (!haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 }))
+ shouldBeTrue("haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 })");
+}
+
Modified: trunk/Source/_javascript_Core/ChangeLog (181890 => 181891)
--- trunk/Source/_javascript_Core/ChangeLog 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1,5 +1,135 @@
2015-03-24 Michael Saboff <msab...@apple.com>
+ 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.
+
+ 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:
+
+2015-03-24 Michael Saboff <msab...@apple.com>
+
Unreviewed build fix for debug builds.
* runtime/ExceptionHelpers.cpp:
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (181890 => 181891)
--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2015-03-24 10:05:21 UTC (rev 181891)
@@ -125,9 +125,9 @@
{ "name" : "op_has_structure_property", "length" : 5 },
{ "name" : "op_has_generic_property", "length" : 4 },
{ "name" : "op_get_direct_pname", "length" : 7 },
- { "name" : "op_get_structure_property_enumerator", "length" : 4 },
- { "name" : "op_get_generic_property_enumerator", "length" : 5 },
- { "name" : "op_next_enumerator_pname", "length" : 4 },
+ { "name" : "op_get_property_enumerator", "length" : 3 },
+ { "name" : "op_enumerator_structure_pname", "length" : 4 },
+ { "name" : "op_enumerator_generic_pname", "length" : 4 },
{ "name" : "op_to_index_string", "length" : 3 }
]
},
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (181890 => 181891)
--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -113,6 +113,7 @@
return;
}
case op_create_lexical_environment:
+ case op_get_property_enumerator:
case op_get_enumerable_length:
case op_new_func_exp:
case op_to_index_string:
@@ -149,9 +150,9 @@
return;
}
case op_has_generic_property:
- case op_get_structure_property_enumerator:
case op_has_indexed_property:
- case op_next_enumerator_pname:
+ case op_enumerator_structure_pname:
+ case op_enumerator_generic_pname:
case op_get_by_val:
case op_in:
case op_instanceof:
@@ -182,7 +183,6 @@
}
case op_has_structure_property:
case op_get_argument_by_val:
- case op_get_generic_property_enumerator:
case op_construct_varargs:
case op_call_varargs: {
functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
@@ -291,14 +291,14 @@
return;
// These all have a single destination for the first argument.
case op_to_index_string:
- case op_get_generic_property_enumerator:
case op_get_enumerable_length:
case op_has_indexed_property:
case op_has_structure_property:
case op_has_generic_property:
case op_get_direct_pname:
- case op_get_structure_property_enumerator:
- case op_next_enumerator_pname:
+ case op_get_property_enumerator:
+ case op_enumerator_structure_pname:
+ case op_enumerator_generic_pname:
case op_pop_scope:
case op_push_name_scope:
case op_push_with_scope:
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1408,31 +1408,30 @@
break;
}
- case op_get_structure_property_enumerator: {
+ case op_get_property_enumerator: {
int dst = it[1].u.operand;
int base = it[2].u.operand;
- printLocationAndOp(out, exec, location, it, "op_get_structure_property_enumerator");
+ printLocationAndOp(out, exec, location, it, "op_get_property_enumerator");
out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
- it += OPCODE_LENGTH(op_get_structure_property_enumerator) - 1;
+ it += OPCODE_LENGTH(op_get_property_enumerator) - 1;
break;
}
- case op_get_generic_property_enumerator: {
+ case op_enumerator_structure_pname: {
int dst = it[1].u.operand;
- int base = it[2].u.operand;
- int length = it[3].u.operand;
- int structureEnumerator = it[4].u.operand;
- printLocationAndOp(out, exec, location, it, "op_get_generic_property_enumerator");
- out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(length).data(), registerName(structureEnumerator).data());
- it += OPCODE_LENGTH(op_get_generic_property_enumerator) - 1;
+ int enumerator = it[2].u.operand;
+ int index = it[3].u.operand;
+ printLocationAndOp(out, exec, location, it, "op_enumerator_structure_pname");
+ out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
+ it += OPCODE_LENGTH(op_enumerator_structure_pname) - 1;
break;
}
- case op_next_enumerator_pname: {
+ case op_enumerator_generic_pname: {
int dst = it[1].u.operand;
int enumerator = it[2].u.operand;
int index = it[3].u.operand;
- printLocationAndOp(out, exec, location, it, "op_next_enumerator_pname");
+ printLocationAndOp(out, exec, location, it, "op_enumerator_generic_pname");
out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
- it += OPCODE_LENGTH(op_next_enumerator_pname) - 1;
+ it += OPCODE_LENGTH(op_enumerator_generic_pname) - 1;
break;
}
case op_to_index_string: {
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -2701,28 +2701,26 @@
return dst;
}
-RegisterID* BytecodeGenerator::emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length)
+RegisterID* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base)
{
- emitOpcode(op_get_structure_property_enumerator);
+ emitOpcode(op_get_property_enumerator);
instructions().append(dst->index());
instructions().append(base->index());
- instructions().append(length->index());
return dst;
}
-RegisterID* BytecodeGenerator::emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator)
+RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
{
- emitOpcode(op_get_generic_property_enumerator);
+ emitOpcode(op_enumerator_structure_pname);
instructions().append(dst->index());
- instructions().append(base->index());
- instructions().append(length->index());
- instructions().append(structureEnumerator->index());
+ instructions().append(enumerator->index());
+ instructions().append(index->index());
return dst;
}
-RegisterID* BytecodeGenerator::emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
+RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
{
- emitOpcode(op_next_enumerator_pname);
+ emitOpcode(op_enumerator_generic_pname);
instructions().append(dst->index());
instructions().append(enumerator->index());
instructions().append(index->index());
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (181890 => 181891)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -531,10 +531,12 @@
RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
+ RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
- RegisterID* emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
+ RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
+ RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -2183,19 +2183,23 @@
RefPtr<RegisterID> base = generator.newTemporary();
RefPtr<RegisterID> length;
- RefPtr<RegisterID> structureEnumerator;
+ 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(), base.get());
+ length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
RefPtr<RegisterID> propertyName = generator.newTemporary();
@@ -2233,32 +2237,31 @@
RefPtr<Label> loopStart = generator.newLabel();
RefPtr<Label> loopEnd = generator.newLabel();
- structureEnumerator = generator.emitGetStructurePropertyEnumerator(generator.newTemporary(), base.get(), length.get());
- RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+ enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
RefPtr<RegisterID> propertyName = generator.newTemporary();
- generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
+ 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(), structureEnumerator.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(), i.get(), propertyName.get(), structureEnumerator.get());
+ 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(i.get());
- generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
+ generator.emitInc(enumeratorIndex.get());
+ generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
generator.emitJump(loopStart.get());
generator.emitLabel(scope->breakTarget());
@@ -2272,17 +2275,19 @@
RefPtr<Label> loopStart = generator.newLabel();
RefPtr<Label> loopEnd = generator.newLabel();
- RefPtr<RegisterID> genericEnumerator = generator.emitGetGenericPropertyEnumerator(generator.newTemporary(), base.get(), length.get(), structureEnumerator.get());
- RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
RefPtr<RegisterID> propertyName = generator.newTemporary();
- generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
- RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
- generator.emitJumpIfTrue(result.get(), loopEnd.get());
+ 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);
@@ -2290,15 +2295,10 @@
generator.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
- generator.emitInc(i.get());
- generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
- generator.emitUnaryOp(op_eq_null, result.get(), propertyName.get());
- generator.emitJumpIfTrue(result.get(), loopEnd.get());
+ generator.emitInc(enumeratorIndex.get());
+ generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+ generator.emitJump(loopStart.get());
- generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
- generator.emitJumpIfTrue(result.get(), loopStart.get());
- generator.emitJump(scope->continueTarget());
-
generator.emitLabel(scope->breakTarget());
generator.emitJump(end.get());
generator.emitLabel(loopEnd.get());
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -3770,28 +3770,26 @@
NEXT_OPCODE(op_get_direct_pname);
}
- case op_get_structure_property_enumerator: {
- set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetStructurePropertyEnumerator,
- get(VirtualRegister(currentInstruction[2].u.operand)),
- get(VirtualRegister(currentInstruction[3].u.operand))));
- NEXT_OPCODE(op_get_structure_property_enumerator);
+ 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_get_generic_property_enumerator: {
- set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetGenericPropertyEnumerator,
+ 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)),
- get(VirtualRegister(currentInstruction[4].u.operand))));
- NEXT_OPCODE(op_get_generic_property_enumerator);
+ get(VirtualRegister(currentInstruction[3].u.operand))));
+ NEXT_OPCODE(op_enumerator_structure_pname);
}
- 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))));
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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:
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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;
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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());
- fixEdge<KnownInt32Use>(node->child2());
break;
}
- case GetGenericPropertyEnumerator: {
- fixEdge<CellUse>(node->child1());
+ case GetEnumeratorStructurePname: {
+ fixEdge<KnownCellUse>(node->child1());
fixEdge<KnownInt32Use>(node->child2());
- fixEdge<KnownCellUse>(node->child3());
break;
}
- case GetEnumeratorPname: {
+ case GetEnumeratorGenericPname: {
fixEdge<KnownCellUse>(node->child1());
fixEdge<KnownInt32Use>(node->child2());
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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,
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -583,15 +583,18 @@
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;
+ }
case ToIndexString: {
changed |= setPrediction(SpecString);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -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);
Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (181890 => 181891)
--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -61,9 +61,11 @@
macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \
macro(JSObject_butterfly, JSObject::butterflyOffset()) \
macro(JSPropertyNameEnumerator_cachedInlineCapacity, JSPropertyNameEnumerator::cachedInlineCapacityOffset()) \
- macro(JSPropertyNameEnumerator_cachedPropertyNamesLength, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()) \
macro(JSPropertyNameEnumerator_cachedPropertyNamesVector, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()) \
macro(JSPropertyNameEnumerator_cachedStructureID, JSPropertyNameEnumerator::cachedStructureIDOffset()) \
+ macro(JSPropertyNameEnumerator_endGenericPropertyIndex, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()) \
+ macro(JSPropertyNameEnumerator_endStructurePropertyIndex, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()) \
+ macro(JSPropertyNameEnumerator_indexLength, JSPropertyNameEnumerator::indexedLengthOffset()) \
macro(JSScope_next, JSScope::offsetOfNext()) \
macro(JSString_flags, JSString::offsetOfFlags()) \
macro(JSString_length, JSString::offsetOfLength()) \
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -171,9 +171,9 @@
case HasStructureProperty:
case GetDirectPname:
case GetEnumerableLength:
- case GetStructurePropertyEnumerator:
- case GetGenericPropertyEnumerator:
- case GetEnumeratorPname:
+ case GetPropertyEnumerator:
+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname:
case ToIndexString:
case BottomValue:
case PhantomNewObject:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -803,14 +803,14 @@
case GetEnumerableLength:
compileGetEnumerableLength();
break;
- case GetStructurePropertyEnumerator:
- compileGetStructurePropertyEnumerator();
+ case GetPropertyEnumerator:
+ compileGetPropertyEnumerator();
break;
- case GetGenericPropertyEnumerator:
- compileGetGenericPropertyEnumerator();
+ case GetEnumeratorStructurePname:
+ compileGetEnumeratorStructurePname();
break;
- case GetEnumeratorPname:
- compileGetEnumeratorPname();
+ case GetEnumeratorGenericPname:
+ compileGetEnumeratorGenericPname();
break;
case ToIndexString:
compileToIndexString();
@@ -4526,41 +4526,59 @@
void compileGetEnumerableLength()
{
- LValue base = lowCell(m_node->child1());
- setInt32(vmCall(m_out.operation(operationGetEnumerableLength), m_callFrame, base));
+ LValue enumerator = lowCell(m_node->child1());
+ setInt32(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_indexLength));
}
- void compileGetStructurePropertyEnumerator()
+ void compileGetPropertyEnumerator()
{
LValue base = lowCell(m_node->child1());
- LValue length = lowInt32(m_node->child2());
- setJSValue(vmCall(m_out.operation(operationGetStructurePropertyEnumerator), m_callFrame, base, length));
+ setJSValue(vmCall(m_out.operation(operationGetPropertyEnumerator), m_callFrame, base));
}
- void compileGetGenericPropertyEnumerator()
+ void compileGetEnumeratorStructurePname()
{
- LValue base = lowCell(m_node->child1());
- LValue length = lowInt32(m_node->child2());
- LValue enumerator = lowCell(m_node->child3());
- setJSValue(vmCall(m_out.operation(operationGetGenericPropertyEnumerator), m_callFrame, base, length, enumerator));
+ LValue enumerator = lowCell(m_node->child1());
+ LValue index = lowInt32(m_node->child2());
+
+ LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorStructurePname in bounds"));
+ LBasicBlock outOfBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorStructurePname out of bounds"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetEnumeratorStructurePname continuation"));
+
+ m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endStructurePropertyIndex)),
+ usually(inBounds), rarely(outOfBounds));
+
+ LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
+ LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
+ ValueFromBlock inBoundsResult = m_out.anchor(
+ m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
+ storage, m_out.signExt(index, m_out.int64), ScaleEight)));
+ m_out.jump(continuation);
+
+ m_out.appendTo(outOfBounds, continuation);
+ ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(ValueNull));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.int64, inBoundsResult, outOfBoundsResult));
}
- void compileGetEnumeratorPname()
+ void compileGetEnumeratorGenericPname()
{
LValue enumerator = lowCell(m_node->child1());
LValue index = lowInt32(m_node->child2());
- LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname in bounds"));
- LBasicBlock outOfBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname out of bounds"));
- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname continuation"));
+ LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorGenericPname in bounds"));
+ LBasicBlock outOfBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorGenericPname out of bounds"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetEnumeratorGenericPname continuation"));
- m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesLength)),
+ m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex)),
usually(inBounds), rarely(outOfBounds));
LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
ValueFromBlock inBoundsResult = m_out.anchor(
- m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
+ m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
storage, m_out.signExt(index, m_out.int64), ScaleEight)));
m_out.jump(continuation);
@@ -4571,7 +4589,7 @@
m_out.appendTo(continuation, lastNext);
setJSValue(m_out.phi(m_out.int64, inBoundsResult, outOfBoundsResult));
}
-
+
void compileToIndexString()
{
LValue index = lowInt32(m_node->child1());
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -306,9 +306,9 @@
DEFINE_OP(op_has_structure_property)
DEFINE_OP(op_has_indexed_property)
DEFINE_OP(op_get_direct_pname)
- DEFINE_OP(op_get_structure_property_enumerator)
- DEFINE_OP(op_get_generic_property_enumerator)
- DEFINE_OP(op_next_enumerator_pname)
+ DEFINE_OP(op_get_property_enumerator)
+ DEFINE_OP(op_enumerator_structure_pname)
+ DEFINE_OP(op_enumerator_generic_pname)
DEFINE_OP(op_to_index_string)
default:
RELEASE_ASSERT_NOT_REACHED();
Modified: trunk/Source/_javascript_Core/jit/JIT.h (181890 => 181891)
--- trunk/Source/_javascript_Core/jit/JIT.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -557,9 +557,9 @@
void emit_op_has_structure_property(Instruction*);
void emit_op_has_indexed_property(Instruction*);
void emit_op_get_direct_pname(Instruction*);
- void emit_op_get_structure_property_enumerator(Instruction*);
- void emit_op_get_generic_property_enumerator(Instruction*);
- void emit_op_next_enumerator_pname(Instruction*);
+ void emit_op_get_property_enumerator(Instruction*);
+ void emit_op_enumerator_structure_pname(Instruction*);
+ void emit_op_enumerator_generic_pname(Instruction*);
void emit_op_to_index_string(Instruction*);
void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1284,7 +1284,7 @@
slowPathCall.call();
}
-void JIT::emit_op_next_enumerator_pname(Instruction* currentInstruction)
+void JIT::emit_op_enumerator_structure_pname(Instruction* currentInstruction)
{
int dst = currentInstruction[1].u.operand;
int enumerator = currentInstruction[2].u.operand;
@@ -1292,7 +1292,7 @@
emitGetVirtualRegister(index, regT0);
emitGetVirtualRegister(enumerator, regT1);
- Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
move(TrustedImm64(JSValue::encode(jsNull())), regT0);
@@ -1307,6 +1307,29 @@
emitPutVirtualRegister(dst);
}
+void JIT::emit_op_enumerator_generic_pname(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int enumerator = currentInstruction[2].u.operand;
+ int index = currentInstruction[3].u.operand;
+
+ emitGetVirtualRegister(index, regT0);
+ emitGetVirtualRegister(enumerator, regT1);
+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
+
+ move(TrustedImm64(JSValue::encode(jsNull())), regT0);
+
+ Jump done = jump();
+ inBounds.link(this);
+
+ loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+ signExtend32ToPtr(regT0, regT0);
+ load64(BaseIndex(regT1, regT0, TimesEight), regT0);
+
+ done.link(this);
+ emitPutVirtualRegister(dst);
+}
+
void JIT::emit_op_profile_type(Instruction* currentInstruction)
{
TypeLocation* cachedTypeLocation = currentInstruction[2].u.location;
@@ -1392,18 +1415,12 @@
slowPathCall.call();
}
-void JIT::emit_op_get_structure_property_enumerator(Instruction* currentInstruction)
+void JIT::emit_op_get_property_enumerator(Instruction* currentInstruction)
{
- JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_structure_property_enumerator);
+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_property_enumerator);
slowPathCall.call();
}
-void JIT::emit_op_get_generic_property_enumerator(Instruction* currentInstruction)
-{
- JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_generic_property_enumerator);
- slowPathCall.call();
-}
-
void JIT::emit_op_to_index_string(Instruction* currentInstruction)
{
JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_index_string);
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1259,7 +1259,7 @@
slowPathCall.call();
}
-void JIT::emit_op_next_enumerator_pname(Instruction* currentInstruction)
+void JIT::emit_op_enumerator_structure_pname(Instruction* currentInstruction)
{
int dst = currentInstruction[1].u.operand;
int enumerator = currentInstruction[2].u.operand;
@@ -1267,7 +1267,7 @@
emitLoadPayload(index, regT0);
emitLoadPayload(enumerator, regT1);
- Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
move(TrustedImm32(JSValue::NullTag), regT2);
move(TrustedImm32(0), regT0);
@@ -1283,6 +1283,30 @@
emitStore(dst, regT2, regT0);
}
+void JIT::emit_op_enumerator_generic_pname(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int enumerator = currentInstruction[2].u.operand;
+ int index = currentInstruction[3].u.operand;
+
+ emitLoadPayload(index, regT0);
+ emitLoadPayload(enumerator, regT1);
+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
+
+ move(TrustedImm32(JSValue::NullTag), regT2);
+ move(TrustedImm32(0), regT0);
+
+ Jump done = jump();
+ inBounds.link(this);
+
+ loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+ loadPtr(BaseIndex(regT1, regT0, timesPtr()), regT0);
+ move(TrustedImm32(JSValue::CellTag), regT2);
+
+ done.link(this);
+ emitStore(dst, regT2, regT0);
+}
+
void JIT::emit_op_profile_type(Instruction* currentInstruction)
{
TypeLocation* cachedTypeLocation = currentInstruction[2].u.location;
Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/jit/JITOperations.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1847,14 +1847,6 @@
#endif // COMPILER(CLANG)
}
-int32_t JIT_OPERATION operationGetEnumerableLength(ExecState* exec, JSCell* baseCell)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
- return base->methodTable(vm)->getEnumerableLength(exec, base);
-}
-
EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
{
VM& vm = exec->vm();
@@ -1875,28 +1867,16 @@
return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
}
-JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState* exec, JSCell* cell, int32_t length)
+JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, JSCell* cell)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
-
+
JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
- ASSERT(length >= 0);
- return structurePropertyNameEnumerator(exec, base, static_cast<uint32_t>(length));
+ return propertyNameEnumerator(exec, base);
}
-JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState* exec, JSCell* baseCell, int32_t length, JSCell* structureEnumeratorCell)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
-
- JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
- ASSERT(length >= 0);
-
- return genericPropertyNameEnumerator(exec, base, length, jsCast<JSPropertyNameEnumerator*>(structureEnumeratorCell));
-}
-
EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
{
VM& vm = exec->vm();
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (181890 => 181891)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -327,11 +327,9 @@
void JIT_OPERATION operationExceptionFuzz();
-int32_t JIT_OPERATION operationGetEnumerableLength(ExecState*, JSCell*);
EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*);
EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState*, JSCell*, int32_t);
-JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState*, JSCell*, int32_t);
-JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState*, JSCell*, int32_t, JSCell*);
+JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState*, JSCell*);
EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState*, JSCell*, int32_t);
JSCell* JIT_OPERATION operationToIndexString(ExecState*, int32_t);
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (181890 => 181891)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1334,19 +1334,19 @@
callSlowPath(_slow_path_get_direct_pname)
dispatch(7)
-_llint_op_get_structure_property_enumerator:
+_llint_op_get_property_enumerator:
traceExecution()
- callSlowPath(_slow_path_get_structure_property_enumerator)
- dispatch(4)
+ callSlowPath(_slow_path_get_property_enumerator)
+ dispatch(3)
-_llint_op_get_generic_property_enumerator:
+_llint_op_enumerator_structure_pname:
traceExecution()
- callSlowPath(_slow_path_get_generic_property_enumerator)
- dispatch(5)
+ callSlowPath(_slow_path_next_structure_enumerator_pname)
+ dispatch(4)
-_llint_op_next_enumerator_pname:
+_llint_op_enumerator_generic_pname:
traceExecution()
- callSlowPath(_slow_path_next_enumerator_pname)
+ callSlowPath(_slow_path_next_generic_enumerator_pname)
dispatch(4)
_llint_op_to_index_string:
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -520,12 +520,13 @@
SLOW_PATH_DECL(slow_path_get_enumerable_length)
{
BEGIN();
- JSValue baseValue = OP(2).jsValue();
- if (baseValue.isUndefinedOrNull())
+ JSValue enumeratorValue = OP(2).jsValue();
+ if (enumeratorValue.isUndefinedOrNull())
RETURN(jsNumber(0));
- JSObject* base = baseValue.toObject(exec);
- RETURN(jsNumber(base->methodTable(vm)->getEnumerableLength(exec, base)));
+ JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
+
+ RETURN(jsNumber(enumerator->indexedLength()));
}
SLOW_PATH_DECL(slow_path_has_indexed_property)
@@ -574,39 +575,39 @@
RETURN(baseValue.get(exec, property.toPropertyKey(exec)));
}
-SLOW_PATH_DECL(slow_path_get_structure_property_enumerator)
+SLOW_PATH_DECL(slow_path_get_property_enumerator)
{
BEGIN();
JSValue baseValue = OP(2).jsValue();
if (baseValue.isUndefinedOrNull())
RETURN(JSPropertyNameEnumerator::create(vm));
-
+
JSObject* base = baseValue.toObject(exec);
- uint32_t length = OP(3).jsValue().asUInt32();
- RETURN(structurePropertyNameEnumerator(exec, base, length));
+ RETURN(propertyNameEnumerator(exec, base));
}
-SLOW_PATH_DECL(slow_path_get_generic_property_enumerator)
+SLOW_PATH_DECL(slow_path_next_structure_enumerator_pname)
{
BEGIN();
- JSValue baseValue = OP(2).jsValue();
- if (baseValue.isUndefinedOrNull())
- RETURN(JSPropertyNameEnumerator::create(vm));
-
- JSObject* base = baseValue.toObject(exec);
- uint32_t length = OP(3).jsValue().asUInt32();
- JSPropertyNameEnumerator* structureEnumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
+ JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
+ uint32_t index = OP(3).jsValue().asUInt32();
- RETURN(genericPropertyNameEnumerator(exec, base, length, structureEnumerator));
+ JSString* propertyName = nullptr;
+ if (index < enumerator->endStructurePropertyIndex())
+ propertyName = enumerator->propertyNameAtIndex(index);
+ RETURN(propertyName ? propertyName : jsNull());
}
-SLOW_PATH_DECL(slow_path_next_enumerator_pname)
+SLOW_PATH_DECL(slow_path_next_generic_enumerator_pname)
{
BEGIN();
JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
uint32_t index = OP(3).jsValue().asUInt32();
- JSString* propertyName = enumerator->propertyNameAtIndex(index);
+
+ JSString* propertyName = nullptr;
+ if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
+ propertyName = enumerator->propertyNameAtIndex(index);
RETURN(propertyName ? propertyName : jsNull());
}
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -226,9 +226,9 @@
SLOW_PATH_HIDDEN_DECL(slow_path_has_structure_property);
SLOW_PATH_HIDDEN_DECL(slow_path_has_indexed_property);
SLOW_PATH_HIDDEN_DECL(slow_path_get_direct_pname);
-SLOW_PATH_HIDDEN_DECL(slow_path_get_structure_property_enumerator);
-SLOW_PATH_HIDDEN_DECL(slow_path_get_generic_property_enumerator);
-SLOW_PATH_HIDDEN_DECL(slow_path_next_enumerator_pname);
+SLOW_PATH_HIDDEN_DECL(slow_path_get_property_enumerator);
+SLOW_PATH_HIDDEN_DECL(slow_path_next_structure_enumerator_pname);
+SLOW_PATH_HIDDEN_DECL(slow_path_next_generic_enumerator_pname);
SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
SLOW_PATH_HIDDEN_DECL(slow_path_profile_type_clear_log);
Modified: trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -37,18 +37,18 @@
{
if (!vm.emptyPropertyNameEnumerator.get()) {
PropertyNameArray propertyNames(&vm);
- vm.emptyPropertyNameEnumerator = Strong<JSCell>(vm, create(vm, 0, propertyNames));
+ vm.emptyPropertyNameEnumerator = Strong<JSCell>(vm, create(vm, 0, 0, 0, propertyNames));
}
return jsCast<JSPropertyNameEnumerator*>(vm.emptyPropertyNameEnumerator.get());
}
-JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm, Structure* structure, PropertyNameArray& propertyNames)
+JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm, Structure* structure, uint32_t indexedLength, uint32_t numberStructureProperties, PropertyNameArray& propertyNames)
{
StructureID structureID = structure ? structure->id() : 0;
uint32_t inlineCapacity = structure ? structure->inlineCapacity() : 0;
JSPropertyNameEnumerator* enumerator = new (NotNull,
allocateCell<JSPropertyNameEnumerator>(vm.heap)) JSPropertyNameEnumerator(vm, structureID, inlineCapacity, propertyNames.identifierSet());
- enumerator->finishCreation(vm, propertyNames.data());
+ enumerator->finishCreation(vm, indexedLength, numberStructureProperties, propertyNames.data());
return enumerator;
}
@@ -60,12 +60,17 @@
{
}
-void JSPropertyNameEnumerator::finishCreation(VM& vm, PassRefPtr<PropertyNameArrayData> idents)
+void JSPropertyNameEnumerator::finishCreation(VM& vm, uint32_t indexedLength, uint32_t endStructurePropertyIndex, PassRefPtr<PropertyNameArrayData> idents)
{
Base::finishCreation(vm);
RefPtr<PropertyNameArrayData> identifiers = idents;
PropertyNameArrayData::PropertyNameVector& vector = identifiers->propertyNameVector();
+
+ m_indexedLength = indexedLength;
+ m_endStructurePropertyIndex = endStructurePropertyIndex;
+ m_endGenericPropertyIndex = vector.size();
+
m_propertyNames.resize(vector.size());
for (unsigned i = 0; i < vector.size(); ++i) {
const Identifier& identifier = vector[i];
Modified: trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/JSPropertyNameEnumerator.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -40,7 +40,7 @@
typedef JSCell Base;
static JSPropertyNameEnumerator* create(VM&);
- static JSPropertyNameEnumerator* create(VM&, Structure*, PropertyNameArray&);
+ static JSPropertyNameEnumerator* create(VM&, Structure*, uint32_t, uint32_t, PropertyNameArray&);
static const bool needsDestruction = true;
static const bool hasImmortalStructure = true;
@@ -75,13 +75,15 @@
return vm.heap.structureIDTable().get(m_cachedStructureID);
}
StructureID cachedStructureID() const { return m_cachedStructureID; }
+ uint32_t indexedLength() const { return m_indexedLength; }
+ uint32_t endStructurePropertyIndex() const { return m_endStructurePropertyIndex; }
+ uint32_t endGenericPropertyIndex() const { return m_endGenericPropertyIndex; }
uint32_t cachedInlineCapacity() const { return m_cachedInlineCapacity; }
static ptrdiff_t cachedStructureIDOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedStructureID); }
+ static ptrdiff_t indexedLengthOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_indexedLength); }
+ static ptrdiff_t endStructurePropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_endStructurePropertyIndex); }
+ static ptrdiff_t endGenericPropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_endGenericPropertyIndex); }
static ptrdiff_t cachedInlineCapacityOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedInlineCapacity); }
- static ptrdiff_t cachedPropertyNamesLengthOffset()
- {
- return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames) + Vector<WriteBarrier<JSString>>::sizeMemoryOffset();
- }
static ptrdiff_t cachedPropertyNamesVectorOffset()
{
return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames) + Vector<WriteBarrier<JSString>>::dataMemoryOffset();
@@ -93,65 +95,53 @@
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
JSPropertyNameEnumerator(VM&, StructureID, uint32_t, RefCountedIdentifierSet*);
- void finishCreation(VM&, PassRefPtr<PropertyNameArrayData>);
+ void finishCreation(VM&, uint32_t, uint32_t, PassRefPtr<PropertyNameArrayData>);
Vector<WriteBarrier<JSString>> m_propertyNames;
RefPtr<RefCountedIdentifierSet> m_identifierSet;
StructureID m_cachedStructureID;
WriteBarrier<StructureChain> m_prototypeChain;
+ uint32_t m_indexedLength;
+ uint32_t m_endStructurePropertyIndex;
+ uint32_t m_endGenericPropertyIndex;
uint32_t m_cachedInlineCapacity;
};
-inline JSPropertyNameEnumerator* structurePropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length)
+inline JSPropertyNameEnumerator* propertyNameEnumerator(ExecState* exec, JSObject* base)
{
VM& vm = exec->vm();
+
+ uint32_t indexedLength = base->methodTable(vm)->getEnumerableLength(exec, base);
+
+ JSPropertyNameEnumerator* enumerator = nullptr;
+
Structure* structure = base->structure(vm);
- if (JSPropertyNameEnumerator* enumerator = structure->cachedStructurePropertyNameEnumerator())
+ if (!indexedLength
+ && (enumerator = structure->cachedPropertyNameEnumerator())
+ && enumerator->cachedPrototypeChain() == structure->prototypeChain(exec))
return enumerator;
- if (!structure->canAccessPropertiesQuickly() || length != base->getArrayLength())
- return JSPropertyNameEnumerator::create(vm);
+ uint32_t numberStructureProperties = 0;
PropertyNameArray propertyNames(exec);
- base->methodTable(vm)->getStructurePropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
- JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, structure, propertyNames);
- if (structure->canCacheStructurePropertyNameEnumerator())
- structure->setCachedStructurePropertyNameEnumerator(vm, enumerator);
- return enumerator;
-}
+ if (structure->canAccessPropertiesQuickly() && indexedLength == base->getArrayLength()) {
+ base->methodTable(vm)->getStructurePropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
-inline JSPropertyNameEnumerator* genericPropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length, JSPropertyNameEnumerator* structureEnumerator)
-{
- VM& vm = exec->vm();
- Structure* structure = base->structure(vm);
- if (JSPropertyNameEnumerator* enumerator = structure->cachedGenericPropertyNameEnumerator()) {
- if (!length && enumerator->cachedPrototypeChain() == structure->prototypeChain(exec))
- return enumerator;
- }
+ numberStructureProperties = propertyNames.size();
- PropertyNameArray propertyNames(exec);
- propertyNames.setPreviouslyEnumeratedLength(length);
- propertyNames.setPreviouslyEnumeratedProperties(structureEnumerator);
-
- // If we still have the same Structure that we started with, our Structure allows us to access its properties
- // quickly (i.e. the Structure property loop was able to do things), and we iterated the full length of the
- // object (i.e. there are no more own indexed properties that need to be enumerated), then the generic property
- // iteration can skip any properties it would get from the JSObject base class. This turns out to be important
- // for hot loops because most of our time is then dominated by trying to add the own Structure properties to
- // the new generic PropertyNameArray and failing because we've already visited them.
- Structure* cachedStructure = structureEnumerator->cachedStructure(vm);
- if (structure == cachedStructure && structure->canAccessPropertiesQuickly() && static_cast<uint32_t>(length) == base->getArrayLength())
base->methodTable(vm)->getGenericPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
- else
+ } else
base->methodTable(vm)->getPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
-
+
+ ASSERT(propertyNames.size() < UINT32_MAX);
+
normalizePrototypeChain(exec, structure);
- JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, base->structure(vm), propertyNames);
+ enumerator = JSPropertyNameEnumerator::create(vm, structure, indexedLength, numberStructureProperties, propertyNames);
enumerator->setCachedPrototypeChain(vm, structure->prototypeChain(exec));
- if (!length && structure->canCacheGenericPropertyNameEnumerator())
- structure->setCachedGenericPropertyNameEnumerator(vm, enumerator);
+ if (!indexedLength && structure->canCachePropertyNameEnumerator())
+ structure->setCachedPropertyNameEnumerator(vm, enumerator);
return enumerator;
}
Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/Structure.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -1216,48 +1216,26 @@
return false;
}
-void Structure::setCachedStructurePropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
+void Structure::setCachedPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
{
ASSERT(!isDictionary());
if (!hasRareData())
allocateRareData(vm);
- rareData()->setCachedStructurePropertyNameEnumerator(vm, enumerator);
+ rareData()->setCachedPropertyNameEnumerator(vm, enumerator);
}
-JSPropertyNameEnumerator* Structure::cachedStructurePropertyNameEnumerator() const
+JSPropertyNameEnumerator* Structure::cachedPropertyNameEnumerator() const
{
if (!hasRareData())
return nullptr;
- return rareData()->cachedStructurePropertyNameEnumerator();
+ return rareData()->cachedPropertyNameEnumerator();
}
-void Structure::setCachedGenericPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
+bool Structure::canCachePropertyNameEnumerator() const
{
- ASSERT(!isDictionary());
- if (!hasRareData())
- allocateRareData(vm);
- rareData()->setCachedGenericPropertyNameEnumerator(vm, enumerator);
-}
-
-JSPropertyNameEnumerator* Structure::cachedGenericPropertyNameEnumerator() const
-{
- if (!hasRareData())
- return nullptr;
- return rareData()->cachedGenericPropertyNameEnumerator();
-}
-
-bool Structure::canCacheStructurePropertyNameEnumerator() const
-{
if (isDictionary())
return false;
- return true;
-}
-bool Structure::canCacheGenericPropertyNameEnumerator() const
-{
- if (!canCacheStructurePropertyNameEnumerator())
- return false;
-
if (hasIndexedProperties(indexingType()))
return false;
@@ -1274,10 +1252,10 @@
return false;
structure++;
}
-
+
return true;
}
-
+
bool Structure::canAccessPropertiesQuickly() const
{
if (hasNonEnumerableProperties())
Modified: trunk/Source/_javascript_Core/runtime/Structure.h (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/Structure.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/Structure.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -315,12 +315,9 @@
return !JSC::isValidOffset(m_offset);
}
- void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
- void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
- JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
- JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
- bool canCacheStructurePropertyNameEnumerator() const;
- bool canCacheGenericPropertyNameEnumerator() const;
+ void setCachedPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
+ JSPropertyNameEnumerator* cachedPropertyNameEnumerator() const;
+ bool canCachePropertyNameEnumerator() const;
bool canAccessPropertiesQuickly() const;
void getPropertyNamesFromStructure(VM&, PropertyNameArray&, EnumerationMode);
Modified: trunk/Source/_javascript_Core/runtime/StructureRareData.cpp (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/StructureRareData.cpp 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/StructureRareData.cpp 2015-03-24 10:05:21 UTC (rev 181891)
@@ -66,28 +66,18 @@
JSCell::visitChildren(thisObject, visitor);
visitor.append(&thisObject->m_previous);
visitor.append(&thisObject->m_objectToStringValue);
- visitor.append(&thisObject->m_cachedStructurePropertyNameEnumerator);
+ visitor.append(&thisObject->m_cachedPropertyNameEnumerator);
visitor.append(&thisObject->m_cachedGenericPropertyNameEnumerator);
}
-JSPropertyNameEnumerator* StructureRareData::cachedStructurePropertyNameEnumerator() const
+JSPropertyNameEnumerator* StructureRareData::cachedPropertyNameEnumerator() const
{
- return m_cachedStructurePropertyNameEnumerator.get();
+ return m_cachedPropertyNameEnumerator.get();
}
-void StructureRareData::setCachedStructurePropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
+void StructureRareData::setCachedPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
{
- m_cachedStructurePropertyNameEnumerator.set(vm, this, enumerator);
+ m_cachedPropertyNameEnumerator.set(vm, this, enumerator);
}
-JSPropertyNameEnumerator* StructureRareData::cachedGenericPropertyNameEnumerator() const
-{
- return m_cachedGenericPropertyNameEnumerator.get();
-}
-
-void StructureRareData::setCachedGenericPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
-{
- m_cachedGenericPropertyNameEnumerator.set(vm, this, enumerator);
-}
-
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/StructureRareData.h (181890 => 181891)
--- trunk/Source/_javascript_Core/runtime/StructureRareData.h 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/runtime/StructureRareData.h 2015-03-24 10:05:21 UTC (rev 181891)
@@ -55,10 +55,8 @@
JSString* objectToStringValue() const;
void setObjectToStringValue(VM&, JSString* value);
- JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
- JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
- void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
- void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
+ JSPropertyNameEnumerator* cachedPropertyNameEnumerator() const;
+ void setCachedPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
DECLARE_EXPORT_INFO;
@@ -71,7 +69,7 @@
WriteBarrier<Structure> m_previous;
WriteBarrier<JSString> m_objectToStringValue;
- WriteBarrier<JSPropertyNameEnumerator> m_cachedStructurePropertyNameEnumerator;
+ WriteBarrier<JSPropertyNameEnumerator> m_cachedPropertyNameEnumerator;
WriteBarrier<JSPropertyNameEnumerator> m_cachedGenericPropertyNameEnumerator;
typedef HashMap<PropertyOffset, RefPtr<WatchpointSet>, WTF::IntHash<PropertyOffset>, WTF::UnsignedWithZeroKeyHashTraits<PropertyOffset>> PropertyWatchpointMap;
Modified: trunk/Source/_javascript_Core/tests/stress/for-in-delete-during-iteration.js (181890 => 181891)
--- trunk/Source/_javascript_Core/tests/stress/for-in-delete-during-iteration.js 2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/_javascript_Core/tests/stress/for-in-delete-during-iteration.js 2015-03-24 10:05:21 UTC (rev 181891)
@@ -36,8 +36,7 @@
};
noInline(foo);
for (var i = 0; i < 10000; ++i) {
- // Note: it's undefined whether we visit o.a or not. Currently we do.
- if (foo() !== "xza")
+ if (foo() !== "xz")
throw new Error("bad result");
}
})();