| Index: src/x64/macro-assembler-x64.cc
|
| diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
|
| index c070fb2d3fe899be3c233c1dc61ba4e5fe67ad3c..9d668dc0ac5402e92928f5b9edefc6df5491d931 100644
|
| --- a/src/x64/macro-assembler-x64.cc
|
| +++ b/src/x64/macro-assembler-x64.cc
|
| @@ -4364,6 +4364,52 @@ void MacroAssembler::EnsureNotWhite(
|
| bind(&done);
|
| }
|
|
|
| +
|
| +void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
|
| + Label next;
|
| + 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::kInstanceDescriptorsOrBitField3Offset));
|
| + JumpIfSmi(rdx, 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.
|
| + Label check_prototype;
|
| + cmpq(rcx, rax);
|
| + j(equal, &check_prototype, Label::kNear);
|
| + 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);
|
| +}
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|
| #endif // V8_TARGET_ARCH_X64
|
|
|