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

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

Issue 1403223003: [turbofan] Make native context specialization dependent on the typed pipeline. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 months 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-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
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 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/js-global-specialization.h" 5 #include "src/compiler/js-global-specialization.h"
6 6
7 #include "src/compilation-dependencies.h" 7 #include "src/compilation-dependencies.h"
8 #include "src/compiler/access-builder.h" 8 #include "src/compiler/access-builder.h"
9 #include "src/compiler/js-graph.h" 9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/js-operator.h" 10 #include "src/compiler/js-operator.h"
11 #include "src/contexts.h" 11 #include "src/contexts.h"
12 #include "src/lookup.h" 12 #include "src/lookup.h"
13 #include "src/objects-inl.h" 13 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 namespace compiler { 17 namespace compiler {
18 18
19 struct JSGlobalSpecialization::ScriptContextTableLookupResult {
20 Handle<Context> context;
21 bool immutable;
22 int index;
23 };
24
25
19 JSGlobalSpecialization::JSGlobalSpecialization( 26 JSGlobalSpecialization::JSGlobalSpecialization(
20 Editor* editor, JSGraph* jsgraph, Flags flags, 27 Editor* editor, JSGraph* jsgraph, Flags flags,
21 Handle<GlobalObject> global_object, CompilationDependencies* dependencies) 28 Handle<GlobalObject> global_object, CompilationDependencies* dependencies)
22 : AdvancedReducer(editor), 29 : AdvancedReducer(editor),
23 jsgraph_(jsgraph), 30 jsgraph_(jsgraph),
24 flags_(flags), 31 flags_(flags),
25 global_object_(global_object), 32 global_object_(global_object),
26 dependencies_(dependencies), 33 dependencies_(dependencies),
27 simplified_(graph()->zone()) {} 34 simplified_(graph()->zone()) {}
28 35
29 36
30 Reduction JSGlobalSpecialization::Reduce(Node* node) { 37 Reduction JSGlobalSpecialization::Reduce(Node* node) {
31 switch (node->opcode()) { 38 switch (node->opcode()) {
32 case IrOpcode::kJSLoadGlobal: 39 case IrOpcode::kJSLoadGlobal:
33 return ReduceJSLoadGlobal(node); 40 return ReduceJSLoadGlobal(node);
34 case IrOpcode::kJSStoreGlobal: 41 case IrOpcode::kJSStoreGlobal:
35 return ReduceJSStoreGlobal(node); 42 return ReduceJSStoreGlobal(node);
36 default: 43 default:
37 break; 44 break;
38 } 45 }
39 return NoChange(); 46 return NoChange();
40 } 47 }
41 48
42 49
43 Reduction JSGlobalSpecialization::ReduceJSLoadGlobal(Node* node) { 50 Reduction JSGlobalSpecialization::ReduceJSLoadGlobal(Node* node) {
44 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); 51 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
45 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); 52 Handle<Name> name = LoadGlobalParametersOf(node->op()).name();
46 Node* effect = NodeProperties::GetEffectInput(node); 53 Node* effect = NodeProperties::GetEffectInput(node);
47
48 // Try to lookup the name on the script context table first (lexical scoping).
49 if (name->IsString()) {
50 Handle<ScriptContextTable> script_context_table(
51 global_object()->native_context()->script_context_table());
52 ScriptContextTable::LookupResult result;
53 if (ScriptContextTable::Lookup(script_context_table,
54 Handle<String>::cast(name), &result)) {
55 Handle<Context> script_context = ScriptContextTable::GetContext(
56 script_context_table, result.context_index);
57 if (script_context->is_the_hole(result.slot_index)) {
58 // TODO(bmeurer): Is this relevant in practice?
59 return NoChange();
60 }
61 Node* context = jsgraph()->Constant(script_context);
62 Node* value = effect = graph()->NewNode(
63 javascript()->LoadContext(0, result.slot_index,
64 IsImmutableVariableMode(result.mode)),
65 context, context, effect);
66 return Replace(node, value, effect);
67 }
68 }
69
70 // Lookup on the global object instead.
71 LookupIterator it(global_object(), name, LookupIterator::OWN);
72 if (it.state() == LookupIterator::DATA) {
73 return ReduceLoadFromPropertyCell(node, it.GetPropertyCell());
74 }
75
76 return NoChange();
77 }
78
79
80 Reduction JSGlobalSpecialization::ReduceJSStoreGlobal(Node* node) {
81 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
82 Handle<Name> name = StoreGlobalParametersOf(node->op()).name();
83 Node* value = NodeProperties::GetValueInput(node, 2);
84 Node* effect = NodeProperties::GetEffectInput(node);
85 Node* control = NodeProperties::GetControlInput(node); 54 Node* control = NodeProperties::GetControlInput(node);
86 55
87 // Try to lookup the name on the script context table first (lexical scoping). 56 // Try to lookup the name on the script context table first (lexical scoping).
88 if (name->IsString()) { 57 ScriptContextTableLookupResult result;
89 Handle<ScriptContextTable> script_context_table( 58 if (LookupInScriptContextTable(name, &result)) {
90 global_object()->native_context()->script_context_table()); 59 Node* context = jsgraph()->Constant(result.context);
91 ScriptContextTable::LookupResult result; 60 Node* value = effect = graph()->NewNode(
92 if (ScriptContextTable::Lookup(script_context_table, 61 javascript()->LoadContext(0, result.index, result.immutable), context,
93 Handle<String>::cast(name), &result)) { 62 context, effect);
94 if (IsImmutableVariableMode(result.mode)) return NoChange(); 63 return Replace(node, value, effect);
95 Handle<Context> script_context = ScriptContextTable::GetContext(
96 script_context_table, result.context_index);
97 if (script_context->is_the_hole(result.slot_index)) {
98 // TODO(bmeurer): Is this relevant in practice?
99 return NoChange();
100 }
101 Node* context = jsgraph()->Constant(script_context);
102 effect =
103 graph()->NewNode(javascript()->StoreContext(0, result.slot_index),
104 context, value, context, effect, control);
105 return Replace(node, value, effect, control);
106 }
107 } 64 }
108 65
109 // Lookup on the global object instead. 66 // Lookup on the global object instead. We only deal with own data
67 // properties of the global object here (represented as PropertyCell).
110 LookupIterator it(global_object(), name, LookupIterator::OWN); 68 LookupIterator it(global_object(), name, LookupIterator::OWN);
111 if (it.state() == LookupIterator::DATA) { 69 if (it.state() != LookupIterator::DATA) return NoChange();
112 return ReduceStoreToPropertyCell(node, it.GetPropertyCell()); 70 Handle<PropertyCell> property_cell = it.GetPropertyCell();
113 } 71 PropertyDetails property_details = property_cell->property_details();
72 Handle<Object> property_cell_value(property_cell->value(), isolate());
114 73
115 return NoChange();
116 }
117
118
119 Reduction JSGlobalSpecialization::ReduceLoadFromPropertyCell(
120 Node* node, Handle<PropertyCell> property_cell) {
121 Node* effect = NodeProperties::GetEffectInput(node);
122 Node* control = NodeProperties::GetControlInput(node);
123 // We only specialize global data property access.
124 PropertyDetails property_details = property_cell->property_details();
125 DCHECK_EQ(kData, property_details.kind());
126 Handle<Object> property_cell_value(property_cell->value(), isolate());
127 DCHECK(!property_cell_value->IsTheHole());
128 // Load from non-configurable, read-only data property on the global 74 // Load from non-configurable, read-only data property on the global
129 // object can be constant-folded, even without deoptimization support. 75 // object can be constant-folded, even without deoptimization support.
130 if (!property_details.IsConfigurable() && property_details.IsReadOnly()) { 76 if (!property_details.IsConfigurable() && property_details.IsReadOnly()) {
131 return Replace(node, property_cell_value); 77 return Replace(node, property_cell_value);
132 } 78 }
79
133 // Load from constant/undefined global property can be constant-folded 80 // Load from constant/undefined global property can be constant-folded
134 // with deoptimization support, by adding a code dependency on the cell. 81 // with deoptimization support, by adding a code dependency on the cell.
135 if ((property_details.cell_type() == PropertyCellType::kConstant || 82 if ((property_details.cell_type() == PropertyCellType::kConstant ||
136 property_details.cell_type() == PropertyCellType::kUndefined) && 83 property_details.cell_type() == PropertyCellType::kUndefined) &&
137 (flags() & kDeoptimizationEnabled)) { 84 (flags() & kDeoptimizationEnabled)) {
138 dependencies()->AssumePropertyCell(property_cell); 85 dependencies()->AssumePropertyCell(property_cell);
139 return Replace(node, property_cell_value); 86 return Replace(node, property_cell_value);
140 } 87 }
141 // Not much we can do if we run the generic pipeline here. 88
142 if (!(flags() & kTypingEnabled)) return NoChange();
143 // Load from constant type global property can benefit from representation 89 // Load from constant type global property can benefit from representation
144 // (and map) feedback with deoptimization support (requires code dependency). 90 // (and map) feedback with deoptimization support (requires code dependency).
145 if (property_details.cell_type() == PropertyCellType::kConstantType && 91 if (property_details.cell_type() == PropertyCellType::kConstantType &&
146 (flags() & kDeoptimizationEnabled)) { 92 (flags() & kDeoptimizationEnabled)) {
147 dependencies()->AssumePropertyCell(property_cell); 93 dependencies()->AssumePropertyCell(property_cell);
148 // Compute proper type based on the current value in the cell. 94 // Compute proper type based on the current value in the cell.
149 Type* property_cell_value_type; 95 Type* property_cell_value_type;
150 if (property_cell_value->IsSmi()) { 96 if (property_cell_value->IsSmi()) {
151 property_cell_value_type = Type::Intersect( 97 property_cell_value_type = Type::Intersect(
152 Type::SignedSmall(), Type::TaggedSigned(), graph()->zone()); 98 Type::SignedSmall(), Type::TaggedSigned(), graph()->zone());
153 } else if (property_cell_value->IsNumber()) { 99 } else if (property_cell_value->IsNumber()) {
154 property_cell_value_type = Type::Intersect( 100 property_cell_value_type = Type::Intersect(
155 Type::Number(), Type::TaggedPointer(), graph()->zone()); 101 Type::Number(), Type::TaggedPointer(), graph()->zone());
156 } else { 102 } else {
157 property_cell_value_type = Type::Of(property_cell_value, graph()->zone()); 103 property_cell_value_type = Type::Of(property_cell_value, graph()->zone());
158 } 104 }
159 Node* value = effect = graph()->NewNode( 105 Node* value = effect = graph()->NewNode(
160 simplified()->LoadField( 106 simplified()->LoadField(
161 AccessBuilder::ForPropertyCellValue(property_cell_value_type)), 107 AccessBuilder::ForPropertyCellValue(property_cell_value_type)),
162 jsgraph()->Constant(property_cell), effect, control); 108 jsgraph()->Constant(property_cell), effect, control);
163 return Replace(node, value, effect); 109 return Replace(node, value, effect);
164 } 110 }
111
165 // Load from non-configurable, data property on the global can be lowered to 112 // Load from non-configurable, data property on the global can be lowered to
166 // a field load, even without deoptimization, because the property cannot be 113 // a field load, even without deoptimization, because the property cannot be
167 // deleted or reconfigured to an accessor/interceptor property. 114 // deleted or reconfigured to an accessor/interceptor property.
168 if (property_details.IsConfigurable()) { 115 if (property_details.IsConfigurable()) {
169 // With deoptimization support, we can lower loads even from configurable 116 // With deoptimization support, we can lower loads even from configurable
170 // data properties on the global object, by adding a code dependency on 117 // data properties on the global object, by adding a code dependency on
171 // the cell. 118 // the cell.
172 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); 119 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
173 dependencies()->AssumePropertyCell(property_cell); 120 dependencies()->AssumePropertyCell(property_cell);
174 } 121 }
175 Node* value = effect = graph()->NewNode( 122 Node* value = effect = graph()->NewNode(
176 simplified()->LoadField(AccessBuilder::ForPropertyCellValue()), 123 simplified()->LoadField(AccessBuilder::ForPropertyCellValue()),
177 jsgraph()->Constant(property_cell), effect, control); 124 jsgraph()->Constant(property_cell), effect, control);
178 return Replace(node, value, effect); 125 return Replace(node, value, effect);
179 } 126 }
180 127
181 128
182 Reduction JSGlobalSpecialization::ReduceStoreToPropertyCell( 129 Reduction JSGlobalSpecialization::ReduceJSStoreGlobal(Node* node) {
183 Node* node, Handle<PropertyCell> property_cell) { 130 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
131 Handle<Name> name = StoreGlobalParametersOf(node->op()).name();
184 Node* value = NodeProperties::GetValueInput(node, 2); 132 Node* value = NodeProperties::GetValueInput(node, 2);
133 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
185 Node* effect = NodeProperties::GetEffectInput(node); 134 Node* effect = NodeProperties::GetEffectInput(node);
186 Node* control = NodeProperties::GetControlInput(node); 135 Node* control = NodeProperties::GetControlInput(node);
187 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 136
188 // We only specialize global data property access. 137 // Try to lookup the name on the script context table first (lexical scoping).
138 ScriptContextTableLookupResult result;
139 if (LookupInScriptContextTable(name, &result)) {
140 if (result.immutable) return NoChange();
141 Node* context = jsgraph()->Constant(result.context);
142 effect = graph()->NewNode(javascript()->StoreContext(0, result.index),
143 context, value, context, effect, control);
144 return Replace(node, value, effect, control);
145 }
146
147 // Lookup on the global object instead. We only deal with own data
148 // properties of the global object here (represented as PropertyCell).
149 LookupIterator it(global_object(), name, LookupIterator::OWN);
150 if (it.state() != LookupIterator::DATA) return NoChange();
151 Handle<PropertyCell> property_cell = it.GetPropertyCell();
189 PropertyDetails property_details = property_cell->property_details(); 152 PropertyDetails property_details = property_cell->property_details();
190 DCHECK_EQ(kData, property_details.kind());
191 Handle<Object> property_cell_value(property_cell->value(), isolate()); 153 Handle<Object> property_cell_value(property_cell->value(), isolate());
192 DCHECK(!property_cell_value->IsTheHole()); 154
193 // Don't even bother trying to lower stores to read-only data properties. 155 // Don't even bother trying to lower stores to read-only data properties.
194 if (property_details.IsReadOnly()) return NoChange(); 156 if (property_details.IsReadOnly()) return NoChange();
195 // Not much we can do if we run the generic pipeline here.
196 if (!(flags() & kTypingEnabled)) return NoChange();
197 switch (property_details.cell_type()) { 157 switch (property_details.cell_type()) {
198 case PropertyCellType::kUndefined: { 158 case PropertyCellType::kUndefined: {
199 return NoChange(); 159 return NoChange();
200 } 160 }
201 case PropertyCellType::kConstant: { 161 case PropertyCellType::kConstant: {
202 // Store to constant property cell requires deoptimization support, 162 // Store to constant property cell requires deoptimization support,
203 // because we might even need to eager deoptimize for mismatch. 163 // because we might even need to eager deoptimize for mismatch.
204 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); 164 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
205 dependencies()->AssumePropertyCell(property_cell); 165 dependencies()->AssumePropertyCell(property_cell);
206 Node* check = 166 Node* check =
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 } 225 }
266 } 226 }
267 effect = graph()->NewNode( 227 effect = graph()->NewNode(
268 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), 228 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()),
269 jsgraph()->Constant(property_cell), value, effect, control); 229 jsgraph()->Constant(property_cell), value, effect, control);
270 return Replace(node, value, effect, control); 230 return Replace(node, value, effect, control);
271 } 231 }
272 232
273 233
274 Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) { 234 Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) {
235 // TODO(bmeurer): Move this to JSGraph::HeapConstant instead?
275 if (value->IsConsString()) { 236 if (value->IsConsString()) {
276 value = String::Flatten(Handle<String>::cast(value), TENURED); 237 value = String::Flatten(Handle<String>::cast(value), TENURED);
277 } 238 }
278 return Replace(node, jsgraph()->Constant(value)); 239 return Replace(node, jsgraph()->Constant(value));
279 } 240 }
280 241
281 242
243 bool JSGlobalSpecialization::LookupInScriptContextTable(
244 Handle<Name> name, ScriptContextTableLookupResult* result) {
245 if (!name->IsString()) return false;
246 Handle<ScriptContextTable> script_context_table(
247 global_object()->native_context()->script_context_table());
248 ScriptContextTable::LookupResult lookup_result;
249 if (!ScriptContextTable::Lookup(script_context_table,
250 Handle<String>::cast(name), &lookup_result)) {
251 return false;
252 }
253 Handle<Context> script_context = ScriptContextTable::GetContext(
254 script_context_table, lookup_result.context_index);
255 if (script_context->is_the_hole(lookup_result.slot_index)) return false;
256 result->context = script_context;
257 result->immutable = IsImmutableVariableMode(lookup_result.mode);
258 result->index = lookup_result.slot_index;
259 return true;
260 }
261
262
282 Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); } 263 Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); }
283 264
284 265
285 Isolate* JSGlobalSpecialization::isolate() const { 266 Isolate* JSGlobalSpecialization::isolate() const {
286 return jsgraph()->isolate(); 267 return jsgraph()->isolate();
287 } 268 }
288 269
289 270
290 CommonOperatorBuilder* JSGlobalSpecialization::common() const { 271 CommonOperatorBuilder* JSGlobalSpecialization::common() const {
291 return jsgraph()->common(); 272 return jsgraph()->common();
292 } 273 }
293 274
294 275
295 JSOperatorBuilder* JSGlobalSpecialization::javascript() const { 276 JSOperatorBuilder* JSGlobalSpecialization::javascript() const {
296 return jsgraph()->javascript(); 277 return jsgraph()->javascript();
297 } 278 }
298 279
299 } // namespace compiler 280 } // namespace compiler
300 } // namespace internal 281 } // namespace internal
301 } // namespace v8 282 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-global-specialization.h ('k') | src/compiler/js-inlining.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698