Chromium Code Reviews| Index: src/arm/codegen-arm.cc |
| =================================================================== |
| --- src/arm/codegen-arm.cc (revision 3395) |
| +++ src/arm/codegen-arm.cc (working copy) |
| @@ -1775,19 +1775,73 @@ |
| jsobject.Bind(); |
| // Get the set of properties (as a FixedArray or Map). |
| - frame_->EmitPush(r0); // duplicate the object being enumerated |
| - frame_->EmitPush(r0); |
| + // r0: value to be iterated over |
| + frame_->EmitPush(r0); // push the object being iterated over |
|
Erik Corry
2009/12/03 08:49:32
!punctuatioN
Mads Ager (chromium)
2009/12/03 10:15:31
Done.
|
| + |
| + // 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. |
| + JumpTarget call_runtime; |
| + JumpTarget loop(JumpTarget::BIDIRECTIONAL); |
| + JumpTarget check_prototype; |
| + JumpTarget use_cache; |
| + __ mov(r1, Operand(r0)); |
| + loop.Bind(); |
| + // Check that there are no elements. |
| + __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| + __ cmp(r2, Operand(Factory::empty_fixed_array())); |
|
Erik Corry
2009/12/03 08:49:32
This gets code-generated as a pc-relative load fol
Mads Ager (chromium)
2009/12/03 10:15:31
Done.
|
| + call_runtime.Branch(ne); |
| + // Check that instance descriptors are not empty so that we can |
| + // check for an enum cache. Leave the map in r3 for the subsequent |
| + // prototype load. |
| + __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| + __ ldr(r2, FieldMemOperand(r3, Map::kInstanceDescriptorsOffset)); |
| + __ cmp(r2, Operand(Factory::empty_descriptor_array())); |
|
Erik Corry
2009/12/03 08:49:32
And here.
Mads Ager (chromium)
2009/12/03 10:15:31
Done.
|
| + call_runtime.Branch(eq); |
| + // Check that there in an enum cache in the non-empty instance |
| + // descriptors. This is the case if the next enumeration index |
| + // field does not contain a smi. |
| + __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumerationIndexOffset)); |
| + __ tst(r2, Operand(kSmiTagMask)); |
| + call_runtime.Branch(eq); |
| + // For all objects but the receiver, check that the cache is empty. |
| + __ cmp(r1, r0); |
| + check_prototype.Branch(eq); |
| + __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
| + __ cmp(r2, Operand(Factory::empty_fixed_array())); |
|
Erik Corry
2009/12/03 08:49:32
And here (perhaps you can reuse the register so yo
Mads Ager (chromium)
2009/12/03 10:15:31
Done.
|
| + call_runtime.Branch(ne); |
| + check_prototype.Bind(); |
| + // Load the prototype from the map and loop if non-null. |
| + __ ldr(r1, FieldMemOperand(r3, Map::kPrototypeOffset)); |
| + __ cmp(r1, Operand(Factory::null_value())); |
|
Erik Corry
2009/12/03 08:49:32
And here.
Mads Ager (chromium)
2009/12/03 10:15:31
Done.
|
| + loop.Branch(ne); |
| + // The enum cache is valid. Load the map of the object being |
| + // iterated over and use the cache for the iteration. |
| + __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| + use_cache.Jump(); |
| + |
| + call_runtime.Bind(); |
| + // Call the runtime to get the property names for the object. |
| + frame_->EmitPush(r0); // push the object (slot 4) for the runtime call |
| frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); |
| - // If we got a Map, we can do a fast modification check. |
| - // Otherwise, we got a FixedArray, and we have to do a slow check. |
| + // If we got a map from the runtime call, we can do a fast |
| + // modification check. Otherwise, we got a fixed array, and we have |
| + // to do a slow check. |
| + // r0: map or fixed array (result from call to |
| + // Runtime::kGetPropertyNamesFast) |
| __ mov(r2, Operand(r0)); |
| __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| __ LoadRoot(ip, Heap::kMetaMapRootIndex); |
| __ cmp(r1, ip); |
| fixed_array.Branch(ne); |
| + use_cache.Bind(); |
| // Get enum cache |
| + // r0: map (either the result from a call to |
| + // Runtime::kGetPropertyNamesFast or has been fetched directly from |
| + // the object) |
| __ mov(r1, Operand(r0)); |
|
Erik Corry
2009/12/03 08:49:32
Unnecessary instruction! (not your fault)
|
| __ ldr(r1, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset)); |
| __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); |
| @@ -6385,7 +6439,7 @@ |
| __ b(eq, &adaptor); |
| // Check index against formal parameters count limit passed in |
| - // through register eax. Use unsigned comparison to get negative |
| + // through register r0. Use unsigned comparison to get negative |
| // check for free. |
| __ cmp(r1, r0); |
| __ b(cs, &slow); |