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

Side by Side Diff: src/compiler/js-type-feedback.cc

Issue 1084533003: Revert of [turbofan] Optimize loads from the global object in JSTypeFeedbackSpecializer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 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-type-feedback.h ('k') | src/compiler/pipeline.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-type-feedback.h" 5 #include "src/compiler/js-type-feedback.h"
6 6
7 #include "src/property-details.h" 7 #include "src/property-details.h"
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/ast.h" 10 #include "src/ast.h"
11 #include "src/compiler.h"
12 #include "src/type-info.h" 11 #include "src/type-info.h"
13 12
14 #include "src/compiler/access-builder.h" 13 #include "src/compiler/access-builder.h"
15 #include "src/compiler/common-operator.h" 14 #include "src/compiler/common-operator.h"
16 #include "src/compiler/node-aux-data.h" 15 #include "src/compiler/node-aux-data.h"
17 #include "src/compiler/node-matchers.h" 16 #include "src/compiler/node-matchers.h"
18 #include "src/compiler/operator-properties.h" 17 #include "src/compiler/operator-properties.h"
19 #include "src/compiler/simplified-operator.h" 18 #include "src/compiler/simplified-operator.h"
20 19
21 namespace v8 { 20 namespace v8 {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 } 71 }
73 return ReduceJSStoreProperty(node); 72 return ReduceJSStoreProperty(node);
74 } 73 }
75 default: 74 default:
76 break; 75 break;
77 } 76 }
78 return NoChange(); 77 return NoChange();
79 } 78 }
80 79
81 80
82 static void AddFieldAccessTypes(FieldAccess* access,
83 PropertyDetails property_details) {
84 if (property_details.representation().IsSmi()) {
85 access->type = Type::SignedSmall();
86 access->machine_type = static_cast<MachineType>(kTypeInt32 | kRepTagged);
87 } else if (property_details.representation().IsDouble()) {
88 access->type = Type::Number();
89 access->machine_type = kMachFloat64;
90 }
91 }
92
93
94 static bool GetInObjectFieldAccess(LoadOrStore mode, Handle<Map> map, 81 static bool GetInObjectFieldAccess(LoadOrStore mode, Handle<Map> map,
95 Handle<Name> name, FieldAccess* access) { 82 Handle<Name> name, FieldAccess* access) {
96 access->base_is_tagged = kTaggedBase; 83 access->base_is_tagged = kTaggedBase;
97 access->offset = -1; 84 access->offset = -1;
98 access->name = name; 85 access->name = name;
99 access->type = Type::Any(); 86 access->type = Type::Any();
100 access->machine_type = kMachAnyTagged; 87 access->machine_type = kMachAnyTagged;
101 88
102 // Check for properties that have accessors but are JSObject fields. 89 // Check for properties that have accessors but are JSObject fields.
103 if (Accessors::IsJSObjectFieldAccessor(map, name, &access->offset)) { 90 if (Accessors::IsJSObjectFieldAccessor(map, name, &access->offset)) {
(...skipping 11 matching lines...) Expand all
115 PropertyDetails property_details = descriptors->GetDetails(number); 102 PropertyDetails property_details = descriptors->GetDetails(number);
116 103
117 bool is_smi = property_details.representation().IsSmi(); 104 bool is_smi = property_details.representation().IsSmi();
118 bool is_double = property_details.representation().IsDouble(); 105 bool is_double = property_details.representation().IsDouble();
119 106
120 if (property_details.type() != DATA) { 107 if (property_details.type() != DATA) {
121 // TODO(turbofan): constant loads and stores. 108 // TODO(turbofan): constant loads and stores.
122 return false; 109 return false;
123 } 110 }
124 111
125 // Transfer known types from property details.
126 AddFieldAccessTypes(access, property_details);
127
128 if (mode == STORE) { 112 if (mode == STORE) {
129 if (property_details.IsReadOnly()) { 113 if (property_details.IsReadOnly()) return false;
130 // TODO(turbofan): deopt, ignore or throw on readonly stores. 114 if (is_smi) {
115 // TODO(turbofan): SMI stores.
131 return false; 116 return false;
132 } 117 }
133 if (is_smi || is_double) { 118 if (is_double) {
134 // TODO(turbofan): check type and deopt for SMI/double stores. 119 // TODO(turbofan): double stores.
135 return false; 120 return false;
136 } 121 }
122 } else {
123 // Check property details for loads.
124 if (is_smi) {
125 access->type = Type::SignedSmall();
126 access->machine_type = static_cast<MachineType>(kTypeInt32 | kRepTagged);
127 }
128 if (is_double) {
129 access->type = Type::Number();
130 access->machine_type = kMachFloat64;
131 }
137 } 132 }
138 133
139 int index = map->instance_descriptors()->GetFieldIndex(number); 134 int index = map->instance_descriptors()->GetFieldIndex(number);
140 FieldIndex field_index = FieldIndex::ForPropertyIndex(*map, index, is_double); 135 FieldIndex field_index = FieldIndex::ForPropertyIndex(*map, index, is_double);
141 136
142 if (field_index.is_inobject()) { 137 if (field_index.is_inobject()) {
143 access->offset = field_index.offset(); 138 access->offset = field_index.offset();
144 return true; 139 return true;
145 } 140 }
146 141
147 // TODO(turbofan): handle out of object properties. 142 // TODO(turbofan): handle out of object properties.
148 return false; 143 return false;
149 } 144 }
150 145
151 146
152 static bool IsGlobalObject(Node* node) {
153 return NodeProperties::IsTyped(node) &&
154 NodeProperties::GetBounds(node).upper->Is(Type::GlobalObject());
155 }
156
157
158 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) { 147 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) {
159 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed); 148 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed);
160 Node* receiver = node->InputAt(0);
161 if (IsGlobalObject(receiver)) {
162 return ReduceJSLoadNamedForGlobalVariable(node);
163 }
164
165 if (!FLAG_turbo_deoptimization) return NoChange();
166 // TODO(titzer): deopt locations are wrong for property accesses 149 // TODO(titzer): deopt locations are wrong for property accesses
167 if (!EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT) return NoChange(); 150 if (!EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT) return NoChange();
168 151
169 // TODO(turbofan): handle vector-based type feedback. 152 // TODO(turbofan): handle vector-based type feedback.
170 TypeFeedbackId id = js_type_feedback_->find(node); 153 TypeFeedbackId id = js_type_feedback_->find(node);
171 if (id.IsNone() || oracle()->LoadInlineCacheState(id) == UNINITIALIZED) { 154 if (id.IsNone() || oracle()->LoadInlineCacheState(id) == UNINITIALIZED) {
172 return NoChange(); 155 return NoChange();
173 } 156 }
174 157
175 const LoadNamedParameters& p = LoadNamedParametersOf(node->op()); 158 const LoadNamedParameters& p = LoadNamedParametersOf(node->op());
176 SmallMapList maps; 159 SmallMapList maps;
177 Handle<Name> name = p.name().handle(); 160 Handle<Name> name = p.name().handle();
161 Node* receiver = node->InputAt(0);
178 Node* effect = NodeProperties::GetEffectInput(node); 162 Node* effect = NodeProperties::GetEffectInput(node);
179 GatherReceiverTypes(receiver, effect, id, name, &maps); 163 GatherReceiverTypes(receiver, effect, id, name, &maps);
180 164
181 if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism 165 if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism
182 166
183 Handle<Map> map = maps.first(); 167 Handle<Map> map = maps.first();
184 FieldAccess field_access; 168 FieldAccess field_access;
185 if (!GetInObjectFieldAccess(LOAD, map, name, &field_access)) { 169 if (!GetInObjectFieldAccess(LOAD, map, name, &field_access)) {
186 return NoChange(); 170 return NoChange();
187 } 171 }
(...skipping 12 matching lines...) Expand all
200 // TODO(titzer): frame state should be from before the load. 184 // TODO(titzer): frame state should be from before the load.
201 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); 185 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
202 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state, effect, 186 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state, effect,
203 check_failed); 187 check_failed);
204 NodeProperties::MergeControlToEnd(graph(), common(), deopt); 188 NodeProperties::MergeControlToEnd(graph(), common(), deopt);
205 NodeProperties::ReplaceWithValue(node, load, load, check_success); 189 NodeProperties::ReplaceWithValue(node, load, load, check_success);
206 return Replace(load); 190 return Replace(load);
207 } 191 }
208 192
209 193
210 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamedForGlobalVariable(
211 Node* node) {
212 Handle<String> name =
213 Handle<String>::cast(LoadNamedParametersOf(node->op()).name().handle());
214 // Try to optimize loads from the global object.
215 Handle<Object> constant_value =
216 jsgraph()->isolate()->factory()->GlobalConstantFor(name);
217 if (!constant_value.is_null()) {
218 // Always optimize global constants.
219 Node* constant = jsgraph()->Constant(constant_value);
220 NodeProperties::ReplaceWithValue(node, constant);
221 return Replace(constant);
222 }
223
224 if (global_object_.is_null()) {
225 // Nothing else can be done if we don't have a global object.
226 return NoChange();
227 }
228
229 if (FLAG_turbo_deoptimization) {
230 // Handle lookups in the script context.
231 {
232 Handle<ScriptContextTable> script_contexts(
233 global_object_->native_context()->script_context_table());
234 ScriptContextTable::LookupResult lookup;
235 if (ScriptContextTable::Lookup(script_contexts, name, &lookup)) {
236 // TODO(turbofan): introduce a LoadContext here.
237 return NoChange();
238 }
239 }
240
241 // Constant promotion or cell access requires lazy deoptimization support.
242 LookupIterator it(global_object_, name, LookupIterator::OWN);
243
244 if (it.state() == LookupIterator::DATA) {
245 Handle<PropertyCell> cell = it.GetPropertyCell();
246 dependencies_->AssumePropertyCell(cell);
247
248 if (it.property_details().cell_type() == PropertyCellType::kConstant) {
249 // Constant promote the global's current value.
250 Handle<Object> constant_value(cell->value(), jsgraph()->isolate());
251 if (constant_value->IsConsString()) {
252 constant_value =
253 String::Flatten(Handle<String>::cast(constant_value));
254 }
255 Node* constant = jsgraph()->Constant(constant_value);
256 NodeProperties::ReplaceWithValue(node, constant);
257 return Replace(constant);
258 } else {
259 // Load directly from the property cell.
260 FieldAccess access = AccessBuilder::ForPropertyCellValue();
261 Node* control = NodeProperties::GetControlInput(node);
262 Node* load_field = graph()->NewNode(
263 simplified()->LoadField(access), jsgraph()->Constant(cell),
264 NodeProperties::GetEffectInput(node), control);
265 NodeProperties::ReplaceWithValue(node, load_field, load_field, control);
266 return Replace(load_field);
267 }
268 }
269 } else {
270 // TODO(turbofan): non-configurable properties on the global object
271 // should be loadable through a cell without deoptimization support.
272 }
273
274 return NoChange();
275 }
276
277
278 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadProperty(Node* node) { 194 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadProperty(Node* node) {
279 return NoChange(); 195 return NoChange();
280 } 196 }
281 197
282 198
283 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreNamed(Node* node) { 199 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreNamed(Node* node) {
284 DCHECK(node->opcode() == IrOpcode::kJSStoreNamed); 200 DCHECK(node->opcode() == IrOpcode::kJSStoreNamed);
285 // TODO(titzer): deopt locations are wrong for property accesses 201 // TODO(titzer): deopt locations are wrong for property accesses
286 if (!EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT) return NoChange(); 202 if (!EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT) return NoChange();
287 203
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 // TODO(turbofan): filter maps by initial receiver map if known 284 // TODO(turbofan): filter maps by initial receiver map if known
369 // TODO(turbofan): filter maps by native context (if specializing) 285 // TODO(turbofan): filter maps by native context (if specializing)
370 // TODO(turbofan): filter maps by effect chain 286 // TODO(turbofan): filter maps by effect chain
371 oracle()->PropertyReceiverTypes(id, name, maps); 287 oracle()->PropertyReceiverTypes(id, name, maps);
372 } 288 }
373 289
374 290
375 } // namespace compiler 291 } // namespace compiler
376 } // namespace internal 292 } // namespace internal
377 } // namespace v8 293 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-type-feedback.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698