| OLD | NEW |
| 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" |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 } | 189 } |
| 190 if (p.load_ic() == NAMED) { | 190 if (p.load_ic() == NAMED) { |
| 191 oracle()->PropertyReceiverTypes(slot, name, &maps); | 191 oracle()->PropertyReceiverTypes(slot, name, &maps); |
| 192 } else { | 192 } else { |
| 193 // The load named was originally a load property. | 193 // The load named was originally a load property. |
| 194 bool is_string; // Unused. | 194 bool is_string; // Unused. |
| 195 IcCheckType key_type; // Unused. | 195 IcCheckType key_type; // Unused. |
| 196 oracle()->KeyedPropertyReceiverTypes(slot, &maps, &is_string, &key_type); | 196 oracle()->KeyedPropertyReceiverTypes(slot, &maps, &is_string, &key_type); |
| 197 } | 197 } |
| 198 | 198 |
| 199 Node* effect = NodeProperties::GetEffectInput(node); | |
| 200 | |
| 201 if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism | 199 if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism |
| 202 if (!ENABLE_FAST_PROPERTY_LOADS) return NoChange(); | 200 if (!ENABLE_FAST_PROPERTY_LOADS) return NoChange(); |
| 203 | 201 |
| 204 Handle<Map> map = maps.first(); | 202 Handle<Map> map = maps.first(); |
| 205 FieldAccess field_access; | 203 FieldAccess field_access; |
| 206 if (!GetInObjectFieldAccess(LOAD, map, name, &field_access)) { | 204 if (!GetInObjectFieldAccess(LOAD, map, name, &field_access)) { |
| 207 return NoChange(); | 205 return NoChange(); |
| 208 } | 206 } |
| 209 | 207 |
| 208 Node* effect = NodeProperties::GetEffectInput(node); |
| 210 Node* control = NodeProperties::GetControlInput(node); | 209 Node* control = NodeProperties::GetControlInput(node); |
| 211 Node* check_success; | 210 Node* map_const = jsgraph()->Constant(map); |
| 212 Node* check_failed; | 211 Node* map_check = |
| 213 BuildMapCheck(receiver, map, true, effect, control, &check_success, | 212 graph()->NewNode(simplified()->CheckMaps(1), receiver, map_const, |
| 214 &check_failed); | 213 frame_state_before, effect, control); |
| 215 | |
| 216 // Build the actual load. | 214 // Build the actual load. |
| 217 Node* load = graph()->NewNode(simplified()->LoadField(field_access), receiver, | 215 Node* load = graph()->NewNode(simplified()->LoadField(field_access), receiver, |
| 218 effect, check_success); | 216 effect, map_check); |
| 219 | 217 |
| 220 // TODO(turbofan): handle slow case instead of deoptimizing. | 218 ReplaceWithValue(node, load, load, map_check); |
| 221 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state_before, | |
| 222 effect, check_failed); | |
| 223 NodeProperties::MergeControlToEnd(graph(), common(), deopt); | |
| 224 ReplaceWithValue(node, load, load, check_success); | |
| 225 return Replace(load); | 219 return Replace(load); |
| 226 } | 220 } |
| 227 | 221 |
| 228 | 222 |
| 229 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamedForGlobalVariable( | 223 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamedForGlobalVariable( |
| 230 Node* node) { | 224 Node* node) { |
| 231 Handle<String> name = | 225 Handle<String> name = |
| 232 Handle<String>::cast(LoadNamedParametersOf(node->op()).name().handle()); | 226 Handle<String>::cast(LoadNamedParametersOf(node->op()).name().handle()); |
| 233 // Try to optimize loads from the global object. | 227 // Try to optimize loads from the global object. |
| 234 Handle<Object> constant_value = | 228 Handle<Object> constant_value = |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 if (p.store_ic() == NAMED) { | 310 if (p.store_ic() == NAMED) { |
| 317 oracle()->PropertyReceiverTypes(id, name, &maps); | 311 oracle()->PropertyReceiverTypes(id, name, &maps); |
| 318 } else { | 312 } else { |
| 319 // The named store was originally a store property. | 313 // The named store was originally a store property. |
| 320 bool is_string; // Unused. | 314 bool is_string; // Unused. |
| 321 IcCheckType key_type; // Unused. | 315 IcCheckType key_type; // Unused. |
| 322 oracle()->KeyedPropertyReceiverTypes(id, &maps, &is_string, &key_type); | 316 oracle()->KeyedPropertyReceiverTypes(id, &maps, &is_string, &key_type); |
| 323 } | 317 } |
| 324 } | 318 } |
| 325 | 319 |
| 326 Node* receiver = node->InputAt(0); | |
| 327 Node* effect = NodeProperties::GetEffectInput(node); | |
| 328 | |
| 329 if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism | 320 if (maps.length() != 1) return NoChange(); // TODO(turbofan): polymorphism |
| 330 | 321 |
| 331 if (!ENABLE_FAST_PROPERTY_STORES) return NoChange(); | 322 if (!ENABLE_FAST_PROPERTY_STORES) return NoChange(); |
| 332 | 323 |
| 333 Handle<Map> map = maps.first(); | 324 Handle<Map> map = maps.first(); |
| 334 FieldAccess field_access; | 325 FieldAccess field_access; |
| 335 if (!GetInObjectFieldAccess(STORE, map, name, &field_access)) { | 326 if (!GetInObjectFieldAccess(STORE, map, name, &field_access)) { |
| 336 return NoChange(); | 327 return NoChange(); |
| 337 } | 328 } |
| 338 | 329 |
| 330 Node* receiver = node->InputAt(0); |
| 331 Node* effect = NodeProperties::GetEffectInput(node); |
| 339 Node* control = NodeProperties::GetControlInput(node); | 332 Node* control = NodeProperties::GetControlInput(node); |
| 340 Node* check_success; | 333 Node* map_const = jsgraph()->Constant(map); |
| 341 Node* check_failed; | 334 Node* map_check = |
| 342 BuildMapCheck(receiver, map, true, effect, control, &check_success, | 335 graph()->NewNode(simplified()->CheckMaps(1), receiver, map_const, |
| 343 &check_failed); | 336 frame_state_before, effect, control); |
| 344 | 337 // Build the actual store. |
| 345 // Build the actual load. | |
| 346 Node* value = node->InputAt(1); | 338 Node* value = node->InputAt(1); |
| 347 Node* store = graph()->NewNode(simplified()->StoreField(field_access), | 339 Node* store = graph()->NewNode(simplified()->StoreField(field_access), |
| 348 receiver, value, effect, check_success); | 340 receiver, value, effect, map_check); |
| 349 | 341 ReplaceWithValue(node, store, store, map_check); |
| 350 // TODO(turbofan): handle slow case instead of deoptimizing. | |
| 351 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state_before, | |
| 352 effect, check_failed); | |
| 353 NodeProperties::MergeControlToEnd(graph(), common(), deopt); | |
| 354 ReplaceWithValue(node, store, store, check_success); | |
| 355 return Replace(store); | 342 return Replace(store); |
| 356 } | 343 } |
| 357 | 344 |
| 358 | 345 |
| 359 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreProperty(Node* node) { | 346 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreProperty(Node* node) { |
| 360 return NoChange(); | 347 return NoChange(); |
| 361 } | 348 } |
| 362 | 349 |
| 363 | 350 |
| 364 void JSTypeFeedbackSpecializer::BuildMapCheck(Node* receiver, Handle<Map> map, | |
| 365 bool smi_check, Node* effect, | |
| 366 Node* control, Node** success, | |
| 367 Node** fail) { | |
| 368 Node* if_smi = nullptr; | |
| 369 if (smi_check) { | |
| 370 Node* branch_smi = graph()->NewNode( | |
| 371 common()->Branch(BranchHint::kFalse), | |
| 372 graph()->NewNode(simplified()->ObjectIsSmi(), receiver), control); | |
| 373 if_smi = graph()->NewNode(common()->IfTrue(), branch_smi); | |
| 374 control = graph()->NewNode(common()->IfFalse(), branch_smi); | |
| 375 } | |
| 376 | |
| 377 FieldAccess map_access = AccessBuilder::ForMap(); | |
| 378 Node* receiver_map = graph()->NewNode(simplified()->LoadField(map_access), | |
| 379 receiver, effect, control); | |
| 380 Node* map_const = jsgraph_->Constant(map); | |
| 381 Node* cmp = graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), | |
| 382 receiver_map, map_const); | |
| 383 Node* branch = | |
| 384 graph()->NewNode(common()->Branch(BranchHint::kTrue), cmp, control); | |
| 385 *success = graph()->NewNode(common()->IfTrue(), branch); | |
| 386 *fail = graph()->NewNode(common()->IfFalse(), branch); | |
| 387 | |
| 388 if (if_smi) { | |
| 389 *fail = graph()->NewNode(common()->Merge(2), *fail, if_smi); | |
| 390 } | |
| 391 } | |
| 392 | |
| 393 | |
| 394 // Get the frame state before an operation if it exists and has a valid | 351 // Get the frame state before an operation if it exists and has a valid |
| 395 // bailout id. | 352 // bailout id. |
| 396 Node* JSTypeFeedbackSpecializer::GetFrameStateBefore(Node* node) { | 353 Node* JSTypeFeedbackSpecializer::GetFrameStateBefore(Node* node) { |
| 397 int count = OperatorProperties::GetFrameStateInputCount(node->op()); | 354 int count = OperatorProperties::GetFrameStateInputCount(node->op()); |
| 398 DCHECK_LE(count, 2); | 355 DCHECK_LE(count, 2); |
| 399 if (count == 2) { | 356 if (count == 2) { |
| 400 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 357 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 401 if (frame_state->opcode() == IrOpcode::kFrameState) { | 358 if (frame_state->opcode() == IrOpcode::kFrameState) { |
| 402 BailoutId id = OpParameter<FrameStateCallInfo>(node).bailout_id(); | 359 BailoutId id = OpParameter<FrameStateCallInfo>(node).bailout_id(); |
| 403 if (id != BailoutId::None()) return frame_state; | 360 if (id != BailoutId::None()) return frame_state; |
| 404 } | 361 } |
| 405 } | 362 } |
| 406 return nullptr; | 363 return nullptr; |
| 407 } | 364 } |
| 408 | 365 |
| 409 } // namespace compiler | 366 } // namespace compiler |
| 410 } // namespace internal | 367 } // namespace internal |
| 411 } // namespace v8 | 368 } // namespace v8 |
| OLD | NEW |