1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_ALLOCATION_BUILDER_H_
6 #define V8_COMPILER_ALLOCATION_BUILDER_H_
7 
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/node.h"
10 #include "src/compiler/simplified-operator.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
16 // A helper class to construct inline allocations on the simplified operator
17 // level. This keeps track of the effect chain for initial stores on a newly
18 // allocated object and also provides helpers for commonly allocated objects.
19 class AllocationBuilder final {
20  public:
AllocationBuilder(JSGraph * jsgraph,Node * effect,Node * control)21   AllocationBuilder(JSGraph* jsgraph, Node* effect, Node* control)
22       : jsgraph_(jsgraph),
23         allocation_(nullptr),
24         effect_(effect),
25         control_(control) {}
26 
27   // Primitive allocation of static size.
28   void Allocate(int size, PretenureFlag pretenure = NOT_TENURED,
29                 Type type = Type::Any()) {
30     DCHECK_LE(size, kMaxRegularHeapObjectSize);
31     effect_ = graph()->NewNode(
32         common()->BeginRegion(RegionObservability::kNotObservable), effect_);
33     allocation_ =
34         graph()->NewNode(simplified()->Allocate(type, pretenure),
35                          jsgraph()->Constant(size), effect_, control_);
36     effect_ = allocation_;
37   }
38 
39   // Primitive store into a field.
Store(const FieldAccess & access,Node * value)40   void Store(const FieldAccess& access, Node* value) {
41     effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_,
42                                value, effect_, control_);
43   }
44 
45   // Primitive store into an element.
Store(ElementAccess const & access,Node * index,Node * value)46   void Store(ElementAccess const& access, Node* index, Node* value) {
47     effect_ = graph()->NewNode(simplified()->StoreElement(access), allocation_,
48                                index, value, effect_, control_);
49   }
50 
51   // Compound allocation of a context.
AllocateContext(int length,Handle<Map> map)52   void AllocateContext(int length, Handle<Map> map) {
53     DCHECK(map->instance_type() >= BLOCK_CONTEXT_TYPE &&
54            map->instance_type() <= WITH_CONTEXT_TYPE);
55     int size = FixedArray::SizeFor(length);
56     Allocate(size, NOT_TENURED, Type::OtherInternal());
57     Store(AccessBuilder::ForMap(), map);
58     Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length));
59   }
60 
61   // Compound allocation of a FixedArray.
62   void AllocateArray(int length, Handle<Map> map,
63                      PretenureFlag pretenure = NOT_TENURED) {
64     DCHECK(map->instance_type() == FIXED_ARRAY_TYPE ||
65            map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE);
66     int size = (map->instance_type() == FIXED_ARRAY_TYPE)
67                    ? FixedArray::SizeFor(length)
68                    : FixedDoubleArray::SizeFor(length);
69     Allocate(size, pretenure, Type::OtherInternal());
70     Store(AccessBuilder::ForMap(), map);
71     Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length));
72   }
73 
74   // Compound store of a constant into a field.
Store(const FieldAccess & access,Handle<Object> value)75   void Store(const FieldAccess& access, Handle<Object> value) {
76     Store(access, jsgraph()->Constant(value));
77   }
78   // Compound store of a constant into a field.
Store(const FieldAccess & access,const ObjectRef & value)79   void Store(const FieldAccess& access, const ObjectRef& value) {
80     Store(access, jsgraph()->Constant(value));
81   }
82 
FinishAndChange(Node * node)83   void FinishAndChange(Node* node) {
84     NodeProperties::SetType(allocation_, NodeProperties::GetType(node));
85     node->ReplaceInput(0, allocation_);
86     node->ReplaceInput(1, effect_);
87     node->TrimInputCount(2);
88     NodeProperties::ChangeOp(node, common()->FinishRegion());
89   }
90 
Finish()91   Node* Finish() {
92     return graph()->NewNode(common()->FinishRegion(), allocation_, effect_);
93   }
94 
95  protected:
jsgraph()96   JSGraph* jsgraph() { return jsgraph_; }
isolate()97   Isolate* isolate() const { return jsgraph_->isolate(); }
graph()98   Graph* graph() { return jsgraph_->graph(); }
common()99   CommonOperatorBuilder* common() { return jsgraph_->common(); }
simplified()100   SimplifiedOperatorBuilder* simplified() { return jsgraph_->simplified(); }
101 
102  private:
103   JSGraph* const jsgraph_;
104   Node* allocation_;
105   Node* effect_;
106   Node* control_;
107 };
108 
109 }  // namespace compiler
110 }  // namespace internal
111 }  // namespace v8
112 
113 #endif  // V8_COMPILER_ALLOCATION_BUILDER_H_
114