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

Side by Side Diff: src/hydrogen.cc

Issue 11365174: A change in the way we place TransitionElementKinds in the tree. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 686
687 687
688 HGraph::HGraph(CompilationInfo* info) 688 HGraph::HGraph(CompilationInfo* info)
689 : isolate_(info->isolate()), 689 : isolate_(info->isolate()),
690 next_block_id_(0), 690 next_block_id_(0),
691 entry_block_(NULL), 691 entry_block_(NULL),
692 blocks_(8, info->zone()), 692 blocks_(8, info->zone()),
693 values_(16, info->zone()), 693 values_(16, info->zone()),
694 phi_list_(NULL), 694 phi_list_(NULL),
695 uint32_instructions_(NULL), 695 uint32_instructions_(NULL),
696 deferred_transitions_(10, info->zone()),
696 info_(info), 697 info_(info),
697 zone_(info->zone()), 698 zone_(info->zone()),
698 is_recursive_(false), 699 is_recursive_(false),
699 use_optimistic_licm_(false), 700 use_optimistic_licm_(false),
700 type_change_checksum_(0) { 701 type_change_checksum_(0) {
701 start_environment_ = 702 start_environment_ =
702 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 703 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
703 start_environment_->set_ast_id(BailoutId::FunctionEntry()); 704 start_environment_->set_ast_id(BailoutId::FunctionEntry());
704 entry_block_ = CreateBasicBlock(); 705 entry_block_ = CreateBasicBlock();
705 entry_block_->SetInitialEnvironment(start_environment_); 706 entry_block_->SetInitialEnvironment(start_environment_);
(...skipping 1789 matching lines...) Expand 10 before | Expand all | Expand 10 after
2495 ZoneList<HValue*> worklist(block->phis()->length(), zone()); 2496 ZoneList<HValue*> worklist(block->phis()->length(), zone());
2496 for (int j = 0; j < block->phis()->length(); ++j) { 2497 for (int j = 0; j < block->phis()->length(); ++j) {
2497 worklist.Add(block->phis()->at(j), zone()); 2498 worklist.Add(block->phis()->at(j), zone());
2498 } 2499 }
2499 InferTypes(&worklist); 2500 InferTypes(&worklist);
2500 } 2501 }
2501 } 2502 }
2502 } 2503 }
2503 2504
2504 2505
2506 static bool TerminalMatch(void* key1, void* key2) {
2507 return key1 == key2;
2508 }
2509
2510 typedef ZoneList<DeferredTransitions*> DeferredTransitionsList;
2511
2512 class HighestMapAndFamily {
danno 2012/11/14 15:28:18 When you say "highest", do you mean most general?
mvstanton 2012/11/16 15:15:06 I needed to update many locations to be consistent
2513 public:
2514 HighestMapAndFamily() : highest_map_(NULL), family_(NULL) { }
2515 HighestMapAndFamily(HighestMapAndFamily& h)
2516 : highest_map_(h.highest_map()),
2517 family_(h.family()) {
2518 }
2519
2520 Map* highest_map() const { return highest_map_; }
2521 Map* family() const { return family_; }
2522
2523 void change(Map* new_highest_map, Map* new_family) {
danno 2012/11/14 15:28:18 Maybe "Update" instead?
mvstanton 2012/11/16 15:15:06 Done.
2524 if (is_valid()) {
2525 ASSERT(new_family == family_); // family shouldn't be changed
2526 highest_map_ = new_highest_map;
2527 } else {
2528 highest_map_ = new_highest_map;
2529 family_ = new_family;
2530 }
2531 }
2532
2533 void invalidate() {
2534 highest_map_ = NULL;
2535 family_ = NULL;
2536 }
2537
2538 bool is_valid() const { return highest_map_ != NULL && family_ != NULL; }
2539 bool operator==(const HighestMapAndFamily& h) const {
danno 2012/11/14 15:28:18 We tend to avoid operator== (see http://google-sty
mvstanton 2012/11/16 15:15:06 Done.
2540 if (!is_valid() || !h.is_valid()) {
2541 return is_valid() == h.is_valid();
2542 }
2543 return highest_map_ == h.highest_map() && family_ == h.family();
2544 }
2545
2546 bool operator!=(const HighestMapAndFamily& h) const {
danno 2012/11/14 15:28:18 operator overloading
mvstanton 2012/11/16 15:15:06 Done.
2547 return !(*this == h);
2548 }
2549
2550 HighestMapAndFamily& operator=(const HighestMapAndFamily& h) {
danno 2012/11/14 15:28:18 operator overloading
mvstanton 2012/11/16 15:15:06 this one I need to keep in order to copy these thi
2551 if(this != &h) {
2552 highest_map_ = h.highest_map();
2553 family_ = h.family();
2554 }
2555 return *this;
2556 }
2557
2558 private:
2559 Map *highest_map_;
danno 2012/11/14 15:28:18 Map* highest_map_
mvstanton 2012/11/16 15:15:06 Done.
2560 Map *family_;
2561 };
2562
2563 typedef EnumSet<ElementsKind> ElementsKindSet;
2564
2565 class TerminalMapValue: public ZoneObject {
danno 2012/11/14 15:28:18 TransitionElementsInputValueData?
mvstanton 2012/11/16 15:15:06 Done.
2566 public:
2567 TerminalMapValue(HInstruction* terminal_node,Zone* zone) :
2568 terminal_node_(terminal_node),
2569 transitions_(new (zone) DeferredTransitionsList(10,zone)),
2570 zone_(zone),
2571 last_in_chain_(NULL) {
2572
2573 }
2574
2575 void add_transition(DeferredTransitions* todo) {
danno 2012/11/14 15:28:18 AddTransition
mvstanton 2012/11/16 15:15:06 Done.
2576 if (todo->terminal_nodes() == 1) {
2577 // put at the front of the list. Processing single element
2578 // transitions first makes score calculation easier.
2579 transitions_->InsertAt(0, todo, zone_);
2580 } else {
2581 transitions_->Add(todo, zone_);
2582 }
2583 }
2584
2585 ElementsKind highest_elementskind() const {
danno 2012/11/14 15:28:18 GetMostGenerateElementsKind()?
mvstanton 2012/11/16 15:15:06 removed method, no callers
2586 ASSERT(highest_.highest_map() != NULL);
2587 return highest_.highest_map()->elements_kind();
2588 }
2589
2590 HighestMapAndFamily& highest() { return highest_; }
2591 void set_highest(HighestMapAndFamily& h) { highest_ = h; }
2592
2593 int todo_count() const { return transitions_->length(); }
2594 DeferredTransitions* todo(int i) { return (*transitions_)[i]; }
2595 Zone* zone() { return zone_; }
2596
2597 // For instruction emission
2598
2599 bool RequiresTransitionElementsKind(ElementsKind from) const {
2600 return !from_elements_.Contains(from);
2601 }
2602
2603 void InsertTransitionElementsKind(HTransitionElementsKind* new_instr) {
2604 ElementsKind from_elements_kind = new_instr->original_map()->elements_kind() ;
2605 ASSERT(RequiresTransitionElementsKind(from_elements_kind));
2606 // At the site, we maintain a most recent instruction we added, and
2607 // new instructions should appear at the end of the chain.
2608 HInstruction* addafter = last_in_chain_;
2609 if (addafter == NULL) {
2610 // This is the first instruction to add.
2611 // We must emit a checknonsmi
2612 addafter = new(zone()) HCheckNonSmi(terminal_node_);
2613 addafter->InsertAfter(terminal_node_);
2614 }
2615
2616 new_instr->InsertAfter(addafter);
2617 last_in_chain_ = new_instr;
2618 from_elements_.Add(from_elements_kind);
2619 }
2620
2621 HTransitionElementsKind* last_transitionelementskind() const {
2622 // Will be NULL if none inserted yet.
2623 return last_in_chain_;
2624 }
2625
2626 private:
2627 HInstruction* terminal_node_;
danno 2012/11/14 15:28:18 HValue*
mvstanton 2012/11/16 15:15:06 Done.
2628 DeferredTransitionsList* transitions_;
2629 Zone* zone_;
2630 HighestMapAndFamily highest_;
2631 ElementsKindSet from_elements_;
2632 HTransitionElementsKind* last_in_chain_;
2633 };
2634
2635
2636 // This method walks through the TODOs that mapped to a particular terminal node
2637 // value. It returns the "TO" map that these nodes unify too. If they return
2638 // a NULL handle, then that means that the nodes couldn't be unified, and have
2639 // already been marked as invalid.
2640 // If they return a non-null value, then all the TODOs have also been updated to
2641 // recognize the returned map as their "TO" map as well.
2642 void ComputeHighest(TerminalMapValue* value, HighestMapAndFamily* highest, Defer redTransitions** cannotTransition) {
2643 *highest = value->highest();
2644
2645 // At the end of this function all todos in the list need to agree on the high est map.
2646 // so one time through the loop isn't enough.
2647 for (int count=0; count<2; count++) {
2648 for (int i=0; i<value->todo_count(); i++) {
2649 DeferredTransitions* todo = value->todo(i);
2650 Map* todo_highest = todo->highest();
2651
2652 if (!highest->is_valid()) {
2653 // First todo, first time through the loop
2654 highest->change(todo_highest, todo->map_family());
2655 } else if (highest->highest_map() != todo_highest) {
2656
2657 // Are they in the same family?
2658 if (highest->family() != todo->map_family()) {
2659 // Yikes. this won't work.
2660 *cannotTransition = todo;
2661 highest->invalidate();
2662 return;
2663 }
2664
2665 // which one is higher? Figure that out and then the other one needs to
2666 // be able to find a path to it.
2667 ElementsKind unified_highest_elements_kind = GetUnifiedFastElementsKind(
2668 highest->highest_map()->elements_kind(), todo_highest->elements_kind ());
2669
2670 // make sure both maps have a path to success
2671 Map* unified_highest_map = highest->highest_map()->LookupElementsTransit ionMap(unified_highest_elements_kind);
2672 Map* unified_todo_highest_map = todo_highest->LookupElementsTransitionMa p(unified_highest_elements_kind);
2673 if (unified_highest_map == NULL || unified_todo_highest_map == NULL ||
2674 (unified_highest_map != unified_todo_highest_map)) {
2675 *cannotTransition = todo;
2676 highest->invalidate();
2677 return;
2678 }
2679
2680 highest->change(unified_highest_map, todo->map_family());
2681 todo->set_highest(highest->highest_map());
2682 }
2683 }
2684 }
2685 }
2686
2687
2688 void ScorchTerminalMap(ZoneAllocationPolicy allocationPolicy, Zone* zone,
2689 DeferredTransitions* cannotTransition, ZoneHashMap* termi nalMap) {
2690 ZoneList<DeferredTransitions*> worklist(10, zone);
2691 cannotTransition->set_invalid();
2692 worklist.Add(cannotTransition, zone);
2693
2694 while (!worklist.is_empty()) {
2695 DeferredTransitions* todo = worklist.RemoveLast();
2696 ASSERT(todo->invalid());
2697 for (int t=0; t<todo->terminal_nodes(); t++) {
2698 HInstruction* terminal_node = todo->terminal_node(t);
2699 ZoneHashMap::Entry* entry = terminalMap->Lookup(terminal_node,
2700 terminal_node->id(),
2701 false,
2702 allocationPolicy);
2703 if (entry != NULL) {
2704 TerminalMapValue* value = reinterpret_cast<TerminalMapValue*>(entry->val ue);
2705 for (int i=0; i<value->todo_count(); i++) {
2706 DeferredTransitions* todo = value->todo(i);
2707 if (!todo->invalid()) {
2708 todo->set_invalid();
2709 worklist.Add(todo, zone);
2710 }
2711 }
2712
2713 terminalMap->Remove(terminal_node, terminal_node->id());
2714 }
2715 }
2716 }
2717 }
2718
2719
2720 Handle<Map>& StashedMapHandle(ZoneList<DeferredTransitions>* transitions,
2721 Map* map) {
2722
2723 // The guarantee is that a handle does exist for the given map, since
2724 // we saved/created it earlier.
2725 // TODO(mvstanton): this could be way more efficient. It is brute force.
2726 for (int i=0; i<transitions->length(); i++) {
2727 DeferredTransitions& todo = transitions->at(i);
2728 for (int r=0; r<todo.transitions(); r++) {
2729 TransitionRecord& record = todo.transition_ref(r);
2730 if (*(record.map_to().location()) == map) {
2731 return record.map_to_ref();
2732 } else if(*(record.optimistic_holey().location()) == map) {
2733 return record.optimistic_holey_ref();
2734 }
2735 }
2736 }
2737
2738 // This code is marked as unreachable because at runtime we can't actually cre ate
2739 // a handle during compiler optimization.
2740 UNREACHABLE();
2741 return transitions->at(0).transition_ref(0).map_to_ref();
2742 }
2743
2744
2745 void FinalizeTransitionToDos(ZoneList<DeferredTransitions>& transitions, int max imumGraphID) {
danno 2012/11/14 15:28:18 How about FinalizeDeferredTransitionElements?
mvstanton 2012/11/16 15:15:06 Done.
2746 for (int i=0; i<transitions.length(); i++) {
2747 DeferredTransitions& todo = transitions[i];
2748 todo.ComputeTerminalNodes(maximumGraphID);
2749 // Also fill in the current highest, which may later be changed externally.
danno 2012/11/14 15:28:18 most general?
mvstanton 2012/11/16 15:15:06 Done.
2750 todo.compute_highest();
2751 }
2752 }
2753
2754 void HGraph::InitializeTerminalMap(ZoneHashMap& terminalMap) {
2755 ZoneAllocationPolicy allocator(zone());
2756 Counters* counters = isolate()->counters();
2757
2758 for (int i=0; i<deferred_transitions_.length(); i++) {
2759 DeferredTransitions& todo = deferred_transitions_[i];
2760 ASSERT(todo.transitions() > 0);
2761 int site_nesting_depth = todo.instr()->block()->LoopNestingDepth();
2762
2763 for (int t=0; t<todo.terminal_nodes(); t++) {
2764 HInstruction* terminal_node = todo.terminal_node(t);
2765
2766 // Score computation
2767 int terminal_site_nesting_depth = terminal_node->block()->LoopNestingDepth ();
2768 int loop_delta = site_nesting_depth - terminal_site_nesting_depth;
2769 int proposedAdds = todo.transitions();
2770 DeferredTransitions::ScoreType scoreType = todo.scoretype_from_loopdelta(l oop_delta);
2771 int score = (loop_delta==0 ? 1 : loop_delta)*proposedAdds;
2772 if (score < 0) score *= -1;
2773 todo.increment_score(scoreType,score);
2774
2775 ZoneHashMap::Entry* entry = terminalMap.Lookup(terminal_node,
2776 terminal_node->id(),
2777 true,
2778 allocator);
2779 TerminalMapValue* value = NULL;
2780 if (entry->value == NULL) {
2781 // It's new, add a value
2782 value = new (zone()) TerminalMapValue(terminal_node,zone());
2783 entry->value = reinterpret_cast<void*>(value);
2784 } else {
2785 value = reinterpret_cast<TerminalMapValue*>(entry->value);
2786 }
2787
2788 value->add_transition(&todo);
2789 }
2790
2791 // Export the site score in aggregate for reporting
2792 counters->transition_site_positive_score()->Increment(todo.score(DeferredTra nsitions::SCORE_POSITIVE));
2793 counters->transition_site_negative_score()->Increment(todo.score(DeferredTra nsitions::SCORE_NEGATIVE));
2794 counters->transition_site_neutral_score()->Increment(todo.score(DeferredTran sitions::SCORE_NEUTRAL));
2795 }
2796 }
2797
2798 void HGraph::InsertElementsTransitions()
2799 {
2800 ZoneAllocationPolicy allocator(zone());
2801 HPhase phase("H_Place elements transitions", this);
2802
2803 // ===========================================================================
2804 // Compute the equivalence classes of the LoadKeyed/StoreKeyed sites that need
2805 // transitions.
2806 FinalizeTransitionToDos(deferred_transitions_, GetMaximumValueID());
2807
2808 //
2809 // IF in a forest of terminal nodes shared among some load/store keyed
2810 // instructions, there are map transitions TO maps that are not in the same
2811 // "floor" of the map tree, then all transitions involving those terminal
danno 2012/11/14 15:28:18 to abuse the metaphor even more, maybe "trunk" ins
danno 2012/11/14 15:28:18 pre-transitioned input value?
2812 // nodes must be left down at the load/store site, rather than factored up.
2813 //
2814 ZoneHashMap terminalMap(TerminalMatch,32,allocator);
danno 2012/11/14 15:28:18 spaces after ,s
mvstanton 2012/11/16 15:15:06 Done.
2815 InitializeTerminalMap(terminalMap);
2816
2817 // Now that the map is created, run the unification algorithm
2818 bool done = false;
2819 while (!done) {
2820 bool changed = false;
2821 for (ZoneHashMap::Entry* p = terminalMap.Start(); p != NULL;
2822 p = terminalMap.Next(p)) {
2823 TerminalMapValue* value = reinterpret_cast<TerminalMapValue*>(p->value);
2824 DeferredTransitions* cannotTransitionTodo = NULL;
2825 HighestMapAndFamily newHighest;
2826 ComputeHighest(value, &newHighest, &cannotTransitionTodo);
2827 if (!newHighest.is_valid()) {
2828 ASSERT(cannotTransitionTodo != NULL);
2829 ScorchTerminalMap(allocator, zone(), cannotTransitionTodo, &terminalMap) ;
2830 changed = true;
2831 break;
2832 }
2833
2834 if (value->highest() != newHighest) {
2835 value->set_highest(newHighest);
2836 changed = true;
2837 }
2838 }
2839
2840 done = !changed;
2841 }
2842
2843 // Now we have the "to" value for each location, and todos have been divided i nto
2844 // sets, including a set that couldn't be transitioned and is no longer repres ented
2845 // in the terminalMap
2846 // Handle each todo again.
2847 if (FLAG_trace_transition_placement) {
2848 for (int i=0; i<deferred_transitions_.length(); i++) {
2849 DeferredTransitions& todo = deferred_transitions_[i];
2850 HeapStringAllocator string_allocator;
2851 StringStream stream(&string_allocator);
2852 todo.PrintTo(&stream);
2853 PrintF("%s", *stream.ToCString());
2854 }
2855 }
2856
2857 // Do the work
2858 for (int i=0; i<deferred_transitions_.length(); i++) {
2859 DeferredTransitions& todo = deferred_transitions_[i];
2860
2861 // All todos need to be finalized, even if we don't take action on them.
2862 todo.Finalize();
2863
2864 if (todo.invalid()) {
2865 // We aren't moving this todo, leave it alone and visit the next
2866 continue;
2867 }
2868
2869 // 1) Remove the nonsmicheck.
2870 todo.checknonsmi_instr()->DeleteAndReplaceWith(NULL);
2871
2872 // 2) alter the elementkind of the loadkeyed/storekeyed instruction if requi red.
2873 // (note that steps a,b,c won't happen if the transition was marked as inval id because
2874 // it operates on a different map family)
2875 // 2a) unlink transitions associated with this site from their current locat ion
2876 // 2b) Create appropriate transition instructions up at the terminal site.
2877 // 2c) Fix the checkmaps instruction if required.
2878
2879 Handle<Map>& handle = StashedMapHandle(&deferred_transitions_, todo.highest( ));
2880
2881 for (int t=0; t<todo.terminal_nodes(); t++) {
2882 HInstruction* terminal_node = todo.terminal_node(t);
2883 ZoneHashMap::Entry* entry = terminalMap.Lookup(terminal_node,
2884 terminal_node->id(),
2885 false,
2886 allocator);
2887 CHECK(entry->value != NULL);
2888 TerminalMapValue* value = reinterpret_cast<TerminalMapValue*>(entry->value );
2889 for (int r=0; r<todo.transitions(); r++) {
2890 TransitionRecord& record = todo.transition_ref(r);
2891 if (value->RequiresTransitionElementsKind(record.from())) {
2892
2893 // We need to emit a transition.
2894 ASSERT(terminal_node->IsInstruction());
2895 HTransitionElementsKind* transition = new(zone())
2896 HTransitionElementsKind(terminal_node, record.map_from(), handle);
2897 value->InsertTransitionElementsKind(transition);
2898
2899 // Remove the transition from it's original location
2900 if (record.transition_instruction()->block() != NULL) {
2901 if (record.transition_instruction()->HasNoUses()) {
2902 record.transition_instruction()->DeleteAndReplaceWith(NULL);
2903 } else {
2904 record.transition_instruction()->DeleteAndReplaceWith(transition);
2905 }
2906 }
2907 }
2908 }
2909
2910 HCheckMaps* checkmaps = todo.checkmaps_instr();
2911 if (checkmaps != NULL) {
2912 // The checkmaps depends on the transition instruction we just unlinked.
2913 // Conveniently, we can make it depend on the last instruction we just e mitted.
2914
2915 // We may need to update the map
2916 // TODO(mvstanton) update the map instruction
2917 // todo.mapcheck_instr()->
2918 // one case:
2919 // HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
2920 // zone(), dependency);
2921 // other case:
2922 // emitted_checkmaps = new(zone()) HCheckMaps(
2923 // elements, isolate()->factory()->fixed_array_map(),
2924 // zone(), elements_kind_branch);
2925
2926 // I'm not sure what to do right now if this is > 1, so
2927 // TODO(mvstanton): this assert is temporary
2928 ASSERT(checkmaps->map_set()->length() == 1);
2929 // Surgically replace the map in there
2930 checkmaps->map_set()->Clear();
2931 checkmaps->map_set()->Add(handle, zone());
2932
2933 // Remove the dependency, only keeping it if our new transition is in th e same basic
2934 // block as the checkmaps.
2935 HTransitionElementsKind* lasttransition = value->last_transitionelements kind();
2936 if (checkmaps->has_typecheck()) {
2937 if (lasttransition->block() == checkmaps->block()) {
2938 checkmaps->SetOperandAt(1, lasttransition);
2939 } else {
2940 checkmaps->SetOperandAt(1, checkmaps->OperandAt(0));
2941 }
2942 }
2943 }
2944 }
2945 }
2946 }
2947
2948
2949 template<class T>
2950 void FinishFastKeyedInitialization(T* instruction, ElementsKind elements_kind) {
2951 instruction->PerformDeferredInitialization(elements_kind);
2952 }
2953
2954
2955
2505 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { 2956 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
2506 HValue* current = value; 2957 HValue* current = value;
2507 while (current != NULL) { 2958 while (current != NULL) {
2508 if (visited->Contains(current->id())) return; 2959 if (visited->Contains(current->id())) return;
2509 2960
2510 // For phis, we must propagate the check to all of its inputs. 2961 // For phis, we must propagate the check to all of its inputs.
2511 if (current->IsPhi()) { 2962 if (current->IsPhi()) {
2512 visited->Add(current->id()); 2963 visited->Add(current->id());
2513 HPhi* phi = HPhi::cast(current); 2964 HPhi* phi = HPhi::cast(current);
2514 for (int i = 0; i < phi->OperandCount(); ++i) { 2965 for (int i = 0; i < phi->OperandCount(); ++i) {
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
3303 } 3754 }
3304 EliminateRedundantPhis(); 3755 EliminateRedundantPhis();
3305 if (!CheckArgumentsPhiUses()) { 3756 if (!CheckArgumentsPhiUses()) {
3306 *bailout_reason = SmartArrayPointer<char>(StrDup( 3757 *bailout_reason = SmartArrayPointer<char>(StrDup(
3307 "Unsupported phi use of arguments")); 3758 "Unsupported phi use of arguments"));
3308 return false; 3759 return false;
3309 } 3760 }
3310 if (FLAG_eliminate_dead_phis) EliminateUnreachablePhis(); 3761 if (FLAG_eliminate_dead_phis) EliminateUnreachablePhis();
3311 CollectPhis(); 3762 CollectPhis();
3312 3763
3764 InsertElementsTransitions();
3765
3313 if (has_osr_loop_entry()) { 3766 if (has_osr_loop_entry()) {
3314 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis(); 3767 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis();
3315 for (int j = 0; j < phis->length(); j++) { 3768 for (int j = 0; j < phis->length(); j++) {
3316 HPhi* phi = phis->at(j); 3769 HPhi* phi = phis->at(j);
3317 osr_values()->at(phi->merged_index())->set_incoming_value(phi); 3770 osr_values()->at(phi->merged_index())->set_incoming_value(phi);
3318 } 3771 }
3319 } 3772 }
3320 3773
3321 HInferRepresentation rep(this); 3774 HInferRepresentation rep(this);
3322 rep.Analyze(); 3775 rep.Analyze();
(...skipping 2767 matching lines...) Expand 10 before | Expand all | Expand 10 after
6090 return load; 6543 return load;
6091 } 6544 }
6092 } 6545 }
6093 6546
6094 6547
6095 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, 6548 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
6096 HValue* checked_key, 6549 HValue* checked_key,
6097 HValue* val, 6550 HValue* val,
6098 HValue* load_dependency, 6551 HValue* load_dependency,
6099 ElementsKind elements_kind, 6552 ElementsKind elements_kind,
6100 bool is_store) { 6553 bool is_store,
6554 bool defer_initialization) {
6101 if (is_store) { 6555 if (is_store) {
6102 ASSERT(val != NULL); 6556 ASSERT(val != NULL);
6103 switch (elements_kind) { 6557 switch (elements_kind) {
6104 case FAST_SMI_ELEMENTS: 6558 case FAST_SMI_ELEMENTS:
6105 case FAST_HOLEY_SMI_ELEMENTS: 6559 case FAST_HOLEY_SMI_ELEMENTS:
6106 // Smi-only arrays need a smi check. 6560 // Smi-only arrays need a smi check.
6107 AddInstruction(new(zone()) HCheckSmi(val)); 6561 AddInstruction(new(zone()) HCheckSmi(val));
6108 // Fall through. 6562 // Fall through.
6109 case FAST_ELEMENTS: 6563 case FAST_ELEMENTS:
6110 case FAST_HOLEY_ELEMENTS: 6564 case FAST_HOLEY_ELEMENTS:
6111 case FAST_DOUBLE_ELEMENTS: 6565 case FAST_DOUBLE_ELEMENTS:
6112 case FAST_HOLEY_DOUBLE_ELEMENTS: 6566 case FAST_HOLEY_DOUBLE_ELEMENTS:
6113 return new(zone()) HStoreKeyed( 6567 return new(zone()) HStoreKeyed(
6114 elements, checked_key, val, elements_kind); 6568 elements, checked_key, val, elements_kind, defer_initialization);
6115 default: 6569 default:
6116 UNREACHABLE(); 6570 UNREACHABLE();
6117 return NULL; 6571 return NULL;
6118 } 6572 }
6119 } 6573 }
6120 // It's an element load (!is_store). 6574 // It's an element load (!is_store).
6121 return new(zone()) HLoadKeyed(elements, 6575 return new(zone()) HLoadKeyed(elements,
6122 checked_key, 6576 checked_key,
6123 load_dependency, 6577 load_dependency,
6124 elements_kind); 6578 elements_kind, defer_initialization);
6125 } 6579 }
6126 6580
6127 6581
6128 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 6582 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
6129 HValue* key, 6583 HValue* key,
6130 HValue* val, 6584 HValue* val,
6131 HValue* dependency, 6585 HValue* dependency,
6132 Handle<Map> map, 6586 Handle<Map> map,
6133 bool is_store) { 6587 bool is_store,
6588 HCheckMaps** checkmap _instr) {
6134 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, 6589 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
6135 zone(), dependency); 6590 zone(), dependency);
6136 AddInstruction(mapcheck); 6591 AddInstruction(mapcheck);
6137 if (dependency) { 6592 if (dependency) {
6138 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 6593 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
6139 } 6594 }
6595
6596 if (checkmap_instr != NULL) {
6597 *checkmap_instr = mapcheck;
6598 }
6599
6140 return BuildUncheckedMonomorphicElementAccess(object, key, val, 6600 return BuildUncheckedMonomorphicElementAccess(object, key, val,
6141 mapcheck, map, is_store); 6601 mapcheck, map, is_store, depende ncy != NULL);
6142 } 6602 }
6143 6603
6144 6604
6145 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 6605 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
6146 HValue* object, 6606 HValue* object,
6147 HValue* key, 6607 HValue* key,
6148 HValue* val, 6608 HValue* val,
6149 HCheckMaps* mapcheck, 6609 HCheckMaps* mapcheck,
6150 Handle<Map> map, 6610 Handle<Map> map,
6151 bool is_store) { 6611 bool is_store,
6612 bool defer_initialization) {
6152 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 6613 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
6153 // on a HElementsTransition instruction. The flag can also be removed if the 6614 // on a HElementsTransition instruction. The flag can also be removed if the
6154 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 6615 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
6155 // ElementsKind transitions. Finally, the dependency can be removed for stores 6616 // ElementsKind transitions. Finally, the dependency can be removed for stores
6156 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 6617 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
6157 // generated store code. 6618 // generated store code.
6158 if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) || 6619 if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) ||
6159 (map->elements_kind() == FAST_ELEMENTS && is_store)) { 6620 (map->elements_kind() == FAST_ELEMENTS && is_store)) {
6160 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 6621 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
6161 } 6622 }
(...skipping 25 matching lines...) Expand all
6187 map->has_fast_double_elements()); 6648 map->has_fast_double_elements());
6188 if (map->instance_type() == JS_ARRAY_TYPE) { 6649 if (map->instance_type() == JS_ARRAY_TYPE) {
6189 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck, 6650 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck,
6190 HType::Smi())); 6651 HType::Smi()));
6191 } else { 6652 } else {
6192 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 6653 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
6193 } 6654 }
6194 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, 6655 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
6195 ALLOW_SMI_KEY)); 6656 ALLOW_SMI_KEY));
6196 return BuildFastElementAccess(elements, checked_key, val, mapcheck, 6657 return BuildFastElementAccess(elements, checked_key, val, mapcheck,
6197 map->elements_kind(), is_store); 6658 map->elements_kind(), is_store, defer_initializa tion);
6198 } 6659 }
6199 6660
6200 6661
6201 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad( 6662 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad(
6202 HValue* object, 6663 HValue* object,
6203 HValue* key, 6664 HValue* key,
6204 HValue* val, 6665 HValue* val,
6205 SmallMapList* maps) { 6666 SmallMapList* maps) {
6206 // For polymorphic loads of similar elements kinds (i.e. all tagged or all 6667 // For polymorphic loads of similar elements kinds (i.e. all tagged or all
6207 // double), always use the "worst case" code without a transition. This is 6668 // double), always use the "worst case" code without a transition. This is
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
6239 most_general_consolidated_map->elements_kind(), 6700 most_general_consolidated_map->elements_kind(),
6240 map->elements_kind())) { 6701 map->elements_kind())) {
6241 most_general_consolidated_map = map; 6702 most_general_consolidated_map = map;
6242 } 6703 }
6243 } 6704 }
6244 if (!has_double_maps && !has_smi_or_object_maps) return NULL; 6705 if (!has_double_maps && !has_smi_or_object_maps) return NULL;
6245 6706
6246 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); 6707 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone());
6247 AddInstruction(check_maps); 6708 AddInstruction(check_maps);
6248 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 6709 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6249 object, key, val, check_maps, most_general_consolidated_map, false); 6710 object, key, val, check_maps, most_general_consolidated_map, false, false) ;
6250 return instr; 6711 return instr;
6251 } 6712 }
6252 6713
6253 6714
6254 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, 6715 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
6255 HValue* key, 6716 HValue* key,
6256 HValue* val, 6717 HValue* val,
6257 Expression* prop, 6718 Expression* prop,
6258 BailoutId ast_id, 6719 BailoutId ast_id,
6259 int position, 6720 int position,
6260 bool is_store, 6721 bool is_store,
6261 bool* has_side_effects) { 6722 bool* has_side_effects) {
6262 *has_side_effects = false; 6723 *has_side_effects = false;
6263 AddInstruction(new(zone()) HCheckNonSmi(object)); 6724 HCheckNonSmi* checknonsmi = new(zone()) HCheckNonSmi(object);
6725 AddInstruction(checknonsmi);
6264 SmallMapList* maps = prop->GetReceiverTypes(); 6726 SmallMapList* maps = prop->GetReceiverTypes();
6265 bool todo_external_array = false; 6727 bool todo_external_array = false;
6266 6728
6267 if (!is_store) { 6729 if (!is_store) {
6730 // TODO(mvstanton): Should I reference this as a TODO for worst case transit ion?
6268 HInstruction* consolidated_load = 6731 HInstruction* consolidated_load =
6269 TryBuildConsolidatedElementLoad(object, key, val, maps); 6732 TryBuildConsolidatedElementLoad(object, key, val, maps);
6270 if (consolidated_load != NULL) { 6733 if (consolidated_load != NULL) {
6271 AddInstruction(consolidated_load); 6734 AddInstruction(consolidated_load);
6272 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 6735 *has_side_effects |= consolidated_load->HasObservableSideEffects();
6273 if (position != RelocInfo::kNoPosition) { 6736 if (position != RelocInfo::kNoPosition) {
6274 consolidated_load->set_position(position); 6737 consolidated_load->set_position(position);
6275 } 6738 }
6276 return consolidated_load; 6739 return consolidated_load;
6277 } 6740 }
(...skipping 21 matching lines...) Expand all
6299 for (int i = 0; i < maps->length(); ++i) { 6762 for (int i = 0; i < maps->length(); ++i) {
6300 Handle<Map> map = maps->at(i); 6763 Handle<Map> map = maps->at(i);
6301 Handle<Map> transitioned_map = 6764 Handle<Map> transitioned_map =
6302 map->FindTransitionedMap(&possible_transitioned_maps); 6765 map->FindTransitionedMap(&possible_transitioned_maps);
6303 transition_target.Add(transitioned_map); 6766 transition_target.Add(transitioned_map);
6304 } 6767 }
6305 6768
6306 int num_untransitionable_maps = 0; 6769 int num_untransitionable_maps = 0;
6307 Handle<Map> untransitionable_map; 6770 Handle<Map> untransitionable_map;
6308 HTransitionElementsKind* transition = NULL; 6771 HTransitionElementsKind* transition = NULL;
6772 ZoneList<TransitionRecord> records(10, zone());
6309 for (int i = 0; i < maps->length(); ++i) { 6773 for (int i = 0; i < maps->length(); ++i) {
6310 Handle<Map> map = maps->at(i); 6774 Handle<Map> map = maps->at(i);
6311 ASSERT(map->IsMap()); 6775 ASSERT(map->IsMap());
6312 if (!transition_target.at(i).is_null()) { 6776 if (!transition_target.at(i).is_null()) {
6313 ASSERT(Map::IsValidElementsTransition( 6777 ASSERT(Map::IsValidElementsTransition(
6314 map->elements_kind(), 6778 map->elements_kind(),
6315 transition_target.at(i)->elements_kind())); 6779 transition_target.at(i)->elements_kind()));
6316 transition = new(zone()) HTransitionElementsKind( 6780 transition = new(zone()) HTransitionElementsKind(
6317 object, map, transition_target.at(i)); 6781 object, map, transition_target.at(i));
6318 AddInstruction(transition); 6782 AddInstruction(transition);
6783
6784 TransitionRecord tr(transition, map, transition_target.at(i));
6785 records.Add(tr,zone());
6319 } else { 6786 } else {
6320 type_todo[map->elements_kind()] = true; 6787 type_todo[map->elements_kind()] = true;
6321 if (IsExternalArrayElementsKind(map->elements_kind())) { 6788 if (IsExternalArrayElementsKind(map->elements_kind())) {
6322 todo_external_array = true; 6789 todo_external_array = true;
6323 } 6790 }
6324 num_untransitionable_maps++; 6791 num_untransitionable_maps++;
6325 untransitionable_map = map; 6792 untransitionable_map = map;
6326 } 6793 }
6327 } 6794 }
6328 6795
6329 // If only one map is left after transitioning, handle this case 6796 // If only one map is left after transitioning, handle this case
6330 // monomorphically. 6797 // monomorphically.
6331 if (num_untransitionable_maps == 1) { 6798 if (num_untransitionable_maps == 1) {
6332 HInstruction* instr = NULL; 6799 HInstruction* instr = NULL;
6333 if (untransitionable_map->has_slow_elements_kind()) { 6800 if (untransitionable_map->has_slow_elements_kind()) {
6334 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 6801 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
6335 : BuildLoadKeyedGeneric(object, key)); 6802 : BuildLoadKeyedGeneric(object, key));
6336 } else { 6803 } else {
6804 // TODO(mvstanton): when we remove the transition what do we do about the
6805 // parameter in the call to BuildMonomorphicElementAccess?
6806 HCheckMaps *checkmaps = NULL;
6337 instr = AddInstruction(BuildMonomorphicElementAccess( 6807 instr = AddInstruction(BuildMonomorphicElementAccess(
6338 object, key, val, transition, untransitionable_map, is_store)); 6808 object, key, val, transition, untransitionable_map, is_store,
6809 &checkmaps));
6810
6811 if (records.length() > 0) {
6812 DeferredTransitions todo(instr,checknonsmi,checkmaps,zone());
6813 todo.add_transitions(records);
6814 graph()->AddDeferredTransitions(todo);
6815 }
6339 } 6816 }
6340 *has_side_effects |= instr->HasObservableSideEffects(); 6817 *has_side_effects |= instr->HasObservableSideEffects();
6341 if (position != RelocInfo::kNoPosition) instr->set_position(position); 6818 if (position != RelocInfo::kNoPosition) instr->set_position(position);
6342 return is_store ? NULL : instr; 6819 return is_store ? NULL : instr;
6343 } 6820 }
6344 6821
6345 HInstruction* checkspec = 6822 HInstruction* checkspec =
6346 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); 6823 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
6347 HBasicBlock* join = graph()->CreateBasicBlock(); 6824 HBasicBlock* join = graph()->CreateBasicBlock();
6348 6825
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
6380 HBasicBlock* if_false = graph()->CreateBasicBlock(); 6857 HBasicBlock* if_false = graph()->CreateBasicBlock();
6381 HCompareConstantEqAndBranch* elements_kind_branch = 6858 HCompareConstantEqAndBranch* elements_kind_branch =
6382 new(zone()) HCompareConstantEqAndBranch( 6859 new(zone()) HCompareConstantEqAndBranch(
6383 elements_kind_instr, elements_kind, Token::EQ_STRICT); 6860 elements_kind_instr, elements_kind, Token::EQ_STRICT);
6384 elements_kind_branch->SetSuccessorAt(0, if_true); 6861 elements_kind_branch->SetSuccessorAt(0, if_true);
6385 elements_kind_branch->SetSuccessorAt(1, if_false); 6862 elements_kind_branch->SetSuccessorAt(1, if_false);
6386 current_block()->Finish(elements_kind_branch); 6863 current_block()->Finish(elements_kind_branch);
6387 6864
6388 set_current_block(if_true); 6865 set_current_block(if_true);
6389 HInstruction* access; 6866 HInstruction* access;
6867 HCheckMaps* checkmaps = NULL;
6390 if (IsFastElementsKind(elements_kind)) { 6868 if (IsFastElementsKind(elements_kind)) {
6391 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { 6869 if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
6392 AddInstruction(new(zone()) HCheckMaps( 6870 checkmaps = new(zone()) HCheckMaps(
6393 elements, isolate()->factory()->fixed_array_map(), 6871 elements, isolate()->factory()->fixed_array_map(),
6394 zone(), elements_kind_branch)); 6872 zone(), elements_kind_branch);
6873 AddInstruction(checkmaps);
6395 } 6874 }
6396 // TODO(jkummerow): The need for these two blocks could be avoided 6875 // TODO(jkummerow): The need for these two blocks could be avoided
6397 // in one of two ways: 6876 // in one of two ways:
6398 // (1) Introduce ElementsKinds for JSArrays that are distinct from 6877 // (1) Introduce ElementsKinds for JSArrays that are distinct from
6399 // those for fast objects. 6878 // those for fast objects.
6400 // (2) Put the common instructions into a third "join" block. This 6879 // (2) Put the common instructions into a third "join" block. This
6401 // requires additional AST IDs that we can deopt to from inside 6880 // requires additional AST IDs that we can deopt to from inside
6402 // that join block. They must be added to the Property class (when 6881 // that join block. They must be added to the Property class (when
6403 // it's a keyed property) and registered in the full codegen. 6882 // it's a keyed property) and registered in the full codegen.
6404 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); 6883 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
6405 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); 6884 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
6406 HHasInstanceTypeAndBranch* typecheck = 6885 HHasInstanceTypeAndBranch* typecheck =
6407 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); 6886 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
6408 typecheck->SetSuccessorAt(0, if_jsarray); 6887 typecheck->SetSuccessorAt(0, if_jsarray);
6409 typecheck->SetSuccessorAt(1, if_fastobject); 6888 typecheck->SetSuccessorAt(1, if_fastobject);
6410 current_block()->Finish(typecheck); 6889 current_block()->Finish(typecheck);
6411 6890
6412 set_current_block(if_jsarray); 6891 set_current_block(if_jsarray);
6413 HInstruction* length; 6892 HInstruction* length;
6414 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, 6893 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
6415 HType::Smi())); 6894 HType::Smi()));
6416 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, 6895 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
6417 ALLOW_SMI_KEY)); 6896 ALLOW_SMI_KEY));
6418 access = AddInstruction(BuildFastElementAccess( 6897 access = AddInstruction(BuildFastElementAccess(
6419 elements, checked_key, val, elements_kind_branch, 6898 elements, checked_key, val, elements_kind_branch,
6420 elements_kind, is_store)); 6899 elements_kind, is_store, true));
6421 if (!is_store) { 6900 if (!is_store) {
6422 Push(access); 6901 Push(access);
6423 } 6902 }
6424 6903
6425 *has_side_effects |= access->HasObservableSideEffects(); 6904 *has_side_effects |= access->HasObservableSideEffects();
6426 if (position != -1) { 6905 if (position != -1) {
6427 access->set_position(position); 6906 access->set_position(position);
6428 } 6907 }
6429 if_jsarray->Goto(join); 6908 if_jsarray->Goto(join);
6430 6909
6431 set_current_block(if_fastobject); 6910 set_current_block(if_fastobject);
6432 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 6911 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
6433 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, 6912 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
6434 ALLOW_SMI_KEY)); 6913 ALLOW_SMI_KEY));
6435 access = AddInstruction(BuildFastElementAccess( 6914 access = AddInstruction(BuildFastElementAccess(
6436 elements, checked_key, val, elements_kind_branch, 6915 elements, checked_key, val, elements_kind_branch,
6437 elements_kind, is_store)); 6916 elements_kind, is_store, true));
6438 } else if (elements_kind == DICTIONARY_ELEMENTS) { 6917 } else if (elements_kind == DICTIONARY_ELEMENTS) {
6439 if (is_store) { 6918 if (is_store) {
6440 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 6919 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
6441 } else { 6920 } else {
6442 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 6921 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
6443 } 6922 }
6444 } else { // External array elements. 6923 } else { // External array elements.
6445 access = AddInstruction(BuildExternalArrayElementAccess( 6924 access = AddInstruction(BuildExternalArrayElementAccess(
6446 external_elements, checked_key, val, elements_kind_branch, 6925 external_elements, checked_key, val, elements_kind_branch,
6447 elements_kind, is_store)); 6926 elements_kind, is_store));
6448 } 6927 }
6449 *has_side_effects |= access->HasObservableSideEffects(); 6928 *has_side_effects |= access->HasObservableSideEffects();
6450 if (position != RelocInfo::kNoPosition) access->set_position(position); 6929 if (position != RelocInfo::kNoPosition) access->set_position(position);
6451 if (!is_store) { 6930 if (!is_store) {
6452 Push(access); 6931 Push(access);
6453 } 6932 }
6933
6934 if (records.length() > 0) {
6935 // Only move transitions for fast element types
6936 if (IsFastElementsKind(elements_kind)) {
6937 ASSERT(access->IsLoadKeyed() || access->IsStoreKeyed());
6938 DeferredTransitions todo(access,checknonsmi,checkmaps,zone());
6939 todo.add_transitions(records);
6940 graph()->AddDeferredTransitions(todo);
6941 }
6942 }
6943
6454 current_block()->Goto(join); 6944 current_block()->Goto(join);
6455 set_current_block(if_false); 6945 set_current_block(if_false);
6456 } 6946 }
6457 } 6947 }
6458 6948
6459 // Deopt if none of the cases matched. 6949 // Deopt if none of the cases matched.
6460 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); 6950 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
6461 join->SetJoinId(ast_id); 6951 join->SetJoinId(ast_id);
6462 set_current_block(join); 6952 set_current_block(join);
6463 return is_store ? NULL : Pop(); 6953 return is_store ? NULL : Pop();
(...skipping 3227 matching lines...) Expand 10 before | Expand all | Expand 10 after
9691 10181
9692 10182
9693 void HEnvironment::PrintToStd() { 10183 void HEnvironment::PrintToStd() {
9694 HeapStringAllocator string_allocator; 10184 HeapStringAllocator string_allocator;
9695 StringStream trace(&string_allocator); 10185 StringStream trace(&string_allocator);
9696 PrintTo(&trace); 10186 PrintTo(&trace);
9697 PrintF("%s", *trace.ToCString()); 10187 PrintF("%s", *trace.ToCString());
9698 } 10188 }
9699 10189
9700 10190
10191 TransitionRecord::TransitionRecord(HTransitionElementsKind* transition_instr,
10192 Handle<Map> map_from, Handle<Map> map_to)
10193 : transition_instr_(transition_instr),
10194 map_from_(map_from),
10195 map_to_(map_to),
10196 optimistic_holey_() {
10197
10198 // When transition records are created, we have the chance to create map trans itions we
10199 // might need later. Transitions are unified during optimization, and we may n eed
10200 // to transition from a packed fastmap to a holey version of same. But we can' t create
10201 // those transitions during optimization. Do it now, recognizing that when the handle
10202 // disappears these maps may be collected if they didn't make it into usage in the
10203 // optimized graph.
10204
10205 // TODO(mvstanton): generalize this service into "MakeWorstCaseMapForElementsK indTransition"
10206 // (ie, not "holey")
10207 if (IsFastPackedElementsKind(map_to->elements_kind())) {
10208 ElementsKind holey_kind = GetHoleyElementsKind(map_to->elements_kind());
10209 // The transition might already exist
10210 Handle<Map> holey_map_handle(FindClosestElementsTransition(*map_to, holey_ki nd));
10211 ASSERT(!holey_map_handle.is_null());
10212 if (holey_map_handle->elements_kind() != holey_kind) {
10213 MaybeObject* holey_map = AddMissingElementsTransitions(*map_to, holey_kind );
10214 holey_map->ToHandle<Map>(&optimistic_holey_);
10215 } else {
10216 optimistic_holey_ = holey_map_handle;
10217 }
10218 } else {
10219 optimistic_holey_ = map_to;
10220 }
10221
10222 ASSERT(!optimistic_holey_.is_null());
10223
10224 // fill in map_family_
10225 // Walk up to the base map from the map_to();
10226 Handle<Map> end_map(FindClosestElementsTransition(*map_to, TERMINAL_FAST_ELEME NTS_KIND));
10227 ASSERT(!end_map.is_null());
10228 map_family_ = end_map;
10229 }
10230
10231
10232 void DeferredTransitions::compute_highest() {
10233 // Walk the transition records and find the "highest to" value, setting it.
10234 Map* newHighest = *(transition(0).map_to().location());
10235 set_highest(newHighest);
10236 }
10237
10238
10239 void DeferredTransitions::ComputeTerminalNodes(int maximumGraphValueID) {
10240 HValue* elements = NULL;
10241
10242 if(instr()->IsStoreKeyed()) {
10243 elements = HStoreKeyed::cast(instr())->elements();
10244 } else {
10245 CHECK(instr()->IsLoadKeyed());
10246 elements = HLoadKeyed::cast(instr())->elements();
10247 }
10248
10249 ASSERT(elements != NULL);
10250 // Now get the item from the elements
10251 ASSERT(elements->IsLoadElements());
10252 HLoadElements *start = HLoadElements::cast(elements);
10253
10254 ASSERT(terminal_nodes_->length() == 0);
10255 BitVector visited(maximumGraphValueID, zone());
10256
10257 ZoneList<HValue*> worklist(10, zone());
10258 worklist.Add(start->value(), zone());
10259
10260 while (!worklist.is_empty()) {
10261 HValue* value = worklist.RemoveLast();
10262 // Have we visited this node?
10263 if (!visited.Contains(value->id())) {
10264 visited.Add(value->id());
10265 if (value->IsPhi()) {
10266 HPhi *phi = HPhi::cast(value);
10267 for (int i=0; i<phi->OperandCount(); i++) {
10268 worklist.Add(phi->OperandAt(i), zone());
10269 }
10270 } else {
10271 // It must be a terminal node.
10272 ASSERT(value->IsInstruction());
10273 terminal_nodes_->Add(HInstruction::cast(value), zone());
10274 }
10275 }
10276 }
10277
10278 // We must have found something.
10279 ASSERT(terminal_nodes_->length() > 0);
10280 }
10281
10282
10283 void DeferredTransitions::PrintTo(StringStream* stream) const {
10284 stream->Add("SITE: block%d %d: ", instr()->block()->block_id(), instr()->id()) ;
10285 instr()->PrintTo(stream);
10286 stream->Add("\n");
10287
10288 // Print validness
10289 stream->Add(" VALIDITY: %s\n", invalid() ? "invalid" : "valid");
10290
10291 // Print score
10292 stream->Add(" SCORE: (+%d,%d,-%d)\n", score_[0], score_[1], score_[2]);
10293
10294 // Find the def point for the instruction
10295 HValue *elementsptr = NULL;
10296 if(instr()->IsStoreKeyed()) {
10297 elementsptr = HStoreKeyed::cast(instr())->elements();
10298 } else {
10299 ASSERT(instr()->IsLoadKeyed());
10300 elementsptr = HLoadKeyed::cast(instr())->elements();
10301 }
10302
10303 ASSERT(elementsptr != NULL);
10304 // Now get the item from the elements
10305 ASSERT(elementsptr->IsLoadElements());
10306 HLoadElements *elements = HLoadElements::cast(elementsptr);
10307 HValue *elementValue = elements->value();
10308 stream->Add(" OBJECT: ");
10309 elementValue->PrintNameTo(stream);
10310 stream->Add(" ");
10311 elementValue->PrintTo(stream);
10312 stream->Add(" %s\n",elementValue->IsPhi() ? "PHI" : "");
10313 stream->Add(" TRANSITIONS:\n");
10314 ElementsKind transitionElementsKind = FAST_SMI_ELEMENTS;
10315 for (int i = 0; i < transitions(); i++) {
10316 stream->Add(" %s", ElementsKindToString(transition(i).from()));
10317 stream->Add("(0x%p)-> ", *(transition(i).map_from()));
10318 stream->Add("%s", ElementsKindToString(transition(i).to()));
10319 stream->Add("(0x%p)\n", *(transition(i).map_to()));
10320 transitionElementsKind = transition(i).to();
10321 }
10322
10323 // Print possibly externally computed map
10324 const char *signifier = (transitionElementsKind != highest()->elements_kind())
10325 ? "*" : "";
10326 stream->Add(" COMPUTED HIGHEST: %s%s(0x%p)\n", signifier,
10327 ElementsKindToString(highest()->elements_kind()),
10328 highest());
10329
10330 // Print terminal nodes if available
10331 stream->Add(" TERMINAL NODES:\n");
10332 for (int j=0; j < terminal_nodes(); j++) {
10333 HValue* node = terminal_node(j);
10334 stream->Add(" block%d %d: ", node->block()->block_id(), node->id());
10335 node->PrintNameTo(stream);
10336 stream->Add(" ");
10337 node->PrintTo(stream);
10338 stream->Add("\n");
10339 }
10340
10341 }
10342
10343
10344 void DeferredTransitions::PrintToStd() const {
10345 HeapStringAllocator string_allocator;
10346 StringStream trace(&string_allocator);
10347 PrintTo(&trace);
10348 PrintF("%s", *trace.ToCString());
10349 }
10350
10351
9701 void HTracer::TraceCompilation(FunctionLiteral* function) { 10352 void HTracer::TraceCompilation(FunctionLiteral* function) {
9702 Tag tag(this, "compilation"); 10353 Tag tag(this, "compilation");
9703 Handle<String> name = function->debug_name(); 10354 Handle<String> name = function->debug_name();
9704 PrintStringProperty("name", *name->ToCString()); 10355 PrintStringProperty("name", *name->ToCString());
9705 PrintStringProperty("method", *name->ToCString()); 10356 PrintStringProperty("method", *name->ToCString());
9706 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 10357 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
9707 } 10358 }
9708 10359
9709 10360
9710 void HTracer::TraceLithium(const char* name, LChunk* chunk) { 10361 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
10011 } 10662 }
10012 } 10663 }
10013 10664
10014 #ifdef DEBUG 10665 #ifdef DEBUG
10015 if (graph_ != NULL) graph_->Verify(false); // No full verify. 10666 if (graph_ != NULL) graph_->Verify(false); // No full verify.
10016 if (allocator_ != NULL) allocator_->Verify(); 10667 if (allocator_ != NULL) allocator_->Verify();
10017 #endif 10668 #endif
10018 } 10669 }
10019 10670
10020 } } // namespace v8::internal 10671 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698