Commit ef0f8985 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

X64: Port r5445

r5445: Implement for-in cache validity checking in the full codegen on IA-32.

BUG=v8:867
TEST=none
Review URL: http://codereview.chromium.org/6576028

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6933 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 20f0b65d
......@@ -854,13 +854,17 @@ 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 = 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.
......@@ -874,12 +878,61 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ 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);
......@@ -892,6 +945,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ 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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment