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

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

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

Powered by Google App Engine
This is Rietveld 408576698