OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 | 4 |
5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
| 9 #include "src/address-map.h" |
9 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 11 #include "src/code-factory.h" |
11 #include "src/compiler/access-builder.h" | 12 #include "src/compiler/access-builder.h" |
12 #include "src/compiler/common-operator.h" | 13 #include "src/compiler/common-operator.h" |
13 #include "src/compiler/diamond.h" | 14 #include "src/compiler/diamond.h" |
14 #include "src/compiler/linkage.h" | 15 #include "src/compiler/linkage.h" |
15 #include "src/compiler/node-matchers.h" | 16 #include "src/compiler/node-matchers.h" |
16 #include "src/compiler/node-properties.h" | 17 #include "src/compiler/node-properties.h" |
17 #include "src/compiler/operator-properties.h" | 18 #include "src/compiler/operator-properties.h" |
18 #include "src/compiler/representation-change.h" | 19 #include "src/compiler/representation-change.h" |
19 #include "src/compiler/simplified-operator.h" | 20 #include "src/compiler/simplified-operator.h" |
20 #include "src/compiler/source-position.h" | 21 #include "src/compiler/source-position.h" |
| 22 #include "src/conversions-inl.h" |
21 #include "src/objects.h" | 23 #include "src/objects.h" |
22 #include "src/type-cache.h" | 24 #include "src/type-cache.h" |
23 | 25 |
24 namespace v8 { | 26 namespace v8 { |
25 namespace internal { | 27 namespace internal { |
26 namespace compiler { | 28 namespace compiler { |
27 | 29 |
28 // Macro for outputting trace information from representation inference. | 30 // Macro for outputting trace information from representation inference. |
29 #define TRACE(...) \ | 31 #define TRACE(...) \ |
30 do { \ | 32 do { \ |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 } | 704 } |
703 | 705 |
704 const Operator* Uint32Op(Node* node) { | 706 const Operator* Uint32Op(Node* node) { |
705 return changer_->Uint32OperatorFor(node->opcode()); | 707 return changer_->Uint32OperatorFor(node->opcode()); |
706 } | 708 } |
707 | 709 |
708 const Operator* Float64Op(Node* node) { | 710 const Operator* Float64Op(Node* node) { |
709 return changer_->Float64OperatorFor(node->opcode()); | 711 return changer_->Float64OperatorFor(node->opcode()); |
710 } | 712 } |
711 | 713 |
| 714 WriteBarrierKind WriteBarrierKindFor( |
| 715 BaseTaggedness base_taggedness, |
| 716 MachineRepresentation field_representation, Type* field_type, |
| 717 Node* value) { |
| 718 if (base_taggedness == kTaggedBase && |
| 719 field_representation == MachineRepresentation::kTagged) { |
| 720 Type* value_type = NodeProperties::GetType(value); |
| 721 if (field_type->Is(Type::TaggedSigned()) || |
| 722 value_type->Is(Type::TaggedSigned())) { |
| 723 // Write barriers are only for stores of heap objects. |
| 724 return kNoWriteBarrier; |
| 725 } |
| 726 if (field_type->Is(Type::BooleanOrNullOrUndefined()) || |
| 727 value_type->Is(Type::BooleanOrNullOrUndefined())) { |
| 728 // Write barriers are not necessary when storing true, false, null or |
| 729 // undefined, because these special oddballs are always in the root set. |
| 730 return kNoWriteBarrier; |
| 731 } |
| 732 if (value_type->IsConstant() && |
| 733 value_type->AsConstant()->Value()->IsHeapObject()) { |
| 734 Handle<HeapObject> value_object = |
| 735 Handle<HeapObject>::cast(value_type->AsConstant()->Value()); |
| 736 if (value_object->IsMap()) { |
| 737 // Write barriers for storing maps are cheaper. |
| 738 return kMapWriteBarrier; |
| 739 } |
| 740 RootIndexMap root_index_map(jsgraph_->isolate()); |
| 741 int root_index = root_index_map.Lookup(*value_object); |
| 742 if (root_index != RootIndexMap::kInvalidRootIndex && |
| 743 jsgraph_->isolate()->heap()->RootIsImmortalImmovable(root_index)) { |
| 744 // Write barriers are unnecessary for immortal immovable roots. |
| 745 return kNoWriteBarrier; |
| 746 } |
| 747 } |
| 748 if (field_type->Is(Type::TaggedPointer()) || |
| 749 value_type->Is(Type::TaggedPointer())) { |
| 750 // Write barriers for heap objects are cheaper. |
| 751 return kPointerWriteBarrier; |
| 752 } |
| 753 NumberMatcher m(value); |
| 754 if (m.HasValue()) { |
| 755 if (IsSmiDouble(m.Value())) { |
| 756 // Storing a smi doesn't need a write barrier. |
| 757 return kNoWriteBarrier; |
| 758 } |
| 759 // The NumberConstant will be represented as HeapNumber. |
| 760 return kPointerWriteBarrier; |
| 761 } |
| 762 return kFullWriteBarrier; |
| 763 } |
| 764 return kNoWriteBarrier; |
| 765 } |
| 766 |
| 767 WriteBarrierKind WriteBarrierKindFor( |
| 768 BaseTaggedness base_taggedness, |
| 769 MachineRepresentation field_representation, int field_offset, |
| 770 Type* field_type, Node* value) { |
| 771 if (base_taggedness == kTaggedBase && |
| 772 field_offset == HeapObject::kMapOffset) { |
| 773 return kMapWriteBarrier; |
| 774 } |
| 775 return WriteBarrierKindFor(base_taggedness, field_representation, |
| 776 field_type, value); |
| 777 } |
| 778 |
712 // Dispatching routine for visiting the node {node} with the usage {use}. | 779 // Dispatching routine for visiting the node {node} with the usage {use}. |
713 // Depending on the operator, propagate new usage info to the inputs. | 780 // Depending on the operator, propagate new usage info to the inputs. |
714 void VisitNode(Node* node, Truncation truncation, | 781 void VisitNode(Node* node, Truncation truncation, |
715 SimplifiedLowering* lowering) { | 782 SimplifiedLowering* lowering) { |
716 switch (node->opcode()) { | 783 switch (node->opcode()) { |
717 //------------------------------------------------------------------ | 784 //------------------------------------------------------------------ |
718 // Common operators. | 785 // Common operators. |
719 //------------------------------------------------------------------ | 786 //------------------------------------------------------------------ |
720 case IrOpcode::kStart: | 787 case IrOpcode::kStart: |
721 case IrOpcode::kDead: | 788 case IrOpcode::kDead: |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 SetOutput(node, access.machine_type.representation()); | 1196 SetOutput(node, access.machine_type.representation()); |
1130 break; | 1197 break; |
1131 } | 1198 } |
1132 case IrOpcode::kStoreField: { | 1199 case IrOpcode::kStoreField: { |
1133 FieldAccess access = FieldAccessOf(node->op()); | 1200 FieldAccess access = FieldAccessOf(node->op()); |
1134 ProcessInput(node, 0, UseInfoForBasePointer(access)); | 1201 ProcessInput(node, 0, UseInfoForBasePointer(access)); |
1135 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation( | 1202 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation( |
1136 access.machine_type.representation())); | 1203 access.machine_type.representation())); |
1137 ProcessRemainingInputs(node, 2); | 1204 ProcessRemainingInputs(node, 2); |
1138 SetOutput(node, MachineRepresentation::kNone); | 1205 SetOutput(node, MachineRepresentation::kNone); |
| 1206 if (lower()) { |
| 1207 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( |
| 1208 access.base_is_tagged, access.machine_type.representation(), |
| 1209 access.offset, access.type, node->InputAt(1)); |
| 1210 if (write_barrier_kind < access.write_barrier_kind) { |
| 1211 access.write_barrier_kind = write_barrier_kind; |
| 1212 NodeProperties::ChangeOp( |
| 1213 node, jsgraph_->simplified()->StoreField(access)); |
| 1214 } |
| 1215 } |
1139 break; | 1216 break; |
1140 } | 1217 } |
1141 case IrOpcode::kLoadBuffer: { | 1218 case IrOpcode::kLoadBuffer: { |
1142 BufferAccess access = BufferAccessOf(node->op()); | 1219 BufferAccess access = BufferAccessOf(node->op()); |
1143 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer | 1220 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
1144 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset | 1221 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
1145 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length | 1222 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
1146 ProcessRemainingInputs(node, 3); | 1223 ProcessRemainingInputs(node, 3); |
1147 | 1224 |
1148 MachineRepresentation output; | 1225 MachineRepresentation output; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 } | 1271 } |
1195 case IrOpcode::kStoreElement: { | 1272 case IrOpcode::kStoreElement: { |
1196 ElementAccess access = ElementAccessOf(node->op()); | 1273 ElementAccess access = ElementAccessOf(node->op()); |
1197 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base | 1274 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
1198 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index | 1275 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
1199 ProcessInput(node, 2, | 1276 ProcessInput(node, 2, |
1200 TruncatingUseInfoFromRepresentation( | 1277 TruncatingUseInfoFromRepresentation( |
1201 access.machine_type.representation())); // value | 1278 access.machine_type.representation())); // value |
1202 ProcessRemainingInputs(node, 3); | 1279 ProcessRemainingInputs(node, 3); |
1203 SetOutput(node, MachineRepresentation::kNone); | 1280 SetOutput(node, MachineRepresentation::kNone); |
| 1281 if (lower()) { |
| 1282 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( |
| 1283 access.base_is_tagged, access.machine_type.representation(), |
| 1284 access.type, node->InputAt(2)); |
| 1285 if (write_barrier_kind < access.write_barrier_kind) { |
| 1286 access.write_barrier_kind = write_barrier_kind; |
| 1287 NodeProperties::ChangeOp( |
| 1288 node, jsgraph_->simplified()->StoreElement(access)); |
| 1289 } |
| 1290 } |
1204 break; | 1291 break; |
1205 } | 1292 } |
1206 case IrOpcode::kObjectIsCallable: | 1293 case IrOpcode::kObjectIsCallable: |
1207 case IrOpcode::kObjectIsNumber: | 1294 case IrOpcode::kObjectIsNumber: |
1208 case IrOpcode::kObjectIsReceiver: | 1295 case IrOpcode::kObjectIsReceiver: |
1209 case IrOpcode::kObjectIsSmi: | 1296 case IrOpcode::kObjectIsSmi: |
1210 case IrOpcode::kObjectIsString: | 1297 case IrOpcode::kObjectIsString: |
1211 case IrOpcode::kObjectIsUndetectable: { | 1298 case IrOpcode::kObjectIsUndetectable: { |
1212 ProcessInput(node, 0, UseInfo::AnyTagged()); | 1299 ProcessInput(node, 0, UseInfo::AnyTagged()); |
1213 SetOutput(node, MachineRepresentation::kBit); | 1300 SetOutput(node, MachineRepresentation::kBit); |
(...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2373 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2460 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
2374 Operator::kNoProperties); | 2461 Operator::kNoProperties); |
2375 to_number_operator_.set(common()->Call(desc)); | 2462 to_number_operator_.set(common()->Call(desc)); |
2376 } | 2463 } |
2377 return to_number_operator_.get(); | 2464 return to_number_operator_.get(); |
2378 } | 2465 } |
2379 | 2466 |
2380 } // namespace compiler | 2467 } // namespace compiler |
2381 } // namespace internal | 2468 } // namespace internal |
2382 } // namespace v8 | 2469 } // namespace v8 |
OLD | NEW |