ARM: Port r5445

r5445: Implement for-in cache validity checking in the full codegen on IA-32.
Review URL: http://codereview.chromium.org/6581031

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6930 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@chromium.org 2011-02-24 11:39:27 +00:00
parent c8f8c69fd6
commit bd2fb51375
2 changed files with 61 additions and 7 deletions

View File

@ -880,6 +880,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
ForIn loop_statement(this, stmt);
increment_loop_depth();
// Load null value as it is used several times below.
Register null_value = r5;
__ 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.
@ -887,8 +891,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r0, ip);
__ b(eq, &exit);
__ LoadRoot(ip, Heap::kNullValueRootIndex);
__ cmp(r0, ip);
__ cmp(r0, null_value);
__ b(eq, &exit);
// Convert the object to a JS object.
@ -902,12 +905,62 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&done_convert);
__ push(r0);
// 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;
// Preload a couple of values used in the loop.
Register empty_fixed_array_value = r6;
__ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
Register empty_descriptor_array_value = r7;
__ LoadRoot(empty_descriptor_array_value,
Heap::kEmptyDescriptorArrayRootIndex);
__ mov(r1, r0);
__ bind(&next);
// Check that there are no elements. Register r1 contains the
// current JS object we've reached through the prototype chain.
__ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
__ cmp(r2, empty_fixed_array_value);
__ b(ne, &call_runtime);
// Check that instance descriptors are not empty so that we can
// check for an enum cache. Leave the map in r2 for the subsequent
// prototype load.
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldr(r3, FieldMemOperand(r2, Map::kInstanceDescriptorsOffset));
__ cmp(r3, empty_descriptor_array_value);
__ b(eq, &call_runtime);
// Check that there is an enum cache in the non-empty instance
// descriptors (r3). This is the case if the next enumeration
// index field does not contain a smi.
__ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumerationIndexOffset));
__ JumpIfSmi(r3, &call_runtime);
// For all objects but the receiver, check that the cache is empty.
Label check_prototype;
__ cmp(r1, r0);
__ b(eq, &check_prototype);
__ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumCacheBridgeCacheOffset));
__ cmp(r3, empty_fixed_array_value);
__ b(ne, &call_runtime);
// Load the prototype from the map and loop if non-null.
__ bind(&check_prototype);
__ ldr(r1, FieldMemOperand(r2, Map::kPrototypeOffset));
__ cmp(r1, null_value);
__ b(ne, &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;
__ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
__ b(&use_cache);
// Get the set of properties to enumerate.
__ bind(&call_runtime);
__ push(r0); // Duplicate the enumerable object on the stack.
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
@ -922,6 +975,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ b(ne, &fixed_array);
// We got a map in register r0. Get the enumeration cache from it.
__ bind(&use_cache);
__ ldr(r1, FieldMemOperand(r0, Map::kInstanceDescriptorsOffset));
__ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
__ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));

View File

@ -895,7 +895,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ cmp(edx, Factory::empty_descriptor_array());
__ j(equal, &call_runtime);
// Check that there in an enum cache in the non-empty instance
// Check that there is 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));