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 5362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5373 const LoadICParameters* p, Node* handler, Label* miss, | 5373 const LoadICParameters* p, Node* handler, Label* miss, |
5374 ElementSupport support_elements) { | 5374 ElementSupport support_elements) { |
5375 Comment("have_handler"); | 5375 Comment("have_handler"); |
5376 Variable var_holder(this, MachineRepresentation::kTagged); | 5376 Variable var_holder(this, MachineRepresentation::kTagged); |
5377 var_holder.Bind(p->receiver); | 5377 var_holder.Bind(p->receiver); |
5378 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 5378 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
5379 var_smi_handler.Bind(handler); | 5379 var_smi_handler.Bind(handler); |
5380 | 5380 |
5381 Variable* vars[] = {&var_holder, &var_smi_handler}; | 5381 Variable* vars[] = {&var_holder, &var_smi_handler}; |
5382 Label if_smi_handler(this, 2, vars); | 5382 Label if_smi_handler(this, 2, vars); |
5383 Label try_proto_cell_handler(this), call_handler(this); | 5383 Label try_proto_handler(this), call_handler(this); |
5384 | 5384 |
5385 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_cell_handler); | 5385 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); |
5386 | 5386 |
5387 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 5387 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
5388 // for the encoding format. | 5388 // for the encoding format. |
5389 Bind(&if_smi_handler); | 5389 Bind(&if_smi_handler); |
5390 { | 5390 { |
5391 Variable var_double_value(this, MachineRepresentation::kFloat64); | 5391 Variable var_double_value(this, MachineRepresentation::kFloat64); |
5392 Label rebox_double(this, &var_double_value); | 5392 Label rebox_double(this, &var_double_value); |
5393 | 5393 |
5394 Node* holder = var_holder.value(); | 5394 Node* holder = var_holder.value(); |
5395 Node* handler_word = SmiUntag(var_smi_handler.value()); | 5395 Node* handler_word = SmiUntag(var_smi_handler.value()); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5495 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); | 5495 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); |
5496 #if defined(DEBUG) | 5496 #if defined(DEBUG) |
5497 CSA_ASSERT(UintPtrLessThan( | 5497 CSA_ASSERT(UintPtrLessThan( |
5498 descriptor, LoadAndUntagFixedArrayBaseLength(descriptors))); | 5498 descriptor, LoadAndUntagFixedArrayBaseLength(descriptors))); |
5499 #endif | 5499 #endif |
5500 Return( | 5500 Return( |
5501 LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS)); | 5501 LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS)); |
5502 } | 5502 } |
5503 } | 5503 } |
5504 | 5504 |
5505 Bind(&try_proto_cell_handler); | 5505 Bind(&try_proto_handler); |
5506 { | 5506 { |
5507 GotoIf(WordNotEqual(LoadMap(handler), LoadRoot(Heap::kTuple3MapRootIndex)), | 5507 GotoIf(WordEqual(LoadMap(handler), LoadRoot(Heap::kCodeMapRootIndex)), |
5508 &call_handler); | 5508 &call_handler); |
5509 Node* validity_cell = LoadObjectField(handler, Tuple3::kValue1Offset); | 5509 HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler, |
5510 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | 5510 &if_smi_handler, miss); |
5511 GotoIf(WordNotEqual(cell_value, | |
5512 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), | |
5513 miss); | |
5514 | |
5515 Node* holder = | |
5516 LoadWeakCellValue(LoadObjectField(handler, Tuple3::kValue2Offset)); | |
5517 // The |holder| is guaranteed to be alive at this point since we passed | |
5518 // both the receiver map check and the validity cell check. | |
5519 CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); | |
5520 | |
5521 Node* smi_handler = LoadObjectField(handler, Tuple3::kValue3Offset); | |
5522 CSA_ASSERT(TaggedIsSmi(smi_handler)); | |
5523 | |
5524 var_holder.Bind(holder); | |
5525 var_smi_handler.Bind(smi_handler); | |
5526 Goto(&if_smi_handler); | |
5527 } | 5511 } |
5528 | 5512 |
5529 // |handler| is a heap object. Must be code, call it. | |
5530 Bind(&call_handler); | 5513 Bind(&call_handler); |
5531 { | 5514 { |
5532 typedef LoadWithVectorDescriptor Descriptor; | 5515 typedef LoadWithVectorDescriptor Descriptor; |
5533 TailCallStub(Descriptor(isolate()), handler, p->context, | 5516 TailCallStub(Descriptor(isolate()), handler, p->context, |
5534 Arg(Descriptor::kReceiver, p->receiver), | 5517 Arg(Descriptor::kReceiver, p->receiver), |
5535 Arg(Descriptor::kName, p->name), | 5518 Arg(Descriptor::kName, p->name), |
5536 Arg(Descriptor::kSlot, p->slot), | 5519 Arg(Descriptor::kSlot, p->slot), |
5537 Arg(Descriptor::kVector, p->vector)); | 5520 Arg(Descriptor::kVector, p->vector)); |
5538 } | 5521 } |
5539 } | 5522 } |
5540 | 5523 |
| 5524 void CodeStubAssembler::HandleLoadICProtoHandler( |
| 5525 const LoadICParameters* p, Node* handler, Variable* var_holder, |
| 5526 Variable* var_smi_handler, Label* if_smi_handler, Label* miss) { |
| 5527 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); |
| 5528 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); |
| 5529 |
| 5530 Node* validity_cell = LoadObjectField(handler, Tuple3::kValue1Offset); |
| 5531 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); |
| 5532 GotoIf(WordNotEqual(cell_value, |
| 5533 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), |
| 5534 miss); |
| 5535 |
| 5536 Node* holder = |
| 5537 LoadWeakCellValue(LoadObjectField(handler, Tuple3::kValue2Offset)); |
| 5538 // The |holder| is guaranteed to be alive at this point since we passed |
| 5539 // both the receiver map check and the validity cell check. |
| 5540 CSA_ASSERT(WordNotEqual(holder, IntPtrConstant(0))); |
| 5541 |
| 5542 Node* smi_handler = LoadObjectField(handler, Tuple3::kValue3Offset); |
| 5543 CSA_ASSERT(TaggedIsSmi(smi_handler)); |
| 5544 var_holder->Bind(holder); |
| 5545 var_smi_handler->Bind(smi_handler); |
| 5546 |
| 5547 GotoUnless(IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>( |
| 5548 SmiUntag(smi_handler)), |
| 5549 if_smi_handler); |
| 5550 |
| 5551 NameDictionaryNegativeLookup(p->receiver, p->name, miss); |
| 5552 Goto(if_smi_handler); |
| 5553 } |
| 5554 |
| 5555 void CodeStubAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, |
| 5556 Label* miss) { |
| 5557 CSA_ASSERT(IsDictionaryMap(LoadMap(object))); |
| 5558 Node* properties = LoadProperties(object); |
| 5559 // Ensure the property does not exist in a dictionary-mode object. |
| 5560 Variable var_name_index(this, MachineType::PointerRepresentation()); |
| 5561 Label done(this); |
| 5562 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, |
| 5563 &done); |
| 5564 Bind(&done); |
| 5565 } |
| 5566 |
5541 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { | 5567 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |
5542 Variable var_handler(this, MachineRepresentation::kTagged); | 5568 Variable var_handler(this, MachineRepresentation::kTagged); |
5543 // TODO(ishell): defer blocks when it works. | 5569 // TODO(ishell): defer blocks when it works. |
5544 Label if_handler(this, &var_handler), try_polymorphic(this), | 5570 Label if_handler(this, &var_handler), try_polymorphic(this), |
5545 try_megamorphic(this /*, Label::kDeferred*/), | 5571 try_megamorphic(this /*, Label::kDeferred*/), |
5546 miss(this /*, Label::kDeferred*/); | 5572 miss(this /*, Label::kDeferred*/); |
5547 | 5573 |
5548 Node* receiver_map = LoadReceiverMap(p->receiver); | 5574 Node* receiver_map = LoadReceiverMap(p->receiver); |
5549 | 5575 |
5550 // Check monomorphic case. | 5576 // Check monomorphic case. |
(...skipping 2994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8545 Node* buffer_bit_field = LoadObjectField( | 8571 Node* buffer_bit_field = LoadObjectField( |
8546 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8572 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8547 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8573 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8548 | 8574 |
8549 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8575 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8550 Int32Constant(0)); | 8576 Int32Constant(0)); |
8551 } | 8577 } |
8552 | 8578 |
8553 } // namespace internal | 8579 } // namespace internal |
8554 } // namespace v8 | 8580 } // namespace v8 |
OLD | NEW |