Chromium Code Reviews| 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-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 48 template <typename T> | 48 template <typename T> |
| 49 bool HasOnlyStringMaps(T const& maps) { | 49 bool HasOnlyStringMaps(T const& maps) { |
| 50 for (auto map : maps) { | 50 for (auto map : maps) { |
| 51 if (!map->IsStringMap()) return false; | 51 if (!map->IsStringMap()) return false; |
| 52 } | 52 } |
| 53 return true; | 53 return true; |
| 54 } | 54 } |
| 55 | 55 |
| 56 } // namespace | 56 } // namespace |
| 57 | 57 |
| 58 struct JSNativeContextSpecialization::ScriptContextTableLookupResult { | |
| 59 Handle<Context> context; | |
| 60 bool immutable; | |
| 61 int index; | |
| 62 }; | |
| 63 | |
| 58 JSNativeContextSpecialization::JSNativeContextSpecialization( | 64 JSNativeContextSpecialization::JSNativeContextSpecialization( |
| 59 Editor* editor, JSGraph* jsgraph, Flags flags, | 65 Editor* editor, JSGraph* jsgraph, Flags flags, |
| 60 Handle<Context> native_context, CompilationDependencies* dependencies, | 66 Handle<Context> native_context, CompilationDependencies* dependencies, |
| 61 Zone* zone) | 67 Zone* zone) |
| 62 : AdvancedReducer(editor), | 68 : AdvancedReducer(editor), |
| 63 jsgraph_(jsgraph), | 69 jsgraph_(jsgraph), |
| 64 flags_(flags), | 70 flags_(flags), |
| 71 global_object_(native_context->global_object()), | |
| 72 global_proxy_(JSGlobalProxy::cast(native_context->global_proxy())), | |
| 65 native_context_(native_context), | 73 native_context_(native_context), |
| 66 dependencies_(dependencies), | 74 dependencies_(dependencies), |
| 67 zone_(zone), | 75 zone_(zone), |
| 68 type_cache_(TypeCache::Get()) {} | 76 type_cache_(TypeCache::Get()) {} |
| 69 | 77 |
| 70 Reduction JSNativeContextSpecialization::Reduce(Node* node) { | 78 Reduction JSNativeContextSpecialization::Reduce(Node* node) { |
| 71 switch (node->opcode()) { | 79 switch (node->opcode()) { |
| 72 case IrOpcode::kJSGetSuperConstructor: | 80 case IrOpcode::kJSGetSuperConstructor: |
| 73 return ReduceJSGetSuperConstructor(node); | 81 return ReduceJSGetSuperConstructor(node); |
| 74 case IrOpcode::kJSInstanceOf: | 82 case IrOpcode::kJSInstanceOf: |
| 75 return ReduceJSInstanceOf(node); | 83 return ReduceJSInstanceOf(node); |
| 76 case IrOpcode::kJSOrdinaryHasInstance: | 84 case IrOpcode::kJSOrdinaryHasInstance: |
| 77 return ReduceJSOrdinaryHasInstance(node); | 85 return ReduceJSOrdinaryHasInstance(node); |
| 78 case IrOpcode::kJSLoadContext: | 86 case IrOpcode::kJSLoadContext: |
| 79 return ReduceJSLoadContext(node); | 87 return ReduceJSLoadContext(node); |
| 88 case IrOpcode::kJSLoadGlobal: | |
| 89 return ReduceJSLoadGlobal(node); | |
| 90 case IrOpcode::kJSStoreGlobal: | |
| 91 return ReduceJSStoreGlobal(node); | |
| 80 case IrOpcode::kJSLoadNamed: | 92 case IrOpcode::kJSLoadNamed: |
| 81 return ReduceJSLoadNamed(node); | 93 return ReduceJSLoadNamed(node); |
| 82 case IrOpcode::kJSStoreNamed: | 94 case IrOpcode::kJSStoreNamed: |
| 83 return ReduceJSStoreNamed(node); | 95 return ReduceJSStoreNamed(node); |
| 84 case IrOpcode::kJSLoadProperty: | 96 case IrOpcode::kJSLoadProperty: |
| 85 return ReduceJSLoadProperty(node); | 97 return ReduceJSLoadProperty(node); |
| 86 case IrOpcode::kJSStoreProperty: | 98 case IrOpcode::kJSStoreProperty: |
| 87 return ReduceJSStoreProperty(node); | 99 return ReduceJSStoreProperty(node); |
| 88 case IrOpcode::kJSStoreDataPropertyInLiteral: | 100 case IrOpcode::kJSStoreDataPropertyInLiteral: |
| 89 return ReduceJSStoreDataPropertyInLiteral(node); | 101 return ReduceJSStoreDataPropertyInLiteral(node); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 // context (if any), so we can constant-fold those fields, which is | 260 // context (if any), so we can constant-fold those fields, which is |
| 249 // safe, since the NATIVE_CONTEXT_INDEX slot is always immutable. | 261 // safe, since the NATIVE_CONTEXT_INDEX slot is always immutable. |
| 250 if (access.index() == Context::NATIVE_CONTEXT_INDEX) { | 262 if (access.index() == Context::NATIVE_CONTEXT_INDEX) { |
| 251 Node* value = jsgraph()->HeapConstant(native_context()); | 263 Node* value = jsgraph()->HeapConstant(native_context()); |
| 252 ReplaceWithValue(node, value); | 264 ReplaceWithValue(node, value); |
| 253 return Replace(value); | 265 return Replace(value); |
| 254 } | 266 } |
| 255 return NoChange(); | 267 return NoChange(); |
| 256 } | 268 } |
| 257 | 269 |
| 270 namespace { | |
| 271 | |
| 272 FieldAccess ForPropertyCellValue(MachineRepresentation representation, | |
| 273 Type* type, MaybeHandle<Map> map, | |
| 274 Handle<Name> name) { | |
| 275 WriteBarrierKind kind = kFullWriteBarrier; | |
| 276 if (representation == MachineRepresentation::kTaggedSigned) { | |
| 277 kind = kNoWriteBarrier; | |
| 278 } else if (representation == MachineRepresentation::kTaggedPointer) { | |
| 279 kind = kPointerWriteBarrier; | |
| 280 } | |
| 281 MachineType r = MachineType::TypeForRepresentation(representation); | |
| 282 FieldAccess access = { | |
| 283 kTaggedBase, PropertyCell::kValueOffset, name, map, type, r, kind}; | |
| 284 return access; | |
| 285 } | |
| 286 | |
| 287 } // namespace | |
| 288 | |
| 289 Reduction JSNativeContextSpecialization::ReduceGlobalAccess( | |
| 290 Node* node, Node* receiver, Node* value, Handle<Name> name, | |
| 291 AccessMode access_mode) { | |
| 292 Node* effect = NodeProperties::GetEffectInput(node); | |
| 293 Node* control = NodeProperties::GetControlInput(node); | |
| 294 | |
| 295 // Lookup on the global object. We only deal with own data properties | |
| 296 // of the global object here (represented as PropertyCell). | |
| 297 LookupIterator it(global_object(), name, LookupIterator::OWN); | |
| 298 it.TryLookupCachedProperty(); | |
| 299 if (it.state() != LookupIterator::DATA) return NoChange(); | |
| 300 if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange(); | |
| 301 Handle<PropertyCell> property_cell = it.GetPropertyCell(); | |
| 302 PropertyDetails property_details = property_cell->property_details(); | |
| 303 Handle<Object> property_cell_value(property_cell->value(), isolate()); | |
| 304 PropertyCellType property_cell_type = property_details.cell_type(); | |
| 305 | |
| 306 // We have additional constraints for stores. | |
| 307 if (access_mode == AccessMode::kStore) { | |
| 308 if (property_details.IsReadOnly()) { | |
| 309 // Don't even bother trying to lower stores to read-only data properties. | |
| 310 return NoChange(); | |
| 311 } else if (property_cell_type == PropertyCellType::kUndefined) { | |
| 312 // There's no fast-path for dealing with undefined property cells. | |
| 313 return NoChange(); | |
| 314 } else if (property_cell_type == PropertyCellType::kConstantType) { | |
| 315 // There's also no fast-path to store to a global cell which pretended | |
| 316 // to be stable, but is no longer stable now. | |
| 317 if (property_cell_value->IsHeapObject() && | |
| 318 !Handle<HeapObject>::cast(property_cell_value)->map()->is_stable()) { | |
| 319 return NoChange(); | |
| 320 } | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 // Check if we have a {receiver} to validate. If so, we need to check that | |
| 325 // the {receiver} is actually the JSGlobalProxy for the native context that | |
| 326 // we are specializing to. | |
| 327 if (receiver != nullptr) { | |
| 328 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), receiver, | |
| 329 jsgraph()->HeapConstant(global_proxy())); | |
| 330 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); | |
| 331 } | |
| 332 | |
| 333 if (access_mode == AccessMode::kLoad) { | |
| 334 // Load from non-configurable, read-only data property on the global | |
| 335 // object can be constant-folded, even without deoptimization support. | |
| 336 if (!property_details.IsConfigurable() && property_details.IsReadOnly()) { | |
| 337 value = jsgraph()->Constant(property_cell_value); | |
| 338 } else { | |
| 339 // Record a code dependency on the cell if we can benefit from the | |
| 340 // additional feedback, or the global property is configurable (i.e. | |
| 341 // can be deleted or reconfigured to an accessor property). | |
| 342 if (property_details.cell_type() != PropertyCellType::kMutable || | |
| 343 property_details.IsConfigurable()) { | |
| 344 dependencies()->AssumePropertyCell(property_cell); | |
| 345 } | |
| 346 | |
| 347 // Load from constant/undefined global property can be constant-folded. | |
| 348 if (property_details.cell_type() == PropertyCellType::kConstant || | |
| 349 property_details.cell_type() == PropertyCellType::kUndefined) { | |
| 350 value = jsgraph()->Constant(property_cell_value); | |
| 351 } else { | |
| 352 // Load from constant type cell can benefit from type feedback. | |
| 353 MaybeHandle<Map> map; | |
| 354 Type* property_cell_value_type = Type::NonInternal(); | |
| 355 MachineRepresentation representation = MachineRepresentation::kTagged; | |
| 356 if (property_details.cell_type() == PropertyCellType::kConstantType) { | |
| 357 // Compute proper type based on the current value in the cell. | |
| 358 if (property_cell_value->IsSmi()) { | |
| 359 property_cell_value_type = Type::SignedSmall(); | |
| 360 representation = MachineRepresentation::kTaggedSigned; | |
| 361 } else if (property_cell_value->IsNumber()) { | |
| 362 property_cell_value_type = Type::Number(); | |
| 363 representation = MachineRepresentation::kTaggedPointer; | |
| 364 } else { | |
| 365 Handle<Map> property_cell_value_map( | |
| 366 Handle<HeapObject>::cast(property_cell_value)->map(), | |
| 367 isolate()); | |
| 368 property_cell_value_type = Type::For(property_cell_value_map); | |
| 369 representation = MachineRepresentation::kTaggedPointer; | |
| 370 | |
| 371 // We can only use the property cell value map for map check | |
| 372 // elimination if it's stable, i.e. the HeapObject wasn't | |
| 373 // mutated without the cell state being updated. | |
| 374 if (property_cell_value_map->is_stable()) { | |
| 375 dependencies()->AssumeMapStable(property_cell_value_map); | |
| 376 map = property_cell_value_map; | |
| 377 } | |
| 378 } | |
| 379 } | |
| 380 value = effect = graph()->NewNode( | |
| 381 simplified()->LoadField(ForPropertyCellValue( | |
| 382 representation, property_cell_value_type, map, name)), | |
| 383 jsgraph()->HeapConstant(property_cell), effect, control); | |
| 384 } | |
| 385 } | |
| 386 } else { | |
| 387 DCHECK_EQ(AccessMode::kStore, access_mode); | |
| 388 DCHECK(!property_details.IsReadOnly()); | |
| 389 switch (property_details.cell_type()) { | |
| 390 case PropertyCellType::kUndefined: { | |
| 391 UNREACHABLE(); | |
| 392 break; | |
| 393 } | |
| 394 case PropertyCellType::kConstant: { | |
| 395 // Record a code dependency on the cell, and just deoptimize if the new | |
| 396 // value doesn't match the previous value stored inside the cell. | |
| 397 dependencies()->AssumePropertyCell(property_cell); | |
| 398 Node* check = | |
| 399 graph()->NewNode(simplified()->ReferenceEqual(), value, | |
| 400 jsgraph()->Constant(property_cell_value)); | |
| 401 effect = | |
| 402 graph()->NewNode(simplified()->CheckIf(), check, effect, control); | |
| 403 break; | |
| 404 } | |
| 405 case PropertyCellType::kConstantType: { | |
| 406 // Record a code dependency on the cell, and just deoptimize if the new | |
| 407 // values' type doesn't match the type of the previous value in the | |
| 408 // cell. | |
| 409 dependencies()->AssumePropertyCell(property_cell); | |
| 410 Type* property_cell_value_type; | |
| 411 MachineRepresentation representation = MachineRepresentation::kTagged; | |
| 412 if (property_cell_value->IsHeapObject()) { | |
| 413 // We cannot do anything if the {property_cell_value}s map is no | |
| 414 // longer stable. | |
| 415 Handle<Map> property_cell_value_map( | |
| 416 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); | |
| 417 DCHECK(!property_cell_value_map->is_stable()); | |
| 418 dependencies()->AssumeMapStable(property_cell_value_map); | |
| 419 | |
| 420 // Check that the {value} is a HeapObject. | |
| 421 value = effect = graph()->NewNode(simplified()->CheckHeapObject(), | |
| 422 value, effect, control); | |
| 423 | |
| 424 // Check {value} map agains the {property_cell} map. | |
| 425 effect = | |
| 426 graph()->NewNode(simplified()->CheckMaps( | |
| 427 CheckMapsFlag::kNone, | |
| 428 ZoneHandleSet<Map>(property_cell_value_map)), | |
| 429 value, effect, control); | |
| 430 property_cell_value_type = Type::OtherInternal(); | |
| 431 representation = MachineRepresentation::kTaggedPointer; | |
| 432 } else { | |
| 433 // Check that the {value} is a Smi. | |
| 434 value = effect = graph()->NewNode(simplified()->CheckSmi(), value, | |
| 435 effect, control); | |
| 436 property_cell_value_type = Type::SignedSmall(); | |
| 437 representation = MachineRepresentation::kTaggedSigned; | |
| 438 } | |
| 439 effect = graph()->NewNode(simplified()->StoreField(ForPropertyCellValue( | |
| 440 representation, property_cell_value_type, | |
| 441 MaybeHandle<Map>(), name)), | |
| 442 jsgraph()->HeapConstant(property_cell), value, | |
| 443 effect, control); | |
| 444 break; | |
| 445 } | |
| 446 case PropertyCellType::kMutable: { | |
| 447 // Record a code dependency on the cell, and just deoptimize if the | |
| 448 // property ever becomes read-only. | |
| 449 dependencies()->AssumePropertyCell(property_cell); | |
| 450 effect = graph()->NewNode( | |
| 451 simplified()->StoreField(ForPropertyCellValue( | |
| 452 MachineRepresentation::kTagged, Type::NonInternal(), | |
| 453 MaybeHandle<Map>(), name)), | |
| 454 jsgraph()->HeapConstant(property_cell), value, effect, control); | |
| 455 break; | |
| 456 } | |
| 457 } | |
| 458 } | |
| 459 | |
| 460 ReplaceWithValue(node, value, effect, control); | |
| 461 return Replace(value); | |
| 462 } | |
| 463 | |
| 464 Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) { | |
| 465 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); | |
| 466 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); | |
| 467 Node* effect = NodeProperties::GetEffectInput(node); | |
| 468 Node* control = NodeProperties::GetControlInput(node); | |
| 469 | |
| 470 // Try to lookup the name on the script context table first (lexical scoping). | |
| 471 ScriptContextTableLookupResult result; | |
| 472 if (LookupInScriptContextTable(name, &result)) { | |
| 473 if (result.context->is_the_hole(isolate(), result.index)) return NoChange(); | |
| 474 Node* context = jsgraph()->HeapConstant(result.context); | |
| 475 Node* value = effect = graph()->NewNode( | |
| 476 javascript()->LoadContext(0, result.index, result.immutable), context, | |
| 477 effect); | |
| 478 ReplaceWithValue(node, value, effect); | |
| 479 return Replace(value); | |
| 480 } | |
| 481 | |
| 482 // Not much we can do if deoptimization support is disabled. | |
| 483 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
| 484 | |
| 485 // Lookup the {name} on the global object instead. | |
| 486 return ReduceGlobalAccess(node, nullptr, nullptr, name, AccessMode::kLoad); | |
| 487 } | |
| 488 | |
| 489 Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) { | |
| 490 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); | |
| 491 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); | |
| 492 Node* value = NodeProperties::GetValueInput(node, 0); | |
| 493 Node* effect = NodeProperties::GetEffectInput(node); | |
| 494 Node* control = NodeProperties::GetControlInput(node); | |
| 495 | |
| 496 // Try to lookup the name on the script context table first (lexical scoping). | |
| 497 ScriptContextTableLookupResult result; | |
| 498 if (LookupInScriptContextTable(name, &result)) { | |
| 499 if (result.context->is_the_hole(isolate(), result.index)) return NoChange(); | |
| 500 if (result.immutable) return NoChange(); | |
| 501 Node* context = jsgraph()->HeapConstant(result.context); | |
| 502 effect = graph()->NewNode(javascript()->StoreContext(0, result.index), | |
| 503 value, context, effect, control); | |
| 504 ReplaceWithValue(node, value, effect, control); | |
| 505 return Replace(value); | |
| 506 } | |
| 507 | |
| 508 // Not much we can do if deoptimization support is disabled. | |
| 509 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
| 510 | |
| 511 // Lookup the {name} on the global object instead. | |
| 512 return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore); | |
| 513 } | |
| 514 | |
| 258 Reduction JSNativeContextSpecialization::ReduceNamedAccess( | 515 Reduction JSNativeContextSpecialization::ReduceNamedAccess( |
| 259 Node* node, Node* value, MapHandleList const& receiver_maps, | 516 Node* node, Node* value, MapHandleList const& receiver_maps, |
| 260 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, | 517 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, |
| 261 Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot, Node* index) { | 518 Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot, Node* index) { |
| 262 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 519 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || |
| 263 node->opcode() == IrOpcode::kJSStoreNamed || | 520 node->opcode() == IrOpcode::kJSStoreNamed || |
| 264 node->opcode() == IrOpcode::kJSLoadProperty || | 521 node->opcode() == IrOpcode::kJSLoadProperty || |
| 265 node->opcode() == IrOpcode::kJSStoreProperty); | 522 node->opcode() == IrOpcode::kJSStoreProperty); |
| 266 Node* receiver = NodeProperties::GetValueInput(node, 0); | 523 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 267 Node* context = NodeProperties::GetContextInput(node); | 524 Node* context = NodeProperties::GetContextInput(node); |
| 268 Node* frame_state_eager = NodeProperties::FindFrameStateBefore(node); | 525 Node* frame_state_eager = NodeProperties::FindFrameStateBefore(node); |
| 269 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); | 526 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); |
| 270 Node* effect = NodeProperties::GetEffectInput(node); | 527 Node* effect = NodeProperties::GetEffectInput(node); |
| 271 Node* control = NodeProperties::GetControlInput(node); | 528 Node* control = NodeProperties::GetControlInput(node); |
| 272 | 529 |
| 273 // Not much we can do if deoptimization support is disabled. | 530 // Not much we can do if deoptimization support is disabled. |
| 274 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 531 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 275 | 532 |
| 533 // Check if we have an access o.x or o.x=v where o is the current | |
| 534 // native contexts' global proxy, and turn that into a direct access | |
| 535 // to the current native contexts' global object instead. | |
| 536 if (receiver_maps.length() == 1) { | |
|
Benedikt Meurer
2017/01/30 18:11:18
This is part one of the new stuff.
| |
| 537 Handle<Map> receiver_map = receiver_maps.first(); | |
| 538 if (receiver_map->IsJSGlobalProxyMap()) { | |
| 539 Handle<JSFunction> receiver_constructor = | |
| 540 handle(JSFunction::cast(receiver_map->GetConstructor()), isolate()); | |
| 541 if (receiver_constructor->native_context() == *native_context()) { | |
| 542 return ReduceGlobalAccess(node, receiver, value, name, access_mode); | |
| 543 } | |
| 544 } | |
| 545 } | |
| 546 | |
| 276 // Compute property access infos for the receiver maps. | 547 // Compute property access infos for the receiver maps. |
| 277 AccessInfoFactory access_info_factory(dependencies(), native_context(), | 548 AccessInfoFactory access_info_factory(dependencies(), native_context(), |
| 278 graph()->zone()); | 549 graph()->zone()); |
| 279 ZoneVector<PropertyAccessInfo> access_infos(zone()); | 550 ZoneVector<PropertyAccessInfo> access_infos(zone()); |
| 280 if (!access_info_factory.ComputePropertyAccessInfos( | 551 if (!access_info_factory.ComputePropertyAccessInfos( |
| 281 receiver_maps, name, access_mode, &access_infos)) { | 552 receiver_maps, name, access_mode, &access_infos)) { |
| 282 return NoChange(); | 553 return NoChange(); |
| 283 } | 554 } |
| 284 | 555 |
| 285 // TODO(turbofan): Add support for inlining into try blocks. | 556 // TODO(turbofan): Add support for inlining into try blocks. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 } | 751 } |
| 481 | 752 |
| 482 Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( | 753 Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( |
| 483 Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name, | 754 Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name, |
| 484 AccessMode access_mode, LanguageMode language_mode) { | 755 AccessMode access_mode, LanguageMode language_mode) { |
| 485 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 756 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || |
| 486 node->opcode() == IrOpcode::kJSStoreNamed); | 757 node->opcode() == IrOpcode::kJSStoreNamed); |
| 487 Node* const receiver = NodeProperties::GetValueInput(node, 0); | 758 Node* const receiver = NodeProperties::GetValueInput(node, 0); |
| 488 Node* const effect = NodeProperties::GetEffectInput(node); | 759 Node* const effect = NodeProperties::GetEffectInput(node); |
| 489 | 760 |
| 761 // Check if we are accessing the current native contexts' global proxy. | |
|
Benedikt Meurer
2017/01/30 18:11:18
And this is part two of the new stuff.
| |
| 762 HeapObjectMatcher m(receiver); | |
| 763 if (m.HasValue() && m.Value().is_identical_to(global_proxy())) { | |
| 764 // Optimize accesses to the current native contexts' global proxy. | |
| 765 return ReduceGlobalAccess(node, nullptr, value, name, access_mode); | |
| 766 } | |
| 767 | |
| 490 // Check if the {nexus} reports type feedback for the IC. | 768 // Check if the {nexus} reports type feedback for the IC. |
| 491 if (nexus.IsUninitialized()) { | 769 if (nexus.IsUninitialized()) { |
| 492 if ((flags() & kDeoptimizationEnabled) && | 770 if ((flags() & kDeoptimizationEnabled) && |
| 493 (flags() & kBailoutOnUninitialized)) { | 771 (flags() & kBailoutOnUninitialized)) { |
| 494 return ReduceSoftDeoptimize( | 772 return ReduceSoftDeoptimize( |
| 495 node, | 773 node, |
| 496 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); | 774 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); |
| 497 } | 775 } |
| 498 return NoChange(); | 776 return NoChange(); |
| 499 } | 777 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 510 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); | 788 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); |
| 511 } | 789 } |
| 512 return NoChange(); | 790 return NoChange(); |
| 513 } | 791 } |
| 514 | 792 |
| 515 // Try to lower the named access based on the {receiver_maps}. | 793 // Try to lower the named access based on the {receiver_maps}. |
| 516 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, | 794 return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, |
| 517 language_mode, nexus.vector_handle(), nexus.slot()); | 795 language_mode, nexus.vector_handle(), nexus.slot()); |
| 518 } | 796 } |
| 519 | 797 |
| 520 | |
| 521 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { | 798 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { |
| 522 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); | 799 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); |
| 523 NamedAccess const& p = NamedAccessOf(node->op()); | 800 NamedAccess const& p = NamedAccessOf(node->op()); |
| 524 Node* const receiver = NodeProperties::GetValueInput(node, 0); | 801 Node* const receiver = NodeProperties::GetValueInput(node, 0); |
| 525 Node* const value = jsgraph()->Dead(); | 802 Node* const value = jsgraph()->Dead(); |
| 526 | 803 |
| 527 // Check if we have a constant receiver. | 804 // Check if we have a constant receiver. |
| 528 HeapObjectMatcher m(receiver); | 805 HeapObjectMatcher m(receiver); |
| 529 if (m.HasValue()) { | 806 if (m.HasValue()) { |
| 530 if (m.Value()->IsJSFunction() && | 807 if (m.Value()->IsJSFunction() && |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 561 | 838 |
| 562 // Try to lower the named access based on the {receiver_maps}. | 839 // Try to lower the named access based on the {receiver_maps}. |
| 563 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), | 840 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), |
| 564 AccessMode::kLoad, p.language_mode()); | 841 AccessMode::kLoad, p.language_mode()); |
| 565 } | 842 } |
| 566 | 843 |
| 567 | 844 |
| 568 Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) { | 845 Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) { |
| 569 DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode()); | 846 DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode()); |
| 570 NamedAccess const& p = NamedAccessOf(node->op()); | 847 NamedAccess const& p = NamedAccessOf(node->op()); |
| 848 Node* const receiver = NodeProperties::GetValueInput(node, 0); | |
| 571 Node* const value = NodeProperties::GetValueInput(node, 1); | 849 Node* const value = NodeProperties::GetValueInput(node, 1); |
| 572 | 850 |
| 573 // Extract receiver maps from the STORE_IC using the StoreICNexus. | 851 // Extract receiver maps from the STORE_IC using the StoreICNexus. |
| 574 if (!p.feedback().IsValid()) return NoChange(); | 852 if (!p.feedback().IsValid()) return NoChange(); |
| 575 StoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 853 StoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
| 576 | 854 |
| 577 // Try to lower the named access based on the {receiver_maps}. | 855 // Try to lower the named access based on the {receiver_maps}. |
| 578 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), | 856 return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), |
| 579 AccessMode::kStore, p.language_mode()); | 857 AccessMode::kStore, p.language_mode()); |
| 580 } | 858 } |
| (...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1935 if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) { | 2213 if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) { |
| 1936 DCHECK_EQ(*initial_map, initial_map->FindRootMap()); | 2214 DCHECK_EQ(*initial_map, initial_map->FindRootMap()); |
| 1937 return initial_map; | 2215 return initial_map; |
| 1938 } | 2216 } |
| 1939 } | 2217 } |
| 1940 } | 2218 } |
| 1941 } | 2219 } |
| 1942 return MaybeHandle<Map>(); | 2220 return MaybeHandle<Map>(); |
| 1943 } | 2221 } |
| 1944 | 2222 |
| 2223 bool JSNativeContextSpecialization::LookupInScriptContextTable( | |
| 2224 Handle<Name> name, ScriptContextTableLookupResult* result) { | |
| 2225 if (!name->IsString()) return false; | |
| 2226 Handle<ScriptContextTable> script_context_table( | |
| 2227 global_object()->native_context()->script_context_table(), isolate()); | |
| 2228 ScriptContextTable::LookupResult lookup_result; | |
| 2229 if (!ScriptContextTable::Lookup(script_context_table, | |
| 2230 Handle<String>::cast(name), &lookup_result)) { | |
| 2231 return false; | |
| 2232 } | |
| 2233 Handle<Context> script_context = ScriptContextTable::GetContext( | |
| 2234 script_context_table, lookup_result.context_index); | |
| 2235 result->context = script_context; | |
| 2236 result->immutable = lookup_result.mode == CONST; | |
| 2237 result->index = lookup_result.slot_index; | |
| 2238 return true; | |
| 2239 } | |
| 2240 | |
| 1945 Graph* JSNativeContextSpecialization::graph() const { | 2241 Graph* JSNativeContextSpecialization::graph() const { |
| 1946 return jsgraph()->graph(); | 2242 return jsgraph()->graph(); |
| 1947 } | 2243 } |
| 1948 | 2244 |
| 1949 Isolate* JSNativeContextSpecialization::isolate() const { | 2245 Isolate* JSNativeContextSpecialization::isolate() const { |
| 1950 return jsgraph()->isolate(); | 2246 return jsgraph()->isolate(); |
| 1951 } | 2247 } |
| 1952 | 2248 |
| 1953 Factory* JSNativeContextSpecialization::factory() const { | 2249 Factory* JSNativeContextSpecialization::factory() const { |
| 1954 return isolate()->factory(); | 2250 return isolate()->factory(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1966 return jsgraph()->javascript(); | 2262 return jsgraph()->javascript(); |
| 1967 } | 2263 } |
| 1968 | 2264 |
| 1969 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 2265 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 1970 return jsgraph()->simplified(); | 2266 return jsgraph()->simplified(); |
| 1971 } | 2267 } |
| 1972 | 2268 |
| 1973 } // namespace compiler | 2269 } // namespace compiler |
| 1974 } // namespace internal | 2270 } // namespace internal |
| 1975 } // namespace v8 | 2271 } // namespace v8 |
| OLD | NEW |