Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(456)

Side by Side Diff: src/compiler/js-global-object-specialization.cc

Issue 1417043006: [turbofan] Split JSGlobalObjectSpecialization into separate class. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-global-object-specialization.h ('k') | src/compiler/js-inlining.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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-global-object-specialization.h"
6
7 #include "src/compilation-dependencies.h"
8 #include "src/compiler/access-builder.h"
9 #include "src/compiler/common-operator.h"
10 #include "src/compiler/js-graph.h"
11 #include "src/compiler/js-operator.h"
12 #include "src/compiler/node-properties.h"
13 #include "src/compiler/simplified-operator.h"
14 #include "src/lookup.h"
15 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
16 #include "src/type-cache.h"
17
18 namespace v8 {
19 namespace internal {
20 namespace compiler {
21
22 struct JSGlobalObjectSpecialization::ScriptContextTableLookupResult {
23 Handle<Context> context;
24 bool immutable;
25 int index;
26 };
27
28
29 JSGlobalObjectSpecialization::JSGlobalObjectSpecialization(
30 Editor* editor, JSGraph* jsgraph, Flags flags,
31 Handle<JSGlobalObject> global_object, CompilationDependencies* dependencies)
32 : AdvancedReducer(editor),
33 jsgraph_(jsgraph),
34 flags_(flags),
35 global_object_(global_object),
36 script_context_table_(
37 global_object->native_context()->script_context_table(), isolate()),
38 dependencies_(dependencies),
39 type_cache_(TypeCache::Get()) {}
40
41
42 Reduction JSGlobalObjectSpecialization::Reduce(Node* node) {
43 switch (node->opcode()) {
44 case IrOpcode::kJSLoadGlobal:
45 return ReduceJSLoadGlobal(node);
46 case IrOpcode::kJSStoreGlobal:
47 return ReduceJSStoreGlobal(node);
48 default:
49 break;
50 }
51 return NoChange();
52 }
53
54
55 Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
56 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
57 Handle<Name> name = LoadGlobalParametersOf(node->op()).name();
58 Node* effect = NodeProperties::GetEffectInput(node);
59 Node* control = NodeProperties::GetControlInput(node);
60
61 // Try to lookup the name on the script context table first (lexical scoping).
62 ScriptContextTableLookupResult result;
63 if (LookupInScriptContextTable(name, &result)) {
64 if (result.context->is_the_hole(result.index)) return NoChange();
65 Node* context = jsgraph()->HeapConstant(result.context);
66 Node* value = effect = graph()->NewNode(
67 javascript()->LoadContext(0, result.index, result.immutable), context,
68 context, effect);
69 ReplaceWithValue(node, value, effect);
70 return Replace(value);
71 }
72
73 // Lookup on the global object instead. We only deal with own data
74 // properties of the global object here (represented as PropertyCell).
75 LookupIterator it(global_object(), name, LookupIterator::OWN);
76 if (it.state() != LookupIterator::DATA) return NoChange();
77 Handle<PropertyCell> property_cell = it.GetPropertyCell();
78 PropertyDetails property_details = property_cell->property_details();
79 Handle<Object> property_cell_value(property_cell->value(), isolate());
80
81 // Load from non-configurable, read-only data property on the global
82 // object can be constant-folded, even without deoptimization support.
83 if (!property_details.IsConfigurable() && property_details.IsReadOnly()) {
84 Node* value = jsgraph()->Constant(property_cell_value);
85 ReplaceWithValue(node, value);
86 return Replace(value);
87 }
88
89 // Load from non-configurable, data property on the global can be lowered to
90 // a field load, even without deoptimization, because the property cannot be
91 // deleted or reconfigured to an accessor/interceptor property. Yet, if
92 // deoptimization support is available, we can constant-fold certain global
93 // properties or at least lower them to field loads annotated with more
94 // precise type feedback.
95 Type* property_cell_value_type = Type::Tagged();
96 if (flags() & kDeoptimizationEnabled) {
97 // Record a code dependency on the cell if we can benefit from the
98 // additional feedback, or the global property is configurable (i.e.
99 // can be deleted or reconfigured to an accessor property).
100 if (property_details.cell_type() != PropertyCellType::kMutable ||
101 property_details.IsConfigurable()) {
102 dependencies()->AssumePropertyCell(property_cell);
103 }
104
105 // Load from constant/undefined global property can be constant-folded.
106 if ((property_details.cell_type() == PropertyCellType::kConstant ||
107 property_details.cell_type() == PropertyCellType::kUndefined)) {
108 Node* value = jsgraph()->Constant(property_cell_value);
109 ReplaceWithValue(node, value);
110 return Replace(value);
111 }
112
113 // Load from constant type cell can benefit from type feedback.
114 if (property_details.cell_type() == PropertyCellType::kConstantType) {
115 // Compute proper type based on the current value in the cell.
116 if (property_cell_value->IsSmi()) {
117 property_cell_value_type = type_cache_.kSmi;
118 } else if (property_cell_value->IsNumber()) {
119 property_cell_value_type = type_cache_.kHeapNumber;
120 } else {
121 Handle<Map> property_cell_value_map(
122 Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
123 property_cell_value_type =
124 Type::Class(property_cell_value_map, graph()->zone());
125 }
126 }
127 } else if (property_details.IsConfigurable()) {
128 // Access to configurable global properties requires deoptimization support.
129 return NoChange();
130 }
131 Node* value = effect = graph()->NewNode(
132 simplified()->LoadField(
133 AccessBuilder::ForPropertyCellValue(property_cell_value_type)),
134 jsgraph()->HeapConstant(property_cell), effect, control);
135 ReplaceWithValue(node, value, effect, control);
136 return Replace(value);
137 }
138
139
140 Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
141 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
142 Handle<Name> name = StoreGlobalParametersOf(node->op()).name();
143 Node* value = NodeProperties::GetValueInput(node, 0);
144 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
145 Node* effect = NodeProperties::GetEffectInput(node);
146 Node* control = NodeProperties::GetControlInput(node);
147
148 // Try to lookup the name on the script context table first (lexical scoping).
149 ScriptContextTableLookupResult result;
150 if (LookupInScriptContextTable(name, &result)) {
151 if (result.context->is_the_hole(result.index)) return NoChange();
152 if (result.immutable) return NoChange();
153 Node* context = jsgraph()->HeapConstant(result.context);
154 effect = graph()->NewNode(javascript()->StoreContext(0, result.index),
155 context, value, context, effect, control);
156 ReplaceWithValue(node, value, effect, control);
157 return Replace(value);
158 }
159
160 // Lookup on the global object instead. We only deal with own data
161 // properties of the global object here (represented as PropertyCell).
162 LookupIterator it(global_object(), name, LookupIterator::OWN);
163 if (it.state() != LookupIterator::DATA) return NoChange();
164 Handle<PropertyCell> property_cell = it.GetPropertyCell();
165 PropertyDetails property_details = property_cell->property_details();
166 Handle<Object> property_cell_value(property_cell->value(), isolate());
167
168 // Don't even bother trying to lower stores to read-only data properties.
169 if (property_details.IsReadOnly()) return NoChange();
170 switch (property_details.cell_type()) {
171 case PropertyCellType::kUndefined: {
172 return NoChange();
173 }
174 case PropertyCellType::kConstant: {
175 // Store to constant property cell requires deoptimization support,
176 // because we might even need to eager deoptimize for mismatch.
177 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
178 dependencies()->AssumePropertyCell(property_cell);
179 Node* check =
180 graph()->NewNode(simplified()->ReferenceEqual(Type::Tagged()), value,
181 jsgraph()->Constant(property_cell_value));
182 Node* branch =
183 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
184 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
185 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
186 effect, if_false);
187 // TODO(bmeurer): This should be on the AdvancedReducer somehow.
188 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
189 control = graph()->NewNode(common()->IfTrue(), branch);
190 break;
191 }
192 case PropertyCellType::kConstantType: {
193 // Store to constant-type property cell requires deoptimization support,
194 // because we might even need to eager deoptimize for mismatch.
195 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
196 dependencies()->AssumePropertyCell(property_cell);
197 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
198 if (property_cell_value->IsHeapObject()) {
199 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
200 check, control);
201 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
202 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
203 effect, if_true);
204 // TODO(bmeurer): This should be on the AdvancedReducer somehow.
205 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
206 control = graph()->NewNode(common()->IfFalse(), branch);
207 Node* value_map =
208 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
209 value, effect, control);
210 Handle<Map> property_cell_value_map(
211 Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
212 check = graph()->NewNode(
213 simplified()->ReferenceEqual(Type::Any()), value_map,
214 jsgraph()->HeapConstant(property_cell_value_map));
215 }
216 Node* branch =
217 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
218 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
219 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
220 effect, if_false);
221 // TODO(bmeurer): This should be on the AdvancedReducer somehow.
222 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
223 control = graph()->NewNode(common()->IfTrue(), branch);
224 effect = graph()->NewNode(
225 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()),
226 jsgraph()->HeapConstant(property_cell), value, effect, control);
227 break;
228 }
229 case PropertyCellType::kMutable: {
230 // Store to non-configurable, data property on the global can be lowered
231 // to a field store, even without deoptimization, because the property
232 // cannot be deleted or reconfigured to an accessor/interceptor property.
233 if (property_details.IsConfigurable()) {
234 // With deoptimization support, we can lower stores even to configurable
235 // data properties on the global object, by adding a code dependency on
236 // the cell.
237 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
238 dependencies()->AssumePropertyCell(property_cell);
239 }
240 effect = graph()->NewNode(
241 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()),
242 jsgraph()->HeapConstant(property_cell), value, effect, control);
243 break;
244 }
245 }
246 ReplaceWithValue(node, value, effect, control);
247 return Replace(value);
248 }
249
250
251 bool JSGlobalObjectSpecialization::LookupInScriptContextTable(
252 Handle<Name> name, ScriptContextTableLookupResult* result) {
253 if (!name->IsString()) return false;
254 ScriptContextTable::LookupResult lookup_result;
255 if (!ScriptContextTable::Lookup(script_context_table(),
256 Handle<String>::cast(name), &lookup_result)) {
257 return false;
258 }
259 Handle<Context> script_context = ScriptContextTable::GetContext(
260 script_context_table(), lookup_result.context_index);
261 result->context = script_context;
262 result->immutable = IsImmutableVariableMode(lookup_result.mode);
263 result->index = lookup_result.slot_index;
264 return true;
265 }
266
267
268 Graph* JSGlobalObjectSpecialization::graph() const {
269 return jsgraph()->graph();
270 }
271
272
273 Isolate* JSGlobalObjectSpecialization::isolate() const {
274 return jsgraph()->isolate();
275 }
276
277
278 CommonOperatorBuilder* JSGlobalObjectSpecialization::common() const {
279 return jsgraph()->common();
280 }
281
282
283 JSOperatorBuilder* JSGlobalObjectSpecialization::javascript() const {
284 return jsgraph()->javascript();
285 }
286
287
288 SimplifiedOperatorBuilder* JSGlobalObjectSpecialization::simplified() const {
289 return jsgraph()->simplified();
290 }
291
292 } // namespace compiler
293 } // namespace internal
294 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-global-object-specialization.h ('k') | src/compiler/js-inlining.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698