| Index: src/ia32/full-codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/full-codegen-ia32.cc (revision 5444)
|
| +++ src/ia32/full-codegen-ia32.cc (working copy)
|
| @@ -756,13 +756,57 @@
|
| __ bind(&done_convert);
|
| __ push(eax);
|
|
|
| - // TODO(kasperl): 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.
|
| + // 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;
|
| + __ mov(ecx, eax);
|
| + __ bind(&next);
|
|
|
| + // Check that there are no elements. Register ecx contains the
|
| + // current JS object we've reached through the prototype chain.
|
| + __ cmp(FieldOperand(ecx, JSObject::kElementsOffset),
|
| + Factory::empty_fixed_array());
|
| + __ j(not_equal, &call_runtime);
|
| +
|
| + // Check that instance descriptors are not empty so that we can
|
| + // check for an enum cache. Leave the map in ebx for the subsequent
|
| + // prototype load.
|
| + __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
|
| + __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
|
| + __ cmp(edx, Factory::empty_descriptor_array());
|
| + __ j(equal, &call_runtime);
|
| +
|
| + // Check that there in an enum cache in the non-empty instance
|
| + // descriptors (edx). This is the case if the next enumeration
|
| + // index field does not contain a smi.
|
| + __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
|
| + __ test(edx, Immediate(kSmiTagMask));
|
| + __ j(zero, &call_runtime);
|
| +
|
| + // For all objects but the receiver, check that the cache is empty.
|
| + Label check_prototype;
|
| + __ cmp(ecx, Operand(eax));
|
| + __ j(equal, &check_prototype);
|
| + __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
|
| + __ cmp(edx, Factory::empty_fixed_array());
|
| + __ j(not_equal, &call_runtime);
|
| +
|
| + // Load the prototype from the map and loop if non-null.
|
| + __ bind(&check_prototype);
|
| + __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
|
| + __ cmp(ecx, Factory::null_value());
|
| + __ j(not_equal, &next);
|
| +
|
| + // The enum cache is valid. Load the map of the object being
|
| + // iterated over and use the cache for the iteration.
|
| + Label use_cache;
|
| + __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
|
| + __ jmp(&use_cache);
|
| +
|
| // Get the set of properties to enumerate.
|
| + __ bind(&call_runtime);
|
| __ push(eax); // Duplicate the enumerable object on the stack.
|
| __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
|
|
|
| @@ -774,6 +818,7 @@
|
| __ j(not_equal, &fixed_array);
|
|
|
| // We got a map in register eax. Get the enumeration cache from it.
|
| + __ bind(&use_cache);
|
| __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset));
|
| __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
|
| __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
|
|
|