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 5512 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 if_negative_lookup_on_receiver(this), if_check_prototypes(this); |
5546 CSA_ASSERT(TaggedIsSmi(smi_handler)); | 5552 Branch(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>( |
5547 var_holder->Bind(holder); | 5553 SmiUntag(smi_handler)), |
5548 var_smi_handler->Bind(smi_handler); | 5554 &if_negative_lookup_on_receiver, &if_check_prototypes); |
5549 | 5555 |
5550 GotoUnless(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>( | 5556 Bind(&if_check_prototypes); |
5551 SmiUntag(smi_handler)), | |
5552 if_smi_handler); | |
5553 | 5557 |
5554 NameDictionaryNegativeLookup(p->receiver, p->name, miss); | 5558 Node* maybe_holder_cell = |
5555 Goto(if_smi_handler); | 5559 LoadObjectField(handler, LoadHandler::kHolderCellOffset); |
5560 Label array_handler(this), tuple_handler(this); | |
5561 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); | |
5562 | |
5563 Bind(&if_negative_lookup_on_receiver); | |
Jakob Kummerow
2016/10/27 11:30:54
nit: I'd put this above the "Bind(&if_check_protot
Igor Sheludko
2016/10/27 14:55:30
Done.
| |
5564 { | |
5565 NameDictionaryNegativeLookup(p->receiver, p->name, miss); | |
5566 Goto(&if_check_prototypes); | |
5567 } | |
5568 | |
5569 Bind(&tuple_handler); | |
5570 { | |
5571 Node* holder = LoadWeakCellValue(maybe_holder_cell); | |
5572 // The |holder| is guaranteed to be alive at this point since we passed | |
5573 // both the receiver map check and the validity cell check. | |
5574 CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); | |
5575 | |
5576 var_holder->Bind(holder); | |
5577 var_smi_handler->Bind(smi_handler); | |
5578 Goto(if_smi_handler); | |
5579 } | |
5580 | |
5581 Bind(&array_handler); | |
5582 { | |
5583 Node* length = SmiUntag(maybe_holder_cell); | |
5584 BuildFastLoop(MachineType::PointerRepresentation(), | |
5585 IntPtrConstant(LoadHandler::kFirstPrototypeIndex), length, | |
5586 [this, p, handler, miss](CodeStubAssembler*, Node* current) { | |
5587 Node* prototype_cell = LoadFixedArrayElement( | |
5588 handler, current, 0, INTPTR_PARAMETERS); | |
5589 CheckPrototype(prototype_cell, p->name, miss); | |
5590 }, | |
5591 1, IndexAdvanceMode::kPost); | |
5592 | |
5593 Node* holder_cell = LoadFixedArrayElement( | |
5594 handler, IntPtrConstant(LoadHandler::kHolderCellIndex), 0, | |
5595 INTPTR_PARAMETERS); | |
5596 Node* holder = LoadWeakCellValue(holder_cell); | |
5597 // The |holder| is guaranteed to be alive at this point since we passed | |
5598 // the receiver map check, the validity cell check and the prototype chain | |
5599 // check. | |
5600 CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); | |
5601 | |
5602 var_holder->Bind(holder); | |
5603 var_smi_handler->Bind(smi_handler); | |
5604 Goto(if_smi_handler); | |
5605 } | |
5606 } | |
5607 | |
5608 void CodeStubAssembler::CheckPrototype(Node* prototype_cell, Node* name, | |
5609 Label* miss) { | |
5610 Node* maybe_prototype = LoadWeakCellValue(prototype_cell, miss); | |
5611 | |
5612 Label done(this); | |
5613 Label if_property_cell(this), if_dictionary_object(this); | |
5614 | |
5615 // |maybe_prototype| is either a PropertyCell or a slow-mode prototype. | |
5616 Branch(WordEqual(LoadMap(maybe_prototype), | |
5617 LoadRoot(Heap::kGlobalPropertyCellMapRootIndex)), | |
5618 &if_property_cell, &if_dictionary_object); | |
5619 | |
5620 Bind(&if_dictionary_object); | |
5621 { | |
5622 NameDictionaryNegativeLookup(maybe_prototype, name, miss); | |
5623 Goto(&done); | |
5624 } | |
5625 | |
5626 Bind(&if_property_cell); | |
5627 { | |
5628 // Ensure the property cell still contains the hole. | |
5629 Node* value = LoadObjectField(maybe_prototype, PropertyCell::kValueOffset); | |
5630 Branch(WordEqual(value, LoadRoot(Heap::kTheHoleValueRootIndex)), &done, | |
Jakob Kummerow
2016/10/27 11:30:53
Is there a reason you prefer this Branch() over "G
Igor Sheludko
2016/10/27 14:55:30
Because it has to be followed by Goto(&done) anywa
| |
5631 miss); | |
5632 } | |
5633 | |
5634 Bind(&done); | |
5556 } | 5635 } |
5557 | 5636 |
5558 void CodeStubAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, | 5637 void CodeStubAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, |
5559 Label* miss) { | 5638 Label* miss) { |
5560 CSA_ASSERT(IsDictionaryMap(LoadMap(object))); | 5639 CSA_ASSERT(IsDictionaryMap(LoadMap(object))); |
5561 Node* properties = LoadProperties(object); | 5640 Node* properties = LoadProperties(object); |
5562 // Ensure the property does not exist in a dictionary-mode object. | 5641 // Ensure the property does not exist in a dictionary-mode object. |
5563 Variable var_name_index(this, MachineType::PointerRepresentation()); | 5642 Variable var_name_index(this, MachineType::PointerRepresentation()); |
5564 Label done(this); | 5643 Label done(this); |
5565 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, | 5644 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( | 8653 Node* buffer_bit_field = LoadObjectField( |
8575 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8654 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8576 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8655 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8577 | 8656 |
8578 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8657 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8579 Int32Constant(0)); | 8658 Int32Constant(0)); |
8580 } | 8659 } |
8581 | 8660 |
8582 } // namespace internal | 8661 } // namespace internal |
8583 } // namespace v8 | 8662 } // namespace v8 |
OLD | NEW |