| Index: src/x64/full-codegen-x64.cc | 
| =================================================================== | 
| --- src/x64/full-codegen-x64.cc	(revision 6929) | 
| +++ src/x64/full-codegen-x64.cc	(working copy) | 
| @@ -847,13 +847,17 @@ | 
| ForIn loop_statement(this, stmt); | 
| increment_loop_depth(); | 
|  | 
| +  // Load null value as it is used several times below. | 
| +  Register null_value = rdi; | 
| +  __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 
| + | 
| // Get the object to enumerate over. Both SpiderMonkey and JSC | 
| // ignore null and undefined in contrast to the specification; see | 
| // ECMA-262 section 12.6.4. | 
| VisitForAccumulatorValue(stmt->enumerable()); | 
| __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 
| __ j(equal, &exit); | 
| -  __ CompareRoot(rax, Heap::kNullValueRootIndex); | 
| +  __ cmpq(rax, null_value); | 
| __ j(equal, &exit); | 
|  | 
| // Convert the object to a JS object. | 
| @@ -867,12 +871,61 @@ | 
| __ bind(&done_convert); | 
| __ push(rax); | 
|  | 
| -  // BUG(867): 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; | 
| +  Register empty_fixed_array_value = r8; | 
| +  __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 
| +  Register empty_descriptor_array_value = r9; | 
| +  __ LoadRoot(empty_descriptor_array_value, | 
| +              Heap::kEmptyDescriptorArrayRootIndex); | 
| +  __ movq(rcx, rax); | 
| +  __ bind(&next); | 
|  | 
| +  // Check that there are no elements.  Register rcx contains the | 
| +  // current JS object we've reached through the prototype chain. | 
| +  __ cmpq(empty_fixed_array_value, | 
| +          FieldOperand(rcx, JSObject::kElementsOffset)); | 
| +  __ 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 rbx for the subsequent | 
| +  // prototype load. | 
| +  __ movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset)); | 
| +  __ movq(rdx, FieldOperand(rbx, Map::kInstanceDescriptorsOffset)); | 
| +  __ cmpq(rdx, empty_descriptor_array_value); | 
| +  __ j(equal, &call_runtime); | 
| + | 
| +  // Check that there is an enum cache in the non-empty instance | 
| +  // descriptors (rdx).  This is the case if the next enumeration | 
| +  // index field does not contain a smi. | 
| +  __ movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumerationIndexOffset)); | 
| +  __ JumpIfSmi(rdx, &call_runtime); | 
| + | 
| +  // For all objects but the receiver, check that the cache is empty. | 
| +  NearLabel check_prototype; | 
| +  __ cmpq(rcx, rax); | 
| +  __ j(equal, &check_prototype); | 
| +  __ movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 
| +  __ cmpq(rdx, empty_fixed_array_value); | 
| +  __ j(not_equal, &call_runtime); | 
| + | 
| +  // Load the prototype from the map and loop if non-null. | 
| +  __ bind(&check_prototype); | 
| +  __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); | 
| +  __ cmpq(rcx, 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. | 
| +  NearLabel use_cache; | 
| +  __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 
| +  __ jmp(&use_cache); | 
| + | 
| // Get the set of properties to enumerate. | 
| +  __ bind(&call_runtime); | 
| __ push(rax);  // Duplicate the enumerable object on the stack. | 
| __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 
|  | 
| @@ -885,6 +938,7 @@ | 
| __ j(not_equal, &fixed_array); | 
|  | 
| // We got a map in register rax. Get the enumeration cache from it. | 
| +  __ bind(&use_cache); | 
| __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset)); | 
| __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); | 
| __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 
|  |