1 // Copyright 2018 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 #include "src/compiler/js-heap-copy-reducer.h"
6
7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/js-heap-broker.h"
9 #include "src/compiler/js-operator.h"
10 #include "src/compiler/node-properties.h"
11 #include "src/compiler/simplified-operator.h"
12 #include "src/heap/factory-inl.h"
13 #include "src/objects/map.h"
14 #include "src/objects/scope-info.h"
15 #include "src/objects/template-objects.h"
16
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20
21 // In the functions below, we call the ObjectRef (or subclass) constructor in
22 // order to trigger serialization if not yet done.
23
JSHeapCopyReducer(JSHeapBroker * broker)24 JSHeapCopyReducer::JSHeapCopyReducer(JSHeapBroker* broker) : broker_(broker) {}
25
broker()26 JSHeapBroker* JSHeapCopyReducer::broker() { return broker_; }
27
Reduce(Node * node)28 Reduction JSHeapCopyReducer::Reduce(Node* node) {
29 switch (node->opcode()) {
30 case IrOpcode::kCheckClosure: {
31 FeedbackCellRef cell(broker(), FeedbackCellOf(node->op()));
32 FeedbackVectorRef feedback_vector = cell.value().AsFeedbackVector();
33 feedback_vector.Serialize();
34 break;
35 }
36 case IrOpcode::kHeapConstant: {
37 ObjectRef object(broker(), HeapConstantOf(node->op()));
38 if (object.IsJSFunction()) object.AsJSFunction().Serialize();
39 if (object.IsJSObject()) {
40 object.AsJSObject().SerializeObjectCreateMap();
41 }
42 if (object.IsSourceTextModule()) {
43 object.AsSourceTextModule().Serialize();
44 }
45 break;
46 }
47 case IrOpcode::kJSCreateArray: {
48 CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
49 Handle<AllocationSite> site;
50 if (p.site().ToHandle(&site)) AllocationSiteRef(broker(), site);
51 break;
52 }
53 case IrOpcode::kJSCreateArguments: {
54 Node* const frame_state = NodeProperties::GetFrameStateInput(node);
55 FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
56 SharedFunctionInfoRef shared(broker(),
57 state_info.shared_info().ToHandleChecked());
58 break;
59 }
60 case IrOpcode::kJSCreateBlockContext: {
61 ScopeInfoRef(broker(), ScopeInfoOf(node->op()));
62 break;
63 }
64 case IrOpcode::kJSCreateBoundFunction: {
65 CreateBoundFunctionParameters const& p =
66 CreateBoundFunctionParametersOf(node->op());
67 MapRef(broker(), p.map());
68 break;
69 }
70 case IrOpcode::kJSCreateCatchContext: {
71 ScopeInfoRef(broker(), ScopeInfoOf(node->op()));
72 break;
73 }
74 case IrOpcode::kJSCreateClosure: {
75 CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
76 SharedFunctionInfoRef(broker(), p.shared_info());
77 HeapObjectRef(broker(), p.code());
78 break;
79 }
80 case IrOpcode::kJSCreateEmptyLiteralArray: {
81 FeedbackParameter const& p = FeedbackParameterOf(node->op());
82 if (p.feedback().IsValid()) {
83 broker()->ProcessFeedbackForArrayOrObjectLiteral(p.feedback());
84 }
85 break;
86 }
87 /* Unary ops. */
88 case IrOpcode::kJSBitwiseNot:
89 case IrOpcode::kJSDecrement:
90 case IrOpcode::kJSIncrement:
91 case IrOpcode::kJSNegate: {
92 FeedbackParameter const& p = FeedbackParameterOf(node->op());
93 if (p.feedback().IsValid()) {
94 // Unary ops are treated as binary ops with respect to feedback.
95 broker()->ProcessFeedbackForBinaryOperation(p.feedback());
96 }
97 break;
98 }
99 /* Binary ops. */
100 case IrOpcode::kJSAdd:
101 case IrOpcode::kJSSubtract:
102 case IrOpcode::kJSMultiply:
103 case IrOpcode::kJSDivide:
104 case IrOpcode::kJSModulus:
105 case IrOpcode::kJSExponentiate:
106 case IrOpcode::kJSBitwiseOr:
107 case IrOpcode::kJSBitwiseXor:
108 case IrOpcode::kJSBitwiseAnd:
109 case IrOpcode::kJSShiftLeft:
110 case IrOpcode::kJSShiftRight:
111 case IrOpcode::kJSShiftRightLogical: {
112 FeedbackParameter const& p = FeedbackParameterOf(node->op());
113 if (p.feedback().IsValid()) {
114 broker()->ProcessFeedbackForBinaryOperation(p.feedback());
115 }
116 break;
117 }
118 /* Compare ops. */
119 case IrOpcode::kJSEqual:
120 case IrOpcode::kJSGreaterThan:
121 case IrOpcode::kJSGreaterThanOrEqual:
122 case IrOpcode::kJSLessThan:
123 case IrOpcode::kJSLessThanOrEqual:
124 case IrOpcode::kJSStrictEqual: {
125 FeedbackParameter const& p = FeedbackParameterOf(node->op());
126 if (p.feedback().IsValid()) {
127 broker()->ProcessFeedbackForCompareOperation(p.feedback());
128 }
129 break;
130 }
131 case IrOpcode::kJSCreateFunctionContext: {
132 CreateFunctionContextParameters const& p =
133 CreateFunctionContextParametersOf(node->op());
134 ScopeInfoRef(broker(), p.scope_info());
135 break;
136 }
137 case IrOpcode::kJSCreateLiteralArray:
138 case IrOpcode::kJSCreateLiteralObject: {
139 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
140 if (p.feedback().IsValid()) {
141 broker()->ProcessFeedbackForArrayOrObjectLiteral(p.feedback());
142 }
143 break;
144 }
145 case IrOpcode::kJSCreateLiteralRegExp: {
146 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
147 if (p.feedback().IsValid()) {
148 broker()->ProcessFeedbackForRegExpLiteral(p.feedback());
149 }
150 break;
151 }
152 case IrOpcode::kJSGetTemplateObject: {
153 GetTemplateObjectParameters const& p =
154 GetTemplateObjectParametersOf(node->op());
155 SharedFunctionInfoRef shared(broker(), p.shared());
156 TemplateObjectDescriptionRef description(broker(), p.description());
157 shared.GetTemplateObject(description, p.feedback(),
158 SerializationPolicy::kSerializeIfNeeded);
159 break;
160 }
161 case IrOpcode::kJSCreateWithContext: {
162 ScopeInfoRef(broker(), ScopeInfoOf(node->op()));
163 break;
164 }
165 case IrOpcode::kJSLoadNamed: {
166 NamedAccess const& p = NamedAccessOf(node->op());
167 NameRef name(broker(), p.name());
168 if (p.feedback().IsValid()) {
169 broker()->ProcessFeedbackForPropertyAccess(p.feedback(),
170 AccessMode::kLoad, name);
171 }
172 break;
173 }
174 case IrOpcode::kJSLoadNamedFromSuper: {
175 NamedAccess const& p = NamedAccessOf(node->op());
176 NameRef name(broker(), p.name());
177 if (p.feedback().IsValid()) {
178 broker()->ProcessFeedbackForPropertyAccess(p.feedback(),
179 AccessMode::kLoad, name);
180 }
181 break;
182 }
183 case IrOpcode::kJSStoreNamed: {
184 NamedAccess const& p = NamedAccessOf(node->op());
185 NameRef name(broker(), p.name());
186 break;
187 }
188 case IrOpcode::kStoreField:
189 case IrOpcode::kLoadField: {
190 FieldAccess access = FieldAccessOf(node->op());
191 Handle<Map> map_handle;
192 if (access.map.ToHandle(&map_handle)) {
193 MapRef(broker(), map_handle);
194 }
195 Handle<Name> name_handle;
196 if (access.name.ToHandle(&name_handle)) {
197 NameRef(broker(), name_handle);
198 }
199 break;
200 }
201 case IrOpcode::kMapGuard: {
202 ZoneHandleSet<Map> const& maps = MapGuardMapsOf(node->op());
203 for (Handle<Map> map : maps) {
204 MapRef(broker(), map);
205 }
206 break;
207 }
208 case IrOpcode::kCheckMaps: {
209 ZoneHandleSet<Map> const& maps = CheckMapsParametersOf(node->op()).maps();
210 for (Handle<Map> map : maps) {
211 MapRef(broker(), map);
212 }
213 break;
214 }
215 case IrOpcode::kCompareMaps: {
216 ZoneHandleSet<Map> const& maps = CompareMapsParametersOf(node->op());
217 for (Handle<Map> map : maps) {
218 MapRef(broker(), map);
219 }
220 break;
221 }
222 case IrOpcode::kJSLoadProperty: {
223 PropertyAccess const& p = PropertyAccessOf(node->op());
224 AccessMode access_mode = AccessMode::kLoad;
225 if (p.feedback().IsValid()) {
226 broker()->ProcessFeedbackForPropertyAccess(p.feedback(), access_mode,
227 base::nullopt);
228 }
229 break;
230 }
231 default:
232 break;
233 }
234 return NoChange();
235 }
236
237 } // namespace compiler
238 } // namespace internal
239 } // namespace v8
240