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