From dffb7533aa551aa0e766ac73ebd5b340b06e48ec Mon Sep 17 00:00:00 2001 From: "kasperl@chromium.org" Date: Mon, 13 Sep 2010 06:13:20 +0000 Subject: [PATCH] Implement for-in cache validity checking in the full codegen on IA-32. Review URL: http://codereview.chromium.org/3376003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5445 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 9 ++++--- src/ia32/full-codegen-ia32.cc | 55 +++++++++++++++++++++++++++++++++++++++---- src/x64/full-codegen-x64.cc | 9 ++++--- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 999bf3d..0f8f6d4 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -744,11 +744,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ bind(&done_convert); __ push(r0); - // 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. + // 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. // Get the set of properties to enumerate. __ push(r0); // Duplicate the enumerable object on the stack. diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index a308941..3d1653c 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -756,13 +756,57 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ 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 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ 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)); diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 6641a22..40e1e35 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -746,11 +746,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ bind(&done_convert); __ push(rax); - // 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. + // 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. // Get the set of properties to enumerate. __ push(rax); // Duplicate the enumerable object on the stack. -- 2.7.4