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

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

Issue 1416973014: [turbofan] Move PropertyAccessInfo and friends to a separate file. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add missing factory() method. Created 5 years, 1 month 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-native-context-specialization.h ('k') | src/compiler/property-access-info.h » ('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-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/compilation-dependencies.h" 8 #include "src/compilation-dependencies.h"
9 #include "src/compiler/access-builder.h" 9 #include "src/compiler/access-builder.h"
10 #include "src/compiler/js-graph.h" 10 #include "src/compiler/js-graph.h"
(...skipping 21 matching lines...) Expand all
32 Editor* editor, JSGraph* jsgraph, Flags flags, 32 Editor* editor, JSGraph* jsgraph, Flags flags,
33 Handle<GlobalObject> global_object, CompilationDependencies* dependencies, 33 Handle<GlobalObject> global_object, CompilationDependencies* dependencies,
34 Zone* zone) 34 Zone* zone)
35 : AdvancedReducer(editor), 35 : AdvancedReducer(editor),
36 jsgraph_(jsgraph), 36 jsgraph_(jsgraph),
37 flags_(flags), 37 flags_(flags),
38 global_object_(global_object), 38 global_object_(global_object),
39 native_context_(global_object->native_context(), isolate()), 39 native_context_(global_object->native_context(), isolate()),
40 dependencies_(dependencies), 40 dependencies_(dependencies),
41 zone_(zone), 41 zone_(zone),
42 type_cache_(TypeCache::Get()) {} 42 type_cache_(TypeCache::Get()),
43 access_info_factory_(dependencies, native_context(), graph()->zone()) {}
43 44
44 45
45 Reduction JSNativeContextSpecialization::Reduce(Node* node) { 46 Reduction JSNativeContextSpecialization::Reduce(Node* node) {
46 switch (node->opcode()) { 47 switch (node->opcode()) {
47 case IrOpcode::kJSCallFunction: 48 case IrOpcode::kJSCallFunction:
48 return ReduceJSCallFunction(node); 49 return ReduceJSCallFunction(node);
49 case IrOpcode::kJSLoadGlobal: 50 case IrOpcode::kJSLoadGlobal:
50 return ReduceJSLoadGlobal(node); 51 return ReduceJSLoadGlobal(node);
51 case IrOpcode::kJSStoreGlobal: 52 case IrOpcode::kJSStoreGlobal:
52 return ReduceJSStoreGlobal(node); 53 return ReduceJSStoreGlobal(node);
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 break; 292 break;
292 } 293 }
293 } 294 }
294 effect = graph()->NewNode( 295 effect = graph()->NewNode(
295 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), 296 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()),
296 jsgraph()->Constant(property_cell), value, effect, control); 297 jsgraph()->Constant(property_cell), value, effect, control);
297 return Replace(node, value, effect, control); 298 return Replace(node, value, effect, control);
298 } 299 }
299 300
300 301
301 // This class encapsulates all information required to access a certain
302 // object property, either on the object itself or on the prototype chain.
303 class JSNativeContextSpecialization::PropertyAccessInfo final {
304 public:
305 enum Kind { kInvalid, kDataConstant, kDataField, kTransitionToField };
306
307 static PropertyAccessInfo DataConstant(Type* receiver_type,
308 Handle<Object> constant,
309 MaybeHandle<JSObject> holder) {
310 return PropertyAccessInfo(holder, constant, receiver_type);
311 }
312 static PropertyAccessInfo DataField(
313 Type* receiver_type, FieldIndex field_index, Type* field_type,
314 MaybeHandle<JSObject> holder = MaybeHandle<JSObject>()) {
315 return PropertyAccessInfo(holder, field_index, field_type, receiver_type);
316 }
317 static PropertyAccessInfo TransitionToField(Type* receiver_type,
318 FieldIndex field_index,
319 Type* field_type,
320 Handle<Map> transition_map,
321 MaybeHandle<JSObject> holder) {
322 return PropertyAccessInfo(holder, transition_map, field_index, field_type,
323 receiver_type);
324 }
325
326 PropertyAccessInfo() : kind_(kInvalid) {}
327 PropertyAccessInfo(MaybeHandle<JSObject> holder, Handle<Object> constant,
328 Type* receiver_type)
329 : kind_(kDataConstant),
330 receiver_type_(receiver_type),
331 constant_(constant),
332 holder_(holder) {}
333 PropertyAccessInfo(MaybeHandle<JSObject> holder, FieldIndex field_index,
334 Type* field_type, Type* receiver_type)
335 : kind_(kDataField),
336 receiver_type_(receiver_type),
337 holder_(holder),
338 field_index_(field_index),
339 field_type_(field_type) {}
340 PropertyAccessInfo(MaybeHandle<JSObject> holder, Handle<Map> transition_map,
341 FieldIndex field_index, Type* field_type,
342 Type* receiver_type)
343 : kind_(kTransitionToField),
344 receiver_type_(receiver_type),
345 transition_map_(transition_map),
346 holder_(holder),
347 field_index_(field_index),
348 field_type_(field_type) {}
349
350 bool IsDataConstant() const { return kind() == kDataConstant; }
351 bool IsDataField() const { return kind() == kDataField; }
352 bool IsTransitionToField() const { return kind() == kTransitionToField; }
353
354 Kind kind() const { return kind_; }
355 MaybeHandle<JSObject> holder() const { return holder_; }
356 Handle<Object> constant() const { return constant_; }
357 Handle<Object> transition_map() const { return transition_map_; }
358 FieldIndex field_index() const { return field_index_; }
359 Type* field_type() const { return field_type_; }
360 Type* receiver_type() const { return receiver_type_; }
361
362 private:
363 Kind kind_;
364 Type* receiver_type_;
365 Handle<Object> constant_;
366 Handle<Map> transition_map_;
367 MaybeHandle<JSObject> holder_;
368 FieldIndex field_index_;
369 Type* field_type_ = Type::Any();
370 };
371
372
373 namespace {
374
375 bool CanInlinePropertyAccess(Handle<Map> map) {
376 // TODO(bmeurer): Do something about the number stuff.
377 if (map->instance_type() == HEAP_NUMBER_TYPE) return false;
378 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
379 return map->IsJSObjectMap() && !map->is_dictionary_map() &&
380 !map->has_named_interceptor() &&
381 // TODO(verwaest): Whitelist contexts to which we have access.
382 !map->is_access_check_needed();
383 }
384
385 } // namespace
386
387
388 bool JSNativeContextSpecialization::ComputePropertyAccessInfo(
389 Handle<Map> map, Handle<Name> name, PropertyAccessMode access_mode,
390 PropertyAccessInfo* access_info) {
391 // Check if it is safe to inline property access for the {map}.
392 if (!CanInlinePropertyAccess(map)) return false;
393
394 // Compute the receiver type.
395 Handle<Map> receiver_map = map;
396 Type* receiver_type = Type::Class(receiver_map, graph()->zone());
397
398 // We support fast inline cases for certain JSObject getters.
399 if (access_mode == kLoad) {
400 // Check for special JSObject field accessors.
401 int offset;
402 if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) {
403 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset);
404 Type* field_type = Type::Tagged();
405 if (map->IsStringMap()) {
406 DCHECK(Name::Equals(factory()->length_string(), name));
407 // The String::length property is always a smi in the range
408 // [0, String::kMaxLength].
409 field_type = type_cache_.kStringLengthType;
410 } else if (map->IsJSArrayMap()) {
411 DCHECK(Name::Equals(factory()->length_string(), name));
412 // The JSArray::length property is a smi in the range
413 // [0, FixedDoubleArray::kMaxLength] in case of fast double
414 // elements, a smi in the range [0, FixedArray::kMaxLength]
415 // in case of other fast elements, and [0, kMaxUInt32] in
416 // case of other arrays.
417 if (IsFastDoubleElementsKind(map->elements_kind())) {
418 field_type = type_cache_.kFixedDoubleArrayLengthType;
419 } else if (IsFastElementsKind(map->elements_kind())) {
420 field_type = type_cache_.kFixedArrayLengthType;
421 } else {
422 field_type = type_cache_.kJSArrayLengthType;
423 }
424 }
425 *access_info =
426 PropertyAccessInfo::DataField(receiver_type, field_index, field_type);
427 return true;
428 }
429 }
430
431 MaybeHandle<JSObject> holder;
432 while (true) {
433 // Lookup the named property on the {map}.
434 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
435 int const number = descriptors->SearchWithCache(*name, *map);
436 if (number != DescriptorArray::kNotFound) {
437 PropertyDetails const details = descriptors->GetDetails(number);
438 if (access_mode == kStore) {
439 // Don't bother optimizing stores to read-only properties.
440 if (details.IsReadOnly()) {
441 return false;
442 }
443 // Check for store to data property on a prototype.
444 if (details.kind() == kData && !holder.is_null()) {
445 // We need to add the data field to the receiver. Leave the loop
446 // and check whether we already have a transition for this field.
447 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver)
448 break;
449 }
450 }
451 if (details.type() == DATA_CONSTANT) {
452 *access_info = PropertyAccessInfo::DataConstant(
453 receiver_type, handle(descriptors->GetValue(number), isolate()),
454 holder);
455 return true;
456 } else if (details.type() == DATA) {
457 int index = descriptors->GetFieldIndex(number);
458 Representation field_representation = details.representation();
459 FieldIndex field_index = FieldIndex::ForPropertyIndex(
460 *map, index, field_representation.IsDouble());
461 Type* field_type = Type::Tagged();
462 if (field_representation.IsSmi()) {
463 field_type = type_cache_.kSmi;
464 } else if (field_representation.IsDouble()) {
465 field_type = type_cache_.kFloat64;
466 } else if (field_representation.IsHeapObject()) {
467 // Extract the field type from the property details (make sure its
468 // representation is TaggedPointer to reflect the heap object case).
469 field_type = Type::Intersect(
470 Type::Convert<HeapType>(
471 handle(descriptors->GetFieldType(number), isolate()),
472 graph()->zone()),
473 Type::TaggedPointer(), graph()->zone());
474 if (field_type->Is(Type::None())) {
475 // Store is not safe if the field type was cleared.
476 if (access_mode == kStore) return false;
477
478 // The field type was cleared by the GC, so we don't know anything
479 // about the contents now.
480 // TODO(bmeurer): It would be awesome to make this saner in the
481 // runtime/GC interaction.
482 field_type = Type::TaggedPointer();
483 } else if (!Type::Any()->Is(field_type)) {
484 // Add proper code dependencies in case of stable field map(s).
485 Handle<Map> field_owner_map(map->FindFieldOwner(number), isolate());
486 dependencies()->AssumeFieldType(field_owner_map);
487 }
488 DCHECK(field_type->Is(Type::TaggedPointer()));
489 }
490 *access_info = PropertyAccessInfo::DataField(receiver_type, field_index,
491 field_type, holder);
492 return true;
493 } else {
494 // TODO(bmeurer): Add support for accessors.
495 return false;
496 }
497 }
498
499 // Don't search on the prototype chain for special indices in case of
500 // integer indexed exotic objects (see ES6 section 9.4.5).
501 if (map->IsJSTypedArrayMap() && name->IsString() &&
502 IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name))) {
503 return false;
504 }
505
506 // Don't lookup private symbols on the prototype chain.
507 if (name->IsPrivate()) return false;
508
509 // Walk up the prototype chain.
510 if (!map->prototype()->IsJSObject()) {
511 // Perform the implicit ToObject for primitives here.
512 // Implemented according to ES6 section 7.3.2 GetV (V, P).
513 Handle<JSFunction> constructor;
514 if (Map::GetConstructorFunction(map, native_context())
515 .ToHandle(&constructor)) {
516 map = handle(constructor->initial_map(), isolate());
517 DCHECK(map->prototype()->IsJSObject());
518 } else if (map->prototype()->IsNull()) {
519 // Store to property not found on the receiver or any prototype, we need
520 // to transition to a new data property.
521 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver)
522 if (access_mode == kStore) {
523 break;
524 }
525 // TODO(bmeurer): Handle the not found case if the prototype is null.
526 return false;
527 } else {
528 return false;
529 }
530 }
531 Handle<JSObject> map_prototype(JSObject::cast(map->prototype()), isolate());
532 if (map_prototype->map()->is_deprecated()) {
533 // Try to migrate the prototype object so we don't embed the deprecated
534 // map into the optimized code.
535 JSObject::TryMigrateInstance(map_prototype);
536 }
537 map = handle(map_prototype->map(), isolate());
538 holder = map_prototype;
539
540 // Check if it is safe to inline property access for the {map}.
541 if (!CanInlinePropertyAccess(map)) return false;
542 }
543 DCHECK_EQ(kStore, access_mode);
544
545 // Check if the {receiver_map} has a data transition with the given {name}.
546 if (receiver_map->unused_property_fields() == 0) return false;
547 if (Map* transition = TransitionArray::SearchTransition(*receiver_map, kData,
548 *name, NONE)) {
549 Handle<Map> transition_map(transition, isolate());
550 int const number = transition_map->LastAdded();
551 PropertyDetails const details =
552 transition_map->instance_descriptors()->GetDetails(number);
553 // Don't bother optimizing stores to read-only properties.
554 if (details.IsReadOnly()) return false;
555 // TODO(bmeurer): Handle transition to data constant?
556 if (details.type() != DATA) return false;
557 int const index = details.field_index();
558 Representation field_representation = details.representation();
559 FieldIndex field_index = FieldIndex::ForPropertyIndex(
560 *transition_map, index, field_representation.IsDouble());
561 Type* field_type = Type::Tagged();
562 if (field_representation.IsSmi()) {
563 field_type = type_cache_.kSmi;
564 } else if (field_representation.IsDouble()) {
565 // TODO(bmeurer): Add support for storing to double fields.
566 return false;
567 } else if (field_representation.IsHeapObject()) {
568 // Extract the field type from the property details (make sure its
569 // representation is TaggedPointer to reflect the heap object case).
570 field_type = Type::Intersect(
571 Type::Convert<HeapType>(
572 handle(
573 transition_map->instance_descriptors()->GetFieldType(number),
574 isolate()),
575 graph()->zone()),
576 Type::TaggedPointer(), graph()->zone());
577 if (field_type->Is(Type::None())) {
578 // Store is not safe if the field type was cleared.
579 return false;
580 } else if (!Type::Any()->Is(field_type)) {
581 // Add proper code dependencies in case of stable field map(s).
582 Handle<Map> field_owner_map(transition_map->FindFieldOwner(number),
583 isolate());
584 dependencies()->AssumeFieldType(field_owner_map);
585 }
586 DCHECK(field_type->Is(Type::TaggedPointer()));
587 }
588 dependencies()->AssumeMapNotDeprecated(transition_map);
589 *access_info = PropertyAccessInfo::TransitionToField(
590 receiver_type, field_index, field_type, transition_map, holder);
591 return true;
592 }
593 return false;
594 }
595
596
597 bool JSNativeContextSpecialization::ComputePropertyAccessInfos(
598 MapHandleList const& maps, Handle<Name> name,
599 PropertyAccessMode access_mode,
600 ZoneVector<PropertyAccessInfo>* access_infos) {
601 for (Handle<Map> map : maps) {
602 if (Map::TryUpdate(map).ToHandle(&map)) {
603 PropertyAccessInfo access_info;
604 if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) {
605 return false;
606 }
607 access_infos->push_back(access_info);
608 }
609 }
610 return true;
611 }
612
613
614 Reduction JSNativeContextSpecialization::ReduceNamedAccess( 302 Reduction JSNativeContextSpecialization::ReduceNamedAccess(
615 Node* node, Node* value, MapHandleList const& receiver_maps, 303 Node* node, Node* value, MapHandleList const& receiver_maps,
616 Handle<Name> name, PropertyAccessMode access_mode) { 304 Handle<Name> name, PropertyAccessMode access_mode) {
617 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || 305 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
618 node->opcode() == IrOpcode::kJSStoreNamed); 306 node->opcode() == IrOpcode::kJSStoreNamed);
619 Node* receiver = NodeProperties::GetValueInput(node, 0); 307 Node* receiver = NodeProperties::GetValueInput(node, 0);
620 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 308 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
621 Node* effect = NodeProperties::GetEffectInput(node); 309 Node* effect = NodeProperties::GetEffectInput(node);
622 Node* control = NodeProperties::GetControlInput(node); 310 Node* control = NodeProperties::GetControlInput(node);
623 311
624 // Not much we can do if deoptimization support is disabled. 312 // Not much we can do if deoptimization support is disabled.
625 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); 313 if (!(flags() & kDeoptimizationEnabled)) return NoChange();
626 314
627 // Compute property access infos for the receiver maps. 315 // Compute property access infos for the receiver maps.
628 ZoneVector<PropertyAccessInfo> access_infos(zone()); 316 ZoneVector<PropertyAccessInfo> access_infos(zone());
629 if (!ComputePropertyAccessInfos(receiver_maps, name, access_mode, 317 if (!access_info_factory().ComputePropertyAccessInfos(
630 &access_infos)) { 318 receiver_maps, name, access_mode, &access_infos)) {
631 return NoChange(); 319 return NoChange();
632 } 320 }
633 321
634 // Nothing to do if we have no non-deprecated maps. 322 // Nothing to do if we have no non-deprecated maps.
635 if (access_infos.empty()) return NoChange(); 323 if (access_infos.empty()) return NoChange();
636 324
637 // The final states for every polymorphic branch. We join them with 325 // The final states for every polymorphic branch. We join them with
638 // Merge++Phi+EffectPhi at the bottom. 326 // Merge++Phi+EffectPhi at the bottom.
639 ZoneVector<Node*> values(zone()); 327 ZoneVector<Node*> values(zone());
640 ZoneVector<Node*> effects(zone()); 328 ZoneVector<Node*> effects(zone());
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 392
705 // Determine actual holder and perform prototype chain checks. 393 // Determine actual holder and perform prototype chain checks.
706 Handle<JSObject> holder; 394 Handle<JSObject> holder;
707 if (access_info.holder().ToHandle(&holder)) { 395 if (access_info.holder().ToHandle(&holder)) {
708 AssumePrototypesStable(receiver_type, holder); 396 AssumePrototypesStable(receiver_type, holder);
709 } 397 }
710 398
711 // Generate the actual property access. 399 // Generate the actual property access.
712 if (access_info.IsDataConstant()) { 400 if (access_info.IsDataConstant()) {
713 this_value = jsgraph()->Constant(access_info.constant()); 401 this_value = jsgraph()->Constant(access_info.constant());
714 if (access_mode == kStore) { 402 if (access_mode == PropertyAccessMode::kStore) {
715 Node* check = graph()->NewNode( 403 Node* check = graph()->NewNode(
716 simplified()->ReferenceEqual(Type::Tagged()), value, this_value); 404 simplified()->ReferenceEqual(Type::Tagged()), value, this_value);
717 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), 405 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
718 check, this_control); 406 check, this_control);
719 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); 407 exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch));
720 this_control = graph()->NewNode(common()->IfTrue(), branch); 408 this_control = graph()->NewNode(common()->IfTrue(), branch);
721 } 409 }
722 } else { 410 } else {
723 DCHECK(access_info.IsDataField() || access_info.IsTransitionToField()); 411 DCHECK(access_info.IsDataField());
724 FieldIndex const field_index = access_info.field_index(); 412 FieldIndex const field_index = access_info.field_index();
725 Type* const field_type = access_info.field_type(); 413 Type* const field_type = access_info.field_type();
726 if (access_mode == kLoad && access_info.holder().ToHandle(&holder)) { 414 if (access_mode == PropertyAccessMode::kLoad &&
415 access_info.holder().ToHandle(&holder)) {
727 this_receiver = jsgraph()->Constant(holder); 416 this_receiver = jsgraph()->Constant(holder);
728 } 417 }
729 Node* this_storage = this_receiver; 418 Node* this_storage = this_receiver;
730 if (!field_index.is_inobject()) { 419 if (!field_index.is_inobject()) {
731 this_storage = this_effect = graph()->NewNode( 420 this_storage = this_effect = graph()->NewNode(
732 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()), 421 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
733 this_storage, this_effect, this_control); 422 this_storage, this_effect, this_control);
734 } 423 }
735 FieldAccess field_access = {kTaggedBase, field_index.offset(), name, 424 FieldAccess field_access = {kTaggedBase, field_index.offset(), name,
736 field_type, kMachAnyTagged}; 425 field_type, kMachAnyTagged};
737 if (field_type->Is(Type::UntaggedFloat64())) { 426 if (field_type->Is(Type::UntaggedFloat64())) {
738 if (!field_index.is_inobject() || field_index.is_hidden_field() || 427 if (!field_index.is_inobject() || field_index.is_hidden_field() ||
739 !FLAG_unbox_double_fields) { 428 !FLAG_unbox_double_fields) {
740 this_storage = this_effect = 429 this_storage = this_effect =
741 graph()->NewNode(simplified()->LoadField(field_access), 430 graph()->NewNode(simplified()->LoadField(field_access),
742 this_storage, this_effect, this_control); 431 this_storage, this_effect, this_control);
743 field_access.offset = HeapNumber::kValueOffset; 432 field_access.offset = HeapNumber::kValueOffset;
744 field_access.name = MaybeHandle<Name>(); 433 field_access.name = MaybeHandle<Name>();
745 } 434 }
746 field_access.machine_type = kMachFloat64; 435 field_access.machine_type = kMachFloat64;
747 } 436 }
748 if (access_mode == kLoad) { 437 if (access_mode == PropertyAccessMode::kLoad) {
749 this_value = this_effect = 438 this_value = this_effect =
750 graph()->NewNode(simplified()->LoadField(field_access), 439 graph()->NewNode(simplified()->LoadField(field_access),
751 this_storage, this_effect, this_control); 440 this_storage, this_effect, this_control);
752 } else { 441 } else {
753 DCHECK_EQ(kStore, access_mode); 442 DCHECK_EQ(PropertyAccessMode::kStore, access_mode);
754 if (field_type->Is(Type::UntaggedFloat64())) { 443 if (field_type->Is(Type::UntaggedFloat64())) {
755 Node* check = 444 Node* check =
756 graph()->NewNode(simplified()->ObjectIsNumber(), this_value); 445 graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
757 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), 446 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
758 check, this_control); 447 check, this_control);
759 exit_controls.push_back( 448 exit_controls.push_back(
760 graph()->NewNode(common()->IfFalse(), branch)); 449 graph()->NewNode(common()->IfFalse(), branch));
761 this_control = graph()->NewNode(common()->IfTrue(), branch); 450 this_control = graph()->NewNode(common()->IfTrue(), branch);
762 this_value = graph()->NewNode(common()->Guard(Type::Number()), 451 this_value = graph()->NewNode(common()->Guard(Type::Number()),
763 this_value, this_control); 452 this_value, this_control);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 this_control = 488 this_control =
800 (this_control_count == 1) 489 (this_control_count == 1)
801 ? this_controls.front() 490 ? this_controls.front()
802 : graph()->NewNode(common()->Merge(this_control_count), 491 : graph()->NewNode(common()->Merge(this_control_count),
803 this_control_count, 492 this_control_count,
804 &this_controls.front()); 493 &this_controls.front());
805 } 494 }
806 } else { 495 } else {
807 DCHECK(field_type->Is(Type::Tagged())); 496 DCHECK(field_type->Is(Type::Tagged()));
808 } 497 }
809 if (access_info.IsTransitionToField()) { 498 Handle<Map> transition_map;
499 if (access_info.transition_map().ToHandle(&transition_map)) {
810 this_effect = graph()->NewNode(common()->BeginRegion(), this_effect); 500 this_effect = graph()->NewNode(common()->BeginRegion(), this_effect);
811 this_effect = graph()->NewNode( 501 this_effect = graph()->NewNode(
812 simplified()->StoreField(AccessBuilder::ForMap()), this_receiver, 502 simplified()->StoreField(AccessBuilder::ForMap()), this_receiver,
813 jsgraph()->Constant(access_info.transition_map()), this_effect, 503 jsgraph()->Constant(transition_map), this_effect, this_control);
814 this_control);
815 } 504 }
816 this_effect = graph()->NewNode(simplified()->StoreField(field_access), 505 this_effect = graph()->NewNode(simplified()->StoreField(field_access),
817 this_storage, this_value, this_effect, 506 this_storage, this_value, this_effect,
818 this_control); 507 this_control);
819 if (access_info.IsTransitionToField()) { 508 if (!access_info.transition_map().is_null()) {
820 this_effect = 509 this_effect =
821 graph()->NewNode(common()->FinishRegion(), 510 graph()->NewNode(common()->FinishRegion(),
822 jsgraph()->UndefinedConstant(), this_effect); 511 jsgraph()->UndefinedConstant(), this_effect);
823 } 512 }
824 } 513 }
825 } 514 }
826 515
827 // Remember the final state for this property access. 516 // Remember the final state for this property access.
828 values.push_back(this_value); 517 values.push_back(this_value);
829 effects.push_back(this_effect); 518 effects.push_back(this_effect);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 Node* const value = jsgraph()->Dead(); 575 Node* const value = jsgraph()->Dead();
887 576
888 // Extract receiver maps from the LOAD_IC using the LoadICNexus. 577 // Extract receiver maps from the LOAD_IC using the LoadICNexus.
889 MapHandleList receiver_maps; 578 MapHandleList receiver_maps;
890 if (!p.feedback().IsValid()) return NoChange(); 579 if (!p.feedback().IsValid()) return NoChange();
891 LoadICNexus nexus(p.feedback().vector(), p.feedback().slot()); 580 LoadICNexus nexus(p.feedback().vector(), p.feedback().slot());
892 if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange(); 581 if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange();
893 DCHECK_LT(0, receiver_maps.length()); 582 DCHECK_LT(0, receiver_maps.length());
894 583
895 // Try to lower the named access based on the {receiver_maps}. 584 // Try to lower the named access based on the {receiver_maps}.
896 return ReduceNamedAccess(node, value, receiver_maps, p.name(), kLoad); 585 return ReduceNamedAccess(node, value, receiver_maps, p.name(),
586 PropertyAccessMode::kLoad);
897 } 587 }
898 588
899 589
900 Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) { 590 Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
901 DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode()); 591 DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode());
902 NamedAccess const& p = NamedAccessOf(node->op()); 592 NamedAccess const& p = NamedAccessOf(node->op());
903 Node* const value = NodeProperties::GetValueInput(node, 1); 593 Node* const value = NodeProperties::GetValueInput(node, 1);
904 594
905 // Extract receiver maps from the STORE_IC using the StoreICNexus. 595 // Extract receiver maps from the STORE_IC using the StoreICNexus.
906 MapHandleList receiver_maps; 596 MapHandleList receiver_maps;
907 if (!p.feedback().IsValid()) return NoChange(); 597 if (!p.feedback().IsValid()) return NoChange();
908 StoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); 598 StoreICNexus nexus(p.feedback().vector(), p.feedback().slot());
909 if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange(); 599 if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange();
910 DCHECK_LT(0, receiver_maps.length()); 600 DCHECK_LT(0, receiver_maps.length());
911 601
912 // Try to lower the named access based on the {receiver_maps}. 602 // Try to lower the named access based on the {receiver_maps}.
913 return ReduceNamedAccess(node, value, receiver_maps, p.name(), kStore); 603 return ReduceNamedAccess(node, value, receiver_maps, p.name(),
604 PropertyAccessMode::kStore);
914 } 605 }
915 606
916 607
917 Reduction JSNativeContextSpecialization::Replace(Node* node, 608 Reduction JSNativeContextSpecialization::Replace(Node* node,
918 Handle<Object> value) { 609 Handle<Object> value) {
919 return Replace(node, jsgraph()->Constant(value)); 610 return Replace(node, jsgraph()->Constant(value));
920 } 611 }
921 612
922 613
923 bool JSNativeContextSpecialization::LookupInScriptContextTable( 614 bool JSNativeContextSpecialization::LookupInScriptContextTable(
924 Handle<Name> name, ScriptContextTableLookupResult* result) { 615 Handle<Name> name, ScriptContextTableLookupResult* result) {
925 if (!name->IsString()) return false; 616 if (!name->IsString()) return false;
926 Handle<ScriptContextTable> script_context_table( 617 Handle<ScriptContextTable> script_context_table(
927 global_object()->native_context()->script_context_table()); 618 native_context()->script_context_table());
928 ScriptContextTable::LookupResult lookup_result; 619 ScriptContextTable::LookupResult lookup_result;
929 if (!ScriptContextTable::Lookup(script_context_table, 620 if (!ScriptContextTable::Lookup(script_context_table,
930 Handle<String>::cast(name), &lookup_result)) { 621 Handle<String>::cast(name), &lookup_result)) {
931 return false; 622 return false;
932 } 623 }
933 Handle<Context> script_context = ScriptContextTable::GetContext( 624 Handle<Context> script_context = ScriptContextTable::GetContext(
934 script_context_table, lookup_result.context_index); 625 script_context_table, lookup_result.context_index);
935 result->context = script_context; 626 result->context = script_context;
936 result->immutable = IsImmutableVariableMode(lookup_result.mode); 627 result->immutable = IsImmutableVariableMode(lookup_result.mode);
937 result->index = lookup_result.slot_index; 628 result->index = lookup_result.slot_index;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 } 686 }
996 687
997 688
998 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 689 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
999 return jsgraph()->simplified(); 690 return jsgraph()->simplified();
1000 } 691 }
1001 692
1002 } // namespace compiler 693 } // namespace compiler
1003 } // namespace internal 694 } // namespace internal
1004 } // namespace v8 695 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/property-access-info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698