Revision f230a1cf deps/v8/src/hydrogen.cc
deps/v8/src/hydrogen.cc | ||
---|---|---|
30 | 30 |
#include <algorithm> |
31 | 31 |
|
32 | 32 |
#include "v8.h" |
33 |
#include "allocation-site-scopes.h" |
|
33 | 34 |
#include "codegen.h" |
34 | 35 |
#include "full-codegen.h" |
35 | 36 |
#include "hashmap.h" |
36 | 37 |
#include "hydrogen-bce.h" |
37 | 38 |
#include "hydrogen-bch.h" |
38 | 39 |
#include "hydrogen-canonicalize.h" |
40 |
#include "hydrogen-check-elimination.h" |
|
39 | 41 |
#include "hydrogen-dce.h" |
40 | 42 |
#include "hydrogen-dehoist.h" |
41 |
#include "hydrogen-deoptimizing-mark.h" |
|
42 | 43 |
#include "hydrogen-environment-liveness.h" |
43 | 44 |
#include "hydrogen-escape-analysis.h" |
44 | 45 |
#include "hydrogen-infer-representation.h" |
45 | 46 |
#include "hydrogen-infer-types.h" |
47 |
#include "hydrogen-load-elimination.h" |
|
46 | 48 |
#include "hydrogen-gvn.h" |
47 | 49 |
#include "hydrogen-mark-deoptimize.h" |
50 |
#include "hydrogen-mark-unreachable.h" |
|
48 | 51 |
#include "hydrogen-minus-zero.h" |
49 | 52 |
#include "hydrogen-osr.h" |
50 | 53 |
#include "hydrogen-range-analysis.h" |
... | ... | |
94 | 97 |
parent_loop_header_(NULL), |
95 | 98 |
inlined_entry_block_(NULL), |
96 | 99 |
is_inline_return_target_(false), |
97 |
is_deoptimizing_(false),
|
|
100 |
is_reachable_(true),
|
|
98 | 101 |
dominates_loop_successors_(false), |
99 | 102 |
is_osr_entry_(false) { } |
100 | 103 |
|
... | ... | |
104 | 107 |
} |
105 | 108 |
|
106 | 109 |
|
110 |
void HBasicBlock::MarkUnreachable() { |
|
111 |
is_reachable_ = false; |
|
112 |
} |
|
113 |
|
|
114 |
|
|
107 | 115 |
void HBasicBlock::AttachLoopInformation() { |
108 | 116 |
ASSERT(!IsLoopHeader()); |
109 | 117 |
loop_information_ = new(zone()) HLoopInformation(this, zone()); |
... | ... | |
132 | 140 |
} |
133 | 141 |
|
134 | 142 |
|
135 |
void HBasicBlock::AddInstruction(HInstruction* instr) { |
|
143 |
void HBasicBlock::AddInstruction(HInstruction* instr, int position) {
|
|
136 | 144 |
ASSERT(!IsStartBlock() || !IsFinished()); |
137 | 145 |
ASSERT(!instr->IsLinked()); |
138 | 146 |
ASSERT(!IsFinished()); |
139 | 147 |
|
148 |
if (position != RelocInfo::kNoPosition) { |
|
149 |
instr->set_position(position); |
|
150 |
} |
|
140 | 151 |
if (first_ == NULL) { |
141 | 152 |
ASSERT(last_environment() != NULL); |
142 | 153 |
ASSERT(!last_environment()->ast_id().IsNone()); |
143 | 154 |
HBlockEntry* entry = new(zone()) HBlockEntry(); |
144 | 155 |
entry->InitializeAsFirst(this); |
156 |
if (position != RelocInfo::kNoPosition) { |
|
157 |
entry->set_position(position); |
|
158 |
} else { |
|
159 |
ASSERT(!FLAG_emit_opt_code_positions || |
|
160 |
!graph()->info()->IsOptimizing()); |
|
161 |
} |
|
145 | 162 |
first_ = last_ = entry; |
146 | 163 |
} |
147 | 164 |
instr->InsertAfter(last_); |
... | ... | |
192 | 209 |
} |
193 | 210 |
|
194 | 211 |
|
195 |
void HBasicBlock::Finish(HControlInstruction* end) { |
|
212 |
void HBasicBlock::Finish(HControlInstruction* end, int position) {
|
|
196 | 213 |
ASSERT(!IsFinished()); |
197 |
AddInstruction(end); |
|
214 |
AddInstruction(end, position);
|
|
198 | 215 |
end_ = end; |
199 | 216 |
for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
200 | 217 |
it.Current()->RegisterPredecessor(this); |
... | ... | |
203 | 220 |
|
204 | 221 |
|
205 | 222 |
void HBasicBlock::Goto(HBasicBlock* block, |
223 |
int position, |
|
206 | 224 |
FunctionState* state, |
207 | 225 |
bool add_simulate) { |
208 | 226 |
bool drop_extra = state != NULL && |
209 | 227 |
state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
210 | 228 |
|
211 | 229 |
if (block->IsInlineReturnTarget()) { |
212 |
AddInstruction(new(zone()) HLeaveInlined()); |
|
230 |
HEnvironment* env = last_environment(); |
|
231 |
int argument_count = env->arguments_environment()->parameter_count(); |
|
232 |
AddInstruction(new(zone()) |
|
233 |
HLeaveInlined(state->entry(), argument_count), |
|
234 |
position); |
|
213 | 235 |
UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
214 | 236 |
} |
215 | 237 |
|
216 |
if (add_simulate) AddNewSimulate(BailoutId::None()); |
|
238 |
if (add_simulate) AddNewSimulate(BailoutId::None(), position);
|
|
217 | 239 |
HGoto* instr = new(zone()) HGoto(block); |
218 |
Finish(instr); |
|
240 |
Finish(instr, position);
|
|
219 | 241 |
} |
220 | 242 |
|
221 | 243 |
|
222 | 244 |
void HBasicBlock::AddLeaveInlined(HValue* return_value, |
223 |
FunctionState* state) { |
|
245 |
FunctionState* state, |
|
246 |
int position) { |
|
224 | 247 |
HBasicBlock* target = state->function_return(); |
225 | 248 |
bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
226 | 249 |
|
227 | 250 |
ASSERT(target->IsInlineReturnTarget()); |
228 | 251 |
ASSERT(return_value != NULL); |
229 |
AddInstruction(new(zone()) HLeaveInlined()); |
|
252 |
HEnvironment* env = last_environment(); |
|
253 |
int argument_count = env->arguments_environment()->parameter_count(); |
|
254 |
AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), |
|
255 |
position); |
|
230 | 256 |
UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
231 | 257 |
last_environment()->Push(return_value); |
232 |
AddNewSimulate(BailoutId::None()); |
|
258 |
AddNewSimulate(BailoutId::None(), position);
|
|
233 | 259 |
HGoto* instr = new(zone()) HGoto(target); |
234 |
Finish(instr); |
|
260 |
Finish(instr, position);
|
|
235 | 261 |
} |
236 | 262 |
|
237 | 263 |
|
... | ... | |
622 | 648 |
// Can't pass GetInvalidContext() to HConstant::New, because that will |
623 | 649 |
// recursively call GetConstant |
624 | 650 |
HConstant* constant = HConstant::New(zone(), NULL, value); |
625 |
constant->InsertAfter(GetConstantUndefined());
|
|
651 |
constant->InsertAfter(entry_block()->first());
|
|
626 | 652 |
pointer->set(constant); |
653 |
return constant; |
|
627 | 654 |
} |
628 |
return pointer->get(); |
|
655 |
return ReinsertConstantIfNecessary(pointer->get()); |
|
656 |
} |
|
657 |
|
|
658 |
|
|
659 |
HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) { |
|
660 |
if (!constant->IsLinked()) { |
|
661 |
// The constant was removed from the graph. Reinsert. |
|
662 |
constant->ClearFlag(HValue::kIsDead); |
|
663 |
constant->InsertAfter(entry_block()->first()); |
|
664 |
} |
|
665 |
return constant; |
|
629 | 666 |
} |
630 | 667 |
|
631 | 668 |
|
... | ... | |
648 | 685 |
HConstant* HGraph::GetConstant##Name() { \ |
649 | 686 |
if (!constant_##name##_.is_set()) { \ |
650 | 687 |
HConstant* constant = new(zone()) HConstant( \ |
651 |
isolate()->factory()->name##_value(), \ |
|
652 |
UniqueValueId::name##_value(isolate()->heap()), \ |
|
688 |
Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \ |
|
653 | 689 |
Representation::Tagged(), \ |
654 | 690 |
htype, \ |
655 | 691 |
false, \ |
656 | 692 |
true, \ |
657 | 693 |
false, \ |
658 | 694 |
boolean_value); \ |
659 |
constant->InsertAfter(GetConstantUndefined()); \
|
|
695 |
constant->InsertAfter(entry_block()->first()); \
|
|
660 | 696 |
constant_##name##_.set(constant); \ |
661 | 697 |
} \ |
662 |
return constant_##name##_.get(); \
|
|
698 |
return ReinsertConstantIfNecessary(constant_##name##_.get()); \
|
|
663 | 699 |
} |
664 | 700 |
|
665 | 701 |
|
702 |
DEFINE_GET_CONSTANT(Undefined, undefined, HType::Tagged(), false) |
|
666 | 703 |
DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) |
667 | 704 |
DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) |
668 | 705 |
DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) |
... | ... | |
690 | 727 |
} |
691 | 728 |
|
692 | 729 |
|
693 |
HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position)
|
|
730 |
HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) |
|
694 | 731 |
: builder_(builder), |
695 |
position_(position), |
|
696 | 732 |
finished_(false), |
697 | 733 |
deopt_then_(false), |
698 | 734 |
deopt_else_(false), |
... | ... | |
715 | 751 |
HGraphBuilder* builder, |
716 | 752 |
HIfContinuation* continuation) |
717 | 753 |
: builder_(builder), |
718 |
position_(RelocInfo::kNoPosition), |
|
719 | 754 |
finished_(false), |
720 | 755 |
deopt_then_(false), |
721 | 756 |
deopt_else_(false), |
... | ... | |
726 | 761 |
captured_(false), |
727 | 762 |
needs_compare_(false), |
728 | 763 |
first_true_block_(NULL), |
764 |
last_true_block_(NULL), |
|
729 | 765 |
first_false_block_(NULL), |
730 | 766 |
split_edge_merge_block_(NULL), |
731 | 767 |
merge_block_(NULL) { |
732 | 768 |
continuation->Continue(&first_true_block_, |
733 |
&first_false_block_, |
|
734 |
&position_); |
|
769 |
&first_false_block_); |
|
735 | 770 |
} |
736 | 771 |
|
737 | 772 |
|
738 |
void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { |
|
773 |
HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( |
|
774 |
HControlInstruction* compare) { |
|
739 | 775 |
if (split_edge_merge_block_ != NULL) { |
740 | 776 |
HEnvironment* env = first_false_block_->last_environment(); |
741 | 777 |
HBasicBlock* split_edge = |
... | ... | |
747 | 783 |
compare->SetSuccessorAt(0, first_true_block_); |
748 | 784 |
compare->SetSuccessorAt(1, split_edge); |
749 | 785 |
} |
750 |
split_edge->GotoNoSimulate(split_edge_merge_block_);
|
|
786 |
builder_->GotoNoSimulate(split_edge, split_edge_merge_block_);
|
|
751 | 787 |
} else { |
752 | 788 |
compare->SetSuccessorAt(0, first_true_block_); |
753 | 789 |
compare->SetSuccessorAt(1, first_false_block_); |
754 | 790 |
} |
755 |
builder_->current_block()->Finish(compare);
|
|
791 |
builder_->FinishCurrentBlock(compare);
|
|
756 | 792 |
needs_compare_ = false; |
793 |
return compare; |
|
757 | 794 |
} |
758 | 795 |
|
759 | 796 |
|
760 | 797 |
void HGraphBuilder::IfBuilder::Or() { |
798 |
ASSERT(!needs_compare_); |
|
761 | 799 |
ASSERT(!did_and_); |
762 | 800 |
did_or_ = true; |
763 | 801 |
HEnvironment* env = first_false_block_->last_environment(); |
764 | 802 |
if (split_edge_merge_block_ == NULL) { |
765 | 803 |
split_edge_merge_block_ = |
766 | 804 |
builder_->CreateBasicBlock(env->Copy()); |
767 |
first_true_block_->GotoNoSimulate(split_edge_merge_block_);
|
|
805 |
builder_->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
|
|
768 | 806 |
first_true_block_ = split_edge_merge_block_; |
769 | 807 |
} |
770 | 808 |
builder_->set_current_block(first_false_block_); |
... | ... | |
773 | 811 |
|
774 | 812 |
|
775 | 813 |
void HGraphBuilder::IfBuilder::And() { |
814 |
ASSERT(!needs_compare_); |
|
776 | 815 |
ASSERT(!did_or_); |
777 | 816 |
did_and_ = true; |
778 | 817 |
HEnvironment* env = first_false_block_->last_environment(); |
779 | 818 |
if (split_edge_merge_block_ == NULL) { |
780 | 819 |
split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); |
781 |
first_false_block_->GotoNoSimulate(split_edge_merge_block_);
|
|
820 |
builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
|
|
782 | 821 |
first_false_block_ = split_edge_merge_block_; |
783 | 822 |
} |
784 | 823 |
builder_->set_current_block(first_true_block_); |
... | ... | |
796 | 835 |
HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
797 | 836 |
? builder_->current_block() |
798 | 837 |
: first_false_block_; |
799 |
continuation->Capture(true_block, false_block, position_); |
|
838 |
continuation->Capture(true_block, false_block); |
|
839 |
captured_ = true; |
|
840 |
End(); |
|
841 |
} |
|
842 |
|
|
843 |
|
|
844 |
void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { |
|
845 |
ASSERT(!finished_); |
|
846 |
ASSERT(!captured_); |
|
847 |
HBasicBlock* true_block = last_true_block_ == NULL |
|
848 |
? first_true_block_ |
|
849 |
: last_true_block_; |
|
850 |
HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
|
851 |
? builder_->current_block() |
|
852 |
: first_false_block_; |
|
853 |
if (true_block != NULL && !true_block->IsFinished()) { |
|
854 |
ASSERT(continuation->IsTrueReachable()); |
|
855 |
builder_->GotoNoSimulate(true_block, continuation->true_branch()); |
|
856 |
} |
|
857 |
if (false_block != NULL && !false_block->IsFinished()) { |
|
858 |
ASSERT(continuation->IsFalseReachable()); |
|
859 |
builder_->GotoNoSimulate(false_block, continuation->false_branch()); |
|
860 |
} |
|
800 | 861 |
captured_ = true; |
801 | 862 |
End(); |
802 | 863 |
} |
... | ... | |
814 | 875 |
HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
815 | 876 |
ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); |
816 | 877 |
boolean_type.Add(ToBooleanStub::BOOLEAN); |
817 |
HBranch* branch = |
|
818 |
new(zone()) HBranch(constant_false, boolean_type, first_true_block_, |
|
819 |
first_false_block_); |
|
820 |
builder_->current_block()->Finish(branch); |
|
878 |
HBranch* branch = builder()->New<HBranch>( |
|
879 |
constant_false, boolean_type, first_true_block_, first_false_block_); |
|
880 |
builder_->FinishCurrentBlock(branch); |
|
821 | 881 |
} |
822 | 882 |
builder_->set_current_block(first_true_block_); |
823 | 883 |
} |
... | ... | |
845 | 905 |
|
846 | 906 |
|
847 | 907 |
void HGraphBuilder::IfBuilder::Return(HValue* value) { |
848 |
HBasicBlock* block = builder_->current_block(); |
|
849 | 908 |
HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
850 |
block->FinishExit(builder_->New<HReturn>(value, parameter_count));
|
|
851 |
builder_->set_current_block(NULL);
|
|
909 |
builder_->FinishExitCurrentBlock(
|
|
910 |
builder_->New<HReturn>(value, parameter_count));
|
|
852 | 911 |
if (did_else_) { |
853 | 912 |
first_false_block_ = NULL; |
854 | 913 |
} else { |
... | ... | |
878 | 937 |
HBasicBlock* last_false_block = builder_->current_block(); |
879 | 938 |
ASSERT(!last_false_block->IsFinished()); |
880 | 939 |
if (deopt_then_) { |
881 |
last_false_block->GotoNoSimulate(merge_block_);
|
|
940 |
builder_->GotoNoSimulate(last_false_block, merge_block_);
|
|
882 | 941 |
builder_->PadEnvironmentForContinuation(last_true_block_, |
883 | 942 |
merge_block_); |
884 |
last_true_block_->GotoNoSimulate(merge_block_);
|
|
943 |
builder_->GotoNoSimulate(last_true_block_, merge_block_);
|
|
885 | 944 |
} else { |
886 |
last_true_block_->GotoNoSimulate(merge_block_);
|
|
945 |
builder_->GotoNoSimulate(last_true_block_, merge_block_);
|
|
887 | 946 |
if (deopt_else_) { |
888 | 947 |
builder_->PadEnvironmentForContinuation(last_false_block, |
889 | 948 |
merge_block_); |
890 | 949 |
} |
891 |
last_false_block->GotoNoSimulate(merge_block_);
|
|
950 |
builder_->GotoNoSimulate(last_false_block, merge_block_);
|
|
892 | 951 |
} |
893 | 952 |
builder_->set_current_block(merge_block_); |
894 | 953 |
} |
... | ... | |
936 | 995 |
phi_ = header_block_->AddNewPhi(env->values()->length()); |
937 | 996 |
phi_->AddInput(initial); |
938 | 997 |
env->Push(initial); |
939 |
builder_->current_block()->GotoNoSimulate(header_block_);
|
|
998 |
builder_->GotoNoSimulate(header_block_); |
|
940 | 999 |
|
941 | 1000 |
HEnvironment* body_env = env->Copy(); |
942 | 1001 |
HEnvironment* exit_env = env->Copy(); |
... | ... | |
948 | 1007 |
|
949 | 1008 |
builder_->set_current_block(header_block_); |
950 | 1009 |
env->Pop(); |
951 |
HCompareNumericAndBranch* compare = |
|
952 |
new(zone()) HCompareNumericAndBranch(phi_, terminating, token); |
|
953 |
compare->SetSuccessorAt(0, body_block_); |
|
954 |
compare->SetSuccessorAt(1, exit_block_); |
|
955 |
builder_->current_block()->Finish(compare); |
|
1010 |
builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>( |
|
1011 |
phi_, terminating, token, body_block_, exit_block_)); |
|
956 | 1012 |
|
957 | 1013 |
builder_->set_current_block(body_block_); |
958 | 1014 |
if (direction_ == kPreIncrement || direction_ == kPreDecrement) { |
... | ... | |
976 | 1032 |
// Its the first time we saw a break. |
977 | 1033 |
HEnvironment* env = exit_block_->last_environment()->Copy(); |
978 | 1034 |
exit_trampoline_block_ = builder_->CreateBasicBlock(env); |
979 |
exit_block_->GotoNoSimulate(exit_trampoline_block_);
|
|
1035 |
builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
|
|
980 | 1036 |
} |
981 | 1037 |
|
982 |
builder_->current_block()->GotoNoSimulate(exit_trampoline_block_);
|
|
1038 |
builder_->GotoNoSimulate(exit_trampoline_block_); |
|
983 | 1039 |
} |
984 | 1040 |
|
985 | 1041 |
|
... | ... | |
999 | 1055 |
// Push the new increment value on the expression stack to merge into the phi. |
1000 | 1056 |
builder_->environment()->Push(increment_); |
1001 | 1057 |
HBasicBlock* last_block = builder_->current_block(); |
1002 |
last_block->GotoNoSimulate(header_block_);
|
|
1058 |
builder_->GotoNoSimulate(last_block, header_block_);
|
|
1003 | 1059 |
header_block_->loop_information()->RegisterBackEdge(last_block); |
1004 | 1060 |
|
1005 | 1061 |
if (exit_trampoline_block_ != NULL) { |
... | ... | |
1017 | 1073 |
CompilationPhase phase("H_Block building", info_); |
1018 | 1074 |
set_current_block(graph()->entry_block()); |
1019 | 1075 |
if (!BuildGraph()) return NULL; |
1020 |
graph()->FinalizeUniqueValueIds();
|
|
1076 |
graph()->FinalizeUniqueness();
|
|
1021 | 1077 |
return graph_; |
1022 | 1078 |
} |
1023 | 1079 |
|
1024 | 1080 |
|
1025 | 1081 |
HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
1026 | 1082 |
ASSERT(current_block() != NULL); |
1027 |
current_block()->AddInstruction(instr); |
|
1083 |
ASSERT(!FLAG_emit_opt_code_positions || |
|
1084 |
position_ != RelocInfo::kNoPosition || !info_->IsOptimizing()); |
|
1085 |
current_block()->AddInstruction(instr, position_); |
|
1028 | 1086 |
if (graph()->IsInsideNoSideEffectsScope()) { |
1029 | 1087 |
instr->SetFlag(HValue::kHasNoObservableSideEffects); |
1030 | 1088 |
} |
... | ... | |
1032 | 1090 |
} |
1033 | 1091 |
|
1034 | 1092 |
|
1035 |
void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, |
|
1036 |
HValue* context) { |
|
1093 |
void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { |
|
1094 |
ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || |
|
1095 |
position_ != RelocInfo::kNoPosition); |
|
1096 |
current_block()->Finish(last, position_); |
|
1097 |
if (last->IsReturn() || last->IsAbnormalExit()) { |
|
1098 |
set_current_block(NULL); |
|
1099 |
} |
|
1100 |
} |
|
1101 |
|
|
1102 |
|
|
1103 |
void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { |
|
1104 |
ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || |
|
1105 |
position_ != RelocInfo::kNoPosition); |
|
1106 |
current_block()->FinishExit(instruction, position_); |
|
1107 |
if (instruction->IsReturn() || instruction->IsAbnormalExit()) { |
|
1108 |
set_current_block(NULL); |
|
1109 |
} |
|
1110 |
} |
|
1111 |
|
|
1112 |
|
|
1113 |
void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
|
1037 | 1114 |
if (FLAG_native_code_counters && counter->Enabled()) { |
1038 | 1115 |
HValue* reference = Add<HConstant>(ExternalReference(counter)); |
1039 | 1116 |
HValue* old_value = Add<HLoadNamedField>(reference, |
... | ... | |
1081 | 1158 |
PadEnvironmentForContinuation(current_block(), continuation); |
1082 | 1159 |
Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1083 | 1160 |
if (graph()->IsInsideNoSideEffectsScope()) { |
1084 |
current_block()->GotoNoSimulate(continuation);
|
|
1161 |
GotoNoSimulate(continuation); |
|
1085 | 1162 |
} else { |
1086 |
current_block()->Goto(continuation);
|
|
1163 |
Goto(continuation); |
|
1087 | 1164 |
} |
1088 | 1165 |
} |
1089 | 1166 |
|
... | ... | |
1128 | 1205 |
HValue* length, |
1129 | 1206 |
HValue* key, |
1130 | 1207 |
bool is_js_array) { |
1131 |
Zone* zone = this->zone(); |
|
1132 | 1208 |
IfBuilder length_checker(this); |
1133 | 1209 |
|
1134 | 1210 |
Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; |
... | ... | |
1144 | 1220 |
Token::GTE); |
1145 | 1221 |
capacity_checker.Then(); |
1146 | 1222 |
|
1147 |
HValue* context = environment()->context(); |
|
1148 |
|
|
1149 | 1223 |
HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); |
1150 | 1224 |
HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); |
1151 | 1225 |
IfBuilder key_checker(this); |
... | ... | |
1166 | 1240 |
capacity_checker.End(); |
1167 | 1241 |
|
1168 | 1242 |
if (is_js_array) { |
1169 |
HValue* new_length = AddInstruction( |
|
1170 |
HAdd::New(zone, context, key, graph_->GetConstant1())); |
|
1243 |
HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); |
|
1171 | 1244 |
new_length->ClearFlag(HValue::kCanOverflow); |
1172 | 1245 |
|
1173 | 1246 |
Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), |
... | ... | |
1252 | 1325 |
} |
1253 | 1326 |
|
1254 | 1327 |
|
1328 |
HValue* HGraphBuilder::BuildNumberToString(HValue* object, |
|
1329 |
Handle<Type> type) { |
|
1330 |
NoObservableSideEffectsScope scope(this); |
|
1331 |
|
|
1332 |
// Create a joinable continuation. |
|
1333 |
HIfContinuation found(graph()->CreateBasicBlock(), |
|
1334 |
graph()->CreateBasicBlock()); |
|
1335 |
|
|
1336 |
// Load the number string cache. |
|
1337 |
HValue* number_string_cache = |
|
1338 |
Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); |
|
1339 |
|
|
1340 |
// Make the hash mask from the length of the number string cache. It |
|
1341 |
// contains two elements (number and string) for each cache entry. |
|
1342 |
HValue* mask = AddLoadFixedArrayLength(number_string_cache); |
|
1343 |
mask->set_type(HType::Smi()); |
|
1344 |
mask = Add<HSar>(mask, graph()->GetConstant1()); |
|
1345 |
mask = Add<HSub>(mask, graph()->GetConstant1()); |
|
1346 |
|
|
1347 |
// Check whether object is a smi. |
|
1348 |
IfBuilder if_objectissmi(this); |
|
1349 |
if_objectissmi.If<HIsSmiAndBranch>(object); |
|
1350 |
if_objectissmi.Then(); |
|
1351 |
{ |
|
1352 |
// Compute hash for smi similar to smi_get_hash(). |
|
1353 |
HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask); |
|
1354 |
|
|
1355 |
// Load the key. |
|
1356 |
HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); |
|
1357 |
HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, |
|
1358 |
static_cast<HValue*>(NULL), |
|
1359 |
FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
|
1360 |
|
|
1361 |
// Check if object == key. |
|
1362 |
IfBuilder if_objectiskey(this); |
|
1363 |
if_objectiskey.If<HCompareObjectEqAndBranch>(object, key); |
|
1364 |
if_objectiskey.Then(); |
|
1365 |
{ |
|
1366 |
// Make the key_index available. |
|
1367 |
Push(key_index); |
|
1368 |
} |
|
1369 |
if_objectiskey.JoinContinuation(&found); |
|
1370 |
} |
|
1371 |
if_objectissmi.Else(); |
|
1372 |
{ |
|
1373 |
if (type->Is(Type::Smi())) { |
|
1374 |
if_objectissmi.Deopt("Excepted smi"); |
|
1375 |
} else { |
|
1376 |
// Check if the object is a heap number. |
|
1377 |
IfBuilder if_objectisnumber(this); |
|
1378 |
if_objectisnumber.If<HCompareMap>( |
|
1379 |
object, isolate()->factory()->heap_number_map()); |
|
1380 |
if_objectisnumber.Then(); |
|
1381 |
{ |
|
1382 |
// Compute hash for heap number similar to double_get_hash(). |
|
1383 |
HValue* low = Add<HLoadNamedField>( |
|
1384 |
object, HObjectAccess::ForHeapNumberValueLowestBits()); |
|
1385 |
HValue* high = Add<HLoadNamedField>( |
|
1386 |
object, HObjectAccess::ForHeapNumberValueHighestBits()); |
|
1387 |
HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high); |
|
1388 |
hash = Add<HBitwise>(Token::BIT_AND, hash, mask); |
|
1389 |
|
|
1390 |
// Load the key. |
|
1391 |
HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); |
|
1392 |
HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, |
|
1393 |
static_cast<HValue*>(NULL), |
|
1394 |
FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
|
1395 |
|
|
1396 |
// Check if key is a heap number (the number string cache contains only |
|
1397 |
// SMIs and heap number, so it is sufficient to do a SMI check here). |
|
1398 |
IfBuilder if_keyisnotsmi(this); |
|
1399 |
if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key); |
|
1400 |
if_keyisnotsmi.Then(); |
|
1401 |
{ |
|
1402 |
// Check if values of key and object match. |
|
1403 |
IfBuilder if_keyeqobject(this); |
|
1404 |
if_keyeqobject.If<HCompareNumericAndBranch>( |
|
1405 |
Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()), |
|
1406 |
Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()), |
|
1407 |
Token::EQ); |
|
1408 |
if_keyeqobject.Then(); |
|
1409 |
{ |
|
1410 |
// Make the key_index available. |
|
1411 |
Push(key_index); |
|
1412 |
} |
|
1413 |
if_keyeqobject.JoinContinuation(&found); |
|
1414 |
} |
|
1415 |
if_keyisnotsmi.JoinContinuation(&found); |
|
1416 |
} |
|
1417 |
if_objectisnumber.Else(); |
|
1418 |
{ |
|
1419 |
if (type->Is(Type::Number())) { |
|
1420 |
if_objectisnumber.Deopt("Expected heap number"); |
|
1421 |
} |
|
1422 |
} |
|
1423 |
if_objectisnumber.JoinContinuation(&found); |
|
1424 |
} |
|
1425 |
} |
|
1426 |
if_objectissmi.JoinContinuation(&found); |
|
1427 |
|
|
1428 |
// Check for cache hit. |
|
1429 |
IfBuilder if_found(this, &found); |
|
1430 |
if_found.Then(); |
|
1431 |
{ |
|
1432 |
// Count number to string operation in native code. |
|
1433 |
AddIncrementCounter(isolate()->counters()->number_to_string_native()); |
|
1434 |
|
|
1435 |
// Load the value in case of cache hit. |
|
1436 |
HValue* key_index = Pop(); |
|
1437 |
HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1()); |
|
1438 |
Push(Add<HLoadKeyed>(number_string_cache, value_index, |
|
1439 |
static_cast<HValue*>(NULL), |
|
1440 |
FAST_ELEMENTS, ALLOW_RETURN_HOLE)); |
|
1441 |
} |
|
1442 |
if_found.Else(); |
|
1443 |
{ |
|
1444 |
// Cache miss, fallback to runtime. |
|
1445 |
Add<HPushArgument>(object); |
|
1446 |
Push(Add<HCallRuntime>( |
|
1447 |
isolate()->factory()->empty_string(), |
|
1448 |
Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), |
|
1449 |
1)); |
|
1450 |
} |
|
1451 |
if_found.End(); |
|
1452 |
|
|
1453 |
return Pop(); |
|
1454 |
} |
|
1455 |
|
|
1456 |
|
|
1255 | 1457 |
HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
1256 | 1458 |
HValue* checked_object, |
1257 | 1459 |
HValue* key, |
... | ... | |
1303 | 1505 |
HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
1304 | 1506 |
key, graph()->GetConstant0(), Token::GTE); |
1305 | 1507 |
negative_checker.Then(); |
1306 |
HInstruction* result = AddExternalArrayElementAccess(
|
|
1508 |
HInstruction* result = AddElementAccess( |
|
1307 | 1509 |
external_elements, key, val, bounds_check, elements_kind, is_store); |
1308 | 1510 |
negative_checker.ElseDeopt("Negative key encountered"); |
1309 | 1511 |
length_checker.End(); |
... | ... | |
1313 | 1515 |
checked_key = Add<HBoundsCheck>(key, length); |
1314 | 1516 |
HLoadExternalArrayPointer* external_elements = |
1315 | 1517 |
Add<HLoadExternalArrayPointer>(elements); |
1316 |
return AddExternalArrayElementAccess(
|
|
1518 |
return AddElementAccess( |
|
1317 | 1519 |
external_elements, checked_key, val, |
1318 | 1520 |
checked_object, elements_kind, is_store); |
1319 | 1521 |
} |
... | ... | |
1346 | 1548 |
elements_kind, length); |
1347 | 1549 |
} else { |
1348 | 1550 |
HCheckMaps* check_cow_map = Add<HCheckMaps>( |
1349 |
elements, isolate()->factory()->fixed_array_map(), |
|
1350 |
top_info()); |
|
1551 |
elements, isolate()->factory()->fixed_array_map(), top_info()); |
|
1351 | 1552 |
check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1352 | 1553 |
} |
1353 | 1554 |
} |
1354 | 1555 |
} |
1355 |
return AddFastElementAccess(elements, checked_key, val, checked_object,
|
|
1356 |
elements_kind, is_store, load_mode, store_mode);
|
|
1556 |
return AddElementAccess(elements, checked_key, val, checked_object, |
|
1557 |
elements_kind, is_store, load_mode);
|
|
1357 | 1558 |
} |
1358 | 1559 |
|
1359 | 1560 |
|
... | ... | |
1443 | 1644 |
} |
1444 | 1645 |
|
1445 | 1646 |
|
1446 |
HInstruction* HGraphBuilder::AddExternalArrayElementAccess(
|
|
1447 |
HValue* external_elements,
|
|
1647 |
HInstruction* HGraphBuilder::AddElementAccess( |
|
1648 |
HValue* elements, |
|
1448 | 1649 |
HValue* checked_key, |
1449 | 1650 |
HValue* val, |
1450 | 1651 |
HValue* dependency, |
1451 | 1652 |
ElementsKind elements_kind, |
1452 |
bool is_store) { |
|
1653 |
bool is_store, |
|
1654 |
LoadKeyedHoleMode load_mode) { |
|
1453 | 1655 |
if (is_store) { |
1454 | 1656 |
ASSERT(val != NULL); |
1455 |
switch (elements_kind) { |
|
1456 |
case EXTERNAL_PIXEL_ELEMENTS: { |
|
1457 |
val = Add<HClampToUint8>(val); |
|
1458 |
break; |
|
1459 |
} |
|
1460 |
case EXTERNAL_BYTE_ELEMENTS: |
|
1461 |
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
|
1462 |
case EXTERNAL_SHORT_ELEMENTS: |
|
1463 |
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
|
1464 |
case EXTERNAL_INT_ELEMENTS: |
|
1465 |
case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
|
1466 |
break; |
|
1467 |
} |
|
1468 |
case EXTERNAL_FLOAT_ELEMENTS: |
|
1469 |
case EXTERNAL_DOUBLE_ELEMENTS: |
|
1470 |
break; |
|
1471 |
case FAST_SMI_ELEMENTS: |
|
1472 |
case FAST_ELEMENTS: |
|
1473 |
case FAST_DOUBLE_ELEMENTS: |
|
1474 |
case FAST_HOLEY_SMI_ELEMENTS: |
|
1475 |
case FAST_HOLEY_ELEMENTS: |
|
1476 |
case FAST_HOLEY_DOUBLE_ELEMENTS: |
|
1477 |
case DICTIONARY_ELEMENTS: |
|
1478 |
case NON_STRICT_ARGUMENTS_ELEMENTS: |
|
1479 |
UNREACHABLE(); |
|
1480 |
break; |
|
1657 |
if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { |
|
1658 |
val = Add<HClampToUint8>(val); |
|
1481 | 1659 |
} |
1482 |
return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); |
|
1483 |
} else { |
|
1484 |
ASSERT(val == NULL); |
|
1485 |
HLoadKeyed* load = Add<HLoadKeyed>(external_elements, |
|
1486 |
checked_key, |
|
1487 |
dependency, |
|
1488 |
elements_kind); |
|
1489 |
if (FLAG_opt_safe_uint32_operations && |
|
1490 |
elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
|
1491 |
graph()->RecordUint32Instruction(load); |
|
1492 |
} |
|
1493 |
return load; |
|
1660 |
return Add<HStoreKeyed>(elements, checked_key, val, elements_kind); |
|
1494 | 1661 |
} |
1495 |
} |
|
1496 |
|
|
1497 | 1662 |
|
1498 |
HInstruction* HGraphBuilder::AddFastElementAccess( |
|
1499 |
HValue* elements, |
|
1500 |
HValue* checked_key, |
|
1501 |
HValue* val, |
|
1502 |
HValue* load_dependency, |
|
1503 |
ElementsKind elements_kind, |
|
1504 |
bool is_store, |
|
1505 |
LoadKeyedHoleMode load_mode, |
|
1506 |
KeyedAccessStoreMode store_mode) { |
|
1507 |
if (is_store) { |
|
1508 |
ASSERT(val != NULL); |
|
1509 |
switch (elements_kind) { |
|
1510 |
case FAST_SMI_ELEMENTS: |
|
1511 |
case FAST_HOLEY_SMI_ELEMENTS: |
|
1512 |
case FAST_ELEMENTS: |
|
1513 |
case FAST_HOLEY_ELEMENTS: |
|
1514 |
case FAST_DOUBLE_ELEMENTS: |
|
1515 |
case FAST_HOLEY_DOUBLE_ELEMENTS: |
|
1516 |
return Add<HStoreKeyed>(elements, checked_key, val, elements_kind); |
|
1517 |
default: |
|
1518 |
UNREACHABLE(); |
|
1519 |
return NULL; |
|
1520 |
} |
|
1663 |
ASSERT(!is_store); |
|
1664 |
ASSERT(val == NULL); |
|
1665 |
HLoadKeyed* load = Add<HLoadKeyed>( |
|
1666 |
elements, checked_key, dependency, elements_kind, load_mode); |
|
1667 |
if (FLAG_opt_safe_uint32_operations && |
|
1668 |
elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
|
1669 |
graph()->RecordUint32Instruction(load); |
|
1521 | 1670 |
} |
1522 |
// It's an element load (!is_store). |
|
1523 |
return Add<HLoadKeyed>( |
|
1524 |
elements, checked_key, load_dependency, elements_kind, load_mode); |
|
1671 |
return load; |
|
1525 | 1672 |
} |
1526 | 1673 |
|
1527 | 1674 |
|
... | ... | |
1771 | 1918 |
void HGraphBuilder::BuildCompareNil( |
1772 | 1919 |
HValue* value, |
1773 | 1920 |
Handle<Type> type, |
1774 |
int position, |
|
1775 | 1921 |
HIfContinuation* continuation) { |
1776 |
IfBuilder if_nil(this, position);
|
|
1922 |
IfBuilder if_nil(this); |
|
1777 | 1923 |
bool some_case_handled = false; |
1778 | 1924 |
bool some_case_missing = false; |
1779 | 1925 |
|
... | ... | |
1824 | 1970 |
HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, |
1825 | 1971 |
int previous_object_size, |
1826 | 1972 |
HValue* alloc_site) { |
1827 |
// TODO(mvstanton): ASSERT altered to CHECK to diagnose chromium bug 284577 |
|
1828 |
CHECK(alloc_site != NULL); |
|
1973 |
ASSERT(alloc_site != NULL); |
|
1829 | 1974 |
HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( |
1830 | 1975 |
previous_object, previous_object_size); |
1831 |
Handle<Map> alloc_memento_map(
|
|
1832 |
isolate()->heap()->allocation_memento_map());
|
|
1976 |
Handle<Map> alloc_memento_map =
|
|
1977 |
isolate()->factory()->allocation_memento_map();
|
|
1833 | 1978 |
AddStoreMapConstant(alloc_memento, alloc_memento_map); |
1834 | 1979 |
HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); |
1835 | 1980 |
Add<HStoreNamedField>(alloc_memento, access, alloc_site); |
... | ... | |
1886 | 2031 |
// No need for a context lookup if the kind_ matches the initial |
1887 | 2032 |
// map, because we can just load the map in that case. |
1888 | 2033 |
HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1889 |
return builder()->AddInstruction( |
|
1890 |
builder()->BuildLoadNamedField(constructor_function_, access)); |
|
2034 |
return builder()->AddLoadNamedField(constructor_function_, access); |
|
1891 | 2035 |
} |
1892 | 2036 |
|
1893 | 2037 |
HInstruction* native_context = builder()->BuildGetNativeContext(); |
... | ... | |
1907 | 2051 |
HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
1908 | 2052 |
// Find the map near the constructor function |
1909 | 2053 |
HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1910 |
return builder()->AddInstruction( |
|
1911 |
builder()->BuildLoadNamedField(constructor_function_, access)); |
|
2054 |
return builder()->AddLoadNamedField(constructor_function_, access); |
|
1912 | 2055 |
} |
1913 | 2056 |
|
1914 | 2057 |
|
... | ... | |
1983 | 2126 |
HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, |
1984 | 2127 |
HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); |
1985 | 2128 |
|
2129 |
// Folded array allocation should be aligned if it has fast double elements. |
|
2130 |
if (IsFastDoubleElementsKind(kind_)) { |
|
2131 |
new_object->MakeDoubleAligned(); |
|
2132 |
} |
|
2133 |
|
|
1986 | 2134 |
// Fill in the fields: map, properties, length |
1987 | 2135 |
HValue* map; |
1988 | 2136 |
if (allocation_site_payload_ == NULL) { |
... | ... | |
2042 | 2190 |
// to know it's the initial state. |
2043 | 2191 |
function_state_= &initial_function_state_; |
2044 | 2192 |
InitializeAstVisitor(info->isolate()); |
2193 |
if (FLAG_emit_opt_code_positions) { |
|
2194 |
SetSourcePosition(info->shared_info()->start_position()); |
|
2195 |
} |
|
2045 | 2196 |
} |
2046 | 2197 |
|
2047 | 2198 |
|
... | ... | |
2054 | 2205 |
return first; |
2055 | 2206 |
} else { |
2056 | 2207 |
HBasicBlock* join_block = graph()->CreateBasicBlock(); |
2057 |
first->Goto(join_block);
|
|
2058 |
second->Goto(join_block);
|
|
2208 |
Goto(first, join_block);
|
|
2209 |
Goto(second, join_block);
|
|
2059 | 2210 |
join_block->SetJoinId(join_id); |
2060 | 2211 |
return join_block; |
2061 | 2212 |
} |
... | ... | |
2066 | 2217 |
HBasicBlock* exit_block, |
2067 | 2218 |
HBasicBlock* continue_block) { |
2068 | 2219 |
if (continue_block != NULL) { |
2069 |
if (exit_block != NULL) exit_block->Goto(continue_block);
|
|
2220 |
if (exit_block != NULL) Goto(exit_block, continue_block);
|
|
2070 | 2221 |
continue_block->SetJoinId(statement->ContinueId()); |
2071 | 2222 |
return continue_block; |
2072 | 2223 |
} |
... | ... | |
2079 | 2230 |
HBasicBlock* body_exit, |
2080 | 2231 |
HBasicBlock* loop_successor, |
2081 | 2232 |
HBasicBlock* break_block) { |
2082 |
if (body_exit != NULL) body_exit->Goto(loop_entry);
|
|
2233 |
if (body_exit != NULL) Goto(body_exit, loop_entry);
|
|
2083 | 2234 |
loop_entry->PostProcessLoopHeader(statement); |
2084 | 2235 |
if (break_block != NULL) { |
2085 |
if (loop_successor != NULL) loop_successor->Goto(break_block);
|
|
2236 |
if (loop_successor != NULL) Goto(loop_successor, break_block);
|
|
2086 | 2237 |
break_block->SetJoinId(statement->ExitId()); |
2087 | 2238 |
return break_block; |
2088 | 2239 |
} |
... | ... | |
2090 | 2241 |
} |
2091 | 2242 |
|
2092 | 2243 |
|
2093 |
void HBasicBlock::FinishExit(HControlInstruction* instruction) { |
|
2094 |
Finish(instruction); |
|
2244 |
// Build a new loop header block and set it as the current block. |
|
2245 |
HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() { |
|
2246 |
HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
|
2247 |
Goto(loop_entry); |
|
2248 |
set_current_block(loop_entry); |
|
2249 |
return loop_entry; |
|
2250 |
} |
|
2251 |
|
|
2252 |
|
|
2253 |
HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( |
|
2254 |
IterationStatement* statement) { |
|
2255 |
HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) |
|
2256 |
? osr()->BuildOsrLoopEntry(statement) |
|
2257 |
: BuildLoopEntry(); |
|
2258 |
return loop_entry; |
|
2259 |
} |
|
2260 |
|
|
2261 |
|
|
2262 |
void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) { |
|
2263 |
Finish(instruction, position); |
|
2095 | 2264 |
ClearEnvironment(); |
2096 | 2265 |
} |
2097 | 2266 |
|
... | ... | |
2109 | 2278 |
zone_(info->zone()), |
2110 | 2279 |
is_recursive_(false), |
2111 | 2280 |
use_optimistic_licm_(false), |
2112 |
has_soft_deoptimize_(false), |
|
2113 | 2281 |
depends_on_empty_array_proto_elements_(false), |
2114 | 2282 |
type_change_checksum_(0), |
2115 | 2283 |
maximum_environment_size_(0), |
... | ... | |
2137 | 2305 |
} |
2138 | 2306 |
|
2139 | 2307 |
|
2140 |
void HGraph::FinalizeUniqueValueIds() {
|
|
2308 |
void HGraph::FinalizeUniqueness() {
|
|
2141 | 2309 |
DisallowHeapAllocation no_gc; |
2142 | 2310 |
ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); |
2143 | 2311 |
for (int i = 0; i < blocks()->length(); ++i) { |
2144 | 2312 |
for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { |
2145 |
it.Current()->FinalizeUniqueValueId();
|
|
2313 |
it.Current()->FinalizeUniqueness();
|
|
2146 | 2314 |
} |
2147 | 2315 |
} |
2148 | 2316 |
} |
... | ... | |
2640 | 2808 |
HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
2641 | 2809 |
instr->SetSuccessorAt(0, empty_true); |
2642 | 2810 |
instr->SetSuccessorAt(1, empty_false); |
2643 |
owner()->current_block()->Finish(instr);
|
|
2811 |
owner()->FinishCurrentBlock(instr);
|
|
2644 | 2812 |
HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
2645 | 2813 |
owner()->set_current_block(join); |
2646 | 2814 |
} |
... | ... | |
2650 | 2818 |
BailoutId ast_id) { |
2651 | 2819 |
HBasicBlock* true_branch = NULL; |
2652 | 2820 |
HBasicBlock* false_branch = NULL; |
2653 |
continuation->Continue(&true_branch, &false_branch, NULL);
|
|
2821 |
continuation->Continue(&true_branch, &false_branch); |
|
2654 | 2822 |
if (!continuation->IsTrueReachable()) { |
2655 | 2823 |
owner()->set_current_block(false_branch); |
2656 | 2824 |
} else if (!continuation->IsFalseReachable()) { |
... | ... | |
2684 | 2852 |
HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
2685 | 2853 |
instr->SetSuccessorAt(0, materialize_true); |
2686 | 2854 |
instr->SetSuccessorAt(1, materialize_false); |
2687 |
owner()->current_block()->Finish(instr);
|
|
2855 |
owner()->FinishCurrentBlock(instr);
|
|
2688 | 2856 |
owner()->set_current_block(materialize_true); |
2689 | 2857 |
owner()->Push(owner()->graph()->GetConstantTrue()); |
2690 | 2858 |
owner()->set_current_block(materialize_false); |
... | ... | |
2699 | 2867 |
BailoutId ast_id) { |
2700 | 2868 |
HBasicBlock* materialize_true = NULL; |
2701 | 2869 |
HBasicBlock* materialize_false = NULL; |
2702 |
continuation->Continue(&materialize_true, &materialize_false, NULL);
|
|
2870 |
continuation->Continue(&materialize_true, &materialize_false); |
|
2703 | 2871 |
if (continuation->IsTrueReachable()) { |
2704 | 2872 |
owner()->set_current_block(materialize_true); |
2705 | 2873 |
owner()->Push(owner()->graph()->GetConstantTrue()); |
... | ... | |
2739 | 2907 |
HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
2740 | 2908 |
instr->SetSuccessorAt(0, empty_true); |
2741 | 2909 |
instr->SetSuccessorAt(1, empty_false); |
2742 |
owner()->current_block()->Finish(instr);
|
|
2743 |
empty_true->Goto(if_true(), owner()->function_state());
|
|
2744 |
empty_false->Goto(if_false(), owner()->function_state());
|
|
2910 |
owner()->FinishCurrentBlock(instr);
|
|
2911 |
owner()->Goto(empty_true, if_true(), owner()->function_state());
|
|
2912 |
owner()->Goto(empty_false, if_false(), owner()->function_state());
|
|
2745 | 2913 |
owner()->set_current_block(NULL); |
2746 | 2914 |
} |
2747 | 2915 |
|
... | ... | |
2750 | 2918 |
BailoutId ast_id) { |
2751 | 2919 |
HBasicBlock* true_branch = NULL; |
2752 | 2920 |
HBasicBlock* false_branch = NULL; |
2753 |
continuation->Continue(&true_branch, &false_branch, NULL);
|
|
2921 |
continuation->Continue(&true_branch, &false_branch); |
|
2754 | 2922 |
if (continuation->IsTrueReachable()) { |
2755 |
true_branch->Goto(if_true(), owner()->function_state());
|
|
2923 |
owner()->Goto(true_branch, if_true(), owner()->function_state());
|
|
2756 | 2924 |
} |
2757 | 2925 |
if (continuation->IsFalseReachable()) { |
2758 |
false_branch->Goto(if_false(), owner()->function_state());
|
|
2926 |
owner()->Goto(false_branch, if_false(), owner()->function_state());
|
|
2759 | 2927 |
} |
2760 | 2928 |
owner()->set_current_block(NULL); |
2761 | 2929 |
} |
... | ... | |
2773 | 2941 |
HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
2774 | 2942 |
HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
2775 | 2943 |
ToBooleanStub::Types expected(condition()->to_boolean_types()); |
2776 |
HBranch* test = new(zone()) HBranch(value, expected, empty_true, empty_false);
|
|
2777 |
builder->current_block()->Finish(test);
|
|
2944 |
builder->FinishCurrentBlock(builder->New<HBranch>(
|
|
2945 |
value, expected, empty_true, empty_false));
|
|
2778 | 2946 |
|
2779 |
empty_true->Goto(if_true(), builder->function_state());
|
|
2780 |
empty_false->Goto(if_false(), builder->function_state());
|
|
2947 |
owner()->Goto(empty_true, if_true(), builder->function_state());
|
|
2948 |
owner()->Goto(empty_false , if_false(), builder->function_state());
|
|
2781 | 2949 |
builder->set_current_block(NULL); |
2782 | 2950 |
} |
2783 | 2951 |
|
... | ... | |
2894 | 3062 |
// not replayed by the Lithium translation. |
2895 | 3063 |
HEnvironment* initial_env = environment()->CopyWithoutHistory(); |
2896 | 3064 |
HBasicBlock* body_entry = CreateBasicBlock(initial_env); |
2897 |
current_block()->Goto(body_entry);
|
|
3065 |
Goto(body_entry); |
|
2898 | 3066 |
body_entry->SetJoinId(BailoutId::FunctionEntry()); |
2899 | 3067 |
set_current_block(body_entry); |
2900 | 3068 |
|
... | ... | |
2906 | 3074 |
VisitDeclarations(scope->declarations()); |
2907 | 3075 |
Add<HSimulate>(BailoutId::Declarations()); |
2908 | 3076 |
|
2909 |
HValue* context = environment()->context(); |
|
2910 |
Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
|
3077 |
Add<HStackCheck>(HStackCheck::kFunctionEntry); |
|
2911 | 3078 |
|
2912 | 3079 |
VisitStatements(current_info()->function()->body()); |
2913 | 3080 |
if (HasStackOverflow()) return false; |
... | ... | |
2932 | 3099 |
type_info->set_inlined_type_change_checksum(composite_checksum); |
2933 | 3100 |
|
2934 | 3101 |
// Perform any necessary OSR-specific cleanups or changes to the graph. |
2935 |
osr_->FinishGraph();
|
|
3102 |
osr()->FinishGraph();
|
|
2936 | 3103 |
|
2937 | 3104 |
return true; |
2938 | 3105 |
} |
... | ... | |
2957 | 3124 |
Run<HEnvironmentLivenessAnalysisPhase>(); |
2958 | 3125 |
} |
2959 | 3126 |
|
2960 |
Run<HPropagateDeoptimizingMarkPhase>(); |
|
2961 | 3127 |
if (!CheckConstPhiUses()) { |
2962 | 3128 |
*bailout_reason = kUnsupportedPhiUseOfConstVariable; |
2963 | 3129 |
return false; |
... | ... | |
2968 | 3134 |
return false; |
2969 | 3135 |
} |
2970 | 3136 |
|
2971 |
// Remove dead code and phis |
|
2972 |
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
|
3137 |
// Find and mark unreachable code to simplify optimizations, especially gvn, |
|
3138 |
// where unreachable code could unnecessarily defeat LICM. |
|
3139 |
Run<HMarkUnreachableBlocksPhase>(); |
|
2973 | 3140 |
|
3141 |
if (FLAG_check_elimination) Run<HCheckEliminationPhase>(); |
|
3142 |
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
|
2974 | 3143 |
if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); |
2975 | 3144 |
|
3145 |
if (FLAG_load_elimination) Run<HLoadEliminationPhase>(); |
|
3146 |
|
|
2976 | 3147 |
CollectPhis(); |
2977 | 3148 |
|
2978 | 3149 |
if (has_osr()) osr()->FinishOsrValues(); |
... | ... | |
3006 | 3177 |
// Eliminate redundant stack checks on backwards branches. |
3007 | 3178 |
Run<HStackCheckEliminationPhase>(); |
3008 | 3179 |
|
3009 |
if (FLAG_array_bounds_checks_elimination) { |
|
3010 |
Run<HBoundsCheckEliminationPhase>(); |
|
3011 |
} |
|
3012 |
if (FLAG_array_bounds_checks_hoisting) { |
|
3013 |
Run<HBoundsCheckHoistingPhase>(); |
|
3014 |
} |
|
3180 |
if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>(); |
|
3181 |
if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>(); |
|
3015 | 3182 |
if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); |
3016 | 3183 |
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
3017 | 3184 |
|
3018 | 3185 |
RestoreActualValues(); |
3019 | 3186 |
|
3187 |
// Find unreachable code a second time, GVN and other optimizations may have |
|
3188 |
// made blocks unreachable that were previously reachable. |
|
3189 |
Run<HMarkUnreachableBlocksPhase>(); |
|
3190 |
|
|
3020 | 3191 |
return true; |
3021 | 3192 |
} |
3022 | 3193 |
|
... | ... | |
3049 | 3220 |
} |
3050 | 3221 |
|
3051 | 3222 |
|
3052 |
void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
|
3053 |
Push(instr); |
|
3054 |
AddInstruction(instr); |
|
3055 |
} |
|
3056 |
|
|
3057 |
|
|
3058 | 3223 |
template <class Instruction> |
3059 | 3224 |
HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
3060 | 3225 |
int count = call->argument_count(); |
... | ... | |
3075 | 3240 |
HInstruction* context = Add<HContext>(); |
3076 | 3241 |
environment()->BindContext(context); |
3077 | 3242 |
|
3078 |
HConstant* undefined_constant = HConstant::cast(Add<HConstant>( |
|
3079 |
isolate()->factory()->undefined_value())); |
|
3080 |
graph()->set_undefined_constant(undefined_constant); |
|
3081 |
|
|
3082 | 3243 |
// Create an arguments object containing the initial parameters. Set the |
3083 | 3244 |
// initial values of parameters including "this" having parameter index 0. |
3084 | 3245 |
ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
... | ... | |
3092 | 3253 |
AddInstruction(arguments_object); |
3093 | 3254 |
graph()->SetArgumentsObject(arguments_object); |
3094 | 3255 |
|
3256 |
HConstant* undefined_constant = graph()->GetConstantUndefined(); |
|
3095 | 3257 |
// Initialize specials and locals to undefined. |
3096 | 3258 |
for (int i = environment()->parameter_count() + 1; |
3097 | 3259 |
i < environment()->length(); |
... | ... | |
3134 | 3296 |
} |
3135 | 3297 |
HBasicBlock* break_block = break_info.break_block(); |
3136 | 3298 |
if (break_block != NULL) { |
3137 |
if (current_block() != NULL) current_block()->Goto(break_block);
|
|
3299 |
if (current_block() != NULL) Goto(break_block); |
|
3138 | 3300 |
break_block->SetJoinId(stmt->ExitId()); |
3139 | 3301 |
set_current_block(break_block); |
3140 | 3302 |
} |
... | ... | |
3244 | 3406 |
HBasicBlock* continue_block = break_scope()->Get( |
3245 | 3407 |
stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra); |
3246 | 3408 |
Drop(drop_extra); |
3247 |
current_block()->Goto(continue_block);
|
|
3409 |
Goto(continue_block); |
|
3248 | 3410 |
set_current_block(NULL); |
3249 | 3411 |
} |
3250 | 3412 |
|
... | ... | |
3257 | 3419 |
HBasicBlock* break_block = break_scope()->Get( |
3258 | 3420 |
stmt->target(), BreakAndContinueScope::BREAK, &drop_extra); |
3259 | 3421 |
Drop(drop_extra); |
3260 |
current_block()->Goto(break_block);
|
|
3422 |
Goto(break_block); |
|
3261 | 3423 |
set_current_block(NULL); |
3262 | 3424 |
} |
3263 | 3425 |
|
... | ... | |
3280 | 3442 |
if (context->IsTest()) { |
3281 | 3443 |
TestContext* test = TestContext::cast(context); |
3282 | 3444 |
CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3283 |
current_block()->Goto(test->if_true(), state);
|
|
3445 |
Goto(test->if_true(), state); |
|
3284 | 3446 |
} else if (context->IsEffect()) { |
3285 | 3447 |
CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3286 |
current_block()->Goto(function_return(), state);
|
|
3448 |
Goto(function_return(), state); |
|
3287 | 3449 |
} else { |
3288 | 3450 |
ASSERT(context->IsValue()); |
3289 | 3451 |
CHECK_ALIVE(VisitForValue(stmt->expression())); |
3290 | 3452 |
HValue* return_value = Pop(); |
3291 | 3453 |
HValue* receiver = environment()->arguments_environment()->Lookup(0); |
3292 | 3454 |
HHasInstanceTypeAndBranch* typecheck = |
3293 |
new(zone()) HHasInstanceTypeAndBranch(return_value,
|
|
3294 |
FIRST_SPEC_OBJECT_TYPE,
|
|
3295 |
LAST_SPEC_OBJECT_TYPE);
|
|
3455 |
New<HHasInstanceTypeAndBranch>(return_value,
|
|
3456 |
FIRST_SPEC_OBJECT_TYPE, |
|
3457 |
LAST_SPEC_OBJECT_TYPE); |
|
3296 | 3458 |
HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); |
3297 | 3459 |
HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); |
3298 | 3460 |
typecheck->SetSuccessorAt(0, if_spec_object); |
3299 | 3461 |
typecheck->SetSuccessorAt(1, not_spec_object); |
3300 |
current_block()->Finish(typecheck);
|
|
3301 |
if_spec_object->AddLeaveInlined(return_value, state);
|
|
3302 |
not_spec_object->AddLeaveInlined(receiver, state);
|
|
3462 |
FinishCurrentBlock(typecheck);
|
|
3463 |
AddLeaveInlined(if_spec_object, return_value, state);
|
|
3464 |
AddLeaveInlined(not_spec_object, receiver, state);
|
|
3303 | 3465 |
} |
3304 | 3466 |
} else if (state->inlining_kind() == SETTER_CALL_RETURN) { |
3305 | 3467 |
// Return from an inlined setter call. The returned value is never used, the |
... | ... | |
3309 | 3471 |
HValue* rhs = environment()->arguments_environment()->Lookup(1); |
3310 | 3472 |
context->ReturnValue(rhs); |
3311 | 3473 |
} else if (context->IsEffect()) { |
3312 |
current_block()->Goto(function_return(), state);
|
|
3474 |
Goto(function_return(), state); |
|
3313 | 3475 |
} else { |
3314 | 3476 |
ASSERT(context->IsValue()); |
3315 | 3477 |
HValue* rhs = environment()->arguments_environment()->Lookup(1); |
3316 |
current_block()->AddLeaveInlined(rhs, state);
|
|
3478 |
AddLeaveInlined(rhs, state); |
|
3317 | 3479 |
} |
3318 | 3480 |
} else { |
3319 | 3481 |
// Return from a normal inlined function. Visit the subexpression in the |
... | ... | |
3323 | 3485 |
VisitForControl(stmt->expression(), test->if_true(), test->if_false()); |
3324 | 3486 |
} else if (context->IsEffect()) { |
3325 | 3487 |
CHECK_ALIVE(VisitForEffect(stmt->expression())); |
3326 |
current_block()->Goto(function_return(), state);
|
|
3488 |
Goto(function_return(), state); |
|
3327 | 3489 |
} else { |
3328 | 3490 |
ASSERT(context->IsValue()); |
3329 | 3491 |
CHECK_ALIVE(VisitForValue(stmt->expression())); |
3330 |
current_block()->AddLeaveInlined(Pop(), state);
|
|
3492 |
AddLeaveInlined(Pop(), state); |
|
3331 | 3493 |
} |
3332 | 3494 |
} |
3333 | 3495 |
set_current_block(NULL); |
... | ... | |
3361 | 3523 |
return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels); |
3362 | 3524 |
} |
3363 | 3525 |
|
3364 |
HValue* context = environment()->context(); |
|
3365 |
|
|
3366 | 3526 |
CHECK_ALIVE(VisitForValue(stmt->tag())); |
3367 | 3527 |
Add<HSimulate>(stmt->EntryId()); |
3368 | 3528 |
HValue* tag_value = Pop(); |
... | ... | |
3373 | 3533 |
|
3374 | 3534 |
// Test switch's tag value if all clauses are string literals |
3375 | 3535 |
if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
3376 |
string_check = new(zone()) HIsStringAndBranch(tag_value); |
|
3377 | 3536 |
first_test_block = graph()->CreateBasicBlock(); |
3378 | 3537 |
not_string_block = graph()->CreateBasicBlock(); |
3379 |
|
|
3380 |
string_check->SetSuccessorAt(0, first_test_block); |
|
3381 |
string_check->SetSuccessorAt(1, not_string_block); |
|
3382 |
current_block()->Finish(string_check); |
|
3538 |
string_check = New<HIsStringAndBranch>( |
|
3539 |
tag_value, first_test_block, not_string_block); |
|
3540 |
FinishCurrentBlock(string_check); |
|
3383 | 3541 |
|
3384 | 3542 |
set_current_block(first_test_block); |
3385 | 3543 |
} |
... | ... | |
3408 | 3566 |
} |
3409 | 3567 |
|
3410 | 3568 |
HCompareNumericAndBranch* compare_ = |
3411 |
new(zone()) HCompareNumericAndBranch(tag_value,
|
|
3412 |
label_value,
|
|
3413 |
Token::EQ_STRICT);
|
|
3569 |
New<HCompareNumericAndBranch>(tag_value,
|
|
3570 |
label_value, |
|
3571 |
Token::EQ_STRICT); |
|
3414 | 3572 |
compare_->set_observed_input_representation( |
3415 | 3573 |
Representation::Smi(), Representation::Smi()); |
3416 | 3574 |
compare = compare_; |
3417 | 3575 |
} else { |
3418 |
compare = new(zone()) HStringCompareAndBranch(context, tag_value,
|
|
3419 |
label_value,
|
|
3420 |
Token::EQ_STRICT);
|
|
3576 |
compare = New<HStringCompareAndBranch>(tag_value,
|
|
3577 |
label_value, |
|
3578 |
Token::EQ_STRICT); |
|
3421 | 3579 |
} |
3422 | 3580 |
|
3423 | 3581 |
compare->SetSuccessorAt(0, body_block); |
3424 | 3582 |
compare->SetSuccessorAt(1, next_test_block); |
3425 |
current_block()->Finish(compare);
|
|
3583 |
FinishCurrentBlock(compare);
|
|
3426 | 3584 |
|
3427 | 3585 |
set_current_block(next_test_block); |
3428 | 3586 |
} |
... | ... | |
3455 | 3613 |
last_block = NULL; // Cleared to indicate we've handled it. |
3456 | 3614 |
} |
3457 | 3615 |
} else { |
3616 |
// If the current test block is deoptimizing due to an unhandled clause |
|
3617 |
// of the switch, the test instruction is in the next block since the |
|
3618 |
// deopt must end the current block. |
|
3619 |
if (curr_test_block->IsDeoptimizing()) { |
|
3620 |
ASSERT(curr_test_block->end()->SecondSuccessor() == NULL); |
|
3621 |
curr_test_block = curr_test_block->end()->FirstSuccessor(); |
|
3622 |
} |
|
3458 | 3623 |
normal_block = curr_test_block->end()->FirstSuccessor(); |
3459 | 3624 |
curr_test_block = curr_test_block->end()->SecondSuccessor(); |
3460 | 3625 |
} |
... | ... | |
3496 | 3661 |
last_block, |
3497 | 3662 |
stmt->ExitId())); |
3498 | 3663 |
} else { |
3499 |
if (fall_through_block != NULL) fall_through_block->Goto(break_block);
|
|
3500 |
if (last_block != NULL) last_block->Goto(break_block);
|
|
3664 |
if (fall_through_block != NULL) Goto(fall_through_block, break_block);
|
|
3665 |
if (last_block != NULL) Goto(last_block, break_block);
|
|
3501 | 3666 |
break_block->SetJoinId(stmt->ExitId()); |
3502 | 3667 |
set_current_block(break_block); |
3503 | 3668 |
} |
... | ... | |
3509 | 3674 |
BreakAndContinueInfo* break_info) { |
3510 | 3675 |
BreakAndContinueScope push(break_info, this); |
3511 | 3676 |
Add<HSimulate>(stmt->StackCheckId()); |
3512 |
HValue* context = environment()->context(); |
|
3513 |
HStackCheck* stack_check = HStackCheck::cast(Add<HStackCheck>( |
|
3514 |
context, HStackCheck::kBackwardsBranch)); |
|
3677 |
HStackCheck* stack_check = |
|
3678 |
HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch)); |
|
3515 | 3679 |
ASSERT(loop_entry->IsLoopHeader()); |
3516 | 3680 |
loop_entry->loop_information()->set_stack_check(stack_check); |
3517 | 3681 |
CHECK_BAILOUT(Visit(stmt->body())); |
... | ... | |
3523 | 3687 |
ASSERT(current_block() != NULL); |
3524 | 3688 |
ASSERT(current_block()->HasPredecessor()); |
3525 | 3689 |
ASSERT(current_block() != NULL); |
3526 |
HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
|
|
3690 |
HBasicBlock* loop_entry = BuildLoopEntry(stmt);
|
|
3527 | 3691 |
|
3528 | 3692 |
BreakAndContinueInfo break_info(stmt); |
3529 | 3693 |
CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
... | ... | |
3562 | 3726 |
ASSERT(current_block() != NULL); |
3563 | 3727 |
ASSERT(current_block()->HasPredecessor()); |
3564 | 3728 |
ASSERT(current_block() != NULL); |
3565 |
HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
|
|
3729 |
HBasicBlock* loop_entry = BuildLoopEntry(stmt);
|
|
3566 | 3730 |
|
3567 | 3731 |
// If the condition is constant true, do not generate a branch. |
3568 | 3732 |
HBasicBlock* loop_successor = NULL; |
... | ... | |
3604 | 3768 |
CHECK_ALIVE(Visit(stmt->init())); |
3605 | 3769 |
} |
3606 | 3770 |
ASSERT(current_block() != NULL); |
3607 |
HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
|
|
3771 |
HBasicBlock* loop_entry = BuildLoopEntry(stmt);
|
|
3608 | 3772 |
|
3609 | 3773 |
HBasicBlock* loop_successor = NULL; |
3610 | 3774 |
if (stmt->cond() != NULL) { |
... | ... | |
3687 | 3851 |
HForInCacheArray::cast(array)->set_index_cache( |
3688 | 3852 |
HForInCacheArray::cast(index_cache)); |
3689 | 3853 |
|
3690 |
HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
|
|
3854 |
HBasicBlock* loop_entry = BuildLoopEntry(stmt);
|
|
3691 | 3855 |
|
3692 | 3856 |
HValue* index = environment()->ExpressionStackAt(0); |
3693 | 3857 |
HValue* limit = environment()->ExpressionStackAt(1); |
3694 | 3858 |
|
3695 | 3859 |
// Check that we still have more keys. |
3696 | 3860 |
HCompareNumericAndBranch* compare_index = |
3697 |
new(zone()) HCompareNumericAndBranch(index, limit, Token::LT);
|
|
3861 |
New<HCompareNumericAndBranch>(index, limit, Token::LT);
|
|
3698 | 3862 |
compare_index->set_observed_input_representation( |
3699 | 3863 |
Representation::Smi(), Representation::Smi()); |
3700 | 3864 |
|
... | ... | |
3703 | 3867 |
|
3704 | 3868 |
compare_index->SetSuccessorAt(0, loop_body); |
3705 | 3869 |
compare_index->SetSuccessorAt(1, loop_successor); |
3706 |
current_block()->Finish(compare_index);
|
|
3870 |
FinishCurrentBlock(compare_index);
|
|
3707 | 3871 |
|
3708 | 3872 |
set_current_block(loop_successor); |
3709 | 3873 |
Drop(5); |
... | ... | |
3733 | 3897 |
set_current_block(body_exit); |
3734 | 3898 |
|
3735 | 3899 |
HValue* current_index = Pop(); |
3736 |
HInstruction* new_index = New<HAdd>(current_index, |
|
3737 |
graph()->GetConstant1()); |
|
3738 |
PushAndAdd(new_index); |
|
3900 |
Push(Add<HAdd>(current_index, graph()->GetConstant1())); |
|
3739 | 3901 |
body_exit = current_block(); |
3740 | 3902 |
} |
3741 | 3903 |
|
... | ... | |
3782 | 3944 |
} |
3783 | 3945 |
|
3784 | 3946 |
|
3947 |
void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) { |
|
3948 |
UNREACHABLE(); |
|
3949 |
} |
|
3950 |
|
|
3951 |
|
|
3785 | 3952 |
static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
3786 | 3953 |
Code* unoptimized_code, FunctionLiteral* expr) { |
3787 | 3954 |
int start_position = expr->start_position(); |
... | ... | |
3812 | 3979 |
} |
3813 | 3980 |
// We also have a stack overflow if the recursive compilation did. |
3814 | 3981 |
if (HasStackOverflow()) return; |
3815 |
HValue* context = environment()->context(); |
|
3816 | 3982 |
HFunctionLiteral* instr = |
3817 |
new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
|
|
3983 |
New<HFunctionLiteral>(shared_info, expr->pretenure());
|
|
3818 | 3984 |
return ast_context()->ReturnInstruction(instr, expr->id()); |
3819 | 3985 |
} |
3820 | 3986 |
|
3821 | 3987 |
|
3822 |
void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral(
|
|
3823 |
SharedFunctionInfoLiteral* expr) {
|
|
3988 |
void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
|
|
3989 |
NativeFunctionLiteral* expr) {
|
|
3824 | 3990 |
ASSERT(!HasStackOverflow()); |
3825 | 3991 |
ASSERT(current_block() != NULL); |
3826 | 3992 |
ASSERT(current_block()->HasPredecessor()); |
3827 |
return Bailout(kSharedFunctionInfoLiteral);
|
|
3993 |
return Bailout(kNativeFunctionLiteral);
|
|
3828 | 3994 |
} |
3829 | 3995 |
|
3830 | 3996 |
|
... | ... | |
3938 | 4104 |
return ast_context()->ReturnInstruction(constant, expr->id()); |
3939 | 4105 |
} else { |
3940 | 4106 |
HLoadGlobalCell* instr = |
3941 |
new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
|
|
4107 |
New<HLoadGlobalCell>(cell, lookup.GetPropertyDetails());
|
|
3942 | 4108 |
return ast_context()->ReturnInstruction(instr, expr->id()); |
3943 | 4109 |
} |
3944 | 4110 |
} else { |
3945 |
HValue* context = environment()->context(); |
|
3946 |
HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
|
3947 |
AddInstruction(global_object); |
|
4111 |
HGlobalObject* global_object = Add<HGlobalObject>(); |
|
3948 | 4112 |
HLoadGlobalGeneric* instr = |
3949 |
new(zone()) HLoadGlobalGeneric(context, |
|
3950 |
global_object, |
|
3951 |
variable->name(), |
|
3952 |
ast_context()->is_for_typeof()); |
|
3953 |
instr->set_position(expr->position()); |
|
4113 |
New<HLoadGlobalGeneric>(global_object, |
|
4114 |
variable->name(), |
|
4115 |
ast_context()->is_for_typeof()); |
|
3954 | 4116 |
return ast_context()->ReturnInstruction(instr, expr->id()); |
3955 | 4117 |
} |
3956 | 4118 |
} |
... | ... | |
3993 | 4155 |
ASSERT(current_block()->HasPredecessor()); |
3994 | 4156 |
Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
3995 | 4157 |
Handle<FixedArray> literals(closure->literals()); |
3996 |
HValue* context = environment()->context(); |
|
3997 |
|
|
3998 |
HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
|
3999 |
literals, |
|
4000 |
expr->pattern(), |
|
4001 |
expr->flags(), |
|
4002 |
expr->literal_index()); |
|
4158 |
HRegExpLiteral* instr = New<HRegExpLiteral>(literals, |
|
4159 |
expr->pattern(), |
|
4160 |
expr->flags(), |
|
4161 |
expr->literal_index()); |
|
4003 | 4162 |
return ast_context()->ReturnInstruction(instr, expr->id()); |
4004 | 4163 |
} |
4005 | 4164 |
|
... | ... | |
4064 | 4223 |
} |
4065 | 4224 |
|
4066 | 4225 |
|
4067 |
static bool LookupGetter(Handle<Map> map, |
|
4068 |
Handle<String> name, |
|
4069 |
Handle<JSFunction>* getter, |
|
4070 |
Handle<JSObject>* holder) { |
|
4071 |
Handle<AccessorPair> accessors; |
|
4072 |
if (LookupAccessorPair(map, name, &accessors, holder) && |
|
4073 |
accessors->getter()->IsJSFunction()) { |
|
4074 |
*getter = Handle<JSFunction>(JSFunction::cast(accessors->getter())); |
|
4075 |
return true; |
|
4076 |
} |
|
4077 |
return false; |
|
4078 |
} |
|
4079 |
|
|
4080 |
|
|
4081 | 4226 |
static bool LookupSetter(Handle<Map> map, |
4082 | 4227 |
Handle<String> name, |
4083 | 4228 |
Handle<JSFunction>* setter, |
... | ... | |
4085 | 4230 |
Handle<AccessorPair> accessors; |
4086 | 4231 |
if (LookupAccessorPair(map, name, &accessors, holder) && |
4087 | 4232 |
accessors->setter()->IsJSFunction()) { |
4088 |
*setter = Handle<JSFunction>(JSFunction::cast(accessors->setter())); |
|
4233 |
Handle<JSFunction> func(JSFunction::cast(accessors->setter())); |
|
4234 |
CallOptimization call_optimization(func); |
|
4235 |
// TODO(dcarney): temporary hack unless crankshaft can handle api calls. |
|
4236 |
if (call_optimization.is_simple_api_call()) return false; |
|
4237 |
*setter = func; |
|
4089 | 4238 |
return true; |
4090 | 4239 |
} |
4091 | 4240 |
return false; |
... | ... | |
4100 | 4249 |
int* max_properties) { |
4101 | 4250 |
if (boilerplate->map()->is_deprecated()) { |
4102 | 4251 |
Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); |
4103 |
if (result->IsSmi()) return false;
|
|
4252 |
if (result.is_null()) return false;
|
|
4104 | 4253 |
} |
4105 | 4254 |
|
4106 | 4255 |
ASSERT(max_depth >= 0 && *max_properties >= 0); |
... | ... | |
4166 | 4315 |
|
4167 | 4316 |
// Check whether to use fast or slow deep-copying for boilerplate. |
4168 | 4317 |
int max_properties = kMaxFastLiteralProperties; |
4169 |
Handle<Object> boilerplate(closure->literals()->get( |
|
4170 |
expr->literal_index()), isolate()); |
|
4171 |
if (boilerplate->IsJSObject() && |
|
4172 |
IsFastLiteral(Handle<JSObject>::cast(boilerplate), |
|
4173 |
kMaxFastLiteralDepth, |
|
4174 |
&max_properties)) { |
|
4175 |
Handle<JSObject> boilerplate_object = |
Also available in: Unified diff