OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 #include "src/ic/handler-configuration.h" | 8 #include "src/ic/handler-configuration.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 5068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5079 // Get the map entry from the cache. | 5079 // Get the map entry from the cache. |
5080 DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() - | 5080 DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() - |
5081 stub_cache->key_reference(table).address()); | 5081 stub_cache->key_reference(table).address()); |
5082 Node* entry_map = | 5082 Node* entry_map = |
5083 Load(MachineType::Pointer(), key_base, | 5083 Load(MachineType::Pointer(), key_base, |
5084 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2))); | 5084 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2))); |
5085 GotoIf(WordNotEqual(map, entry_map), if_miss); | 5085 GotoIf(WordNotEqual(map, entry_map), if_miss); |
5086 | 5086 |
5087 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - | 5087 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - |
5088 stub_cache->key_reference(table).address()); | 5088 stub_cache->key_reference(table).address()); |
5089 Node* handler = Load(MachineType::Pointer(), key_base, | 5089 Node* handler = Load(MachineType::TaggedPointer(), key_base, |
5090 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); | 5090 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); |
5091 | 5091 |
5092 // We found the handler. | 5092 // We found the handler. |
5093 var_handler->Bind(handler); | 5093 var_handler->Bind(handler); |
5094 Goto(if_handler); | 5094 Goto(if_handler); |
5095 } | 5095 } |
5096 | 5096 |
5097 void CodeStubAssembler::TryProbeStubCache( | 5097 void CodeStubAssembler::TryProbeStubCache( |
5098 StubCache* stub_cache, compiler::Node* receiver, compiler::Node* name, | 5098 StubCache* stub_cache, compiler::Node* receiver, compiler::Node* name, |
5099 Label* if_handler, Variable* var_handler, Label* if_miss) { | 5099 Label* if_handler, Variable* var_handler, Label* if_miss) { |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5523 Arg(Descriptor::kVector, p->vector)); | 5523 Arg(Descriptor::kVector, p->vector)); |
5524 } | 5524 } |
5525 } | 5525 } |
5526 | 5526 |
5527 void CodeStubAssembler::HandleLoadICProtoHandler( | 5527 void CodeStubAssembler::HandleLoadICProtoHandler( |
5528 const LoadICParameters* p, Node* handler, Variable* var_holder, | 5528 const LoadICParameters* p, Node* handler, Variable* var_holder, |
5529 Variable* var_smi_handler, Label* if_smi_handler, Label* miss) { | 5529 Variable* var_smi_handler, Label* if_smi_handler, Label* miss) { |
5530 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); | 5530 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); |
5531 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); | 5531 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); |
5532 | 5532 |
5533 Node* validity_cell = LoadObjectField(handler, Tuple3::kValue1Offset); | 5533 // IC dispatchers rely on these assumptions to be held. |
| 5534 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); |
| 5535 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), |
| 5536 LoadHandler::kSmiHandlerOffset); |
| 5537 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), |
| 5538 LoadHandler::kValidityCellOffset); |
| 5539 |
| 5540 // Both FixedArray and Tuple3 handlers have validity cell at the same offset. |
| 5541 Node* validity_cell = |
| 5542 LoadObjectField(handler, LoadHandler::kValidityCellOffset); |
5534 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | 5543 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); |
5535 GotoIf(WordNotEqual(cell_value, | 5544 GotoIf(WordNotEqual(cell_value, |
5536 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), | 5545 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), |
5537 miss); | 5546 miss); |
5538 | 5547 |
5539 Node* holder = | 5548 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); |
5540 LoadWeakCellValue(LoadObjectField(handler, Tuple3::kValue2Offset)); | 5549 CSA_ASSERT(TaggedIsSmi(smi_handler)); |
5541 // The |holder| is guaranteed to be alive at this point since we passed | |
5542 // both the receiver map check and the validity cell check. | |
5543 CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); | |
5544 | 5550 |
5545 Node* smi_handler = LoadObjectField(handler, Tuple3::kValue3Offset); | 5551 Label check_prototypes(this); |
5546 CSA_ASSERT(TaggedIsSmi(smi_handler)); | |
5547 var_holder->Bind(holder); | |
5548 var_smi_handler->Bind(smi_handler); | |
5549 | |
5550 GotoUnless(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>( | 5552 GotoUnless(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>( |
5551 SmiUntag(smi_handler)), | 5553 SmiUntag(smi_handler)), |
5552 if_smi_handler); | 5554 &check_prototypes); |
| 5555 { |
| 5556 // We have a dictionary receiver, do a negative lookup check. |
| 5557 NameDictionaryNegativeLookup(p->receiver, p->name, miss); |
| 5558 Goto(&check_prototypes); |
| 5559 } |
5553 | 5560 |
5554 NameDictionaryNegativeLookup(p->receiver, p->name, miss); | 5561 Bind(&check_prototypes); |
5555 Goto(if_smi_handler); | 5562 Node* maybe_holder_cell = |
| 5563 LoadObjectField(handler, LoadHandler::kHolderCellOffset); |
| 5564 Label array_handler(this), tuple_handler(this); |
| 5565 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); |
| 5566 |
| 5567 Bind(&tuple_handler); |
| 5568 { |
| 5569 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| 5570 // The |holder| is guaranteed to be alive at this point since we passed |
| 5571 // both the receiver map check and the validity cell check. |
| 5572 CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); |
| 5573 |
| 5574 var_holder->Bind(holder); |
| 5575 var_smi_handler->Bind(smi_handler); |
| 5576 Goto(if_smi_handler); |
| 5577 } |
| 5578 |
| 5579 Bind(&array_handler); |
| 5580 { |
| 5581 Node* length = SmiUntag(maybe_holder_cell); |
| 5582 BuildFastLoop(MachineType::PointerRepresentation(), |
| 5583 IntPtrConstant(LoadHandler::kFirstPrototypeIndex), length, |
| 5584 [this, p, handler, miss](CodeStubAssembler*, Node* current) { |
| 5585 Node* prototype_cell = LoadFixedArrayElement( |
| 5586 handler, current, 0, INTPTR_PARAMETERS); |
| 5587 CheckPrototype(prototype_cell, p->name, miss); |
| 5588 }, |
| 5589 1, IndexAdvanceMode::kPost); |
| 5590 |
| 5591 Node* holder_cell = LoadFixedArrayElement( |
| 5592 handler, IntPtrConstant(LoadHandler::kHolderCellIndex), 0, |
| 5593 INTPTR_PARAMETERS); |
| 5594 Node* holder = LoadWeakCellValue(holder_cell); |
| 5595 // The |holder| is guaranteed to be alive at this point since we passed |
| 5596 // the receiver map check, the validity cell check and the prototype chain |
| 5597 // check. |
| 5598 CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); |
| 5599 |
| 5600 var_holder->Bind(holder); |
| 5601 var_smi_handler->Bind(smi_handler); |
| 5602 Goto(if_smi_handler); |
| 5603 } |
| 5604 } |
| 5605 |
| 5606 void CodeStubAssembler::CheckPrototype(Node* prototype_cell, Node* name, |
| 5607 Label* miss) { |
| 5608 Node* maybe_prototype = LoadWeakCellValue(prototype_cell, miss); |
| 5609 |
| 5610 Label done(this); |
| 5611 Label if_property_cell(this), if_dictionary_object(this); |
| 5612 |
| 5613 // |maybe_prototype| is either a PropertyCell or a slow-mode prototype. |
| 5614 Branch(WordEqual(LoadMap(maybe_prototype), |
| 5615 LoadRoot(Heap::kGlobalPropertyCellMapRootIndex)), |
| 5616 &if_property_cell, &if_dictionary_object); |
| 5617 |
| 5618 Bind(&if_dictionary_object); |
| 5619 { |
| 5620 NameDictionaryNegativeLookup(maybe_prototype, name, miss); |
| 5621 Goto(&done); |
| 5622 } |
| 5623 |
| 5624 Bind(&if_property_cell); |
| 5625 { |
| 5626 // Ensure the property cell still contains the hole. |
| 5627 Node* value = LoadObjectField(maybe_prototype, PropertyCell::kValueOffset); |
| 5628 GotoIf(WordNotEqual(value, LoadRoot(Heap::kTheHoleValueRootIndex)), miss); |
| 5629 Goto(&done); |
| 5630 } |
| 5631 |
| 5632 Bind(&done); |
5556 } | 5633 } |
5557 | 5634 |
5558 void CodeStubAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, | 5635 void CodeStubAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, |
5559 Label* miss) { | 5636 Label* miss) { |
5560 CSA_ASSERT(IsDictionaryMap(LoadMap(object))); | 5637 CSA_ASSERT(IsDictionaryMap(LoadMap(object))); |
5561 Node* properties = LoadProperties(object); | 5638 Node* properties = LoadProperties(object); |
5562 // Ensure the property does not exist in a dictionary-mode object. | 5639 // Ensure the property does not exist in a dictionary-mode object. |
5563 Variable var_name_index(this, MachineType::PointerRepresentation()); | 5640 Variable var_name_index(this, MachineType::PointerRepresentation()); |
5564 Label done(this); | 5641 Label done(this); |
5565 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, | 5642 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, |
(...skipping 3008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8574 Node* buffer_bit_field = LoadObjectField( | 8651 Node* buffer_bit_field = LoadObjectField( |
8575 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8652 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8576 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8653 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8577 | 8654 |
8578 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8655 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8579 Int32Constant(0)); | 8656 Int32Constant(0)); |
8580 } | 8657 } |
8581 | 8658 |
8582 } // namespace internal | 8659 } // namespace internal |
8583 } // namespace v8 | 8660 } // namespace v8 |
OLD | NEW |