Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index d49048f26491f866c3584f23249ba300e39abe67..32a92a6c651f9402f3089f82afc39d8c1e19982f 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -2898,6 +2898,14 @@ void MacroAssembler::LoadInstanceDescriptors(Register map, |
} |
+void MacroAssembler::EnumLength(Register dst, Register map) { |
+ STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); |
+ movq(dst, FieldOperand(map, Map::kBitField3Offset)); |
+ Move(kScratchRegister, Smi::FromInt(Map::EnumLengthBits::kMask)); |
+ and_(dst, kScratchRegister); |
+} |
+ |
+ |
void MacroAssembler::DispatchMap(Register obj, |
Handle<Map> map, |
Handle<Code> success, |
@@ -4479,52 +4487,38 @@ void MacroAssembler::EnsureNotWhite( |
void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { |
- Label next; |
+ Label next, start; |
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. |
+ // Check if the enum length field is properly initialized, indicating that |
+ // there is an enum cache. |
movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset)); |
- movq(rdx, FieldOperand(rbx, Map::kTransitionsOrBackPointerOffset)); |
- CheckMap(rdx, |
- isolate()->factory()->fixed_array_map(), |
- call_runtime, |
- DONT_DO_SMI_CHECK); |
- |
- movq(rdx, FieldOperand(rdx, TransitionArray::kDescriptorsOffset)); |
- cmpq(rdx, empty_descriptor_array_value); |
+ EnumLength(rdx, rbx); |
+ Cmp(rdx, Smi::FromInt(Map::kInvalidEnumCache)); |
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::kEnumCacheOffset)); |
- JumpIfSmi(rdx, call_runtime); |
+ jmp(&start); |
+ |
+ bind(&next); |
+ |
+ movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset)); |
// 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); |
+ EnumLength(rdx, rbx); |
+ Cmp(rdx, Smi::FromInt(0)); |
+ j(not_equal, call_runtime); |
+ |
+ bind(&start); |
+ |
+ // 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); |
- // 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); |