Index: src/arm/full-codegen-arm.cc |
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc |
index 353ce5b10646e2bd79319612be07a85bbc632b6c..7caf8d80c579190a59606447c5e59ee4db64d187 100644 |
--- a/src/arm/full-codegen-arm.cc |
+++ b/src/arm/full-codegen-arm.cc |
@@ -929,11 +929,17 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
__ bind(&done_convert); |
__ push(r0); |
+ // Check for proxies. |
+ Label call_runtime; |
+ STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
+ __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); |
+ __ b(le, &call_runtime); |
+ |
// Check cache validity in generated code. This is a fast case for |
// the JSObject::IsSimpleEnum cache validity checks. If we cannot |
// guarantee cache validity, call the runtime system to check cache |
// validity or get the property names in a fixed array. |
- Label next, call_runtime; |
+ Label next; |
// Preload a couple of values used in the loop. |
Register empty_fixed_array_value = r6; |
__ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); |
@@ -1012,9 +1018,16 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
__ jmp(&loop); |
// We got a fixed array in register r0. Iterate through that. |
+ Label non_proxy; |
__ bind(&fixed_array); |
- __ mov(r1, Operand(Smi::FromInt(0))); // Map (0) - force slow check. |
- __ Push(r1, r0); |
+ __ mov(r1, Operand(Smi::FromInt(1))); // smi indicates slow check |
Rico
2011/10/20 14:25:31
Capitalize start of comment + below
rossberg
2011/10/24 13:31:35
Done.
|
+ __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object |
+ STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
+ __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); |
+ __ b(gt, &non_proxy); |
+ __ mov(r1, Operand(Smi::FromInt(0))); // zero indicates proxy |
+ __ bind(&non_proxy); |
+ __ Push(r1, r0); // map or smi, and array |
Rico
2011/10/20 14:25:31
how can r1 be a map, we either load smi 1 or smi 0
rossberg
2011/10/24 13:31:35
Done.
|
__ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); |
__ mov(r0, Operand(Smi::FromInt(0))); |
__ Push(r1, r0); // Fixed array length (as smi) and initial index. |
@@ -1031,18 +1044,23 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
__ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
__ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
- // Get the expected map from the stack or a zero map in the |
+ // Get the expected map from the stack or a smi in the |
// permanent slow case into register r2. |
__ ldr(r2, MemOperand(sp, 3 * kPointerSize)); |
// Check if the expected map still matches that of the enumerable. |
- // If not, we have to filter the key. |
+ // If not, we may have to filter the key. |
Label update_each; |
__ ldr(r1, MemOperand(sp, 4 * kPointerSize)); |
__ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); |
__ cmp(r4, Operand(r2)); |
__ b(eq, &update_each); |
+ // For proxies, no filtering is done. |
+ // TODO(rossberg): What if only a prototype is a proxy? Not specified. |
Rico
2011/10/20 14:25:31
Please file a bug
rossberg
2011/10/24 13:31:35
Will note it in bug v8:1543.
|
+ __ cmp(r2, Operand(Smi::FromInt(0))); |
+ __ b(eq, &update_each); |
+ |
// Convert the entry to a string or (smi) 0 if it isn't a property |
// any more. If the property has been removed while iterating, we |
// just skip it. |