Chromium Code Reviews| Index: src/interpreter/interpreter-assembler.cc |
| diff --git a/src/interpreter/interpreter-assembler.cc b/src/interpreter/interpreter-assembler.cc |
| index 8f5d941e5a2e6632fd93c8a0965fc5999375e629..00cfd165001281e71f640969f7a7e0df963fbf71 100644 |
| --- a/src/interpreter/interpreter-assembler.cc |
| +++ b/src/interpreter/interpreter-assembler.cc |
| @@ -630,6 +630,76 @@ Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context, |
| first_arg, function_entry, result_size); |
| } |
| +Node* InterpreterAssembler::EnumLength(Node* map) { |
| + Node* bitfield_3 = LoadMapBitField3(map); |
| + Node* enum_length = BitFieldDecode<Map::EnumLengthBits>(bitfield_3); |
| + return SmiTag(enum_length); |
| +} |
| + |
| +void InterpreterAssembler::CheckEnumCache(Node* receiver, Label* use_cache, |
|
rmcilroy
2016/07/19 11:08:54
Could we move these both to CodeStubAssembler - th
oth
2016/07/19 12:59:25
Done.
|
| + Label* use_runtime) { |
| + Variable current_js_object(this, MachineRepresentation::kTagged); |
| + current_js_object.Bind(receiver); |
| + |
| + Variable current_map(this, MachineRepresentation::kTagged); |
| + current_map.Bind(LoadMap(current_js_object.value())); |
| + |
| + // These variables are updated in the loop below. |
| + Variable* loop_vars[2] = {¤t_js_object, ¤t_map}; |
| + Label start(this, 2, loop_vars); |
|
rmcilroy
2016/07/19 11:08:54
nit - start->loop
oth
2016/07/19 12:59:25
Done.
|
| + |
| + // Check if the enum length field is properly initialized, indicating that |
| + // there is an enum cache. |
| + { |
| + Node* invalid_enum_cache_sentinel = |
| + SmiConstant(Smi::FromInt(kInvalidEnumCacheSentinel)); |
| + Node* enum_length = EnumLength(current_map.value()); |
| + |
| + Node* condition = WordEqual(enum_length, invalid_enum_cache_sentinel); |
| + BranchIf(condition, use_runtime, &start); |
| + } |
| + |
| + Label next(this); |
|
rmcilroy
2016/07/19 11:08:54
nit - move definition next to start
oth
2016/07/19 12:59:25
Done.
|
| + |
| + // Check that there are no elements. prototype contains the current JS |
|
rmcilroy
2016/07/19 11:08:54
/s/prototype/|current_js_object| ?
oth
2016/07/19 12:59:25
Done.
|
| + // object we've reached through the prototype chain. |
| + Bind(&start); |
| + { |
| + Label if_elements(this), if_no_elements(this); |
| + Node* elements = LoadElements(current_js_object.value()); |
| + Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex); |
| + // Check that there are no elements. |
| + BranchIf(WordEqual(elements, empty_fixed_array), &if_no_elements, |
|
rmcilroy
2016/07/19 11:08:54
You can do BranchIfWordEqual if you like.
oth
2016/07/19 12:59:25
Done.
|
| + &if_elements); |
| + Bind(&if_elements); |
| + { |
| + // Second chance, the object may be using the empty slow element |
| + // dictionary. |
| + Node* slow_empty_dictionary = |
| + LoadRoot(Heap::kEmptySlowElementDictionaryRootIndex); |
| + BranchIf(WordNotEqual(elements, slow_empty_dictionary), use_runtime, |
| + &if_no_elements); |
| + } |
| + |
| + Bind(&if_no_elements); |
| + { |
| + // Update map prototype. |
| + current_js_object.Bind(LoadMapPrototype(current_map.value())); |
| + BranchIf(WordEqual(current_js_object.value(), NullConstant()), use_cache, |
| + &next); |
| + } |
| + } |
| + |
| + Bind(&next); |
| + { |
| + // For all objects but the receiver, check that the cache is empty. |
| + current_map.Bind(LoadMap(current_js_object.value())); |
| + Node* enum_length = EnumLength(current_map.value()); |
| + Node* zero_constant = SmiConstant(Smi::FromInt(0)); |
| + BranchIf(WordEqual(enum_length, zero_constant), &start, use_runtime); |
| + } |
| +} |
| + |
| void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { |
| Label ok(this), interrupt_check(this, Label::kDeferred), end(this); |
| Node* budget_offset = |